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.
This commit is contained in:
Esteban Küber 2024-12-31 18:51:36 +00:00
parent 06a24e98c6
commit 1b98d0ed13
6 changed files with 94 additions and 42 deletions

View File

@ -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,
);

View File

@ -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,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<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 +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<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 +1497,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()
{
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);

View File

@ -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();

View File

@ -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 {

View File

@ -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]

View File

@ -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