Skip to content

Commit

Permalink
Explain that in paths generics can't be set on both the enum and the …
Browse files Browse the repository at this point in the history
…variant

```
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::<()>(());
   |
LL -     Enum::<()>::TSVariant::<()>(());
LL +     Enum::<()>::TSVariant(());
   |
```

Fix #93993.
  • Loading branch information
estebank committed Jan 30, 2025
1 parent 2f348cb commit 20ebe59
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 14 deletions.
7 changes: 4 additions & 3 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
Expand Down
36 changes: 28 additions & 8 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_errors::{
Applicability, Diag, ErrorGuaranteed, MultiSpan, 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};
Expand Down Expand Up @@ -1059,15 +1059,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} 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,
Expand Down Expand Up @@ -1426,7 +1426,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
},
SelfTyParam(Span),
Param(DefId),
DefVariant,
DefVariant(&'tcx [hir::PathSegment<'tcx>]),
None,
}

Expand Down Expand Up @@ -1522,6 +1522,29 @@ 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 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.multipart_suggestions(
"remove the generics arguments from one of the path segments",
args.into_iter().map(|span| vec![(span, String::new())]),
Applicability::MaybeIncorrect,
);
}
}
GenericsArgsErrExtend::PrimTy(prim_ty) => {
let name = prim_ty.name_str();
for segment in segments {
Expand All @@ -1538,9 +1561,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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,7 +1913,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();
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,12 +1031,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);
Expand Down Expand Up @@ -1083,7 +1088,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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@ 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::<()>(());
|
LL - Enum::<()>::TSVariant::<()>(());
LL + Enum::<()>::TSVariant(());
|

error[E0109]: type arguments are not allowed on this type
--> $DIR/enum-variant-generic-args.rs:57:24
Expand Down Expand Up @@ -348,7 +358,15 @@ 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: () };
|
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
Expand Down Expand Up @@ -445,6 +463,16 @@ 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::<()>;
|
LL - Enum::<()>::UVariant::<()>;
LL + Enum::<()>::UVariant;
|

error[E0109]: type arguments are not allowed on this type
--> $DIR/enum-variant-generic-args.rs:93:23
Expand Down

0 comments on commit 20ebe59

Please sign in to comment.