Skip to content

Commit 599742b

Browse files
super-tupledaboross
authored andcommitted
Add InferenceVar root-finding to NormalizeDeep
This changes NormalizeDeep to normalize unified inference variables without values to the same 'root' inference variable, and fixes the normalize_deep::test::infer test. The change is necessary to accomodate the generalizer, which commonly creates new inference variables and then unifies them with old ones. This has no functional change, but would have broken normalization without this new behavior. Co-authored-by: David Ross <daboross@daboross.net>
1 parent ecf20dc commit 599742b

File tree

3 files changed

+33
-8
lines changed

3 files changed

+33
-8
lines changed

chalk-engine/src/normalize_deep.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ where
5555
.assert_ty_ref(interner)
5656
.fold_with(self, DebruijnIndex::INNERMOST)?
5757
.shifted_in(interner)), // FIXME shift
58-
None => Ok(var.to_ty(interner, kind)),
58+
None => {
59+
// Normalize all inference vars which have been unified into a
60+
// single variable. Ena calls this the "root" variable.
61+
Ok(self.table.inference_var_root(var).to_ty(interner, kind))
62+
}
5963
}
6064
}
6165

@@ -104,6 +108,7 @@ mod test {
104108
use super::*;
105109
use chalk_integration::interner::ChalkIr;
106110
use chalk_integration::{arg, ty};
111+
use chalk_solve::logging::with_tracing_logs;
107112

108113
const U0: UniverseIndex = UniverseIndex { counter: 0 };
109114

@@ -138,13 +143,16 @@ mod test {
138143
&ty!(apply (item 0) (expr b)),
139144
)
140145
.unwrap();
141-
// FIXME: can't just assert these are equal because the inference var gets set to a new var (?2)
142-
// which is unified with b (?1). It might be good to pick a root to return. For now,
143-
// this doesn't work as-is.
144-
//assert_eq!(
145-
// DeepNormalizer::normalize_deep(&mut table, interner, &a),
146-
// &ty!(apply (item 1)),
147-
//);
146+
// a is unified to Adt<#0>(c), where 'c' is a new inference var
147+
// created by the generalizer to generalize 'b'. It then unifies 'b'
148+
// and 'c', and when we normalize them, they'll both be output as
149+
// the same "root" variable. However, there are no guarantees for
150+
// _which_ of 'b' and 'c' becomes the root. We need to normalize
151+
// "b" too, then, to ensure we get a consistent result.
152+
assert_eq!(
153+
DeepNormalizer::normalize_deep(&mut table, interner, &a),
154+
ty!(apply (item 0) (expr DeepNormalizer::normalize_deep(&mut table, interner, &b))),
155+
);
148156
table
149157
.relate(
150158
interner,

chalk-solve/src/infer.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ impl<I: Interner> InferenceTable<I> {
146146
.map(|p| p.assert_const_ref(interner).clone())
147147
}
148148

149+
/// Finds the root inference var for the given variable.
150+
///
151+
/// The returned variable will be exactly equivalent to the given
152+
/// variable except in name. All variables which have been unified to
153+
/// eachother (but don't yet have a value) have the same "root".
154+
///
155+
/// This is useful for `DeepNormalizer`.
156+
pub fn inference_var_root(&mut self, var: InferenceVar) -> InferenceVar {
157+
self.unify.find(var).into()
158+
}
159+
149160
/// If type `leaf` is a free inference variable, and that variable has been
150161
/// bound, returns `Some(P)` where `P` is the parameter to which it has been bound.
151162
pub fn probe_var(&mut self, leaf: InferenceVar) -> Option<GenericArg<I>> {

chalk-solve/src/infer/var.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ impl<I: Interner> From<InferenceVar> for EnaVariable<I> {
5050
}
5151
}
5252

53+
impl<I: Interner> From<EnaVariable<I>> for InferenceVar {
54+
fn from(ena_var: EnaVariable<I>) -> InferenceVar {
55+
ena_var.var
56+
}
57+
}
58+
5359
impl<I: Interner> EnaVariable<I> {
5460
/// Convert this inference variable into a type. When using this
5561
/// method, naturally you should know from context that the kind

0 commit comments

Comments
 (0)