diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-11-20 03:08:52 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2024-12-04 20:29:36 +0000 |
| commit | 87ddc1ea33edbe1be119d73e57c2783940e797fe (patch) | |
| tree | 1078cb612921aa307c2700910e38c4441beccbd8 | |
| parent | c0f00086f85ae1fff34dd2daf6a11850e5bfc2f0 (diff) | |
| download | rust-87ddc1ea33edbe1be119d73e57c2783940e797fe.tar.gz rust-87ddc1ea33edbe1be119d73e57c2783940e797fe.zip | |
Point at generic param through which a const is used in a pattern
```
error[E0158]: constant pattern depends on a generic parameter, which is not allowed
--> $DIR/associated-const-type-parameter-pattern.rs:20:9
|
LL | pub trait Foo {
| -------------
LL | const X: EFoo;
| ------------- constant defined here
...
LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
| - constant depends on this generic param
LL | match arg {
LL | A::X => println!("A::X"),
| ^^^^ `const` depends on a generic parameter
```
7 files changed, 59 insertions, 21 deletions
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 2bf49137e8f..4bc7dcf9564 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -88,8 +88,8 @@ mir_build_const_defined_here = constant defined here mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns -mir_build_const_pattern_depends_on_generic_parameter = - constant pattern depends on a generic parameter +mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter, which is not allowed + .label = `const` depends on a generic parameter mir_build_could_not_eval_const_pattern = could not evaluate constant pattern .label = could not evaluate constant diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 7f4bb139fad..1068c56eeca 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -695,6 +695,7 @@ pub(crate) struct WantedConstant { #[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)] pub(crate) struct ConstPatternDependsOnGenericParameter { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 3690459bf51..b625c655fac 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -53,6 +53,7 @@ struct ConstToPat<'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, span: Span, + id: hir::HirId, treat_byte_string_as_slice: bool, @@ -66,6 +67,7 @@ impl<'tcx> ConstToPat<'tcx> { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, + id, treat_byte_string_as_slice: pat_ctxt .typeck_results .treat_byte_string_as_slice @@ -135,10 +137,28 @@ impl<'tcx> ConstToPat<'tcx> { return self.mk_err(err, ty); } Err(ErrorHandled::TooGeneric(_)) => { - let e = self + let mut e = self .tcx .dcx() .create_err(ConstPatternDependsOnGenericParameter { span: self.span }); + for arg in uv.args { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Param(param_ty) = ty.kind() + { + let def_id = self.tcx.hir().enclosing_body_owner(self.id); + let generics = self.tcx.generics_of(def_id); + let param = generics.type_param(*param_ty, self.tcx); + let span = self.tcx.def_span(param.def_id); + e.span_label(span, "constant depends on this generic param"); + if let Some(ident) = self.tcx.def_ident_span(def_id) + && self.tcx.sess.source_map().is_multiline(ident.between(span)) + { + // Display the `fn` name as well in the diagnostic, as the generic isn't + // in the same line and it could be confusing otherwise. + e.span_label(ident, ""); + } + } + } return self.mk_err(e, ty); } Ok(Err(bad_ty)) => { diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr index 5aef0fa414b..455831e8401 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | LL | pub trait Foo { @@ -6,10 +6,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) { + | - constant depends on this generic param +LL | match arg { LL | A::X => println!("A::X"), - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:22:9 | LL | pub trait Foo { @@ -17,10 +20,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) { + | - constant depends on this generic param +... LL | B::X => println!("B::X"), - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:30:9 | LL | pub trait Foo { @@ -28,10 +34,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) { + | - constant depends on this generic param +LL | LL | let A::X = arg; - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:28:48 | LL | pub trait Foo { @@ -40,7 +49,9 @@ LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) { - | ^^^^ + | - ^^^^ `const` depends on a generic parameter + | | + | constant depends on this generic param error: aborting due to 4 previous errors diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr index 79a03d4ec32..2f50e6ac2fd 100644 --- a/tests/ui/consts/issue-73976-polymorphic.stderr +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-73976-polymorphic.rs:20:37 | LL | impl<T: 'static> GetTypeId<T> { @@ -6,10 +6,12 @@ LL | impl<T: 'static> GetTypeId<T> { LL | pub const VALUE: TypeId = TypeId::of::<T>(); | ----------------------- constant defined here ... +LL | const fn check_type_id<T: 'static>() -> bool { + | - constant depends on this generic param LL | matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-73976-polymorphic.rs:31:42 | LL | impl<T: 'static> GetTypeNameLen<T> { @@ -17,8 +19,10 @@ LL | impl<T: 'static> GetTypeNameLen<T> { LL | pub const VALUE: usize = any::type_name::<T>().len(); | ---------------------- constant defined here ... +LL | const fn check_type_name_len<T: 'static>() -> bool { + | - constant depends on this generic param LL | matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index 9b53a259547..d36f3ecbb76 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | impl<T> GetVariantCount<T> { @@ -6,8 +6,10 @@ LL | impl<T> GetVariantCount<T> { LL | pub const VALUE: usize = std::mem::variant_count::<T>(); | ---------------------- constant defined here ... +LL | const fn check_variant_count<T>() -> bool { + | - constant depends on this generic param LL | matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 1 previous error diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index 26f72b34eca..cf48161b5e3 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -1,14 +1,14 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/const-match-pat-generic.rs:7:9 | LL | const { V } => {}, - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/const-match-pat-generic.rs:19:9 | LL | const { f(V) } => {}, - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 2 previous errors |
