mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
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
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
// known-bug: unknown
|
||||
// check-pass
|
||||
|
||||
fn main() {
|
||||
(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…
Reference in New Issue
Block a user