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,10 +148,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rhs_ty,
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
}
}
}

View File

@ -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")

View File

@ -119,20 +119,30 @@ impl<'tcx> InferCtxt<'tcx> {
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
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
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),
}
}

View File

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

View File

@ -995,7 +995,7 @@ impl<'tcx> Term<'tcx> {
pub fn is_infer(&self) -> bool {
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(),
}
}

View File

@ -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 {

View File

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

View File

@ -15,8 +15,16 @@ LL | second == 1
= note: expected fn item `fn() {second}`
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}`
--> $DIR/issue-66667-function-cmp-cycle.rs:7:11
--> $DIR/issue-66667-function-cmp-cycle.rs:8:11
|
LL | first == 1
| ----- ^^ - {integer}
@ -24,7 +32,7 @@ LL | first == 1
| fn() {first}
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
| ^ expected fn item, found integer
@ -32,8 +40,16 @@ LL | first == 1
= note: expected fn item `fn() {first}`
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}`
--> $DIR/issue-66667-function-cmp-cycle.rs:12:9
--> $DIR/issue-66667-function-cmp-cycle.rs:14:9
|
LL | bar == 1
| --- ^^ - {integer}
@ -41,7 +57,7 @@ LL | bar == 1
| fn() {bar}
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
| ^ expected fn item, found integer
@ -49,7 +65,15 @@ LL | bar == 1
= note: expected fn item `fn() {bar}`
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.
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
// known-bug: unknown
// check-pass
fn main() {
(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`.