Skip to content

Commit ad95c62

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 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.
1 parent 534d79a commit ad95c62

File tree

6 files changed

+94
-42
lines changed

6 files changed

+94
-42
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

+41-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{
66
Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, 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};
@@ -1027,7 +1027,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10271027
&self,
10281028
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
10291029
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1030-
err_extend: GenericsArgsErrExtend<'_>,
1030+
err_extend: GenericsArgsErrExtend<'a>,
10311031
) -> ErrorGuaranteed {
10321032
#[derive(PartialEq, Eq, Hash)]
10331033
enum ProhibitGenericsArg {
@@ -1047,23 +1047,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10471047
};
10481048
});
10491049

1050+
let segments: Vec<_> = match err_extend {
1051+
GenericsArgsErrExtend::DefVariant(segments) => segments.iter().collect(),
1052+
_ => segments.collect(),
1053+
};
10501054
let types_and_spans: Vec<_> = segments
1051-
.clone()
1055+
.iter()
10521056
.flat_map(|segment| {
10531057
if segment.args().args.is_empty() {
10541058
None
10551059
} else {
10561060
Some((
10571061
match segment.res {
1058-
hir::def::Res::PrimTy(ty) => {
1062+
Res::PrimTy(ty) => {
10591063
format!("{} `{}`", segment.res.descr(), ty.name())
10601064
}
1061-
hir::def::Res::Def(_, def_id)
1065+
Res::Def(_, def_id)
10621066
if let Some(name) = self.tcx().opt_item_name(def_id) =>
10631067
{
10641068
format!("{} `{name}`", segment.res.descr())
10651069
}
1066-
hir::def::Res::Err => "this type".to_string(),
1070+
Res::Err => "this type".to_string(),
10671071
_ => segment.res.descr().to_string(),
10681072
},
10691073
segment.ident.span,
@@ -1074,11 +1078,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10741078
let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
10751079
.expect("expected one segment to deny");
10761080

1077-
let arg_spans: Vec<Span> = segments
1078-
.clone()
1079-
.flat_map(|segment| segment.args().args)
1080-
.map(|arg| arg.span())
1081-
.collect();
1081+
let arg_spans: Vec<Span> =
1082+
segments.iter().flat_map(|segment| segment.args().args).map(|arg| arg.span()).collect();
10821083

10831084
let mut kinds = Vec::with_capacity(4);
10841085
prohibit_args.iter().for_each(|arg| match arg {
@@ -1103,7 +1104,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11031104
for (what, span) in types_and_spans {
11041105
err.span_label(span, format!("not allowed on {what}"));
11051106
}
1106-
generics_args_err_extend(self.tcx(), segments, &mut err, err_extend);
1107+
generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend);
11071108
err.emit()
11081109
}
11091110

@@ -1400,15 +1401,15 @@ pub enum GenericsArgsErrExtend<'tcx> {
14001401
},
14011402
SelfTyParam(Span),
14021403
Param(DefId),
1403-
DefVariant,
1404+
DefVariant(&'tcx [hir::PathSegment<'tcx>]),
14041405
None,
14051406
}
14061407

14071408
fn generics_args_err_extend<'a>(
14081409
tcx: TyCtxt<'_>,
14091410
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
14101411
err: &mut Diag<'_>,
1411-
err_extend: GenericsArgsErrExtend<'_>,
1412+
err_extend: GenericsArgsErrExtend<'a>,
14121413
) {
14131414
match err_extend {
14141415
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def } => {
@@ -1496,6 +1497,32 @@ fn generics_args_err_extend<'a>(
14961497
];
14971498
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MaybeIncorrect);
14981499
}
1500+
GenericsArgsErrExtend::DefVariant(segments) => {
1501+
let args: Vec<Span> = segments
1502+
.iter()
1503+
.filter_map(|segment| match segment.res {
1504+
Res::Def(
1505+
DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant | DefKind::Enum,
1506+
_,
1507+
) => segment.args().span_ext().map(|s| s.with_lo(segment.ident.span.hi())),
1508+
_ => None,
1509+
})
1510+
.collect();
1511+
if args.len() > 1
1512+
&& let Some(span) = args.into_iter().last()
1513+
{
1514+
let msg = "generic arguments are not allowed on both an enum and its variant's \
1515+
path segments simultaneously; they are only valid in one place or the \
1516+
other";
1517+
err.note(msg);
1518+
err.span_suggestion_verbose(
1519+
span,
1520+
"remove the generics arguments from one of the path segments",
1521+
String::new(),
1522+
Applicability::MaybeIncorrect,
1523+
);
1524+
}
1525+
}
14991526
GenericsArgsErrExtend::PrimTy(prim_ty) => {
15001527
let name = prim_ty.name_str();
15011528
for segment in segments {
@@ -1512,9 +1539,6 @@ fn generics_args_err_extend<'a>(
15121539
GenericsArgsErrExtend::OpaqueTy => {
15131540
err.note("`impl Trait` types can't have type parameters");
15141541
}
1515-
GenericsArgsErrExtend::DefVariant => {
1516-
err.note("enum variants can't have type parameters");
1517-
}
15181542
GenericsArgsErrExtend::Param(def_id) => {
15191543
let span = tcx.def_ident_span(def_id).unwrap();
15201544
let kind = tcx.def_descr(def_id);

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16941694
pub fn prohibit_generic_args<'a>(
16951695
&self,
16961696
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1697-
err_extend: GenericsArgsErrExtend<'_>,
1697+
err_extend: GenericsArgsErrExtend<'a>,
16981698
) -> Result<(), ErrorGuaranteed> {
16991699
let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
17001700
let mut result = Ok(());
@@ -1911,7 +1911,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19111911
path.segments.iter().enumerate().filter_map(|(index, seg)| {
19121912
if !indices.contains(&index) { Some(seg) } else { None }
19131913
}),
1914-
GenericsArgsErrExtend::DefVariant,
1914+
GenericsArgsErrExtend::DefVariant(&path.segments),
19151915
);
19161916

19171917
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
@@ -1035,12 +1035,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10351035

10361036
let mut user_self_ty = None;
10371037
let mut is_alias_variant_ctor = false;
1038+
let mut err_extend = GenericsArgsErrExtend::None;
10381039
match res {
10391040
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) if let Some(self_ty) = self_ty => {
10401041
let adt_def = self_ty.normalized.ty_adt_def().unwrap();
10411042
user_self_ty =
10421043
Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
10431044
is_alias_variant_ctor = true;
1045+
err_extend = GenericsArgsErrExtend::DefVariant(segments);
1046+
}
1047+
Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
1048+
err_extend = GenericsArgsErrExtend::DefVariant(segments);
10441049
}
10451050
Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
10461051
let assoc_item = tcx.associated_item(def_id);
@@ -1087,7 +1092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10871092
segments.iter().enumerate().filter_map(|(index, seg)| {
10881093
if !indices.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None }
10891094
}),
1090-
GenericsArgsErrExtend::None,
1095+
err_extend,
10911096
);
10921097

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

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn main() {
5252
// Tuple struct variant
5353

5454
Enum::<()>::TSVariant::<()>(());
55-
//~^ ERROR type arguments are not allowed on tuple variant `TSVariant` [E0109]
55+
//~^ ERROR type arguments are not allowed on enum `Enum` and tuple variant `TSVariant` [E0109]
5656

5757
Alias::TSVariant::<()>(());
5858
//~^ ERROR type arguments are not allowed on this type [E0109]
@@ -70,7 +70,7 @@ fn main() {
7070
// Struct variant
7171

7272
Enum::<()>::SVariant::<()> { v: () };
73-
//~^ ERROR type arguments are not allowed on variant `SVariant` [E0109]
73+
//~^ ERROR type arguments are not allowed on enum `Enum` and variant `SVariant` [E0109]
7474

7575
Alias::SVariant::<()> { v: () };
7676
//~^ ERROR type arguments are not allowed on this type [E0109]
@@ -88,7 +88,7 @@ fn main() {
8888
// Unit variant
8989

9090
Enum::<()>::UVariant::<()>;
91-
//~^ ERROR type arguments are not allowed on unit variant `UVariant` [E0109]
91+
//~^ ERROR type arguments are not allowed on enum `Enum` and unit variant `UVariant` [E0109]
9292

9393
Alias::UVariant::<()>;
9494
//~^ ERROR type arguments are not allowed on this type [E0109]

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

+38-16
Original file line numberDiff line numberDiff line change
@@ -272,13 +272,21 @@ LL | Self::<()>::UVariant::<()>;
272272
| |
273273
| not allowed on this type
274274

275-
error[E0109]: type arguments are not allowed on tuple variant `TSVariant`
276-
--> $DIR/enum-variant-generic-args.rs:54:29
275+
error[E0109]: type arguments are not allowed on enum `Enum` and tuple variant `TSVariant`
276+
--> $DIR/enum-variant-generic-args.rs:54:12
277277
|
278278
LL | Enum::<()>::TSVariant::<()>(());
279-
| --------- ^^ type argument not allowed
280-
| |
281-
| not allowed on tuple variant `TSVariant`
279+
| ---- ^^ --------- ^^ type argument not allowed
280+
| | |
281+
| | not allowed on tuple variant `TSVariant`
282+
| not allowed on enum `Enum`
283+
|
284+
= 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
285+
help: remove the generics arguments from one of the path segments
286+
|
287+
LL - Enum::<()>::TSVariant::<()>(());
288+
LL + Enum::<()>::TSVariant(());
289+
|
282290

283291
error[E0109]: type arguments are not allowed on this type
284292
--> $DIR/enum-variant-generic-args.rs:57:24
@@ -340,15 +348,21 @@ LL | AliasFixed::<()>::TSVariant::<()>(());
340348
| |
341349
| not allowed on this type
342350

343-
error[E0109]: type arguments are not allowed on variant `SVariant`
344-
--> $DIR/enum-variant-generic-args.rs:72:28
351+
error[E0109]: type arguments are not allowed on enum `Enum` and variant `SVariant`
352+
--> $DIR/enum-variant-generic-args.rs:72:12
345353
|
346354
LL | Enum::<()>::SVariant::<()> { v: () };
347-
| -------- ^^ type argument not allowed
348-
| |
349-
| not allowed on variant `SVariant`
355+
| ---- ^^ -------- ^^ type argument not allowed
356+
| | |
357+
| | not allowed on variant `SVariant`
358+
| not allowed on enum `Enum`
359+
|
360+
= 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
361+
help: remove the generics arguments from one of the path segments
362+
|
363+
LL - Enum::<()>::SVariant::<()> { v: () };
364+
LL + Enum::<()>::SVariant { v: () };
350365
|
351-
= note: enum variants can't have type parameters
352366

353367
error[E0109]: type arguments are not allowed on this type
354368
--> $DIR/enum-variant-generic-args.rs:75:23
@@ -438,13 +452,21 @@ LL - AliasFixed::<()>::SVariant::<()> { v: () };
438452
LL + AliasFixed::<()>::SVariant { v: () };
439453
|
440454

441-
error[E0109]: type arguments are not allowed on unit variant `UVariant`
442-
--> $DIR/enum-variant-generic-args.rs:90:28
455+
error[E0109]: type arguments are not allowed on enum `Enum` and unit variant `UVariant`
456+
--> $DIR/enum-variant-generic-args.rs:90:12
443457
|
444458
LL | Enum::<()>::UVariant::<()>;
445-
| -------- ^^ type argument not allowed
446-
| |
447-
| not allowed on unit variant `UVariant`
459+
| ---- ^^ -------- ^^ type argument not allowed
460+
| | |
461+
| | not allowed on unit variant `UVariant`
462+
| not allowed on enum `Enum`
463+
|
464+
= 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
465+
help: remove the generics arguments from one of the path segments
466+
|
467+
LL - Enum::<()>::UVariant::<()>;
468+
LL + Enum::<()>::UVariant;
469+
|
448470

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

0 commit comments

Comments
 (0)