Rollup merge of #108828 - compiler-errors:new-solver-alias-eq-on-num-var, r=lcnr

Emit alias-eq when equating numeric var and projection

This doesn't fix everything having to do with projections and infer vars, but it does fix a common case I saw in HIR typeck.

r? `@lcnr`
This commit is contained in:
Matthias Krüger 2023-03-10 19:59:18 +01:00 committed by GitHub
commit 233ed35e84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 144 additions and 41 deletions

View file

@ -148,13 +148,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rhs_ty, rhs_ty,
op, op,
); );
self.demand_suptype(expr.span, builtin_return_ty, return_ty); self.demand_eqtype(expr.span, builtin_return_ty, return_ty);
} builtin_return_ty
} else {
return_ty return_ty
} }
} }
} }
}
fn enforce_builtin_binop_types( fn enforce_builtin_binop_types(
&self, &self,

View file

@ -411,15 +411,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
} }
} }
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var( 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) }, CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t, t,
), )
}
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var( }
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) }, CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t, t,
), )
}
}
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("encountered a fresh type during canonicalization") bug!("encountered a fresh type during canonicalization")

View file

@ -119,20 +119,30 @@ impl<'tcx> InferCtxt<'tcx> {
self.unify_float_variable(!a_is_expected, v_id, v) self.unify_float_variable(!a_is_expected, v_id, v)
} }
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
(
ty::Alias(AliasKind::Projection, _),
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
)
| (
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
ty::Alias(AliasKind::Projection, _),
) if self.tcx.trait_solver_next() => {
bug!()
}
(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
if self.tcx.trait_solver_next() =>
{
relation.register_type_equate_obligation(a, b);
Ok(a)
}
// All other cases of inference are errors // All other cases of inference are errors
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b))) Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
} }
(ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
relation.register_type_equate_obligation(a, b);
Ok(b)
}
(_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
relation.register_type_equate_obligation(b, a);
Ok(a)
}
_ => ty::relate::super_relate_tys(relation, a, b), _ => ty::relate::super_relate_tys(relation, a, b),
} }
} }

View file

@ -1363,6 +1363,28 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().const_unification_table().find(var) 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 /// Where possible, replaces type/const variables in
/// `value` with their final value. Note that region variables /// `value` with their final value. Note that region variables
/// are unaffected. If a type/const variable has not been unified, it /// are unaffected. If a type/const variable has not been unified, it

View file

