From 1b98d0ed13e4a8ff8d94e6aee0f11fab07d6139a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 31 Dec 2024 18:51:36 +0000 Subject: [PATCH 1/2] Explain that in paths generics can't be set on both the enum and the variant ``` error[E0109]: type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` --> $DIR/enum-variant-generic-args.rs:54:12 | LL | Enum::<()>::TSVariant::<()>(()); | ---- ^^ --------- ^^ type argument not allowed | | | | | not allowed on tuple variant `TSVariant` | not allowed on enum `Enum` | = 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(()); | ``` Fix #93993. --- compiler/rustc_hir_analysis/src/collect.rs | 7 ++- .../src/hir_ty_lowering/errors.rs | 58 +++++++++++++------ .../src/hir_ty_lowering/mod.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 7 ++- .../enum-variant-generic-args.rs | 6 +- .../enum-variant-generic-args.stderr | 54 ++++++++++++----- 6 files changed, 94 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index ce7319f656190..126237799562f 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 79aa2f4b8ccd2..66746dfc3875d 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> + Clone, args_visitors: impl Iterator> + Clone, - err_extend: GenericsArgsErrExtend<'_>, + err_extend: GenericsArgsErrExtend<'a>, ) -> ErrorGuaranteed { #[derive(PartialEq, Eq, Hash)] enum ProhibitGenericsArg { @@ -1047,23 +1047,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; }); + let segments: Vec<_> = match err_extend { + GenericsArgsErrExtend::DefVariant(segments) => segments.iter().collect(), + _ => 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 +1078,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 = segments - .clone() - .flat_map(|segment| segment.args().args) - .map(|arg| arg.span()) - .collect(); + let arg_spans: Vec = + 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 +1104,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 +1401,7 @@ pub enum GenericsArgsErrExtend<'tcx> { }, SelfTyParam(Span), Param(DefId), - DefVariant, + DefVariant(&'tcx [hir::PathSegment<'tcx>]), None, } @@ -1408,7 +1409,7 @@ fn generics_args_err_extend<'a>( tcx: TyCtxt<'_>, segments: impl Iterator> + Clone, err: &mut Diag<'_>, - err_extend: GenericsArgsErrExtend<'_>, + err_extend: GenericsArgsErrExtend<'a>, ) { match err_extend { GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => { @@ -1496,6 +1497,32 @@ fn generics_args_err_extend<'a>( ]; err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect); } + GenericsArgsErrExtend::DefVariant(segments) => { + let args: Vec = 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() + { + let msg = "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.note(msg); + 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 +1539,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 ffddf6f73aaf0..aef5c7aa38f1d 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> + 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 6bb8cf5f33159..e74ffeff343a2 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.rs b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs index 759a7fd7e05a9..e4897005a5c1a 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs @@ -52,7 +52,7 @@ fn main() { // Tuple struct variant Enum::<()>::TSVariant::<()>(()); - //~^ ERROR type arguments are not allowed on tuple variant `TSVariant` [E0109] + //~^ ERROR type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` [E0109] Alias::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this type [E0109] @@ -70,7 +70,7 @@ fn main() { // Struct variant Enum::<()>::SVariant::<()> { v: () }; - //~^ ERROR type arguments are not allowed on variant `SVariant` [E0109] + //~^ ERROR type arguments are not allowed on enum `Enum` and variant `SVariant` [E0109] Alias::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this type [E0109] @@ -88,7 +88,7 @@ fn main() { // Unit variant Enum::<()>::UVariant::<()>; - //~^ ERROR type arguments are not allowed on unit variant `UVariant` [E0109] + //~^ ERROR type arguments are not allowed on enum `Enum` and unit variant `UVariant` [E0109] Alias::UVariant::<()>; //~^ ERROR type arguments are not allowed on this type [E0109] 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 8caf17ae2da5a..3f98a1eb5c09a 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 @@ -278,13 +278,21 @@ LL | Self::<()>::UVariant::<()>; | | | not allowed on this type -error[E0109]: type arguments are not allowed on tuple variant `TSVariant` - --> $DIR/enum-variant-generic-args.rs:54:29 +error[E0109]: type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` + --> $DIR/enum-variant-generic-args.rs:54:12 | LL | Enum::<()>::TSVariant::<()>(()); - | --------- ^^ type argument not allowed - | | - | not allowed on tuple variant `TSVariant` + | ---- ^^ --------- ^^ type argument not allowed + | | | + | | not allowed on tuple variant `TSVariant` + | not allowed on enum `Enum` + | + = 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 @@ -346,15 +354,21 @@ LL | AliasFixed::<()>::TSVariant::<()>(()); | | | not allowed on this type -error[E0109]: type arguments are not allowed on variant `SVariant` - --> $DIR/enum-variant-generic-args.rs:72:28 +error[E0109]: type arguments are not allowed on enum `Enum` and variant `SVariant` + --> $DIR/enum-variant-generic-args.rs:72:12 | LL | Enum::<()>::SVariant::<()> { v: () }; - | -------- ^^ type argument not allowed - | | - | not allowed on variant `SVariant` + | ---- ^^ -------- ^^ type argument not allowed + | | | + | | not allowed on variant `SVariant` + | not allowed on enum `Enum` + | + = 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: () }; | - = note: enum variants can't have type parameters error[E0109]: type arguments are not allowed on this type --> $DIR/enum-variant-generic-args.rs:75:23 @@ -444,13 +458,21 @@ LL - AliasFixed::<()>::SVariant::<()> { v: () }; LL + AliasFixed::<()>::SVariant { v: () }; | -error[E0109]: type arguments are not allowed on unit variant `UVariant` - --> $DIR/enum-variant-generic-args.rs:90:28 +error[E0109]: type arguments are not allowed on enum `Enum` and unit variant `UVariant` + --> $DIR/enum-variant-generic-args.rs:90:12 | LL | Enum::<()>::UVariant::<()>; - | -------- ^^ type argument not allowed - | | - | not allowed on unit variant `UVariant` + | ---- ^^ -------- ^^ type argument not allowed + | | | + | | not allowed on unit variant `UVariant` + | not allowed on enum `Enum` + | + = 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 From 23daa8c724cccc4ef75de60d271a50ef193abf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Feb 2025 23:47:56 +0000 Subject: [PATCH 2/2] Remove some the spans pointing at the enum in the path and its generic args ``` error[E0109]: type arguments are not allowed on tuple variant `TSVariant` --> $DIR/enum-variant-generic-args.rs:54:29 | 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(()); | ``` --- .../src/hir_ty_lowering/errors.rs | 13 +++----- .../enum-variant-generic-args.rs | 6 ++-- .../enum-variant-generic-args.stderr | 33 +++++++++---------- 3 files changed, 23 insertions(+), 29 deletions(-) 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 66746dfc3875d..7eb982a31798c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1047,10 +1047,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; }); - let segments: Vec<_> = match err_extend { - GenericsArgsErrExtend::DefVariant(segments) => segments.iter().collect(), - _ => segments.collect(), - }; + let segments: Vec<_> = segments.collect(); let types_and_spans: Vec<_> = segments .iter() .flat_map(|segment| { @@ -1511,10 +1508,10 @@ fn generics_args_err_extend<'a>( if args.len() > 1 && let Some(span) = args.into_iter().last() { - let msg = "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.note(msg); + 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", diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs index e4897005a5c1a..759a7fd7e05a9 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs @@ -52,7 +52,7 @@ fn main() { // Tuple struct variant Enum::<()>::TSVariant::<()>(()); - //~^ ERROR type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` [E0109] + //~^ ERROR type arguments are not allowed on tuple variant `TSVariant` [E0109] Alias::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this type [E0109] @@ -70,7 +70,7 @@ fn main() { // Struct variant Enum::<()>::SVariant::<()> { v: () }; - //~^ ERROR type arguments are not allowed on enum `Enum` and variant `SVariant` [E0109] + //~^ ERROR type arguments are not allowed on variant `SVariant` [E0109] Alias::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this type [E0109] @@ -88,7 +88,7 @@ fn main() { // Unit variant Enum::<()>::UVariant::<()>; - //~^ ERROR type arguments are not allowed on enum `Enum` and unit variant `UVariant` [E0109] + //~^ ERROR type arguments are not allowed on unit variant `UVariant` [E0109] Alias::UVariant::<()>; //~^ ERROR type arguments are not allowed on this type [E0109] 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 3f98a1eb5c09a..5039ae8f288ee 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 @@ -278,14 +278,13 @@ LL | Self::<()>::UVariant::<()>; | | | not allowed on this type -error[E0109]: type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` - --> $DIR/enum-variant-generic-args.rs:54:12 +error[E0109]: type arguments are not allowed on tuple variant `TSVariant` + --> $DIR/enum-variant-generic-args.rs:54:29 | LL | Enum::<()>::TSVariant::<()>(()); - | ---- ^^ --------- ^^ type argument not allowed - | | | - | | not allowed on tuple variant `TSVariant` - | not allowed on enum `Enum` + | --------- ^^ 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 @@ -354,14 +353,13 @@ LL | AliasFixed::<()>::TSVariant::<()>(()); | | | not allowed on this type -error[E0109]: type arguments are not allowed on enum `Enum` and variant `SVariant` - --> $DIR/enum-variant-generic-args.rs:72:12 +error[E0109]: type arguments are not allowed on variant `SVariant` + --> $DIR/enum-variant-generic-args.rs:72:28 | LL | Enum::<()>::SVariant::<()> { v: () }; - | ---- ^^ -------- ^^ type argument not allowed - | | | - | | not allowed on variant `SVariant` - | not allowed on enum `Enum` + | -------- ^^ type argument not allowed + | | + | not allowed on variant `SVariant` | = 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 @@ -458,14 +456,13 @@ LL - AliasFixed::<()>::SVariant::<()> { v: () }; LL + AliasFixed::<()>::SVariant { v: () }; | -error[E0109]: type arguments are not allowed on enum `Enum` and unit variant `UVariant` - --> $DIR/enum-variant-generic-args.rs:90:12 +error[E0109]: type arguments are not allowed on unit variant `UVariant` + --> $DIR/enum-variant-generic-args.rs:90:28 | LL | Enum::<()>::UVariant::<()>; - | ---- ^^ -------- ^^ type argument not allowed - | | | - | | not allowed on unit variant `UVariant` - | not allowed on enum `Enum` + | -------- ^^ 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