@@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
10
10
use rustc_hir:: intravisit:: { walk_ty, ErasedMap , NestedVisitorMap , Visitor } ;
11
11
use rustc_hir:: { self as hir, GenericBound , Item , ItemKind , Lifetime , LifetimeName , Node , TyKind } ;
12
12
use rustc_middle:: ty:: {
13
- self , AssocItemContainer , RegionKind , Ty , TyCtxt , TypeFoldable , TypeVisitor ,
13
+ self , AssocItemContainer , RegionKind , StaticLifetimeVisitor , Ty , TyCtxt , TypeFoldable ,
14
+ TypeVisitor ,
14
15
} ;
15
16
use rustc_span:: symbol:: Ident ;
16
17
use rustc_span:: { MultiSpan , Span } ;
@@ -23,16 +24,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
23
24
pub ( super ) fn try_report_static_impl_trait ( & self ) -> Option < ErrorReported > {
24
25
debug ! ( "try_report_static_impl_trait(error={:?})" , self . error) ;
25
26
let tcx = self . tcx ( ) ;
26
- let ( var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self . error . as_ref ( ) ? {
27
+ let ( var_origin, sub_origin, sub_r, sup_origin, sup_r, spans ) = match self . error . as_ref ( ) ? {
27
28
RegionResolutionError :: SubSupConflict (
28
29
_,
29
30
var_origin,
30
31
sub_origin,
31
32
sub_r,
32
33
sup_origin,
33
34
sup_r,
35
+ spans,
34
36
) if * * sub_r == RegionKind :: ReStatic => {
35
- ( var_origin, sub_origin, sub_r, sup_origin, sup_r)
37
+ ( var_origin, sub_origin, sub_r, sup_origin, sup_r, spans )
36
38
}
37
39
RegionResolutionError :: ConcreteFailure (
38
40
SubregionOrigin :: Subtype ( box TypeTrace { cause, .. } ) ,
@@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
74
76
err. span_label (
75
77
cause. span ,
76
78
& format ! (
77
- "...is captured and required to live as long as `'static` here \
79
+ "...is used and required to live as long as `'static` here \
78
80
because of an implicit lifetime bound on the {}",
79
81
match ctxt. assoc_item. container {
80
82
AssocItemContainer :: TraitContainer ( id) =>
@@ -123,56 +125,101 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
123
125
param_name,
124
126
lifetime,
125
127
) ;
126
- err. span_label ( param. param_ty_span , & format ! ( "this data with {}..." , lifetime) ) ;
127
- debug ! ( "try_report_static_impl_trait: param_info={:?}" , param) ;
128
128
129
- // We try to make the output have fewer overlapping spans if possible.
130
- if ( sp == sup_origin. span ( ) || !return_sp. overlaps ( sup_origin. span ( ) ) )
131
- && sup_origin. span ( ) != return_sp
132
- {
133
- // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
134
-
135
- // Customize the spans and labels depending on their relative order so
136
- // that split sentences flow correctly.
137
- if sup_origin. span ( ) . overlaps ( return_sp) && sp == sup_origin. span ( ) {
138
- // Avoid the following:
139
- //
140
- // error: cannot infer an appropriate lifetime
141
- // --> $DIR/must_outlive_least_region_or_bound.rs:18:50
142
- // |
143
- // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
144
- // | ---- ---------^-
129
+ let ( mention_influencer, influencer_point) =
130
+ if sup_origin. span ( ) . overlaps ( param. param_ty_span ) {
131
+ // Account for `async fn` like in `async-await/issues/issue-62097.rs`.
132
+ // The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same
133
+ // place (but with different `ctxt`, hence `overlaps` instead of `==` above).
145
134
//
146
- // and instead show :
135
+ // This avoids the following :
147
136
//
148
- // error: cannot infer an appropriate lifetime
149
- // --> $DIR/must_outlive_least_region_or_bound.rs:18:50
150
- // |
151
- // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
152
- // | ---- ^
153
- err. span_label (
154
- sup_origin. span ( ) ,
155
- "...is captured here, requiring it to live as long as `'static`" ,
156
- ) ;
137
+ // LL | pub async fn run_dummy_fn(&self) {
138
+ // | ^^^^^
139
+ // | |
140
+ // | this data with an anonymous lifetime `'_`...
141
+ // | ...is captured here...
142
+ ( false , sup_origin. span ( ) )
157
143
} else {
158
- err. span_label ( sup_origin. span ( ) , "...is captured here..." ) ;
159
- if return_sp < sup_origin. span ( ) {
160
- err. span_note (
161
- return_sp,
162
- "...and is required to live as long as `'static` here" ,
144
+ ( !sup_origin. span ( ) . overlaps ( return_sp) , param. param_ty_span )
145
+ } ;
146
+ err. span_label ( influencer_point, & format ! ( "this data with {}..." , lifetime) ) ;
147
+
148
+ debug ! ( "try_report_static_impl_trait: param_info={:?}" , param) ;
149
+
150
+ let mut spans = spans. clone ( ) ;
151
+
152
+ if mention_influencer {
153
+ spans. push ( sup_origin. span ( ) ) ;
154
+ }
155
+ // We dedup the spans *ignoring* expansion context.
156
+ spans. sort ( ) ;
157
+ spans. dedup_by_key ( |span| ( span. lo ( ) , span. hi ( ) ) ) ;
158
+
159
+ // We try to make the output have fewer overlapping spans if possible.
160
+ let require_msg = if spans. is_empty ( ) {
161
+ "...is used and required to live as long as `'static` here"
162
+ } else {
163
+ "...and is required to live as long as `'static` here"
164
+ } ;
165
+ let require_span =
166
+ if sup_origin. span ( ) . overlaps ( return_sp) { sup_origin. span ( ) } else { return_sp } ;
167
+
168
+ for span in & spans {
169
+ err. span_label ( * span, "...is used here..." ) ;
170
+ }
171
+
172
+ if spans. iter ( ) . any ( |sp| sp. overlaps ( return_sp) || * sp > return_sp) {
173
+ // If any of the "captured here" labels appears on the same line or after
174
+ // `require_span`, we put it on a note to ensure the text flows by appearing
175
+ // always at the end.
176
+ err. span_note ( require_span, require_msg) ;
177
+ } else {
178
+ // We don't need a note, it's already at the end, it can be shown as a `span_label`.
179
+ err. span_label ( require_span, require_msg) ;
180
+ }
181
+
182
+ if let SubregionOrigin :: RelateParamBound ( _, _, Some ( bound) ) = sub_origin {
183
+ err. span_note ( * bound, "`'static` lifetime requirement introduced by this bound" ) ;
184
+ }
185
+ if let SubregionOrigin :: Subtype ( box TypeTrace { cause, .. } ) = sub_origin {
186
+ if let ObligationCauseCode :: ReturnValue ( hir_id)
187
+ | ObligationCauseCode :: BlockTailExpression ( hir_id) = & cause. code
188
+ {
189
+ let parent_id = tcx. hir ( ) . get_parent_item ( * hir_id) ;
190
+ if let Some ( fn_decl) = tcx. hir ( ) . fn_decl_by_hir_id ( parent_id) {
191
+ let mut span: MultiSpan = fn_decl. output . span ( ) . into ( ) ;
192
+ let mut add_label = true ;
193
+ if let hir:: FnRetTy :: Return ( ty) = fn_decl. output {
194
+ let mut v = StaticLifetimeVisitor ( vec ! [ ] , tcx. hir ( ) ) ;
195
+ v. visit_ty ( ty) ;
196
+ if !v. 0 . is_empty ( ) {
197
+ span = v. 0 . clone ( ) . into ( ) ;
198
+ for sp in v. 0 {
199
+ span. push_span_label (
200
+ sp,
201
+ "`'static` requirement introduced here" . to_string ( ) ,
202
+ ) ;
203
+ }
204
+ add_label = false ;
205
+ }
206
+ }
207
+ if add_label {
208
+ span. push_span_label (
209
+ fn_decl. output . span ( ) ,
210
+ "requirement introduced by this return type" . to_string ( ) ,
211
+ ) ;
212
+ }
213
+ span. push_span_label (
214
+ cause. span ,
215
+ "because of this returned expression" . to_string ( ) ,
163
216
) ;
164
- } else {
165
- err. span_label (
166
- return_sp,
167
- "...and is required to live as long as `'static` here" ,
217
+ err. span_note (
218
+ span,
219
+ "`'static` lifetime requirement introduced by the return type" ,
168
220
) ;
169
221
}
170
222
}
171
- } else {
172
- err. span_label (
173
- return_sp,
174
- "...is captured and required to live as long as `'static` here" ,
175
- ) ;
176
223
}
177
224
178
225
let fn_returns = tcx. return_type_impl_or_dyn_traits ( anon_reg_sup. def_id ) ;
0 commit comments