@ -995,7 +995,7 @@ impl<'tcx> Term<'tcx> {
pub fn is_infer(&self) -> bool { pub fn is_infer(&self) -> bool {
match self.unpack() { match self.unpack() {
TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(), TermKind::Ty(ty) => ty.is_ty_var(),
TermKind::Const(ct) => ct.is_ct_infer(), TermKind::Const(ct) => ct.is_ct_infer(),
} }
} }

View file

@ -278,16 +278,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
} }
} }
ty::Infer(ty::IntVar(_)) => { ty::Infer(ty::IntVar(vid)) => {
let nt = self.infcx.shallow_resolve(t); let nt = self.infcx.opportunistic_resolve_int_var(vid);
if nt != t { if nt != t {
return self.fold_ty(nt); return self.fold_ty(nt);
} else { } else {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int) CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
} }
} }
ty::Infer(ty::FloatVar(_)) => { ty::Infer(ty::FloatVar(vid)) => {
let nt = self.infcx.shallow_resolve(t); let nt = self.infcx.opportunistic_resolve_float_var(vid);
if nt != t { if nt != t {
return self.fold_ty(nt); return self.fold_ty(nt);
} else { } else {

View file

@ -1,16 +1,19 @@
fn first() { fn first() {
second == 1 //~ ERROR binary operation second == 1 //~ ERROR binary operation
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| ERROR mismatched types
} }
fn second() { fn second() {
first == 1 //~ ERROR binary operation first == 1 //~ ERROR binary operation
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| ERROR mismatched types
} }
fn bar() { fn bar() {
bar == 1 //~ ERROR binary operation bar == 1 //~ ERROR binary operation
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| ERROR mismatched types
} }
fn main() {} fn main() {}

View file

@ -15,8 +15,16 @@ LL | second == 1
= note: expected fn item `fn() {second}` = note: expected fn item `fn() {second}`
found type `{integer}` found type `{integer}`
error[E0308]: mismatched types
--> $DIR/issue-66667-function-cmp-cycle.rs:2:5
|
LL | fn first() {
| - help: try adding a return type: `-> bool`
LL | second == 1
| ^^^^^^^^^^^ expected `()`, found `bool`
error[E0369]: binary operation `==` cannot be applied to type `fn() {first}` error[E0369]: binary operation `==` cannot be applied to type `fn() {first}`
--> $DIR/issue-66667-function-cmp-cycle.rs:7:11 --> $DIR/issue-66667-function-cmp-cycle.rs:8:11
| |
LL | first == 1 LL | first == 1
| ----- ^^ - {integer} | ----- ^^ - {integer}
@ -24,7 +32,7 @@ LL | first == 1
| fn() {first} | fn() {first}
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-66667-function-cmp-cycle.rs:7:14 --> $DIR/issue-66667-function-cmp-cycle.rs:8:14
| |
LL | first == 1 LL | first == 1
| ^ expected fn item, found integer | ^ expected fn item, found integer
@ -32,8 +40,16 @@ LL | first == 1
= note: expected fn item `fn() {first}` = note: expected fn item `fn() {first}`
found type `{integer}` found type `{integer}`
error[E0308]: mismatched types
--> $DIR/issue-66667-function-cmp-cycle.rs:8:5
|
LL | fn second() {
| - help: try adding a return type: `-> bool`
LL | first == 1
| ^^^^^^^^^^ expected `()`, found `bool`
error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}` error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}`
--> $DIR/issue-66667-function-cmp-cycle.rs:12:9 --> $DIR/issue-66667-function-cmp-cycle.rs:14:9
| |
LL | bar == 1 LL | bar == 1
| --- ^^ - {integer} | --- ^^ - {integer}
@ -41,7 +57,7 @@ LL | bar == 1
| fn() {bar} | fn() {bar}
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-66667-function-cmp-cycle.rs:12:12 --> $DIR/issue-66667-function-cmp-cycle.rs:14:12
| |
LL | bar == 1 LL | bar == 1
| ^ expected fn item, found integer | ^ expected fn item, found integer
@ -49,7 +65,15 @@ LL | bar == 1
= note: expected fn item `fn() {bar}` = note: expected fn item `fn() {bar}`
found type `{integer}` found type `{integer}`
error: aborting due to 6 previous errors error[E0308]: mismatched types
--> $DIR/issue-66667-function-cmp-cycle.rs:14:5
|
LL | fn bar() {
| - help: try adding a return type: `-> bool`
LL | bar == 1
| ^^^^^^^^ expected `()`, found `bool`
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0308, E0369. Some errors have detailed explanations: E0308, E0369.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0308`.

View file

@ -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;
}

View file

@ -0,0 +1,18 @@
// check-pass
// compile-flags: -Ztrait-solver=next
// HIR typeck ends up equating `<_#0i as Add>::Output == _#0i`.
// Want to make sure that we emit an alias-eq goal for this,
// instead of treating it as a type error and bailing.
fn test() {
// fallback
let x = 1 + 2;
}
fn test2() -> u32 {
// expectation from return ty
1 + 2
}
fn main() {}

View file

@ -1,5 +1,5 @@
// compile-flags: -Ztrait-solver=next // compile-flags: -Ztrait-solver=next
// known-bug: unknown // check-pass
fn main() { fn main() {
(0u8 + 0u8) as char; (0u8 + 0u8) as char;

View file

@ -1,9 +0,0 @@
error[E0271]: type mismatch resolving `char == <u8 as Add>::Output`
--> $DIR/cast-checks-handling-projections.rs:5:5
|
LL | (0u8 + 0u8) as char;
| ^^^^^^^^^^^ types differ
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.