Skip to content

Commit 9454b51

Browse files
committed
Make generic const type mismatches not hide trait impls from the trait solver
1 parent 366d112 commit 9454b51

File tree

7 files changed

+80
-31
lines changed

7 files changed

+80
-31
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
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ struct S<const L: usize>;
88
impl<const N: i32> Copy for S<N> {}
99
//~^ ERROR the constant `N` is not of type `usize`
1010
impl<const M: usize> Copy for S<M> {}
11+
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
1112

1213
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
1+
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
2+
--> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
3+
|
4+
LL | impl<const N: i32> Copy for S<N> {}
5+
| -------------------------------- first implementation here
6+
LL |
7+
LL | impl<const M: usize> Copy for S<M> {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
9+
110
error: the constant `N` is not of type `usize`
211
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
312
|
413
LL | impl<const N: i32> Copy for S<N> {}
514
| ^^^^ expected `usize`, found `i32`
615
|
7-
note: required by a bound in `S`
8-
--> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
16+
note: required for `S<N>` to implement `Clone`
17+
--> $DIR/bad-const-wf-doesnt-specialize.rs:5:10
918
|
19+
LL | #[derive(Clone)]
20+
| ^^^^^
1021
LL | struct S<const L: usize>;
11-
| ^^^^^^^^^^^^^^ required by this bound in `S`
22+
| ----- unsatisfied trait bound introduced in this `derive` macro
23+
note: required by a bound in `Copy`
24+
--> $SRC_DIR/core/src/marker.rs:LL:COL
25+
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
1226

13-
error: aborting due to 1 previous error
27+
error: aborting due to 2 previous errors
1428

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

0 commit comments

Comments
 (0)