Skip to content

Commit f89eacd

Browse files
committed
implement name resolution in parser
1 parent 338ab7c commit f89eacd

File tree

11 files changed

+154
-185
lines changed

11 files changed

+154
-185
lines changed

chalk-integration/src/error.rs

+6-6
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

+109-125
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), Associa
2727
type AssociatedTyValueIds =
2828
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
2929

30-
type NamedGenericArg = chalk_ir::WithKind<ChalkIr, Ident>;
31-
type ParameterMap = BTreeMap<NamedGenericArg, BoundVar>;
30+
type ParameterMap = BTreeMap<Ident, chalk_ir::WithKind<ChalkIr, BoundVar>>;
3231

3332
pub type LowerResult<T> = Result<T, RustIrError>;
3433

@@ -70,85 +69,96 @@ struct AssociatedTyLookup {
7069
addl_variable_kinds: Vec<chalk_ir::VariableKind<ChalkIr>>,
7170
}
7271

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

8776
const SELF: &str = "Self";
8877
const FIXME_SELF: &str = "__FIXME_SELF__";
8978

9079
impl<'k> Env<'k> {
91-
fn lookup_type(&self, name: &Identifier) -> LowerResult<TypeLookup> {
92-
if let Some(k) = self.parameter_map.get(&NamedGenericArg::new(
93-
chalk_ir::VariableKind::Ty,
94-
name.str.clone(),
95-
)) {
96-
return Ok(TypeLookup::GenericArg(*k));
80+
fn lookup_generic_arg(&self, name: Identifier) -> LowerResult<chalk_ir::GenericArg<ChalkIr>> {
81+
let interner = self.interner();
82+
83+
if let Some(p) = self.parameter_map.get(&name.str) {
84+
return match *p {
85+
chalk_ir::GenericArgData::Ty(b) => Ok(chalk_ir::TyData::BoundVar(b)
86+
.intern(interner)
87+
.cast(interner)),
88+
chalk_ir::GenericArgData::Lifetime(b) => Ok(chalk_ir::LifetimeData::BoundVar(b)
89+
.intern(interner)
90+
.cast(interner)),
91+
chalk_ir::GenericArgData::Const(b) => Ok(chalk_ir::ConstData::BoundVar(b)
92+
.intern(interner)
93+
.cast(interner)),
94+
};
9795
}
9896

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

103115
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
104-
return Ok(TypeLookup::Opaque(*id));
116+
return Ok(
117+
chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
118+
opaque_ty_id: *id,
119+
substitution: chalk_ir::Substitution::empty(interner),
120+
}))
121+
.intern(interner)
122+
.cast(interner),
123+
);
105124
}
106125
if let Some(_) = self.trait_ids.get(&name.str) {
107126
return Err(RustIrError::NotStruct(name.clone()));
108127
}
109128

110-
Err(RustIrError::InvalidTypeName(name.clone()))
129+
Err(RustIrError::InvalidParameterName(name))
111130
}
112131

