@@ -1625,7 +1625,7 @@ pub(crate) fn fn_trait_to_string(
1625
1625
}
1626
1626
}
1627
1627
1628
- /// Used for generics args error extend .
1628
+ /// Extra information for diagnostics of generics args error.
1629
1629
pub enum GenericsArgsErrExtend < ' tcx > {
1630
1630
EnumVariant {
1631
1631
qself : & ' tcx hir:: Ty < ' tcx > ,
@@ -1652,87 +1652,65 @@ fn generics_args_err_extend<'a>(
1652
1652
) {
1653
1653
match err_extend {
1654
1654
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" ) ;
1656
1656
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 {
1662
1658
return ;
1663
1659
} ;
1664
1660
// Get the span of the generics args *including* the leading `::`.
1665
1661
// We do so by stretching args.span_ext to the left by 2. Earlier
1666
1662
// it was done based on the end of assoc segment but that sometimes
1667
1663
// 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 ) ) ;
1669
1666
if tcx. generics_of ( adt_def. did ( ) ) . is_empty ( ) {
1670
1667
// FIXME(estebank): we could also verify that the arguments being
1671
1668
// work for the `enum`, instead of just looking if it takes *any*.
1672
1669
err. span_suggestion_verbose (
1673
- args_span ,
1670
+ variant_args_span ,
1674
1671
format ! ( "{type_name} doesn't have generic parameters" ) ,
1675
1672
"" ,
1676
1673
Applicability :: MachineApplicable ,
1677
1674
) ;
1678
1675
return ;
1679
1676
}
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 {
1681
1696
err. note ( msg) ;
1682
1697
return ;
1683
1698
} ;
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
- } ;
1726
1699
let suggestion = vec ! [
1727
- if is_self {
1700
+ if path . segments . len ( ) == 1 && kw :: SelfUpper == ident . name {
1728
1701
// Account for people writing `Self::Variant::<Args>`, where
1729
1702
// `Self` is the enum, and suggest replacing `Self` with the
1730
1703
// appropriate type: `Type::<Args>::Variant`.
1731
1704
( qself. span, format!( "{type_name}{snippet}" ) )
1732
1705
} 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)
1734
1712
} ,
1735
- ( args_span , String :: new( ) ) ,
1713
+ ( variant_args_span , String :: new( ) ) ,
1736
1714
] ;
1737
1715
err. multipart_suggestion_verbose ( msg, suggestion, Applicability :: MaybeIncorrect ) ;
1738
1716
}
0 commit comments