@@ -646,7 +646,24 @@ struct DiagMetadata<'ast> {
646
646
}
647
647
648
648
#[ derive( Debug ) ]
649
- struct ResolvedNestedElisionTarget {
649
+ enum ResolvedElisionTarget {
650
+ /// Elision in `&u8` -> `&'_ u8`
651
+ TopLevel ( NodeId ) ,
652
+ /// Elision in `Foo` -> `Foo<'_>`
653
+ Nested ( NestedResolvedElisionTarget ) ,
654
+ }
655
+
656
+ impl ResolvedElisionTarget {
657
+ fn node_id ( & self ) -> NodeId {
658
+ match * self {
659
+ Self :: TopLevel ( n) => n,
660
+ Self :: Nested ( NestedResolvedElisionTarget { segment_id, .. } ) => segment_id,
661
+ }
662
+ }
663
+ }
664
+
665
+ #[ derive( Debug ) ]
666
+ struct NestedResolvedElisionTarget {
650
667
segment_id : NodeId ,
651
668
elided_lifetime_span : Span ,
652
669
diagnostic : lint:: BuiltinLintDiag ,
@@ -694,7 +711,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
694
711
lifetime_uses : FxHashMap < LocalDefId , LifetimeUseSet > ,
695
712
696
713
/// Track which types participated in lifetime elision
697
- resolved_lifetime_elisions : Vec < ResolvedNestedElisionTarget > ,
714
+ resolved_lifetime_elisions : Vec < ResolvedElisionTarget > ,
698
715
}
699
716
700
717
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
@@ -1742,6 +1759,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
1742
1759
LifetimeElisionCandidate :: Ignore ,
1743
1760
) ;
1744
1761
self . resolve_anonymous_lifetime ( & lt, true ) ;
1762
+
1763
+ self . resolved_lifetime_elisions . push ( ResolvedElisionTarget :: TopLevel ( anchor_id) ) ;
1745
1764
}
1746
1765
1747
1766
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -1953,16 +1972,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
1953
1972
}
1954
1973
1955
1974
if should_lint {
1956
- self . resolved_lifetime_elisions . push ( ResolvedNestedElisionTarget {
1957
- segment_id,
1958
- elided_lifetime_span,
1959
- diagnostic : lint:: BuiltinLintDiag :: ElidedLifetimesInPaths (
1960
- expected_lifetimes,
1961
- path_span,
1962
- !segment. has_generic_args ,
1975
+ self . resolved_lifetime_elisions . push ( ResolvedElisionTarget :: Nested (
1976
+ NestedResolvedElisionTarget {
1977
+ segment_id,
1963
1978
elided_lifetime_span,
1964
- ) ,
1965
- } ) ;
1979
+ diagnostic : lint:: BuiltinLintDiag :: ElidedLifetimesInPaths (
1980
+ expected_lifetimes,
1981
+ path_span,
1982
+ !segment. has_generic_args ,
1983
+ elided_lifetime_span,
1984
+ ) ,
1985
+ } ,
1986
+ ) ) ;
1966
1987
}
1967
1988
}
1968
1989
}
@@ -2024,22 +2045,80 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
2024
2045
2025
2046
let elision_failures =
2026
2047
replace ( & mut self . diag_metadata . current_elision_failures , outer_failures) ;
2027
- if !elision_failures. is_empty ( ) {
2028
- let Err ( failure_info) = elision_lifetime else { bug ! ( ) } ;
2029
- self . report_missing_lifetime_specifiers ( elision_failures, Some ( failure_info) ) ;
2030
- }
2048
+
2049
+ let elision_lifetime = match ( elision_failures. is_empty ( ) , elision_lifetime) {
2050
+ ( true , Ok ( lifetime) ) => Some ( lifetime) ,
2051
+
2052
+ ( true , Err ( _) ) => None ,
2053
+
2054
+ ( false , Ok ( _) ) => bug ! ( ) ,
2055
+
2056
+ ( false , Err ( failure_info) ) => {
2057
+ self . report_missing_lifetime_specifiers ( elision_failures, Some ( failure_info) ) ;
2058
+ None
2059
+ }
2060
+ } ;
2061
+
2062
+ // We've recorded all elisions that occurred in the params and
2063
+ // outputs, categorized by top-level or nested.
2064
+ //
2065
+ // Our primary lint case is when an output lifetime is tied to
2066
+ // an input lifetime. In that case, we want to warn about any
2067
+ // nested hidden lifetimes in those params or outputs.
2068
+ //
2069
+ // The secondary case is for nested elisions that are not part
2070
+ // of the tied lifetime relationship.
2031
2071
2032
2072
let output_resolved_lifetime_elisions =
2033
2073
replace ( & mut self . resolved_lifetime_elisions , outer_resolved_lifetime_elisions) ;
2034
2074
2035
- let resolved_lifetime_elisions =
2036
- param_resolved_lifetime_elisions. into_iter ( ) . chain ( output_resolved_lifetime_elisions) ;
2075
+ match ( output_resolved_lifetime_elisions. is_empty ( ) , elision_lifetime) {
2076
+ ( true , _) | ( _, None ) => {
2077
+ // Treat all parameters as untied
2078
+ self . report_elided_lifetimes_in_paths (
2079
+ param_resolved_lifetime_elisions,
2080
+ lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS_UNTIED ,
2081
+ ) ;
2082
+ }
2083
+ ( false , Some ( elision_lifetime) ) => {
2084
+ let ( primary, secondary) : ( Vec < _ > , Vec < _ > ) =
2085
+ param_resolved_lifetime_elisions. into_iter ( ) . partition ( |re| {
2086
+ // Recover the `NodeId` of an elided lifetime
2087
+ let lvl1 = & self . r . lifetimes_res_map [ & re. node_id ( ) ] ;
2088
+ let lvl2 = match lvl1 {
2089
+ LifetimeRes :: ElidedAnchor { start, .. } => {
2090
+ & self . r . lifetimes_res_map [ & start]
2091
+ }
2092
+ o => o,
2093
+ } ;
2094
+
2095
+ lvl2 == & elision_lifetime
2096
+ } ) ;
2097
+
2098
+ self . report_elided_lifetimes_in_paths (
2099
+ primary. into_iter ( ) . chain ( output_resolved_lifetime_elisions) ,
2100
+ lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS_TIED ,
2101
+ ) ;
2102
+ self . report_elided_lifetimes_in_paths (
2103
+ secondary,
2104
+ lint:: builtin:: ELIDED_LIFETIMES_IN_PATHS_UNTIED ,
2105
+ ) ;
2106
+ }
2107
+ }
2108
+ }
2109
+
2110
+ fn report_elided_lifetimes_in_paths (
2111
+ & mut self ,
2112
+ resolved_elisions : impl IntoIterator < Item = ResolvedElisionTarget > ,
2113
+ lint : & ' static lint:: Lint ,
2114
+ ) {
2115
+ for re in resolved_elisions {
2116
+ let ResolvedElisionTarget :: Nested ( d) = re else { continue } ;
2037
2117
2038
- for re in resolved_lifetime_elisions {
2039
- let ResolvedNestedElisionTarget { segment_id, elided_lifetime_span, diagnostic } = re;
2118
+ let NestedResolvedElisionTarget { segment_id, elided_lifetime_span, diagnostic } = d;
2040
2119
2041
2120
self . r . lint_buffer . buffer_lint_with_diagnostic (
2042
- lint:: builtin :: ELIDED_LIFETIMES_IN_PATHS ,
2121
+ lint,
2043
2122
segment_id,
2044
2123
elided_lifetime_span,
2045
2124
"hidden lifetime parameters in types are deprecated" ,
0 commit comments