@@ -6,7 +6,7 @@ use rustc_errors::{
6
6
Applicability , Diag , ErrorGuaranteed , MultiSpan , listify, pluralize, struct_span_code_err,
7
7
} ;
8
8
use rustc_hir as hir;
9
- use rustc_hir:: def:: { DefKind , Res } ;
9
+ use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
10
10
use rustc_hir:: def_id:: DefId ;
11
11
use rustc_middle:: bug;
12
12
use rustc_middle:: ty:: fast_reject:: { TreatParams , simplify_type} ;
@@ -1027,7 +1027,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1027
1027
& self ,
1028
1028
segments : impl Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone ,
1029
1029
args_visitors : impl Iterator < Item = & ' a hir:: GenericArg < ' a > > + Clone ,
1030
- err_extend : GenericsArgsErrExtend < ' _ > ,
1030
+ err_extend : GenericsArgsErrExtend < ' a > ,
1031
1031
) -> ErrorGuaranteed {
1032
1032
#[ derive( PartialEq , Eq , Hash ) ]
1033
1033
enum ProhibitGenericsArg {
@@ -1047,23 +1047,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1047
1047
} ;
1048
1048
} ) ;
1049
1049
1050
+ let segments: Vec < _ > = segments. collect ( ) ;
1050
1051
let types_and_spans: Vec < _ > = segments
1051
- . clone ( )
1052
+ . iter ( )
1052
1053
. flat_map ( |segment| {
1053
1054
if segment. args ( ) . args . is_empty ( ) {
1054
1055
None
1055
1056
} else {
1056
1057
Some ( (
1057
1058
match segment. res {
1058
- hir :: def :: Res :: PrimTy ( ty) => {
1059
+ Res :: PrimTy ( ty) => {
1059
1060
format ! ( "{} `{}`" , segment. res. descr( ) , ty. name( ) )
1060
1061
}
1061
- hir :: def :: Res :: Def ( _, def_id)
1062
+ Res :: Def ( _, def_id)
1062
1063
if let Some ( name) = self . tcx ( ) . opt_item_name ( def_id) =>
1063
1064
{
1064
1065
format ! ( "{} `{name}`" , segment. res. descr( ) )
1065
1066
}
1066
- hir :: def :: Res :: Err => "this type" . to_string ( ) ,
1067
+ Res :: Err => "this type" . to_string ( ) ,
1067
1068
_ => segment. res . descr ( ) . to_string ( ) ,
1068
1069
} ,
1069
1070
segment. ident . span ,
@@ -1074,11 +1075,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1074
1075
let this_type = listify ( & types_and_spans, |( t, _) | t. to_string ( ) )
1075
1076
. expect ( "expected one segment to deny" ) ;
1076
1077
1077
- let arg_spans: Vec < Span > = segments
1078
- . clone ( )
1079
- . flat_map ( |segment| segment. args ( ) . args )
1080
- . map ( |arg| arg. span ( ) )
1081
- . collect ( ) ;
1078
+ let arg_spans: Vec < Span > =
1079
+ segments. iter ( ) . flat_map ( |segment| segment. args ( ) . args ) . map ( |arg| arg. span ( ) ) . collect ( ) ;
1082
1080
1083
1081
let mut kinds = Vec :: with_capacity ( 4 ) ;
1084
1082
prohibit_args. iter ( ) . for_each ( |arg| match arg {
@@ -1103,7 +1101,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1103
1101
for ( what, span) in types_and_spans {
1104
1102
err. span_label ( span, format ! ( "not allowed on {what}" ) ) ;
1105
1103
}
1106
- generics_args_err_extend ( self . tcx ( ) , segments, & mut err, err_extend) ;
1104
+ generics_args_err_extend ( self . tcx ( ) , segments. into_iter ( ) , & mut err, err_extend) ;
1107
1105
err. emit ( )
1108
1106
}
1109
1107
@@ -1400,15 +1398,15 @@ pub enum GenericsArgsErrExtend<'tcx> {
1400
1398
} ,
1401
1399
SelfTyParam ( Span ) ,
1402
1400
Param ( DefId ) ,
1403
- DefVariant ,
1401
+ DefVariant ( & ' tcx [ hir :: PathSegment < ' tcx > ] ) ,
1404
1402
None ,
1405
1403
}
1406
1404
1407
1405
fn generics_args_err_extend < ' a > (
1408
1406
tcx : TyCtxt < ' _ > ,
1409
1407
segments : impl Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone ,
1410
1408
err : & mut Diag < ' _ > ,
1411
- err_extend : GenericsArgsErrExtend < ' _ > ,
1409
+ err_extend : GenericsArgsErrExtend < ' a > ,
1412
1410
) {
1413
1411
match err_extend {
1414
1412
GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } => {
@@ -1496,6 +1494,32 @@ fn generics_args_err_extend<'a>(
1496
1494
] ;
1497
1495
err. multipart_suggestion_verbose ( msg, suggestion, Applicability :: MaybeIncorrect ) ;
1498
1496
}
1497
+ GenericsArgsErrExtend :: DefVariant ( segments) => {
1498
+ let args: Vec < Span > = segments
1499
+ . iter ( )
1500
+ . filter_map ( |segment| match segment. res {
1501
+ Res :: Def (
1502
+ DefKind :: Ctor ( CtorOf :: Variant , _) | DefKind :: Variant | DefKind :: Enum ,
1503
+ _,
1504
+ ) => segment. args ( ) . span_ext ( ) . map ( |s| s. with_lo ( segment. ident . span . hi ( ) ) ) ,
1505
+ _ => None ,
1506
+ } )
1507
+ . collect ( ) ;
1508
+ if args. len ( ) > 1
1509
+ && let Some ( span) = args. into_iter ( ) . last ( )
1510
+ {
1511
+ err. note (
1512
+ "generic arguments are not allowed on both an enum and its variant's path \
1513
+ segments simultaneously; they are only valid in one place or the other",
1514
+ ) ;
1515
+ err. span_suggestion_verbose (
1516
+ span,
1517
+ "remove the generics arguments from one of the path segments" ,
1518
+ String :: new ( ) ,
1519
+ Applicability :: MaybeIncorrect ,
1520
+ ) ;
1521
+ }
1522
+ }
1499
1523
GenericsArgsErrExtend :: PrimTy ( prim_ty) => {
1500
1524
let name = prim_ty. name_str ( ) ;
1501
1525
for segment in segments {
@@ -1512,9 +1536,6 @@ fn generics_args_err_extend<'a>(
1512
1536
GenericsArgsErrExtend :: OpaqueTy => {
1513
1537
err. note ( "`impl Trait` types can't have type parameters" ) ;
1514
1538
}
1515
- GenericsArgsErrExtend :: DefVariant => {
1516
- err. note ( "enum variants can't have type parameters" ) ;
1517
- }
1518
1539
GenericsArgsErrExtend :: Param ( def_id) => {
1519
1540
let span = tcx. def_ident_span ( def_id) . unwrap ( ) ;
1520
1541
let kind = tcx. def_descr ( def_id) ;
0 commit comments