From 2040c1c6358e67eef82bf39091476ecd3755e574 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 | 2 +- .../bad-const-wf-doesnt-specialize.stderr | 15 ++++---- 7 files changed, 67 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 4b254fc7df518..5912064a51a37 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -167,9 +167,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 @@ -179,32 +179,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..a0ee771441772 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 @@ -6,7 +6,7 @@ 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..2953bc95917c9 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,11 @@ -error: the constant `N` is not of type `usize` - --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29 +error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` + --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 | 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 - | -LL | struct S; - | ^^^^^^^^^^^^^^ required by this bound in `S` + | -------------------------------- first implementation here +LL | impl Copy for S {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0119`.