Skip to content

Commit

Permalink
Rollup merge of #108828 - compiler-errors:new-solver-alias-eq-on-num-…
Browse files Browse the repository at this point in the history
…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`
  • Loading branch information
matthiaskrgr committed Mar 10, 2023
2 parents b90277e + d4b59a0 commit 233ed35
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 40 deletions.
7 changes: 4 additions & 3 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Expand Down
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
26 changes: 18 additions & 8 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,30 @@ impl<'tcx> InferCtxt<'tcx> {
self.unify_float_variable(!a_is_expected, v_id, v)
}

// All other cases of inference are errors
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
// 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, _), _) if self.tcx.trait_solver_next() => {
(_, ty::Alias(AliasKind::Projection, _)) | (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)
}

// All other cases of inference are errors
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
}

_ => ty::relate::super_relate_tys(relation, a, b),
}
}
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
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}
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
3 changes: 3 additions & 0 deletions tests/ui/issues/issue-66667-function-cmp-cycle.rs
Original file line number Diff line number Diff line change
@@ -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() {}
34 changes: 29 additions & 5 deletions tests/ui/issues/issue-66667-function-cmp-cycle.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,65 @@ 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}
| |
| 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
|
= 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}
| |
| 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
|
= 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`.
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;
}
18 changes: 18 additions & 0 deletions tests/ui/traits/new-solver/int-var-alias-eq.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// compile-flags: -Ztrait-solver=next
// known-bug: unknown
// check-pass

fn main() {
(0u8 + 0u8) as char;
Expand Down

This file was deleted.

0 comments on commit 233ed35

Please sign in to comment.