Skip to content

Commit 233ed35

Browse files
authored
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`
2 parents b90277e + d4b59a0 commit 233ed35

File tree

12 files changed

+143
-40
lines changed

12 files changed

+143
-40
lines changed

compiler/rustc_hir_typeck/src/op.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
148148
rhs_ty,
149149
op,
150150
);
151-
self.demand_suptype(expr.span, builtin_return_ty, return_ty);
151+
self.demand_eqtype(expr.span, builtin_return_ty, return_ty);
152+
builtin_return_ty
153+
} else {
154+
return_ty
152155
}
153-
154-
return_ty
155156
}
156157
}
157158
}

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
411411
}
412412
}
413413

414-
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
415-
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
416-
t,
417-
),
418-
419-
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
420-
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
421-
t,
422-
),
414+
ty::Infer(ty::IntVar(vid)) => {
415+
let nt = self.infcx.opportunistic_resolve_int_var(vid);
416+
if nt != t {
417+
return self.fold_ty(nt);
418+
} else {
419+
self.canonicalize_ty_var(
420+
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
421+
t,
422+
)
423+
}
424+
}
425+
ty::Infer(ty::FloatVar(vid)) => {
426+
let nt = self.infcx.opportunistic_resolve_float_var(vid);
427+
if nt != t {
428+
return self.fold_ty(nt);
429+
} else {
430+
self.canonicalize_ty_var(
431+
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
432+
t,
433+
)
434+
}
435+
}
423436

424437
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
425438
bug!("encountered a fresh type during canonicalization")

compiler/rustc_infer/src/infer/combine.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,30 @@ impl<'tcx> InferCtxt<'tcx> {
119119
self.unify_float_variable(!a_is_expected, v_id, v)
120120
}
121121

122-
// All other cases of inference are errors
123-
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
124-
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
122+
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
123+
(
124+
ty::Alias(AliasKind::Projection, _),
125+
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
126+
)
127+
| (
128+
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
129+
ty::Alias(AliasKind::Projection, _),
130+
) if self.tcx.trait_solver_next() => {
131+
bug!()
125132
}
126133

127-
(ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
134+
(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
135+
if self.tcx.trait_solver_next() =>
136+
{
128137
relation.register_type_equate_obligation(a, b);
129-
Ok(b)
130-
}
131-
(_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
132-
relation.register_type_equate_obligation(b, a);
133138
Ok(a)
134139
}
135140

141+
// All other cases of inference are errors
142+
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
143+
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
144+
}
145+
136146
_ => ty::relate::super_relate_tys(relation, a, b),
137147
}
138148
}

compiler/rustc_infer/src/infer/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,28 @@ impl<'tcx> InferCtxt<'tcx> {
13631363
self.inner.borrow_mut().const_unification_table().find(var)
13641364
}
13651365

1366+
/// Resolves an int var to a rigid int type, if it was constrained to one,
1367+
/// or else the root int var in the unification table.
1368+
pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
1369+
let mut inner = self.inner.borrow_mut();
1370+
if let Some(value) = inner.int_unification_table().probe_value(vid) {
1371+
value.to_type(self.tcx)
1372+
} else {
1373+
self.tcx.mk_int_var(inner.int_unification_table().find(vid))
1374+
}
1375+
}
1376+
1377+
/// Resolves a float var to a rigid int type, if it was constrained to one,
1378+
/// or else the root float var in the unification table.
1379+
pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
1380+
let mut inner = self.inner.borrow_mut();
1381+
if let Some(value) = inner.float_unification_table().probe_value(vid) {
1382+
value.to_type(self.tcx)
1383+
} else {
1384+
self.tcx.mk_float_var(inner.float_unification_table().find(vid))
1385+
}
1386+
}
1387+
13661388
/// Where possible, replaces type/const variables in
13671389
/// `value` with their final value. Note that region variables
13681390
/// are unaffected. If a type/const variable has not been unified, it

compiler/rustc_middle/src/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ impl<'tcx> Term<'tcx> {
995995

996996
pub fn is_infer(&self) -> bool {
997997
match self.unpack() {
998-
TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
998+
TermKind::Ty(ty) => ty.is_ty_var(),
999999
TermKind::Const(ct) => ct.is_ct_infer(),
10001000
}
10011001
}

compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -278,16 +278,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
278278
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
279279
}
280280
}
281-
ty::Infer(ty::IntVar(_)) => {
282-
let nt = self.infcx.shallow_resolve(t);
281+
ty::Infer(ty::IntVar(vid)) => {
282+
let nt = self.infcx.opportunistic_resolve_int_var(vid);
283283
if nt != t {
284284
return self.fold_ty(nt);
285285
} else {
286286
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
287287
}
288288
}
289-
ty::Infer(ty::FloatVar(_)) => {
290-
let nt = self.infcx.shallow_resolve(t);
289+
ty::Infer(ty::FloatVar(vid)) => {
290+
let nt = self.infcx.opportunistic_resolve_float_var(vid);
291291
if nt != t {
292292
return self.fold_ty(nt);
293293
} else {
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
fn first() {
22
second == 1 //~ ERROR binary operation
33
//~^ ERROR mismatched types
4+
//~| ERROR mismatched types
45
}
56

67
fn second() {
78
first == 1 //~ ERROR binary operation
89
//~^ ERROR mismatched types
10+
//~| ERROR mismatched types
911
}
1012

1113
fn bar() {
1214
bar == 1 //~ ERROR binary operation
1315
//~^ ERROR mismatched types
16+
//~| ERROR mismatched types
1417
}
1518

1619
fn main() {}

tests/ui/issues/issue-66667-function-cmp-cycle.stderr

+29-5
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,65 @@ LL | second == 1
1515
= note: expected fn item `fn() {second}`
1616
found type `{integer}`
1717

18+
error[E0308]: mismatched types
19+
--> $DIR/issue-66667-function-cmp-cycle.rs:2:5
20+
|
21+
LL | fn first() {
22+
| - help: try adding a return type: `-> bool`
23+
LL | second == 1
24+
| ^^^^^^^^^^^ expected `()`, found `bool`
25+
1826
error[E0369]: binary operation `==` cannot be applied to type `fn() {first}`
19-
--> $DIR/issue-66667-function-cmp-cycle.rs:7:11
27+
--> $DIR/issue-66667-function-cmp-cycle.rs:8:11
2028
|
2129
LL | first == 1
2230
| ----- ^^ - {integer}
2331
| |
2432
| fn() {first}
2533

2634
error[E0308]: mismatched types
27-
--> $DIR/issue-66667-function-cmp-cycle.rs:7:14
35+
--> $DIR/issue-66667-function-cmp-cycle.rs:8:14
2836
|
2937
LL | first == 1
3038
| ^ expected fn item, found integer
3139
|
3240
= note: expected fn item `fn() {first}`
3341
found type `{integer}`
3442

43+
error[E0308]: mismatched types
44+
--> $DIR/issue-66667-function-cmp-cycle.rs:8:5
45+
|
46+
LL | fn second() {
47+
| - help: try adding a return type: `-> bool`
48+
LL | first == 1
49+
| ^^^^^^^^^^ expected `()`, found `bool`
50+
3551
error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}`
36-
--> $DIR/issue-66667-function-cmp-cycle.rs:12:9
52+
--> $DIR/issue-66667-function-cmp-cycle.rs:14:9
3753
|
3854
LL | bar == 1
3955
| --- ^^ - {integer}
4056
| |
4157
| fn() {bar}
4258

