Skip to content

Commit f805cd9

Browse files
committed
implement name resolution in parser
1 parent c0daff5 commit f805cd9

File tree

7 files changed

+145
-177
lines changed

7 files changed

+145
-177
lines changed

chalk-integration/src/error.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,8 @@ impl std::error::Error for ChalkError {}
5454

5555
#[derive(Debug)]
5656
pub enum RustIrError {
57-
InvalidTypeName(Identifier),
58-
InvalidLifetimeName(Identifier),
59-
InvalidConstName(Identifier),
57+
InvalidParameterName(Identifier),
58+
InvalidTraitName(Identifier),
6059
NotTrait(Identifier),
6160
NotStruct(Identifier),
6261
DuplicateOrShadowedParameters,
@@ -97,9 +96,10 @@ pub enum RustIrError {
9796
impl std::fmt::Display for RustIrError {
9897
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9998
match self {
100-
RustIrError::InvalidTypeName(name) => write!(f, "invalid type name `{}`", name),
101-
RustIrError::InvalidLifetimeName(name) => write!(f, "invalid lifetime name `{}`", name),
102-
RustIrError::InvalidConstName(name) => write!(f, "invalid const name `{}`", name),
99+
RustIrError::InvalidParameterName(name) => {
100+
write!(f, "invalid parameter name `{}`", name)
101+
}
102+
RustIrError::InvalidTraitName(name) => write!(f, "invalid trait name `{}`", name),
103103
RustIrError::NotTrait(name) => write!(
104104
f,
105105
"expected a trait, found `{}`, which is not a trait",

chalk-integration/src/lowering.rs

Lines changed: 105 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type TraitKinds = BTreeMap<chalk_ir::TraitId<ChalkIr>, TypeKind>;
2626
type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
2727
type AssociatedTyValueIds =
2828
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
29-
type ParameterMap = BTreeMap<chalk_ir::ParameterKind<Ident>, BoundVar>;
29+
type ParameterMap = BTreeMap<Ident, chalk_ir::ParameterKind<BoundVar>>;
3030

3131
pub type LowerResult<T> = Result<T, RustIrError>;
3232

@@ -68,85 +68,96 @@ struct AssociatedTyLookup {
6868
addl_parameter_kinds: Vec<chalk_ir::ParameterKind<()>>,
6969
}
7070

71-
enum TypeLookup {
72-
Struct(chalk_ir::StructId<ChalkIr>),
73-
Parameter(BoundVar),
74-
Opaque(chalk_ir::OpaqueTyId<ChalkIr>),
75-
}
76-
77-
enum LifetimeLookup {
78-
Parameter(BoundVar),
79-
}
80-
81-
enum ConstLookup {
82-
Parameter(BoundVar),
71+
enum ApplyTypeLookup {
72+
Struct(StructId<ChalkIr>),
8373
}
8474

8575
const SELF: &str = "Self";
8676
const FIXME_SELF: &str = "__FIXME_SELF__";
8777

8878
impl<'k> Env<'k> {
89-
fn lookup_type(&self, name: Identifier) -> LowerResult<TypeLookup> {
90-
if let Some(k) = self
91-
.parameter_map
92-
.get(&chalk_ir::ParameterKind::Ty(name.str))
93-
{
94-
return Ok(TypeLookup::Parameter(*k));
79+
fn lookup_parameter(&self, name: Identifier) -> LowerResult<chalk_ir::Parameter<ChalkIr>> {
80+
let interner = self.interner();
81+
82+
if let Some(p) = self.parameter_map.get(&name.str) {
83+
return match *p {
84+
chalk_ir::ParameterKind::Ty(b) => Ok(chalk_ir::TyData::BoundVar(b)
85+
.intern(interner)
86+
.cast(interner)),
87+
chalk_ir::ParameterKind::Lifetime(b) => Ok(chalk_ir::LifetimeData::BoundVar(b)
88+
.intern(interner)
89+
.cast(interner)),
90+
chalk_ir::ParameterKind::Const(b) => Ok(chalk_ir::ConstData::BoundVar(b)
91+
.intern(interner)
92+
.cast(interner)),
93+
};
9594
}
9695

9796
if let Some(id) = self.struct_ids.get(&name.str) {
98-
return Ok(TypeLookup::Struct(*id));
97+
let k = self.struct_kind(*id);
98+
if k.binders.len(interner) > 0 {
99+
return Err(RustIrError::IncorrectNumberOfTypeParameters {
100+
identifier: name,
101+
expected: k.binders.len(interner),
102+
actual: 0,
103+
});
104+
} else {
105+
return Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
106+
name: chalk_ir::TypeName::Struct(*id),
107+
substitution: chalk_ir::Substitution::empty(interner),
108+
})
109+
.intern(interner)
110+
.cast(interner));
111+
};
99112
}
100113

101114
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
102-
return Ok(TypeLookup::Opaque(*id));
115+
return Ok(
116+
chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
117+
opaque_ty_id: *id,
118+
substitution: chalk_ir::Substitution::empty(interner),
119+
}))
120+
.intern(interner)
121+
.cast(interner),
122+
);
103123
}
104124
if let Some(_) = self.trait_ids.get(&name.str) {
105125
return Err(RustIrError::NotStruct(name));
106126
}
107127

108-
Err(RustIrError::InvalidTypeName(name))
128+
Err(RustIrError::InvalidParameterName(name))
109129
}
110130

111-
fn lookup_trait(&self, name: Identifier) -> LowerResult<TraitId<ChalkIr>> {
112-
if let Some(_) = self
113-
.parameter_map
114-
.get(&chalk_ir::ParameterKind::Ty(name.str))
115-
{
116-
return Err(RustIrError::NotTrait(name));
131+
fn lookup_apply_type(&self, name: Identifier) -> LowerResult<ApplyTypeLookup> {
132+
if let Some(_) = self.parameter_map.get(&name.str) {
133+
return Err(RustIrError::CannotApplyTypeParameter(name));
117134
}
118135

119-
if let Some(_) = self.struct_ids.get(&name.str) {
120-
return Err(RustIrError::NotTrait(name));
136+
if let Some(_) = self.opaque_ty_ids.get(&name.str) {
137+
return Err(RustIrError::CannotApplyTypeParameter(name));
121138
}
122139

123-
if let Some(id) = self.trait_ids.get(&name.str) {
124-
return Ok(*id);
140+
if let Some(id) = self.struct_ids.get(&name.str) {
141+
return Ok(ApplyTypeLookup::Struct(*id));
125142
}
126143

127-
Err(RustIrError::InvalidTypeName(name))
144+
Err(RustIrError::NotStruct(name))
128145
}
129146

130-
fn lookup_lifetime(&self, name: Identifier) -> LowerResult<LifetimeLookup> {
131-
if let Some(k) = self
132-
.parameter_map
133-
.get(&chalk_ir::ParameterKind::Lifetime(name.str))
134-
{
135-
return Ok(LifetimeLookup::Parameter(*k));
147+
fn lookup_trait(&self, name: Identifier) -> LowerResult<TraitId<ChalkIr>> {
148+
if let Some(_) = self.parameter_map.get(&name.str) {
149+
return Err(RustIrError::NotTrait(name));
136150
}
137151

138-
Err(RustIrError::InvalidLifetimeName(name))
139-
}
152+
if let Some(_) = self.struct_ids.get(&name.str) {
153+
return Err(RustIrError::NotTrait(name));
154+
}
140155

141-
fn lookup_const(&self, name: Identifier) -> LowerResult<ConstLookup> {
142-
if let Some(k) = self
143-
.parameter_map
144-
.get(&chalk_ir::ParameterKind::Const(name.str))
145-
{
146-
return Ok(ConstLookup::Parameter(*k));
156+
if let Some(id) = self.trait_ids.get(&name.str) {
157+
return Ok(*id);
147158
}
148159

149-
Err(RustIrError::InvalidConstName(name))
160+
Err(RustIrError::InvalidTraitName(name))
150161
}
151162

152163
fn struct_kind(&self, id: chalk_ir::StructId<ChalkIr>) -> &TypeKind {
@@ -165,15 +176,23 @@ impl<'k> Env<'k> {
165176
I: IntoIterator<Item = chalk_ir::ParameterKind<Ident>>,
166177
I::IntoIter: ExactSizeIterator,
167178
{
179+
// As binders to introduce we recieve `ParameterKind<Ident>`,
180+
// which we need to transform into `(Ident, ParameterKind<BoundVar>)`,
181+
// because that is the key-value pair for ParameterMap.
182+
// `swap_inner` lets us do precisely that, replacing `Ident` inside
183+
// `ParameterKind<Ident>` with a `BoundVar` and returning both.
168184
let binders = binders
169185
.into_iter()
170186
.enumerate()
171-
.map(|(i, k)| (k, BoundVar::new(DebruijnIndex::INNERMOST, i)));
187+
.map(|(i, k)| k.swap_inner(BoundVar::new(DebruijnIndex::INNERMOST, i)));
172188
let len = binders.len();
189+
190+
// For things already in the parameter map, we take each existing key-value pair
191+
// `(Ident, ParameterKind<BoundVar>)` and shift in the inner `BoundVar`.
173192
let parameter_map: ParameterMap = self
174193
.parameter_map
175194
.iter()
176-
.map(|(&k, &v)| (k, v.shifted_in()))
195+
.map(|(&k, &v)| (k, v.map(|b| b.shifted_in())))
177196
.chain(binders)
178197
.collect();
179198
if parameter_map.len() != self.parameter_map.len() + len {
@@ -521,6 +540,7 @@ trait LowerParameterMap {
521540
self.all_parameters()
522541
.into_iter()
523542
.zip((0..).map(|i| BoundVar::new(DebruijnIndex::INNERMOST, i)))
543+
.map(|(k, v)| k.swap_inner(v))
524544
.collect()
525545
}
526546

@@ -787,17 +807,7 @@ impl LowerLeafGoal for LeafGoal {
787807
LeafGoal::DomainGoal { goal } => {
788808
chalk_ir::Goal::all(interner, goal.lower(env)?.into_iter().casted(interner))
789809
}
790-
LeafGoal::UnifyTys { a, b } => chalk_ir::EqGoal {
791-
a: a.lower(env)?.cast(interner),
792-
b: b.lower(env)?.cast(interner),
793-
}
794-
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
795-
LeafGoal::UnifyLifetimes { ref a, ref b } => chalk_ir::EqGoal {
796-
a: a.lower(env)?.cast(interner),
797-
b: b.lower(env)?.cast(interner),
798-
}
799-
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
800-
LeafGoal::UnifyConsts { ref a, ref b } => chalk_ir::EqGoal {
810+
LeafGoal::UnifyParameters { a, b } => chalk_ir::EqGoal {
801811
a: a.lower(env)?.cast(interner),
802812
b: b.lower(env)?.cast(interner),
803813
}
@@ -1096,33 +1106,16 @@ impl LowerTy for Ty {
10961106
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Ty<ChalkIr>> {
10971107
let interner = env.interner();
10981108
match *self {
1099-
Ty::Id { name } => match env.lookup_type(name)? {
1100-
TypeLookup::Struct(id) => {
1101-
let k = env.struct_kind(id);
1102-
if k.binders.len(interner) > 0 {
1103-
Err(RustIrError::IncorrectNumberOfTypeParameters {
1104-
identifier: name,
1105-
expected: k.binders.len(interner),
1106-
actual: 0,
1107-
})
1108-
} else {
1109-
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
1110-
name: chalk_ir::TypeName::Struct(id),
1111-
substitution: chalk_ir::Substitution::empty(interner),
1112-
})
1113-
.intern(interner))
1109+
Ty::Id { name } => {
1110+
let parameter = env.lookup_parameter(name)?;
1111+
parameter.ty(interner).map(|ty| ty.clone()).ok_or_else(|| {
1112+
RustIrError::IncorrectParameterKind {
1113+
identifier: name,
1114+
expected: Kind::Ty,
1115+
actual: parameter.kind(),
11141116
}
1115-
}
1116-
TypeLookup::Parameter(d) => Ok(chalk_ir::TyData::BoundVar(d).intern(interner)),
1117-
TypeLookup::Opaque(id) => Ok(chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(
1118-
chalk_ir::OpaqueTy {
1119-
opaque_ty_id: id,
1120-
substitution: chalk_ir::Substitution::empty(interner),
1121-
},
1122-
))
1123-
.intern(interner)),
1124-
},
1125-
1117+
})
1118+
}
11261119
Ty::Dyn { ref bounds } => Ok(chalk_ir::TyData::Dyn(chalk_ir::DynTy {
11271120
bounds: env.in_binders(
11281121
// FIXME: Figure out a proper name for this type parameter
@@ -1147,11 +1140,8 @@ impl LowerTy for Ty {
11471140
.intern(interner)),
11481141

11491142
Ty::Apply { name, ref args } => {
1150-
let id = match env.lookup_type(name)? {
1151-
TypeLookup::Struct(id) => id,
1152-
TypeLookup::Parameter(_) | TypeLookup::Opaque(_) => {
1153-
Err(RustIrError::CannotApplyTypeParameter(name))?
1154-
}
1143+
let id = match env.lookup_apply_type(name)? {
1144+
ApplyTypeLookup::Struct(id) => id,
11551145
};
11561146

11571147
let k = env.struct_kind(id);
@@ -1168,7 +1158,12 @@ impl LowerTy for Ty {
11681158
args.iter().map(|t| Ok(t.lower(env)?)),
11691159
)?;
11701160

1171-
for (param, arg) in k.binders.binders.iter(interner).zip(args.iter()) {
1161+
for (param, arg) in k
1162+
.binders
1163+
.binders
1164+
.iter(interner)
1165+
.zip(substitution.iter(interner))
1166+
{
11721167
if param.kind() != arg.kind() {
11731168
Err(RustIrError::IncorrectParameterKind {
11741169
identifier: name,
@@ -1237,28 +1232,12 @@ impl LowerParameter for Parameter {
12371232
match *self {
12381233
Parameter::Ty(ref t) => Ok(t.lower(env)?.cast(interner)),
12391234
Parameter::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)),
1240-
Parameter::Const(ref c) => Ok(c.lower(env)?.cast(interner)),
1241-
}
1242-
}
1243-
}
1244-
1245-
trait LowerConst {
1246-
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>>;
1247-
}
1248-
1249-
impl LowerConst for Const {
1250-
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>> {
1251-
let interner = env.interner();
1252-
match *self {
1253-
Const::Id { name } => match env.lookup_const(name)? {
1254-
ConstLookup::Parameter(d) => Ok(chalk_ir::ConstData::BoundVar(d).intern(interner)),
1255-
},
1256-
Const::Value { value } => {
1257-
Ok(
1258-
chalk_ir::ConstData::Concrete(chalk_ir::ConcreteConst { interned: value })
1259-
.intern(interner),
1260-
)
1261-
}
1235+
Parameter::Id(name) => env.lookup_parameter(name),
1236+
Parameter::ConstValue(value) => Ok(chalk_ir::ConstData::Concrete(
1237+
chalk_ir::ConcreteConst { interned: value },
1238+
)
1239+
.intern(interner)
1240+
.cast(interner)),
12621241
}
12631242
}
12641243
}
@@ -1271,11 +1250,17 @@ impl LowerLifetime for Lifetime {
12711250
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Lifetime<ChalkIr>> {
12721251
let interner = env.interner();
12731252
match *self {
1274-
Lifetime::Id { name } => match env.lookup_lifetime(name)? {
1275-
LifetimeLookup::Parameter(d) => {
1276-
Ok(chalk_ir::LifetimeData::BoundVar(d).intern(interner))
1277-
}
1278-
},
1253+
Lifetime::Id { name } => {
1254+
let parameter = env.lookup_parameter(name)?;
1255+
parameter
1256+
.lifetime(interner)
1257+
.map(|l| l.clone())
1258+
.ok_or_else(|| RustIrError::IncorrectParameterKind {
1259+
identifier: name,
1260+
expected: Kind::Lifetime,
1261+
actual: parameter.kind(),
1262+
})
1263+
}
12791264
}
12801265
}
12811266
}
@@ -1575,16 +1560,6 @@ impl Kinded for ParameterKind {
15751560
}
15761561
}
15771562

1578-
impl Kinded for Parameter {
1579-
fn kind(&self) -> Kind {
1580-
match *self {
1581-
Parameter::Ty(_) => Kind::Ty,
1582-
Parameter::Lifetime(_) => Kind::Lifetime,
1583-
Parameter::Const(_) => Kind::Const,
1584-
}
1585-
}
1586-
}
1587-
15881563
impl<T, L, C> Kinded for chalk_ir::ParameterKind<T, L, C> {
15891564
fn kind(&self) -> Kind {
15901565
match *self {

chalk-ir/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,14 @@ impl<T> ParameterKind<T> {
859859
}
860860
}
861861

862+
pub fn swap_inner<U>(self, u: U) -> (T, ParameterKind<U>) {
863+
match self {
864+
ParameterKind::Ty(t) => (t, ParameterKind::Ty(u)),
865+
ParameterKind::Lifetime(t) => (t, ParameterKind::Lifetime(u)),
866+
ParameterKind::Const(t) => (t, ParameterKind::Const(u)),
867+
}
868+
}
869+
862870
pub fn map<OP, U>(self, op: OP) -> ParameterKind<U>
863871
where
864872
OP: FnOnce(T) -> U,

0 commit comments

Comments
 (0)