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:
commit
233ed35e84
12 changed files with 144 additions and 41 deletions
|
@ -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,
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
18
tests/ui/traits/new-solver/int-var-alias-eq.rs
Normal file
18
tests/ui/traits/new-solver/int-var-alias-eq.rs
Normal 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() {}
|
|
@ -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;
|
||||||
|
|
|
@ -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`.
|
|
Loading…
Add table
Reference in a new issue