Skip to content

Commit 8d13454

Browse files
Canonicalize the ROOT VAR
1 parent 160c2eb commit 8d13454

File tree

5 files changed

+83
-11
lines changed

5 files changed

+83
-11
lines changed

compiler/rustc_infer/src/infer/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,10 @@ impl<'tcx> InferCtxt<'tcx> {
13561356
self.inner.borrow_mut().type_variables().root_var(var)
13571357
}
13581358

1359+
pub fn root_const_var(&self, var: ty::ConstVid<'tcx>) -> ty::ConstVid<'tcx> {
1360+
self.inner.borrow_mut().const_unification_table().find(var)
1361+
}
1362+
13591363
/// Where possible, replaces type/const variables in
13601364
/// `value` with their final value. Note that region variables
13611365
/// are unaffected. If a type/const variable has not been unified, it

compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs

+33-11
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,24 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
261261
self.interner().mk_re_late_bound(self.binder_index, br)
262262
}
263263

264-
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
264+
fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
265265
let kind = match *t.kind() {
266-
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
267-
Ok(t) => return self.fold_ty(t),
268-
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
269-
},
266+
ty::Infer(ty::TyVar(mut vid)) => {
267+
// We need to canonicalize the *root* of our ty var.
268+
// This is so that our canonical response correctly reflects
269+
// any equated inference vars correctly!
270+
271+
let root_vid = self.infcx.root_var(vid);
272+
if root_vid != vid {
273+
t = self.infcx.tcx.mk_ty_var(root_vid);
274+
vid = root_vid;
275+
}
276+
277+
match self.infcx.probe_ty_var(vid) {
278+
Ok(t) => return self.fold_ty(t),
279+
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
280+
}
281+
}
270282
ty::Infer(ty::IntVar(_)) => {
271283
let nt = self.infcx.shallow_resolve(t);
272284
if nt != t {
@@ -338,13 +350,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
338350
self.interner().mk_bound(self.binder_index, bt)
339351
}
340352

341-
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
353+
fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> {
342354
let kind = match c.kind() {
343-
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
344-
{
345-
Ok(c) => return self.fold_const(c),
346-
Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
347-
},
355+
ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => {
356+
// We need to canonicalize the *root* of our const var.
357+
// This is so that our canonical response correctly reflects
358+
// any equated inference vars correctly!
359+
let root_vid = self.infcx.root_const_var(vid);
360+
if root_vid != vid {
361+
c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty());
362+
vid = root_vid;
363+
}
364+
365+
match self.infcx.probe_const_var(vid) {
366+
Ok(c) => return self.fold_const(c),
367+
Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
368+
}
369+
}
348370
ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
349371
bug!("fresh var during canonicalization: {c:?}")
350372
}

compiler/rustc_trait_selection/src/solve/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
238238
&& has_changed
239239
&& !self.in_projection_eq_hack
240240
&& !self.search_graph.in_cycle()
241+
&& false
241242
{
242243
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
243244
let canonical_response =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
// compile-flags: -Ztrait-solver=next
3+
4+
trait Mirror {
5+
type Item;
6+
}
7+
8+
struct Wrapper<T>(T);
9+
impl<T> Mirror for Wrapper<T> {
10+
type Item = T;
11+
}
12+
13+
fn mirror<T>()
14+
where
15+
Wrapper<T>: Mirror<Item = i32>,
16+
{
17+
}
18+
19+
fn main() {
20+
mirror::<_ /* ?0 */>();
21+
22+
// Solving `<Wrapper<?0> as Mirror>::Item = i32`
23+
24+
// First, we replace the term with a fresh infer var:
25+
// `<Wrapper<?0> as Mirror>::Item = ?1`
26+
27+
// We select the impl candidate on line #6, which leads us to learn that
28+
// `?0 == ?1`.
29+
30+
// That should be reflected in our canonical response, which should have
31+
// `^0 = ^0, ^1 = ^0`
32+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33+
// !! We used to return a totally unconstrained response here :< !!
34+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35+
36+
// Then, during the "equate term" part of the projection solving, we
37+
// instantiate the response from the unconstrained projection predicate,
38+
// and equate `?0 == i32`.
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// check-pass
2+
// compile-flags: -Ztrait-solver=next
3+
4+
fn main() {
5+
let x: Box<dyn Iterator<Item = ()>> = Box::new(std::iter::empty());
6+
}

0 commit comments

Comments
 (0)