about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs55
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs7
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr21
5 files changed, 70 insertions, 24 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ce7319f6561..12623779956 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -614,9 +614,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
             if !infer_replacements.is_empty() {
                 diag.multipart_suggestion(
                     format!(
-                    "try replacing `_` with the type{} in the corresponding trait method signature",
-                    rustc_errors::pluralize!(infer_replacements.len()),
-                ),
+                        "try replacing `_` with the type{} in the corresponding trait method \
+                         signature",
+                        rustc_errors::pluralize!(infer_replacements.len()),
+                    ),
                     infer_replacements,
                     Applicability::MachineApplicable,
                 );
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 79aa2f4b8cc..7eb982a3179 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err,
 };
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
@@ -1027,7 +1027,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         &self,
         segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
         args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
-        err_extend: GenericsArgsErrExtend<'_>,
+        err_extend: GenericsArgsErrExtend<'a>,
     ) -> ErrorGuaranteed {
         #[derive(PartialEq, Eq, Hash)]
         enum ProhibitGenericsArg {
@@ -1047,23 +1047,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             };
         });
 
+        let segments: Vec<_> = segments.collect();
         let types_and_spans: Vec<_> = segments
-            .clone()
+            .iter()
             .flat_map(|segment| {
                 if segment.args().args.is_empty() {
                     None
                 } else {
                     Some((
                         match segment.res {
-                            hir::def::Res::PrimTy(ty) => {
+                            Res::PrimTy(ty) => {
                                 format!("{} `{}`", segment.res.descr(), ty.name())
                             }
-                            hir::def::Res::Def(_, def_id)
+                            Res::Def(_, def_id)
                                 if let Some(name) = self.tcx().opt_item_name(def_id) =>
                             {
                                 format!("{} `{name}`", segment.res.descr())
                             }
-                            hir::def::Res::Err => "this type".to_string(),
+                            Res::Err => "this type".to_string(),
                             _ => segment.res.descr().to_string(),
                         },
                         segment.ident.span,
@@ -1074,11 +1075,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
             .expect("expected one segment to deny");
 
-        let arg_spans: Vec<Span> = segments
-            .clone()
-            .flat_map(|segment| segment.args().args)
-            .map(|arg| arg.span())
-            .collect();
+        let arg_spans: Vec<Span> =
+            segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
 
         let mut kinds = Vec::with_capacity(4);
         prohibit_args.iter().for_each(|arg| match arg {
@@ -1103,7 +1101,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         for (what, span) in types_and_spans {
             err.span_label(span, format!("not allowed on {what}"));
         }
-        generics_args_err_extend(self.tcx(), segments, &mut err, err_extend);
+        generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
         err.emit()
     }
 
@@ -1400,7 +1398,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
     },
     SelfTyParam(Span),
     Param(DefId),
-    DefVariant,
+    DefVariant(&'tcx [hir::PathSegment<'tcx>]),
     None,
 }
 
@@ -1408,7 +1406,7 @@ fn generics_args_err_extend<'a>(
     tcx: TyCtxt<'_>,
     segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
     err: &mut Diag<'_>,
-    err_extend: GenericsArgsErrExtend<'_>,
+    err_extend: GenericsArgsErrExtend<'a>,
 ) {
     match err_extend {
         GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
@@ -1496,6 +1494,32 @@ fn generics_args_err_extend<'a>(
             ];
             err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
         }
+        GenericsArgsErrExtend::DefVariant(segments) => {
+            let args: Vec<Span> = segments
+                .iter()
+                .filter_map(|segment| match segment.res {
+                    Res::Def(
+                        DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
+                        _,
+                    ) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
+                    _ => None,
+                })
+                .collect();
+            if args.len() > 1
+                && let Some(span) = args.into_iter().last()
+            {
+                err.note(
+                    "generic arguments are not allowed on both an enum and its variant's path \
+                     segments simultaneously; they are only valid in one place or the other",
+                );
+                err.span_suggestion_verbose(
+                    span,
+                    "remove the generics arguments from one of the path segments",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
         GenericsArgsErrExtend::PrimTy(prim_ty) => {
             let name = prim_ty.name_str();
             for segment in segments {
@@ -1512,9 +1536,6 @@ fn generics_args_err_extend<'a>(
         GenericsArgsErrExtend::OpaqueTy => {
             err.note("`impl Trait` types can't have type parameters");
         }
-        GenericsArgsErrExtend::DefVariant => {
-            err.note("enum variants can't have type parameters");
-        }
         GenericsArgsErrExtend::Param(def_id) => {
             let span = tcx.def_ident_span(def_id).unwrap();
             let kind = tcx.def_descr(def_id);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 697852c5ed3..c6e47a804dc 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1694,7 +1694,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     pub fn prohibit_generic_args<'a>(
         &self,
         segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
-        err_extend: GenericsArgsErrExtend<'_>,
+        err_extend: GenericsArgsErrExtend<'a>,
     ) -> Result<(), ErrorGuaranteed> {
         let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
         let mut result = Ok(());
@@ -1911,7 +1911,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     path.segments.iter().enumerate().filter_map(|(index, seg)| {
                         if !indices.contains(&index) { Some(seg) } else { None }
                     }),
-                    GenericsArgsErrExtend::DefVariant,
+                    GenericsArgsErrExtend::DefVariant(&path.segments),
                 );
 
                 let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6bb8cf5f331..e74ffeff343 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1043,12 +1043,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut user_self_ty = None;
         let mut is_alias_variant_ctor = false;
+        let mut err_extend = GenericsArgsErrExtend::None;
         match res {
             Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => {
                 let adt_def = self_ty.normalized.ty_adt_def().unwrap();
                 user_self_ty =
                     Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
                 is_alias_variant_ctor = true;
+                err_extend = GenericsArgsErrExtend::DefVariant(segments);
+            }
+            Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
+                err_extend = GenericsArgsErrExtend::DefVariant(segments);
             }
             Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
                 let assoc_item = tcx.associated_item(def_id);
@@ -1095,7 +1100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             segments.iter().enumerate().filter_map(|(index, seg)| {
                 if !indices.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None }
             }),
-            GenericsArgsErrExtend::None,
+            err_extend,
         );
 
         if let Res::Local(hid) = res {
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index 8caf17ae2da..5039ae8f288 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -285,6 +285,13 @@ LL |     Enum::<()>::TSVariant::<()>(());
    |                 ---------   ^^ type argument not allowed
    |                 |
    |                 not allowed on tuple variant `TSVariant`
+   |
+   = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
+help: remove the generics arguments from one of the path segments
+   |
+LL -     Enum::<()>::TSVariant::<()>(());
+LL +     Enum::<()>::TSVariant(());
+   |
 
 error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:57:24
@@ -354,7 +361,12 @@ LL |     Enum::<()>::SVariant::<()> { v: () };
    |                 |
    |                 not allowed on variant `SVariant`
    |
-   = note: enum variants can't have type parameters
+   = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
+help: remove the generics arguments from one of the path segments
+   |
+LL -     Enum::<()>::SVariant::<()> { v: () };
+LL +     Enum::<()>::SVariant { v: () };
+   |
 
 error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:75:23
@@ -451,6 +463,13 @@ LL |     Enum::<()>::UVariant::<()>;
    |                 --------   ^^ type argument not allowed
    |                 |
    |                 not allowed on unit variant `UVariant`
+   |
+   = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other
+help: remove the generics arguments from one of the path segments
+   |
+LL -     Enum::<()>::UVariant::<()>;
+LL +     Enum::<()>::UVariant;
+   |
 
 error[E0109]: type arguments are not allowed on this type
   --> $DIR/enum-variant-generic-args.rs:93:23