Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make generic const type mismatches not hide trait impls from the trait solver #120059

Merged
merged 1 commit into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 10 additions & 24 deletions compiler/rustc_infer/src/infer/relate/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
//
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
let compatible_types = self.probe(|_| {
self.probe(|_| {
if a.ty() == b.ty() {
return Ok(());
return;
}

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

// If the consts have differing types, just bail with a const error with
// the expected const's type. Specifically, we don't want const infer vars
// to do any type shapeshifting before and after resolution.
if let Err(guar) = compatible_types {
// HACK: equating both sides with `[const error]` eagerly prevents us
// from leaving unconstrained inference vars during things like impl
// matching in the solver.
let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
return self.unify_const_variable(vid, a_error, relation.param_env());
}
let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
return self.unify_const_variable(vid, b_error, relation.param_env());
}

return Ok(if relation.a_is_expected() { a_error } else { b_error });
}

match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),
Expand Down
1 change: 1 addition & 0 deletions tests/ui/const-generics/bad-subst-const-kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ impl<const N: u64> Q for [u8; N] {
}

pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
//~^ ERROR: the constant `13` is not of type `u64`
16 changes: 15 additions & 1 deletion tests/ui/const-generics/bad-subst-const-kind.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
error: the constant `13` is not of type `u64`
--> $DIR/bad-subst-const-kind.rs:13:24
|
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
| ^^^^^^^^ expected `u64`, found `usize`
Comment on lines +1 to +5
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the compiler suggests using a u64 as an array length

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we have bad spans for this in general

|
note: required for `[u8; 13]` to implement `Q`
--> $DIR/bad-subst-const-kind.rs:8:20
|
LL | impl<const N: u64> Q for [u8; N] {
| ------------ ^ ^^^^^^^
| |
| unsatisfied trait bound introduced here

error[E0308]: mismatched types
--> $DIR/bad-subst-const-kind.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {
| ^ expected `usize`, found `u64`

Comment on lines 15 to 20
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only diagnostic I would expect to see. But I haven't figured out yet how to poison the impl so it doesn't get picked up

error: aborting due to 1 previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
3 changes: 3 additions & 0 deletions tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ trait Q {

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

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

pub fn main() {}
33 changes: 31 additions & 2 deletions tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,35 @@ LL | const ASSOC: usize;
LL | impl<const N: u64> Q for [u8; N] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation

error: aborting due to 1 previous error
error: the constant `13` is not of type `u64`
--> $DIR/type_mismatch.rs:12:26
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
| ^^^^^^^^ expected `u64`, found `usize`
|
note: required for `[u8; 13]` to implement `Q`
--> $DIR/type_mismatch.rs:8:20
|
LL | impl<const N: u64> Q for [u8; N] {}
| ------------ ^ ^^^^^^^
| |
| unsatisfied trait bound introduced here

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:12:20
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {}
| ^ expected `usize`, found `u64`

Comment on lines +32 to +37
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good, I want this error. But now we also got a bunch of "follow-up" errors happening before. Maybe we can move whatever causes this error into a query that is guaranteed to be called before impl overlap checking

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0046`.
Some errors have detailed explanations: E0046, E0308.
For more information about an error, try `rustc --explain E0046`.
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ struct S<const L: usize>;
impl<const N: i32> Copy for S<N> {}
//~^ ERROR the constant `N` is not of type `usize`
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
impl<const M: usize> Copy for S<M> {}
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
--> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
|
LL | impl<const N: i32> Copy for S<N> {}
| -------------------------------- first implementation here
LL |
LL | impl<const M: usize> Copy for S<M> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`

error: the constant `N` is not of type `usize`
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
|
LL | impl<const N: i32> Copy for S<N> {}
| ^^^^ expected `usize`, found `i32`
|
note: required by a bound in `S`
--> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
note: required for `S<N>` to implement `Clone`
--> $DIR/bad-const-wf-doesnt-specialize.rs:5:10
|
LL | #[derive(Clone)]
| ^^^^^
LL | struct S<const L: usize>;
| ^^^^^^^^^^^^^^ required by this bound in `S`
| ----- unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `Copy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error
error: aborting due to 2 previous errors

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