8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use borrow_check:: nll:: constraints:: OutlivesConstraint ;
11
+ use borrow_check:: nll:: constraints:: { OutlivesConstraint , ConstraintCategory } ;
12
12
use borrow_check:: nll:: region_infer:: RegionInferenceContext ;
13
- use borrow_check:: nll:: type_check:: Locations ;
14
13
use rustc:: hir:: def_id:: DefId ;
15
14
use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
16
15
use rustc:: infer:: InferCtxt ;
17
- use rustc:: mir:: { self , Location , Mir , Place , Rvalue , StatementKind , TerminatorKind } ;
18
- use rustc:: ty:: { self , TyCtxt , RegionVid } ;
16
+ use rustc:: mir:: { Location , Mir } ;
17
+ use rustc:: ty:: { self , RegionVid } ;
19
18
use rustc_data_structures:: indexed_vec:: IndexVec ;
20
19
use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
21
20
use std:: collections:: VecDeque ;
@@ -29,19 +28,6 @@ mod var_name;
29
28
30
29
use self :: region_name:: RegionName ;
31
30
32
- /// Constraints that are considered interesting can be categorized to
33
- /// determine why they are interesting. Order of variants indicates
34
- /// sort order of the category, thereby influencing diagnostic output.
35
- #[ derive( Copy , Clone , Debug , Eq , PartialEq , PartialOrd , Ord ) ]
36
- enum ConstraintCategory {
37
- Cast ,
38
- Assignment ,
39
- Return ,
40
- CallArgument ,
41
- Other ,
42
- Boring ,
43
- }
44
-
45
31
impl fmt:: Display for ConstraintCategory {
46
32
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
47
33
// Must end with a space. Allows for empty names to be provided.
@@ -50,7 +36,14 @@ impl fmt::Display for ConstraintCategory {
50
36
ConstraintCategory :: Return => write ! ( f, "returning this value " ) ,
51
37
ConstraintCategory :: Cast => write ! ( f, "cast " ) ,
52
38
ConstraintCategory :: CallArgument => write ! ( f, "argument " ) ,
53
- _ => write ! ( f, "" ) ,
39
+ ConstraintCategory :: TypeAnnotation => write ! ( f, "type annotation " ) ,
40
+ ConstraintCategory :: ClosureBounds => write ! ( f, "closure body " ) ,
41
+ ConstraintCategory :: SizedBound => write ! ( f, "proving this value is `Sized` " ) ,
42
+ ConstraintCategory :: CopyBound => write ! ( f, "copying this value " ) ,
43
+ ConstraintCategory :: OpaqueType => write ! ( f, "opaque type " ) ,
44
+ ConstraintCategory :: Boring
45
+ | ConstraintCategory :: BoringNoLocation
46
+ | ConstraintCategory :: Internal => write ! ( f, "" ) ,
54
47
}
55
48
}
56
49
}
@@ -72,7 +65,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
72
65
fn best_blame_constraint (
73
66
& self ,
74
67
mir : & Mir < ' tcx > ,
75
- tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
76
68
from_region : RegionVid ,
77
69
target_test : impl Fn ( RegionVid ) -> bool ,
78
70
) -> ( ConstraintCategory , Span , RegionVid ) {
@@ -97,7 +89,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
97
89
// Classify each of the constraints along the path.
98
90
let mut categorized_path: Vec < ( ConstraintCategory , Span ) > = path
99
91
. iter ( )
100
- . map ( |& index| self . classify_constraint ( index , mir, tcx ) )
92
+ . map ( |constraint| ( constraint . category , constraint . locations . span ( mir) ) )
101
93
. collect ( ) ;
102
94
debug ! (
103
95
"best_blame_constraint: categorized_path={:#?}" ,
@@ -130,12 +122,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
130
122
let constraint_sup_scc = self . constraint_sccs . scc ( constraint. sup ) ;
131
123
132
124
match categorized_path[ i] . 0 {
133
- ConstraintCategory :: Boring => false ,
134
- ConstraintCategory :: Other => {
135
- // other isn't interesting when the two lifetimes
136
- // are unified.
137
- constraint_sup_scc != self . constraint_sccs . scc ( constraint. sub )
138
- }
125
+ ConstraintCategory :: OpaqueType
126
+ | ConstraintCategory :: Boring
127
+ | ConstraintCategory :: BoringNoLocation
128
+ | ConstraintCategory :: Internal => false ,
139
129
_ => constraint_sup_scc != target_scc,
140
130
}
141
131
} ) ;
@@ -221,106 +211,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
221
211
None
222
212
}
223
213
224
- /// This function will return true if a constraint is interesting and false if a constraint
225
- /// is not. It is useful in filtering constraint paths to only interesting points.
226
- fn constraint_is_interesting ( & self , constraint : OutlivesConstraint ) -> bool {
227
- debug ! (
228
- "constraint_is_interesting: locations={:?} constraint={:?}" ,
229
- constraint. locations, constraint
230
- ) ;
231
-
232
- match constraint. locations {
233
- Locations :: Interesting ( _) | Locations :: All => true ,
234
- _ => false ,
235
- }
236
- }
237
-
238
- /// This function classifies a constraint from a location.
239
- fn classify_constraint (
240
- & self ,
241
- constraint : OutlivesConstraint ,
242
- mir : & Mir < ' tcx > ,
243
- tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
244
- ) -> ( ConstraintCategory , Span ) {
245
- debug ! ( "classify_constraint: constraint={:?}" , constraint) ;
246
- let span = constraint. locations . span ( mir) ;
247
- let location = constraint
248
- . locations
249
- . from_location ( )
250
- . unwrap_or ( Location :: START ) ;
251
-
252
- if !self . constraint_is_interesting ( constraint) {
253
- return ( ConstraintCategory :: Boring , span) ;
254
- }
255
-
256
- let data = & mir[ location. block ] ;
257
- debug ! (
258
- "classify_constraint: location={:?} data={:?}" ,
259
- location, data
260
- ) ;
261
- let category = if location. statement_index == data. statements . len ( ) {
262
- if let Some ( ref terminator) = data. terminator {
263
- debug ! ( "classify_constraint: terminator.kind={:?}" , terminator. kind) ;
264
- match terminator. kind {
265
- TerminatorKind :: DropAndReplace { .. } => ConstraintCategory :: Assignment ,
266
- // Classify calls differently depending on whether or not
267
- // the sub region appears in the destination type (so the
268
- // sup region is in the return type). If the return type
269
- // contains the sub-region, then this is either an
270
- // assignment or a return, depending on whether we are
271
- // writing to the RETURN_PLACE or not.
272
- //
273
- // The idea here is that the region is being propagated
274
- // from an input into the output place, so it's a kind of
275
- // assignment. Otherwise, if the sub-region only appears in
276
- // the argument types, then use the CallArgument
277
- // classification.
278
- TerminatorKind :: Call { destination : Some ( ( ref place, _) ) , .. } => {
279
- if tcx. any_free_region_meets (
280
- & place. ty ( mir, tcx) . to_ty ( tcx) ,
281
- |region| self . to_region_vid ( region) == constraint. sub ,
282
- ) {
283
- match place {
284
- Place :: Local ( mir:: RETURN_PLACE ) => ConstraintCategory :: Return ,
285
- _ => ConstraintCategory :: Assignment ,
286
- }
287
- } else {
288
- ConstraintCategory :: CallArgument
289
- }
290
- }
291
- TerminatorKind :: Call { destination : None , .. } => {
292
- ConstraintCategory :: CallArgument
293
- }
294
- _ => ConstraintCategory :: Other ,
295
- }
296
- } else {
297
- ConstraintCategory :: Other
298
- }
299
- } else {
300
- let statement = & data. statements [ location. statement_index ] ;
301
- debug ! ( "classify_constraint: statement.kind={:?}" , statement. kind) ;
302
- match statement. kind {
303
- StatementKind :: Assign ( ref place, ref rvalue) => {
304
- debug ! ( "classify_constraint: place={:?} rvalue={:?}" , place, rvalue) ;
305
- if * place == Place :: Local ( mir:: RETURN_PLACE ) {
306
- ConstraintCategory :: Return
307
- } else {
308
- match rvalue {
309
- Rvalue :: Cast ( ..) => ConstraintCategory :: Cast ,
310
- Rvalue :: Use ( ..) | Rvalue :: Aggregate ( ..) => {
311
- ConstraintCategory :: Assignment
312
- }
313
- _ => ConstraintCategory :: Other ,
314
- }
315
- }
316
- }
317
- _ => ConstraintCategory :: Other ,
318
- }
319
- } ;
320
-
321
- ( category, span)
322
- }
323
-
324
214
/// Report an error because the universal region `fr` was required to outlive
325
215
/// `outlived_fr` but it is not known to do so. For example:
326
216
///
@@ -342,7 +232,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
342
232
343
233
let ( category, span, _) = self . best_blame_constraint (
344
234
mir,
345
- infcx. tcx ,
346
235
fr,
347
236
|r| r == outlived_fr
348
237
) ;
@@ -392,7 +281,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
392
281
393
282
let escapes_from = if infcx. tcx . is_closure ( mir_def_id) { "closure" } else { "function" } ;
394
283
395
- if fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) {
284
+ // Revert to the normal error in these cases.
285
+ // Assignments aren't "escapes" in function items.
286
+ if ( fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) )
287
+ || ( category == ConstraintCategory :: Assignment && escapes_from == "function" )
288
+ {
396
289
return self . report_general_error ( mir, infcx, mir_def_id,
397
290
fr, true , outlived_fr, false ,
398
291
category, span, errors_buffer) ;
@@ -572,11 +465,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
572
465
crate fn find_outlives_blame_span (
573
466
& self ,
574
467
mir : & Mir < ' tcx > ,
575
- tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
576
468
fr1 : RegionVid ,
577
469
fr2 : RegionVid ,
578
470
) -> Span {
579
- let ( _, span, _) = self . best_blame_constraint ( mir, tcx , fr1, |r| r == fr2) ;
471
+ let ( _, span, _) = self . best_blame_constraint ( mir, fr1, |r| r == fr2) ;
580
472
span
581
473
}
582
474
}
0 commit comments