about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-11-20 03:08:52 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-12-04 20:29:36 +0000
commit87ddc1ea33edbe1be119d73e57c2783940e797fe (patch)
tree1078cb612921aa307c2700910e38c4441beccbd8 /compiler
parentc0f00086f85ae1fff34dd2daf6a11850e5bfc2f0 (diff)
downloadrust-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
```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir_build/messages.ftl4
-rw-r--r--compiler/rustc_mir_build/src/errors.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs22
3 files changed, 24 insertions, 3 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)) => {