Skip to content

Commit c4ad0e7

Browse files
Rollup merge of rust-lang#120059 - oli-obk:const_arg_type_mismatch, r=compiler-errors
Make generic const type mismatches not hide trait impls from the trait solver pulled out of rust-lang#119895 It does improve diagnostics somewhat, but also causes some extraneous diagnostics in potentially misleading order. The issue was that a const type mismatch, instead of reporting an error, would silently poison the constant, only for that information to be thrown away and the impl to be treated as "not matching". In rust-lang#119895 this would cause ICEs as well as errors on impls stating that the impl needs to exist for itself to be valid.
2 parents 13134f5 + 2040c1c commit c4ad0e7

File tree

7 files changed

+67
-37
lines changed

7 files changed

+67
-37
lines changed

compiler/rustc_infer/src/infer/relate/combine.rs

+10-24
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
165165
//
166166
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
167167
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
168-
let compatible_types = self.probe(|_| {
168+
self.probe(|_| {
169169
if a.ty() == b.ty() {
170-
return Ok(());
170+
return;
171171
}
172172

173173
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
@@ -177,32 +177,18 @@ impl<'tcx> InferCtxt<'tcx> {
177177
relation.param_env().and((a.ty(), b.ty())),
178178
&mut OriginalQueryValues::default(),
179179
);
180-
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
180+
self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
181+
// The error will only be reported later. If we emit an ErrorGuaranteed
182+
// here, then we will never get to the code that actually emits the error.
181183
self.tcx.dcx().delayed_bug(format!(
182184
"cannot relate consts of different types (a={a:?}, b={b:?})",
183-
))
184-
})
185+
));
186+
// We treat these constants as if they were of the same type, so that any
187+
// such constants being used in impls make these impls match barring other mismatches.
188+
// This helps with diagnostics down the road.
189+
});
185190
});
186191

187-
// If the consts have differing types, just bail with a const error with
188-
// the expected const's type. Specifically, we don't want const infer vars
189-
// to do any type shapeshifting before and after resolution.
190-
if let Err(guar) = compatible_types {
191-
// HACK: equating both sides with `[const error]` eagerly prevents us
192-
// from leaving unconstrained inference vars during things like impl
193-
// matching in the solver.
194-
let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
195-
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
196-
return self.unify_const_variable(vid, a_error, relation.param_env());
197-
}
198-
let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
199-
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
200-
return self.unify_const_variable(vid, b_error, relation.param_env());
201-
}
202-
203-
return Ok(if relation.a_is_expected() { a_error } else { b_error });
204-
}
205-
206192
match (a.kind(), b.kind()) {
207193
(
208194
ty::ConstKind::Infer(InferConst::Var(a_vid)),

tests/ui/const-generics/bad-subst-const-kind.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ impl<const N: u64> Q for [u8; N] {
1111
}
1212

1313
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
14+
//~^ ERROR: the constant `13` is not of type `u64`
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
1+
error: the constant `13` is not of type `u64`
2+
--> $DIR/bad-subst-const-kind.rs:13:24
3+
|
4+
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
5+
| ^^^^^^^^ expected `u64`, found `usize`
6+
|
7+
note: required for `[u8; 13]` to implement `Q`
8+
--> $DIR/bad-subst-const-kind.rs:8:20
9+
|
10+
LL | impl<const N: u64> Q for [u8; N] {
11+
| ------------ ^ ^^^^^^^
12+
| |
13+
| unsatisfied trait bound introduced here
14+
115
error[E0308]: mismatched types
216
--> $DIR/bad-subst-const-kind.rs:8:31
317
|
418
LL | impl<const N: u64> Q for [u8; N] {
519
| ^ expected `usize`, found `u64`
620

7-
error: aborting due to 1 previous error
21+
error: aborting due to 2 previous errors
822

923
For more information about this error, try `rustc --explain E0308`.

tests/ui/const-generics/generic_const_exprs/type_mismatch.rs

+3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ trait Q {
77

88
impl<const N: u64> Q for [u8; N] {}
99
//~^ ERROR not all trait items implemented
10+
//~| ERROR mismatched types
1011

1112
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
13+
//~^ ERROR the constant `13` is not of type `u64`
14+
//~| ERROR mismatched types
1215

1316
pub fn main() {}

tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr

+31-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,35 @@ LL | const ASSOC: usize;
77
LL | impl<const N: u64> Q for [u8; N] {}
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation
99

10-
error: aborting due to 1 previous error
10+
error: the constant `13` is not of type `u64`
11+
--> $DIR/type_mismatch.rs:12:26
12+
|
13+
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
14+
| ^^^^^^^^ expected `u64`, found `usize`
15+
|
16+
note: required for `[u8; 13]` to implement `Q`
17+
--> $DIR/type_mismatch.rs:8:20
18+
|
19+
LL | impl<const N: u64> Q for [u8; N] {}
20+
| ------------ ^ ^^^^^^^
21+
| |
22+
| unsatisfied trait bound introduced here
23+
24+
error[E0308]: mismatched types
25+
--> $DIR/type_mismatch.rs:12:20
26+
|
27+
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
28+
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()`
29+
| |
30+
| implicitly returns `()` as its body has no tail or `return` expression
31+
32+
error[E0308]: mismatched types
33+
--> $DIR/type_mismatch.rs:8:31
34+
|
35+
LL | impl<const N: u64> Q for [u8; N] {}
36+
| ^ expected `usize`, found `u64`
37+
38+
error: aborting due to 4 previous errors
1139

12-
For more information about this error, try `rustc --explain E0046`.
40+
Some errors have detailed explanations: E0046, E0308.
41+
For more information about an error, try `rustc --explain E0046`.

tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
struct S<const L: usize>;
77

88
impl<const N: i32> Copy for S<N> {}
9-
//~^ ERROR the constant `N` is not of type `usize`
109
impl<const M: usize> Copy for S<M> {}
10+
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
1111

1212
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
error: the constant `N` is not of type `usize`
2-
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
1+
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
2+
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
33
|
44
LL | impl<const N: i32> Copy for S<N> {}
5-
| ^^^^ expected `usize`, found `i32`
6-
|
7-
note: required by a bound in `S`
8-
--> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
9-
|
10-
LL | struct S<const L: usize>;
11-
| ^^^^^^^^^^^^^^ required by this bound in `S`
5+
| -------------------------------- first implementation here
6+
LL | impl<const M: usize> Copy for S<M> {}
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
128

139
error: aborting due to 1 previous error
1410

11+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)