@@ -1625,7 +1625,7 @@ pub(crate) fn fn_trait_to_string(
16251625 }
16261626}
16271627
1628- /// Used for generics args error extend .
1628+ /// Extra information for diagnostics of generics args error.
16291629pub enum GenericsArgsErrExtend < ' tcx > {
16301630 EnumVariant {
16311631 qself : & ' tcx hir:: Ty < ' tcx > ,
@@ -1652,87 +1652,65 @@ fn generics_args_err_extend<'a>(
16521652) {
16531653 match err_extend {
16541654 GenericsArgsErrExtend :: EnumVariant { qself, assoc_segment, adt_def } => {
1655- err. note ( "enum variants can't have type parameters" ) ;
1655+ err. note ( "variants of type-aliased enum can't have type parameters" ) ;
16561656 let type_name = tcx. item_name ( adt_def. did ( ) ) ;
1657- let msg = format ! (
1658- "you might have meant to specify type parameters on enum \
1659- `{type_name}`"
1660- ) ;
1661- let Some ( args) = assoc_segment. args else {
1657+ let Some ( variant_args) = assoc_segment. args else {
16621658 return ;
16631659 } ;
16641660 // Get the span of the generics args *including* the leading `::`.
16651661 // We do so by stretching args.span_ext to the left by 2. Earlier
16661662 // it was done based on the end of assoc segment but that sometimes
16671663 // led to impossible spans and caused issues like #116473
1668- let args_span = args. span_ext . with_lo ( args. span_ext . lo ( ) - BytePos ( 2 ) ) ;
1664+ let variant_args_span =
1665+ variant_args. span_ext . with_lo ( variant_args. span_ext . lo ( ) - BytePos ( 2 ) ) ;
16691666 if tcx. generics_of ( adt_def. did ( ) ) . is_empty ( ) {
16701667 // FIXME(estebank): we could also verify that the arguments being
16711668 // work for the `enum`, instead of just looking if it takes *any*.
16721669 err. span_suggestion_verbose (
1673- args_span ,
1670+ variant_args_span ,
16741671 format ! ( "{type_name} doesn't have generic parameters" ) ,
16751672 "" ,
16761673 Applicability :: MachineApplicable ,
16771674 ) ;
16781675 return ;
16791676 }
1680- let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( args_span) else {
1677+ let msg = "you might have meant to specify type parameters on the enum" ;
1678+ let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( variant_args_span) else {
1679+ err. note ( msg) ;
1680+ return ;
1681+ } ;
1682+ // If the path segment already has type params, we want to overwrite them.
1683+ let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind else {
1684+ err. note ( msg) ;
1685+ return ;
1686+ } ;
1687+ // The last element of `path.segments` is the previous to last element
1688+ // on the path and would normally be the enum alias itself.
1689+ let Some ( hir:: PathSegment {
1690+ ident,
1691+ args : enum_args,
1692+ res : Res :: SelfTyAlias { .. } | Res :: Def ( DefKind :: TyAlias , _) ,
1693+ ..
1694+ } ) = & path. segments . last ( )
1695+ else {
16811696 err. note ( msg) ;
16821697 return ;
16831698 } ;
1684- let ( qself_sugg_span, is_self) =
1685- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & qself. kind {
1686- // If the path segment already has type params, we want to overwrite
1687- // them.
1688- match & path. segments {
1689- // `segment` is the previous to last element on the path,
1690- // which would normally be the `enum` itself, while the last
1691- // `_` `PathSegment` corresponds to the variant.
1692- [
1693- ..,
1694- hir:: PathSegment {
1695- ident, args, res : Res :: Def ( DefKind :: Enum , _) , ..
1696- } ,
1697- _,
1698- ] => (
1699- // We need to include the `::` in `Type::Variant::<Args>`
1700- // to point the span to `::<Args>`, not just `<Args>`.
1701- ident
1702- . span
1703- . shrink_to_hi ( )
1704- . to ( args. map_or ( ident. span . shrink_to_hi ( ) , |a| a. span_ext ) ) ,
1705- false ,
1706- ) ,
1707- [ segment] => {
1708- (
1709- // We need to include the `::` in `Type::Variant::<Args>`
1710- // to point the span to `::<Args>`, not just `<Args>`.
1711- segment. ident . span . shrink_to_hi ( ) . to ( segment
1712- . args
1713- . map_or ( segment. ident . span . shrink_to_hi ( ) , |a| a. span_ext ) ) ,
1714- kw:: SelfUpper == segment. ident . name ,
1715- )
1716- }
1717- _ => {
1718- err. note ( msg) ;
1719- return ;
1720- }
1721- }
1722- } else {
1723- err. note ( msg) ;
1724- return ;
1725- } ;
17261699 let suggestion = vec ! [
1727- if is_self {
1700+ if path . segments . len ( ) == 1 && kw :: SelfUpper == ident . name {
17281701 // Account for people writing `Self::Variant::<Args>`, where
17291702 // `Self` is the enum, and suggest replacing `Self` with the
17301703 // appropriate type: `Type::<Args>::Variant`.
17311704 ( qself. span, format!( "{type_name}{snippet}" ) )
17321705 } else {
1733- ( qself_sugg_span, snippet)
1706+ // We need to include the `::` in `Type::<Args>::Variants`
1707+ // to point the span to `::<Args>`, not just `<Args>`.
1708+ let enum_args_span = ident. span. shrink_to_hi( ) . to( enum_args
1709+ . and_then( |a| a. span_ext( ) )
1710+ . unwrap_or( ident. span. shrink_to_hi( ) ) ) ;
1711+ ( enum_args_span, snippet)
17341712 } ,
1735- ( args_span , String :: new( ) ) ,
1713+ ( variant_args_span , String :: new( ) ) ,
17361714 ] ;
17371715 err. multipart_suggestion_verbose ( msg, suggestion, Applicability :: MaybeIncorrect ) ;
17381716 }
0 commit comments