113-
fn lookup_trait(&self, name: &Identifier) -> LowerResult<TraitId<ChalkIr>> {
114-
if let Some(_) = self.parameter_map.get(&NamedGenericArg::new(
115-
chalk_ir::VariableKind::Ty,
116-
name.str.clone(),
117-
)) {
118-
return Err(RustIrError::NotTrait(name.clone()));
132+
fn lookup_apply_type(&self, name: Identifier) -> LowerResult<ApplyTypeLookup> {
133+
if let Some(_) = self.parameter_map.get(&name.str) {
134+
return Err(RustIrError::CannotApplyTypeParameter(name));
119135
}
120136

121-
if let Some(_) = self.struct_ids.get(&name.str) {
122-
return Err(RustIrError::NotTrait(name.clone()));
137+
if let Some(_) = self.opaque_ty_ids.get(&name.str) {
138+
return Err(RustIrError::CannotApplyTypeParameter(name));
123139
}
124140

125-
if let Some(id) = self.trait_ids.get(&name.str) {
126-
return Ok(*id);
141+
if let Some(id) = self.struct_ids.get(&name.str) {
142+
return Ok(ApplyTypeLookup::Struct(*id));
127143
}
128144

129-
Err(RustIrError::InvalidTypeName(name.clone()))
145+
Err(RustIrError::NotStruct(name))
130146
}
131147

132-
fn lookup_lifetime(&self, name: &Identifier) -> LowerResult<LifetimeLookup> {
133-
if let Some(k) = self.parameter_map.get(&NamedGenericArg::new(
134-
chalk_ir::VariableKind::Lifetime,
135-
name.str.clone(),
136-
)) {
137-
return Ok(LifetimeLookup::GenericArg(*k));
148+
fn lookup_trait(&self, name: Identifier) -> LowerResult<TraitId<ChalkIr>> {
149+
if let Some(_) = self.parameter_map.get(&name.str) {
150+
return Err(RustIrError::NotTrait(name));
138151
}
139152

140-
Err(RustIrError::InvalidLifetimeName(name.clone()))
141-
}
153+
if let Some(_) = self.struct_ids.get(&name.str) {
154+
return Err(RustIrError::NotTrait(name));
155+
}
142156

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

151-
Err(RustIrError::InvalidConstName(name))
161+
Err(RustIrError::InvalidTraitName(name))
152162
}
153163

154164
fn struct_kind(&self, id: chalk_ir::StructId<ChalkIr>) -> &TypeKind {
@@ -167,15 +177,23 @@ impl<'k> Env<'k> {
167177
I: IntoIterator<Item = NamedGenericArg>,
168178
I::IntoIter: ExactSizeIterator,
169179
{
180+
// As binders to introduce we recieve `ParameterKind<Ident>`,
181+
// which we need to transform into `(Ident, ParameterKind<BoundVar>)`,
182+
// because that is the key-value pair for ParameterMap.
183+
// `swap_inner` lets us do precisely that, replacing `Ident` inside
184+
// `ParameterKind<Ident>` with a `BoundVar` and returning both.
170185
let binders = binders
171186
.into_iter()
172187
.enumerate()
173-
.map(|(i, k)| (k, BoundVar::new(DebruijnIndex::INNERMOST, i)));
188+
.map(|(i, k)| k.swap_inner(BoundVar::new(DebruijnIndex::INNERMOST, i)));
174189
let len = binders.len();
190+
191+
// For things already in the parameter map, we take each existing key-value pair
192+
// `(Ident, ParameterKind<BoundVar>)` and shift in the inner `BoundVar`.
175193
let parameter_map: ParameterMap = self
176194
.parameter_map
177195
.iter()
178-
.map(|(k, v)| (k.clone(), v.shifted_in()))
196+
.map(|(&k, &v)| (k, v.map(|b| b.shifted_in())))
179197
.chain(binders)
180198
.collect();
181199
if parameter_map.len() != self.parameter_map.len() + len {
@@ -535,6 +553,7 @@ trait LowerParameterMap {
535553
self.all_parameters()
536554
.into_iter()
537555
.zip((0..).map(|i| BoundVar::new(DebruijnIndex::INNERMOST, i)))
556+
.map(|(k, v)| k.swap_inner(v))
538557
.collect()
539558
}
540559

@@ -808,17 +827,7 @@ impl LowerLeafGoal for LeafGoal {
808827
LeafGoal::DomainGoal { goal } => {
809828
chalk_ir::Goal::all(interner, goal.lower(env)?.into_iter().casted(interner))
810829
}
811-
LeafGoal::UnifyTys { a, b } => chalk_ir::EqGoal {
812-
a: a.lower(env)?.cast(interner),
813-
b: b.lower(env)?.cast(interner),
814-
}
815-
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
816-
LeafGoal::UnifyLifetimes { ref a, ref b } => chalk_ir::EqGoal {
817-
a: a.lower(env)?.cast(interner),
818-
b: b.lower(env)?.cast(interner),
819-
}
820-
.cast::<chalk_ir::Goal<ChalkIr>>(interner),
821-
LeafGoal::UnifyConsts { ref a, ref b } => chalk_ir::EqGoal {
830+
LeafGoal::UnifyGenericArgs { a, b } => chalk_ir::EqGoal {
822831
a: a.lower(env)?.cast(interner),
823832
b: b.lower(env)?.cast(interner),
824833
}
@@ -1122,34 +1131,17 @@ trait LowerTy {
11221131
impl LowerTy for Ty {
11231132
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Ty<ChalkIr>> {
11241133
let interner = env.interner();
1125-
match self {
1126-
Ty::Id { name } => match env.lookup_type(name)? {
1127-
TypeLookup::Struct(id) => {
1128-
let k = env.struct_kind(id);
1129-
if k.binders.len(interner) > 0 {
1130-
Err(RustIrError::IncorrectNumberOfTypeParameters {
1131-
identifier: name.clone(),
1132-
expected: k.binders.len(interner),
1133-
actual: 0,
1134-
})
1135-
} else {
1136-
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
1137-
name: chalk_ir::TypeName::Struct(id),
1138-
substitution: chalk_ir::Substitution::empty(interner),
1139-
})
1140-
.intern(interner))
1134+
match *self {
1135+
Ty::Id { name } => {
1136+
let parameter = env.lookup_parameter(name)?;
1137+
parameter.ty(interner).map(|ty| ty.clone()).ok_or_else(|| {
1138+
RustIrError::IncorrectParameterKind {
1139+
identifier: name,
1140+
expected: Kind::Ty,
1141+
actual: parameter.kind(),
11411142
}
1142-
}
1143-
TypeLookup::GenericArg(d) => Ok(chalk_ir::TyData::BoundVar(d).intern(interner)),
1144-
TypeLookup::Opaque(id) => Ok(chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(
1145-
chalk_ir::OpaqueTy {
1146-
opaque_ty_id: id,
1147-
substitution: chalk_ir::Substitution::empty(interner),
1148-
},
1149-
))
1150-
.intern(interner)),
1151-
},
1152-
1143+
})
1144+
}
11531145
Ty::Dyn { ref bounds } => Ok(chalk_ir::TyData::Dyn(chalk_ir::DynTy {
11541146
bounds: env.in_binders(
11551147
// FIXME: Figure out a proper name for this type parameter
@@ -1177,11 +1169,8 @@ impl LowerTy for Ty {
11771169
.intern(interner)),
11781170

11791171
Ty::Apply { name, ref args } => {
1180-
let id = match env.lookup_type(name)? {
1181-
TypeLookup::Struct(id) => id,
1182-
TypeLookup::GenericArg(_) | TypeLookup::Opaque(_) => {
1183-
Err(RustIrError::CannotApplyTypeParameter(name.clone()))?
1184-
}
1172+
let id = match env.lookup_apply_type(name)? {
1173+
ApplyTypeLookup::Struct(id) => id,
11851174
};
11861175

11871176
let k = env.struct_kind(id);
@@ -1198,7 +1187,12 @@ impl LowerTy for Ty {
11981187
args.iter().map(|t| Ok(t.lower(env)?)),
11991188
)?;
12001189

1201-
for (param, arg) in k.binders.binders.iter(interner).zip(args.iter()) {
1190+
for (param, arg) in k
1191+
.binders
1192+
.binders
1193+
.iter(interner)
1194+
.zip(substitution.iter(interner))
1195+
{
12021196
if param.kind() != arg.kind() {
12031197
Err(RustIrError::IncorrectParameterKind {
12041198
identifier: name.clone(),
@@ -1307,30 +1301,14 @@ impl LowerGenericArg for GenericArg {
13071301
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::GenericArg<ChalkIr>> {
13081302
let interner = env.interner();
13091303
match *self {
1310-
GenericArg::Ty(ref t) => Ok(t.lower(env)?.cast(interner)),
1311-
GenericArg::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)),
1312-
GenericArg::Const(ref c) => Ok(c.lower(env)?.cast(interner)),
1313-
}
1314-
}
1315-
}
1316-
1317-
trait LowerConst {
1318-
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>>;
1319-
}
1320-
1321-
impl LowerConst for Const {
1322-
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>> {
1323-
let interner = env.interner();
1324-
match *self {
1325-
Const::Id { name } => match env.lookup_const(name)? {
1326-
ConstLookup::Parameter(d) => Ok(chalk_ir::ConstData::BoundVar(d).intern(interner)),
1327-
},
1328-
Const::Value { value } => {
1329-
Ok(
1330-
chalk_ir::ConstData::Concrete(chalk_ir::ConcreteConst { interned: value })
1331-
.intern(interner),
1332-
)
1333-
}
1304+
Parameter::Ty(ref t) => Ok(t.lower(env)?.cast(interner)),
1305+
Parameter::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)),
1306+
Parameter::Id(name) => env.lookup_parameter(name),
1307+
Parameter::ConstValue(value) => Ok(chalk_ir::ConstData::Concrete(
1308+
chalk_ir::ConcreteConst { interned: value },
1309+
)
1310+
.intern(interner)
1311+
.cast(interner)),
13341312
}
13351313
}
13361314
}
@@ -1342,12 +1320,18 @@ trait LowerLifetime {
13421320
impl LowerLifetime for Lifetime {
13431321
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Lifetime<ChalkIr>> {
13441322
let interner = env.interner();
1345-
match self {
1346-
Lifetime::Id { name } => match env.lookup_lifetime(name)? {
1347-
LifetimeLookup::GenericArg(d) => {
1348-
Ok(chalk_ir::LifetimeData::BoundVar(d).intern(interner))
1349-
}
1350-
},
1323+
match *self {
1324+
Lifetime::Id { name } => {
1325+
let parameter = env.lookup_parameter(name)?;
1326+
parameter
1327+
.lifetime(interner)
1328+
.map(|l| l.clone())
1329+
.ok_or_else(|| RustIrError::IncorrectParameterKind {
1330+
identifier: name,
1331+
expected: Kind::Lifetime,
1332+
actual: parameter.kind(),
1333+
})
1334+
}
13511335
}
13521336
}
13531337
}

chalk-ir/src/cast.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ impl<I: Interner> CastTo<GenericArg<I>> for Lifetime<I> {
175175
}
176176
}
177177

178-
impl<I: Interner> CastTo<Parameter<I>> for Const<I> {
179-
fn cast_to(self, interner: &I) -> Parameter<I> {
180-
Parameter::new(interner, ParameterKind::Const(self))
178+
impl<I: Interner> CastTo<GenericArg<I>> for Const<I> {
179+
fn cast_to(self, interner: &I) -> GenericArg<I> {
180+
GenericArg::new(interner, GenericArgData::Const(self))
181181
}
182182
}
183183

0 commit comments

Comments
 (0)