Skip to content

Commit 20ebe59

Browse files
committed
Explain that in paths generics can't be set on both the enum and the 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.
1 parent 2f348cb commit 20ebe59

File tree

5 files changed

+68
-14
lines changed

5 files changed

+68
-14
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
614614
if !infer_replacements.is_empty() {
615615
diag.multipart_suggestion(
616616
format!(
617-
"try replacing `_` with the type{} in the corresponding trait method signature",
618-
rustc_errors::pluralize!(infer_replacements.len()),
619-
),
617+
"try replacing `_` with the type{} in the corresponding trait method \
618+
signature",
619+
rustc_errors::pluralize!(infer_replacements.len()),
620+
),
620621
infer_replacements,
621622
Applicability::MachineApplicable,
622623
);

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{
66
Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err,
77
};
88
use rustc_hir as hir;
9-
use rustc_hir::def::{DefKind, Res};
9+
use rustc_hir::def::{CtorOf, DefKind, Res};
1010
use rustc_hir::def_id::DefId;
1111
use rustc_middle::bug;
1212
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
@@ -1059,15 +1059,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10591059
} else {
10601060
Some((
10611061
match segment.res {
1062-
hir::def::Res::PrimTy(ty) => {
1062+
Res::PrimTy(ty) => {
10631063
format!("{} `{}`", segment.res.descr(), ty.name())
10641064
}
1065-
hir::def::Res::Def(_, def_id)
1065+
Res::Def(_, def_id)
10661066
if let Some(name) = self.tcx().opt_item_name(def_id) =>
10671067
{
10681068
format!("{} `{name}`", segment.res.descr())
10691069
}
1070-
hir::def::Res::Err => "this type".to_string(),
1070+
Res::Err => "this type".to_string(),
10711071
_ => segment.res.descr().to_string(),
10721072
},
10731073
segment.ident.span,
@@ -1426,7 +1426,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
14261426
},
14271427
SelfTyParam(Span),
14281428
Param(DefId),
1429-
DefVariant,
1429+
DefVariant(&'tcx [hir::PathSegment<'tcx>]),
14301430
None,
14311431
}
14321432

@@ -1522,6 +1522,29 @@ fn generics_args_err_extend<'a>(
15221522
];
15231523
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
15241524
}
1525+
GenericsArgsErrExtend::DefVariant(segments) => {
1526+
let args: Vec<Span> = segments
1527+
.iter()
1528+
.filter_map(|segment| match segment.res {
1529+
Res::Def(
1530+
DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1531+
_,
1532+
) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1533+
_ => None,
1534+
})
1535+
.collect();
1536+
if args.len() > 1 {
1537+
let msg = "generic arguments are not allowed on both an enum and its variant's \
1538+
path segments simultaneously; they are only valid in one place or the \
1539+
other";
1540+
err.note(msg);
1541+
err.multipart_suggestions(
1542+
"remove the generics arguments from one of the path segments",
1543+
args.into_iter().map(|span| vec![(span, String::new())]),
1544+
Applicability::MaybeIncorrect,
1545+
);
1546+
}
1547+
}
15251548
GenericsArgsErrExtend::PrimTy(prim_ty) => {
15261549
let name = prim_ty.name_str();
15271550
for segment in segments {
@@ -1538,9 +1561,6 @@ fn generics_args_err_extend<'a>(
15381561
GenericsArgsErrExtend::OpaqueTy => {
15391562
err.note("`impl Trait` types can't have type parameters");
15401563
}
1541-
GenericsArgsErrExtend::DefVariant => {
1542-
err.note("enum variants can't have type parameters");
1543-
}
15441564
GenericsArgsErrExtend::Param(def_id) => {
15451565
let span = tcx.def_ident_span(def_id).unwrap();
15461566
let kind = tcx.def_descr(def_id);

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1913,7 +1913,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19131913
path.segments.iter().enumerate().filter_map(|(index, seg)| {
19141914
if !indices.contains(&index) { Some(seg) } else { None }
19151915
}),
1916-
GenericsArgsErrExtend::DefVariant,
1916+
GenericsArgsErrExtend::DefVariant(&path.segments),
19171917
);
19181918

19191919
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1031,12 +1031,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10311031

10321032
let mut user_self_ty = None;
10331033
let mut is_alias_variant_ctor = false;
1034+
let mut err_extend = GenericsArgsErrExtend::None;
10341035
match res {
10351036
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => {
10361037
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
10371038
user_self_ty =
10381039
Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
10391040
is_alias_variant_ctor = true;
1041+
err_extend = GenericsArgsErrExtend::DefVariant(segments);
1042+
}
1043+
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
1044+
err_extend = GenericsArgsErrExtend::DefVariant(segments);
10401045
}
10411046
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
10421047
let assoc_item = tcx.associated_item(def_id);
@@ -1083,7 +1088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10831088
segments.iter().enumerate().filter_map(|(index, seg)| {
10841089
if !indices.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None }
10851090
}),
1086-
GenericsArgsErrExtend::None,
1091+
err_extend,
10871092
);
10881093

10891094
if let Res::Local(hid) = res {

tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr

+29-1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,16 @@ LL | Enum::<()>::TSVariant::<()>(());
279279
| --------- ^^ type argument not allowed
280280
| |
281281
| not allowed on tuple variant `TSVariant`
282+
|
283+
= 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
284+
help: remove the generics arguments from one of the path segments
285+
|
286+
LL - Enum::<()>::TSVariant::<()>(());
287+
LL + Enum::TSVariant::<()>(());
288+
|
289+
LL - Enum::<()>::TSVariant::<()>(());
290+
LL + Enum::<()>::TSVariant(());
291+
|
282292

283293
error[E0109]: type arguments are not allowed on this type
284294
--> $DIR/enum-variant-generic-args.rs:57:24
@@ -348,7 +358,15 @@ LL | Enum::<()>::SVariant::<()> { v: () };
348358
| |
349359
| not allowed on variant `SVariant`
350360
|
351-
= note: enum variants can't have type parameters
361+
= 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
362+
help: remove the generics arguments from one of the path segments
363+
|
364+
LL - Enum::<()>::SVariant::<()> { v: () };
365+
LL + Enum::SVariant::<()> { v: () };
366+
|
367+
LL - Enum::<()>::SVariant::<()> { v: () };
368+
LL + Enum::<()>::SVariant { v: () };
369+
|
352370

353371
error[E0109]: type arguments are not allowed on this type
354372
--> $DIR/enum-variant-generic-args.rs:75:23
@@ -445,6 +463,16 @@ LL | Enum::<()>::UVariant::<()>;
445463
| -------- ^^ type argument not allowed
446464
| |
447465
| not allowed on unit variant `UVariant`
466+
|
467+
= 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
468+
help: remove the generics arguments from one of the path segments
469+
|
470+
LL - Enum::<()>::UVariant::<()>;
471+
LL + Enum::UVariant::<()>;
472+
|
473+
LL - Enum::<()>::UVariant::<()>;
474+
LL + Enum::<()>::UVariant;
475+
|
448476

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

0 commit comments

Comments
 (0)