Rollup merge of #108839 - compiler-errors:canonicalize-the-root-var, r=lcnr
Canonicalize root var when making response from new solver During trait solving, if we equate two inference variables `?0` and `?1` but don't equate them with any rigid types, then `InferCtxt::probe_ty_var` will return `Err` for both of these. The canonicalizer code will then canonicalize the variables independently(!), and the response will not reflect the fact that these two variables have been made equal. This hinders inference and I also don't think it's sound? I haven't thought too much about it past that, so let's talk about it. r? ``@lcnr``
This commit is contained in:
commit
2428083558
6 changed files with 104 additions and 15 deletions
|
@ -261,12 +261,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
|||
self.interner().mk_re_late_bound(self.binder_index, br)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let kind = match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
|
||||
Ok(t) => return self.fold_ty(t),
|
||||
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
|
||||
},
|
||||
ty::Infer(ty::TyVar(mut vid)) => {
|
||||
// We need to canonicalize the *root* of our ty var.
|
||||
// This is so that our canonical response correctly reflects
|
||||
// any equated inference vars correctly!
|
||||
let root_vid = self.infcx.root_var(vid);
|
||||
if root_vid != vid {
|
||||
t = self.infcx.tcx.mk_ty_var(root_vid);
|
||||
vid = root_vid;
|
||||
}
|
||||
|
||||
match self.infcx.probe_ty_var(vid) {
|
||||
Ok(t) => return self.fold_ty(t),
|
||||
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::IntVar(_)) => {
|
||||
let nt = self.infcx.shallow_resolve(t);
|
||||
if nt != t {
|
||||
|
@ -338,13 +349,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
|||
self.interner().mk_bound(self.binder_index, bt)
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
let kind = match c.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
|
||||
{
|
||||
Ok(c) => return self.fold_const(c),
|
||||
Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
|
||||
},
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => {
|
||||
// We need to canonicalize the *root* of our const var.
|
||||
// This is so that our canonical response correctly reflects
|
||||
// any equated inference vars correctly!
|
||||
let root_vid = self.infcx.root_const_var(vid);
|
||||
if root_vid != vid {
|
||||
c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty());
|
||||
vid = root_vid;
|
||||
}
|
||||
|
||||
match self.infcx.probe_const_var(vid) {
|
||||
Ok(c) => return self.fold_const(c),
|
||||
Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
|
||||
bug!("fresh var during canonicalization: {c:?}")
|
||||
}
|
||||
|
|
|
@ -238,6 +238,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||
&& has_changed
|
||||
&& !self.in_projection_eq_hack
|
||||
&& !self.search_graph.in_cycle()
|
||||
&& false
|
||||
{
|
||||
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
||||
let canonical_response =
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue