@@ -21,7 +21,7 @@ use hir::map::Map;
21
21
use hir:: { GenericArg , GenericParam , ItemLocalId , LifetimeName , ParamName } ;
22
22
use ty:: { self , TyCtxt , GenericParamDefKind } ;
23
23
24
- use errors:: DiagnosticBuilder ;
24
+ use errors:: { Applicability , DiagnosticBuilder } ;
25
25
use rustc:: lint;
26
26
use rustc_data_structures:: sync:: Lrc ;
27
27
use session:: Session ;
@@ -609,7 +609,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
609
609
// resolved the same as the `'_` in `&'_ Foo`.
610
610
//
611
611
// cc #48468
612
- self . resolve_elided_lifetimes ( vec ! [ lifetime] , false )
612
+ self . resolve_elided_lifetimes ( vec ! [ lifetime] )
613
613
}
614
614
LifetimeName :: Param ( _) | LifetimeName :: Static => {
615
615
// If the user wrote an explicit name, use that.
@@ -855,7 +855,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
855
855
856
856
fn visit_lifetime ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
857
857
if lifetime_ref. is_elided ( ) {
858
- self . resolve_elided_lifetimes ( vec ! [ lifetime_ref] , false ) ;
858
+ self . resolve_elided_lifetimes ( vec ! [ lifetime_ref] ) ;
859
859
return ;
860
860
}
861
861
if lifetime_ref. is_static ( ) {
@@ -866,10 +866,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
866
866
}
867
867
868
868
fn visit_path ( & mut self , path : & ' tcx hir:: Path , _: ast:: NodeId ) {
869
- for ( i, segment) in path. segments . iter ( ) . enumerate ( ) {
869
+ for ( i, ref segment) in path. segments . iter ( ) . enumerate ( ) {
870
870
let depth = path. segments . len ( ) - i - 1 ;
871
871
if let Some ( ref args) = segment. args {
872
- self . visit_segment_args ( path. def , depth, args) ;
872
+ self . visit_segment_args ( path. def , depth, segment . ident , args) ;
873
873
}
874
874
}
875
875
}
@@ -1667,6 +1667,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1667
1667
& mut self ,
1668
1668
def : Def ,
1669
1669
depth : usize ,
1670
+ segment_ident : ast:: Ident ,
1670
1671
generic_args : & ' tcx hir:: GenericArgs ,
1671
1672
) {
1672
1673
if generic_args. parenthesized {
@@ -1687,9 +1688,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1687
1688
Some ( lt)
1688
1689
}
1689
1690
_ => None ,
1690
- } ) . collect ( ) ;
1691
+ } ) . collect :: < Vec < _ > > ( ) ;
1691
1692
if elide_lifetimes {
1692
- self . resolve_elided_lifetimes ( lifetimes, true ) ;
1693
+ self . lint_implicit_lifetimes_in_segment (
1694
+ segment_ident, generic_args, & lifetimes
1695
+ ) ;
1696
+ self . resolve_elided_lifetimes ( lifetimes) ;
1693
1697
} else {
1694
1698
lifetimes. iter ( ) . for_each ( |lt| self . visit_lifetime ( lt) ) ;
1695
1699
}
@@ -2066,27 +2070,80 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2066
2070
}
2067
2071
}
2068
2072
2073
+ fn lint_implicit_lifetimes_in_segment ( & mut self ,
2074
+ segment_ident : ast:: Ident ,
2075
+ generic_args : & ' tcx hir:: GenericArgs ,
2076
+ lifetime_refs : & [ & ' tcx hir:: Lifetime ] ) {
2077
+ let num_implicit_lifetimes = lifetime_refs. iter ( )
2078
+ . filter ( |lt| lt. name . is_implicit ( ) ) . count ( ) ;
2079
+ if num_implicit_lifetimes == 0 {
2080
+ return ;
2081
+ }
2082
+
2083
+ let mut err = self . tcx . struct_span_lint_node (
2084
+ lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS ,
2085
+ lifetime_refs[ 0 ] . id , // FIXME: HirIdify #50928
2086
+ segment_ident. span ,
2087
+ & format ! ( "implicit lifetime parameters in types are deprecated" ) ,
2088
+ ) ;
2089
+
2090
+ if num_implicit_lifetimes == 1 {
2091
+ let ( replace_span,
2092
+ suggestion) = if generic_args. args . len ( ) == num_implicit_lifetimes &&
2093
+ generic_args. bindings . is_empty ( ) {
2094
+ // If there are no (non-implicit) generic args or bindings, our
2095
+ // suggestion includes the angle brackets
2096
+ ( segment_ident. span . shrink_to_hi ( ) , "<'_>" )
2097
+ } else {
2098
+ // Otherwise—sorry, this is kind of gross—we need to infer the
2099
+ // replacement point span from the generics that do exist
2100
+ let mut first_generic_span = None ;
2101
+ for ref arg in & generic_args. args {
2102
+ match arg {
2103
+ hir:: GenericArg :: Lifetime ( lt) => {
2104
+ // Really, this branch shouldn't happen—you can't elide only
2105
+ // some lifetimes—but the responsibility for catching that
2106
+ // error lives elsewhere
2107
+ if !lt. name . is_implicit ( ) {
2108
+ first_generic_span = Some ( lt. span ) ;
2109
+ break ;
2110
+ }
2111
+ } ,
2112
+ hir:: GenericArg :: Type ( ty) => {
2113
+ first_generic_span = Some ( ty. span ) ;
2114
+ break ;
2115
+ }
2116
+ }
2117
+ }
2118
+ if let None = first_generic_span {
2119
+ for ref binding in & generic_args. bindings {
2120
+ first_generic_span = Some ( binding. span ) ;
2121
+ break ;
2122
+ }
2123
+ }
2124
+ let replace_span = first_generic_span
2125
+ . expect ( "checked earlier that non-implicit args or bindings exist" ) ;
2126
+ ( replace_span. shrink_to_lo ( ) , "'_, " )
2127
+ } ;
2128
+ err. span_suggestion_with_applicability (
2129
+ replace_span,
2130
+ "indicate the anonymous lifetime" ,
2131
+ suggestion. to_owned ( ) ,
2132
+ Applicability :: MachineApplicable
2133
+ ) ;
2134
+ }
2135
+ err. emit ( ) ;
2136
+ }
2137
+
2069
2138
fn resolve_elided_lifetimes ( & mut self ,
2070
- lifetime_refs : Vec < & ' tcx hir:: Lifetime > ,
2071
- deprecate_implicit : bool ) {
2139
+ lifetime_refs : Vec < & ' tcx hir:: Lifetime > ) {
2072
2140
if lifetime_refs. is_empty ( ) {
2073
2141
return ;
2074
2142
}
2075
2143
2076
2144
let span = lifetime_refs[ 0 ] . span ;
2077
2145
let mut late_depth = 0 ;
2078
2146
let mut scope = self . scope ;
2079
- if deprecate_implicit && lifetime_refs[ 0 ] . name . is_implicit ( ) {
2080
- let mut err = self . tcx . struct_span_lint_node (
2081
- lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS ,
2082
- lifetime_refs[ 0 ] . id , // FIXME: HirIdify #50928
2083
- span,
2084
- & format ! ( "implicit lifetime parameters in types are deprecated" ) ,
2085
- ) ;
2086
- // FIXME: suggest `'_` (need to take into account whether angle-bracketed
2087
- // params already exist)
2088
- err. emit ( ) ;
2089
- }
2090
2147
let error = loop {
2091
2148
match * scope {
2092
2149
// Do not assign any resolution, it will be inferred.
0 commit comments