From 9454b51b0525632a6459d5802c7dbafc95a9a533 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Jan 2024 14:57:48 +0000 Subject: [PATCH] Make generic const type mismatches not hide trait impls from the trait solver --- .../rustc_infer/src/infer/relate/combine.rs | 34 ++++++------------- .../ui/const-generics/bad-subst-const-kind.rs | 1 + .../bad-subst-const-kind.stderr | 16 ++++++++- .../generic_const_exprs/type_mismatch.rs | 3 ++ .../generic_const_exprs/type_mismatch.stderr | 33 ++++++++++++++++-- .../bad-const-wf-doesnt-specialize.rs | 1 + .../bad-const-wf-doesnt-specialize.stderr | 23 ++++++++++--- 7 files changed, 80 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 9e1dab12b4d43..1c120646f1f90 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -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 @@ -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)), diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index e13dfbacd2422..376b18c15b8ae 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -11,3 +11,4 @@ impl Q for [u8; N] { } pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() } +//~^ ERROR: the constant `13` is not of type `u64` diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 6f5bc567c378b..c04a05573bed0 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -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` + | +note: required for `[u8; 13]` to implement `Q` + --> $DIR/bad-subst-const-kind.rs:8:20 + | +LL | impl Q for [u8; N] { + | ------------ ^ ^^^^^^^ + | | + | unsatisfied trait bound introduced here + error[E0308]: mismatched types --> $DIR/bad-subst-const-kind.rs:8:31 | LL | impl Q for [u8; N] { | ^ expected `usize`, found `u64` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs index 5813f09818410..6b0d9e047dbc3 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -7,7 +7,10 @@ trait Q { impl 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() {} diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index c73d1022ed312..bb6d650b7ab27 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -7,6 +7,35 @@ LL | const ASSOC: usize; LL | impl 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 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 Q for [u8; N] {} + | ^ expected `usize`, found `u64` + +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`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index 5fd7c647c2531..8ceecd801d3a7 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -8,5 +8,6 @@ struct S; impl Copy for S {} //~^ ERROR the constant `N` is not of type `usize` impl Copy for S {} +//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` fn main() {} diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index def4a413af111..3268a8767339f 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -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 Copy for S {} + | -------------------------------- first implementation here +LL | +LL | impl Copy for S {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` + error: the constant `N` is not of type `usize` --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29 | LL | impl Copy for S {} | ^^^^ expected `usize`, found `i32` | -note: required by a bound in `S` - --> $DIR/bad-const-wf-doesnt-specialize.rs:6:10 +note: required for `S` to implement `Clone` + --> $DIR/bad-const-wf-doesnt-specialize.rs:5:10 | +LL | #[derive(Clone)] + | ^^^^^ LL | struct S; - | ^^^^^^^^^^^^^^ 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`.