Skip to content

Commit a234501

Browse files
committed
introduce indices into BoundVar
1 parent 2c0c785 commit a234501

File tree

22 files changed

+392
-237
lines changed

22 files changed

+392
-237
lines changed

chalk-integration/src/lowering.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,12 @@ impl<'k> Env<'k> {
141141
let binders = binders
142142
.into_iter()
143143
.enumerate()
144-
.map(|(i, k)| (k, BoundVar::new(DebruijnIndex::from(i))));
144+
.map(|(i, k)| (k, BoundVar::new(DebruijnIndex::INNERMOST, i)));
145145
let len = binders.len();
146146
let parameter_map: ParameterMap = self
147147
.parameter_map
148148
.iter()
149-
.map(|(&k, &v)| (k, v.shifted_in(len)))
149+
.map(|(&k, &v)| (k, v.shifted_in(1)))
150150
.chain(binders)
151151
.collect();
152152
if parameter_map.len() != self.parameter_map.len() + len {
@@ -398,6 +398,16 @@ trait LowerParameterMap {
398398
.chain(self.synthetic_parameters()) // (*) see below
399399
.collect()
400400
*/
401+
402+
// (*) It is important that the declared parameters come
403+
// before the synthetic parameters in the ordering. This is
404+
// because of traits, when used as types, only have the first
405+
// N parameters in their kind (that is, they do not have Self).
406+
//
407+
// Note that if `Self` appears in the where-clauses etc, the
408+
// trait is not object-safe, and hence not supposed to be used
409+
// as an object. Actually the handling of object types is
410+
// probably just kind of messed up right now. That's ok.
401411
}
402412

403413
fn parameter_refs(&self) -> Vec<chalk_ir::Parameter<ChalkIr>> {
@@ -410,18 +420,9 @@ trait LowerParameterMap {
410420
}
411421

412422
fn parameter_map(&self) -> ParameterMap {
413-
// (*) It is important that the declared parameters come
414-
// before the subtle parameters in the ordering. This is
415-
// because of traits, when used as types, only have the first
416-
// N parameters in their kind (that is, they do not have Self).
417-
//
418-
// Note that if `Self` appears in the where-clauses etc, the
419-
// trait is not object-safe, and hence not supposed to be used
420-
// as an object. Actually the handling of object types is
421-
// probably just kind of messed up right now. That's ok.
422423
self.all_parameters()
423424
.into_iter()
424-
.zip((0..).map(|i| BoundVar::new(DebruijnIndex::from_u32(i))))
425+
.zip((0..).map(|i| BoundVar::new(DebruijnIndex::INNERMOST, i)))
425426
.collect()
426427
}
427428

@@ -1005,6 +1006,7 @@ impl LowerTy for Ty {
10051006
interner,
10061007
chalk_ir::TyData::BoundVar(BoundVar::new(
10071008
DebruijnIndex::INNERMOST,
1009+
0,
10081010
))
10091011
.intern(interner),
10101012
)
@@ -1241,12 +1243,16 @@ impl LowerTrait for TraitDefn {
12411243
.map(|defn| env.associated_ty_lookups[&(trait_id, defn.name.str)].id)
12421244
.collect();
12431245

1244-
Ok(rust_ir::TraitDatum {
1246+
let trait_datum = rust_ir::TraitDatum {
12451247
id: trait_id,
12461248
binders: binders,
12471249
flags: self.flags.lower(),
12481250
associated_ty_ids,
1249-
})
1251+
};
1252+
1253+
debug!("trait_datum={:?}", trait_datum);
1254+
1255+
Ok(trait_datum)
12501256
}
12511257
}
12521258

chalk-ir/src/debug.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ impl<I: Interner> Debug for TyData<I> {
136136

137137
impl Debug for BoundVar {
138138
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
139-
let BoundVar { debruijn } = self;
140-
write!(fmt, "{:?}", debruijn)
139+
let BoundVar { debruijn, index } = self;
140+
write!(fmt, "{:?}.{:?}", debruijn, index)
141141
}
142142
}
143143

chalk-ir/src/fold.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ where
124124
/// `binders` in scope.
125125
fn fold_free_var_ty(&mut self, bound_var: BoundVar, binders: usize) -> Fallible<Ty<TI>> {
126126
if self.forbid_free_vars() {
127-
panic!("unexpected free variable with depth `{:?}`", bound_var)
127+
panic!(
128+
"unexpected free variable with depth `{:?}` in {} binders",
129+
bound_var, binders
130+
)
128131
} else {
129132
let bound_var = bound_var.shifted_in(binders);
130133
Ok(TyData::<TI>::BoundVar(bound_var).intern(self.target_interner()))
@@ -138,7 +141,10 @@ where
138141
binders: usize,
139142
) -> Fallible<Lifetime<TI>> {
140143
if self.forbid_free_vars() {
141-
panic!("unexpected free variable with depth `{:?}`", bound_var)
144+
panic!(
145+
"unexpected free variable with depth `{:?}` in {} binders",
146+
bound_var, binders
147+
)
142148
} else {
143149
let bound_var = bound_var.shifted_in(binders);
144150
Ok(LifetimeData::<TI>::BoundVar(bound_var).intern(self.target_interner()))
@@ -312,17 +318,17 @@ where
312318
let interner = folder.interner();
313319
match self.data(interner) {
314320
TyData::BoundVar(bound_var) => {
315-
let BoundVar { debruijn } = *bound_var;
316-
if debruijn.within(binders) {
317-
// If `debruijn` refers to one of the binders that
318-
// we folded over, then just return a bound
319-
// variable.
320-
Ok(TyData::<TI>::BoundVar(BoundVar::new(debruijn))
321-
.intern(folder.target_interner()))
321+
if let Some(bound_var1) = bound_var.checked_shifted_out(binders) {
322+
// This variable was bound outside of the binders
323+
// that we have traversed during folding;
324+
// therefore, it is free. Let the folder have a
325+
// crack at it.
326+
folder.fold_free_var_ty(bound_var1, binders)
322327
} else {
323-
// Otherwise, this variable was bound outside the
324-
// folded term, so invoke `fold_free_var_ty`.
325-
folder.fold_free_var_ty(bound_var.shifted_out(binders), binders)
328+
// This variable was bound within the binders that
329+
// we folded over, so just return a bound
330+
// variable.
331+
Ok(TyData::<TI>::BoundVar(*bound_var).intern(folder.target_interner()))
326332
}
327333
}
328334
TyData::Dyn(clauses) => {
@@ -380,21 +386,19 @@ where
380386
TI: 'i,
381387
{
382388
let interner = folder.interner();
383-
let target_interner = folder.target_interner();
384389
match self.data(interner) {
385390
LifetimeData::BoundVar(bound_var) => {
386-
let BoundVar { debruijn } = *bound_var;
387-
if debruijn.within(binders) {
388-
// If `debruijn` refers to one of the binders that
389-
// we folded over, then just return a bound
390-
// variable.
391-
Ok(LifetimeData::<TI>::BoundVar(BoundVar::new(debruijn))
392-
.intern(target_interner))
391+
if let Some(bound_var1) = bound_var.checked_shifted_out(binders) {
392+
// This variable was bound outside of the binders
393+
// that we have traversed during folding;
394+
// therefore, it is free. Let the folder have a
395+
// crack at it.
396+
folder.fold_free_var_lifetime(bound_var1, binders)
393397
} else {
394-
// Otherwise, this variable was bound outside the
395-
// folded term, so invoke `fold_free_var_lifetime`.
396-
let bound_var = BoundVar::new(debruijn.shifted_out(binders));
397-
folder.fold_free_var_lifetime(bound_var, binders)
398+
// This variable was bound within the binders that
399+
// we folded over, so just return a bound
400+
// variable.
401+
Ok(LifetimeData::<TI>::BoundVar(*bound_var).intern(folder.target_interner()))
398402
}
399403
}
400404
LifetimeData::InferenceVar(var) => folder.fold_inference_lifetime(*var, binders),

chalk-ir/src/fold/binder_impls.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Fn<I> {
1919
{
2020
let Fn {
2121
num_binders,
22-
ref parameters,
23-
} = *self;
22+
parameters,
23+
} = self;
2424
Ok(Fn {
25-
num_binders,
26-
parameters: parameters.fold_with(folder, binders + num_binders)?,
25+
num_binders: num_binders.clone(),
26+
parameters: parameters.fold_with(folder, binders + 1)?,
2727
})
2828
}
2929
}
@@ -44,10 +44,10 @@ where
4444
TI: 'i,
4545
{
4646
let Binders {
47-
binders: ref self_binders,
48-
value: ref self_value,
49-
} = *self;
50-
let value = self_value.fold_with(folder, binders + self_binders.len())?;
47+
binders: self_binders,
48+
value: self_value,
49+
} = self;
50+
let value = self_value.fold_with(folder, binders + 1)?;
5151
Ok(Binders {
5252
binders: self_binders.clone(),
5353
value: value,
@@ -72,10 +72,10 @@ where
7272
TI: 'i,
7373
{
7474
let Canonical {
75-
binders: ref self_binders,
76-
value: ref self_value,
77-
} = *self;
78-
let value = self_value.fold_with(folder, binders + self_binders.len())?;
75+
binders: self_binders,
76+
value: self_value,
77+
} = self;
78+
let value = self_value.fold_with(folder, binders + 1)?;
7979
Ok(Canonical {
8080
binders: self_binders.clone(),
8181
value: value,

chalk-ir/src/fold/shift.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ impl<I> DownShifter<'_, I> {
143143
/// this will fail with `Err`. Otherwise, returns the variable at
144144
/// this new depth (but adjusted to appear within `binders`).
145145
fn adjust(&self, bound_var: BoundVar, binders: usize) -> Fallible<BoundVar> {
146-
match bound_var.debruijn.checked_shifted_out(self.adjustment) {
147-
Some(new_depth) => Ok(BoundVar::new(new_depth.shifted_in(binders))),
146+
match bound_var.checked_shifted_out(self.adjustment) {
147+
Some(bound_var1) => Ok(bound_var1.shifted_in(binders)),
148148
None => Err(NoSolution),
149149
}
150150
}

chalk-ir/src/fold/subst.rs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::fold::shift::Shift;
33

44
pub struct Subst<'s, 'i, I: Interner> {
55
/// Values to substitute. A reference to a free variable with
6-
/// index `i` will be mapped to `parameters[i]` -- if `i >
7-
/// parameters.len()`, then we will leave the variable untouched.
6+
/// index `i` will be mapped to `parameter_lists[i]` -- if `i >
7+
/// parameter_lists.len()`, then we will leave the variable untouched.
88
parameters: &'s [Parameter<I>],
99
interner: &'i I,
1010
}
@@ -29,16 +29,35 @@ impl<'i, I: Interner> Folder<'i, I> for Subst<'_, 'i, I> {
2929
}
3030

3131
fn fold_free_var_ty(&mut self, bound_var: BoundVar, binders: usize) -> Fallible<Ty<I>> {
32-
let interner = self.interner();
33-
let index = bound_var.index();
34-
if index >= self.parameters.len() {
35-
let debruijn = DebruijnIndex::from(index - self.parameters.len()).shifted_in(binders);
36-
Ok(TyData::<I>::BoundVar(BoundVar::new(debruijn)).intern(interner))
37-
} else {
38-
match self.parameters[index].data(interner) {
39-
ParameterKind::Ty(t) => Ok(t.shifted_in(interner, binders)),
32+
// We are eliminating one binder, but binders outside of that get preserved.
33+
//
34+
// So e.g. consider this:
35+
//
36+
// ```
37+
// for<A, B> { for<C> { [A, C] } }
38+
// // ^ the binder we are substituing with `[u32]`
39+
// ```
40+
//
41+
// Here, `A` would be `^1.0` and `C` would be `^0.0`. We will replace `^0.0` with the
42+
// 0th index from the list (`u32`). We will convert `^1.0` (A) to `^0.0` -- i.e., shift
43+
// it **out** of one level of binder (the `for<C>` binder we are eliminating).
44+
//
45+
// This gives us as a result:
46+
//
47+
// ```
48+
// for<A, B> { [A, u32] }
49+
// ^ represented as `^0.0`
50+
// ```
51+
if let Some(index) = bound_var.index_if_innermost() {
52+
match self.parameters[index].data(self.interner()) {
53+
ParameterKind::Ty(t) => Ok(t.shifted_in(self.interner(), binders)),
4054
_ => panic!("mismatched kinds in substitution"),
4155
}
56+
} else {
57+
Ok(bound_var
58+
.shifted_out(1)
59+
.shifted_in(binders)
60+
.to_ty(self.interner()))
4261
}
4362
}
4463

@@ -47,16 +66,18 @@ impl<'i, I: Interner> Folder<'i, I> for Subst<'_, 'i, I> {
4766
bound_var: BoundVar,
4867
binders: usize,
4968
) -> Fallible<Lifetime<I>> {
50-
let interner = self.interner();
51-
let index = bound_var.index();
52-
if index >= self.parameters.len() {
53-
let debruijn = DebruijnIndex::from(index - self.parameters.len()).shifted_in(binders);
54-
Ok(LifetimeData::<I>::BoundVar(BoundVar::new(debruijn)).intern(interner))
55-
} else {
56-
match self.parameters[index].data(interner) {
57-
ParameterKind::Lifetime(l) => Ok(l.shifted_in(interner, binders)),
69+
// see comment in `fold_free_var_ty`
70+
71+
if let Some(index) = bound_var.index_if_innermost() {
72+
match self.parameters[index].data(self.interner()) {
73+
ParameterKind::Lifetime(l) => Ok(l.shifted_in(self.interner(), binders)),
5874
_ => panic!("mismatched kinds in substitution"),
5975
}
76+
} else {
77+
Ok(bound_var
78+
.shifted_out(1)
79+
.shifted_in(binders)
80+
.to_lifetime(self.interner()))
6081
}
6182
}
6283

0 commit comments

Comments
 (0)