4359
error[E0308]: mismatched types
44-
--> $DIR/issue-66667-function-cmp-cycle.rs:12:12
60+
--> $DIR/issue-66667-function-cmp-cycle.rs:14:12
4561
|
4662
LL | bar == 1
4763
| ^ expected fn item, found integer
4864
|
4965
= note: expected fn item `fn() {bar}`
5066
found type `{integer}`
5167

52-
error: aborting due to 6 previous errors
68+
error[E0308]: mismatched types
69+
--> $DIR/issue-66667-function-cmp-cycle.rs:14:5
70+
|
71+
LL | fn bar() {
72+
| - help: try adding a return type: `-> bool`
73+
LL | bar == 1
74+
| ^^^^^^^^ expected `()`, found `bool`
75+
76+
error: aborting due to 9 previous errors
5377

5478
Some errors have detailed explanations: E0308, E0369.
5579
For more information about an error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
3+
trait Mirror {
4+
type Assoc;
5+
}
6+
7+
impl<T> Mirror for T {
8+
type Assoc = T;
9+
}
10+
11+
trait Test {}
12+
impl Test for i64 {}
13+
impl Test for u64 {}
14+
15+
fn mirror_me<T: Mirror>(t: T, s: <T as Mirror>::Assoc) where <T as Mirror>::Assoc: Test {}
16+
17+
fn main() {
18+
let mut x = 0;
19+
mirror_me(x, 1);
20+
x = 1i64;
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
// compile-flags: -Ztrait-solver=next
3+
4+
// HIR typeck ends up equating `<_#0i as Add>::Output == _#0i`.
5+
// Want to make sure that we emit an alias-eq goal for this,
6+
// instead of treating it as a type error and bailing.
7+
8+
fn test() {
9+
// fallback
10+
let x = 1 + 2;
11+
}
12+
13+
fn test2() -> u32 {
14+
// expectation from return ty
15+
1 + 2
16+
}
17+
18+
fn main() {}

tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// compile-flags: -Ztrait-solver=next
2-
// known-bug: unknown
2+
// check-pass
33

44
fn main() {
55
(0u8 + 0u8) as char;

tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr

-9
This file was deleted.

0 commit comments

Comments
 (0)