Skip to content

Commit

Permalink
Fix canonicalizer bug for int/float vars too
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Mar 9, 2023
1 parent 3aea469 commit 1b6d6f9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 13 deletions.
31 changes: 22 additions & 9 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,15 +411,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}

ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t,
),

ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t,
),
ty::Infer(ty::IntVar(vid)) => {
let nt = self.infcx.opportunistic_resolve_int_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t,
)
}
}
ty::Infer(ty::FloatVar(vid)) => {
let nt = self.infcx.opportunistic_resolve_float_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t,
)
}
}

ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("encountered a fresh type during canonicalization")
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,28 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().const_unification_table().find(var)
}

/// Resolves an int var to a rigid int type, if it was constrained to one,
/// or else the root int var in the unification table.
pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
let mut inner = self.inner.borrow_mut();
if let Some(value) = inner.int_unification_table().probe_value(vid) {
value.to_type(self.tcx)
} else {
self.tcx.mk_int_var(inner.int_unification_table().find(vid))
}
}

/// Resolves a float var to a rigid int type, if it was constrained to one,
/// or else the root float var in the unification table.
pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
let mut inner = self.inner.borrow_mut();
if let Some(value) = inner.float_unification_table().probe_value(vid) {
value.to_type(self.tcx)
} else {
self.tcx.mk_float_var(inner.float_unification_table().find(vid))
}
}

/// Where possible, replaces type/const variables in
/// `value` with their final value. Note that region variables
/// are unaffected. If a type/const variable has not been unified, it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
}
}
ty::Infer(ty::IntVar(_)) => {
let nt = self.infcx.shallow_resolve(t);
ty::Infer(ty::IntVar(vid)) => {
let nt = self.infcx.opportunistic_resolve_int_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
}
}
ty::Infer(ty::FloatVar(_)) => {
let nt = self.infcx.shallow_resolve(t);
ty::Infer(ty::FloatVar(vid)) => {
let nt = self.infcx.opportunistic_resolve_float_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// check-pass

trait Mirror {
type Assoc;
}

impl<T> Mirror for T {
type Assoc = T;
}

trait Test {}
impl Test for i64 {}
impl Test for u64 {}

fn mirror_me<T: Mirror>(t: T, s: <T as Mirror>::Assoc) where <T as Mirror>::Assoc: Test {}

fn main() {
let mut x = 0;
mirror_me(x, 1);
x = 1i64;
}

0 comments on commit 1b6d6f9

Please sign in to comment.