88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use borrow_check:: nll:: constraints:: OutlivesConstraint ;
11+ use borrow_check:: nll:: constraints:: { OutlivesConstraint , ConstraintCategory } ;
1212use borrow_check:: nll:: region_infer:: RegionInferenceContext ;
13- use borrow_check:: nll:: type_check:: Locations ;
1413use rustc:: hir:: def_id:: DefId ;
1514use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
1615use 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 } ;
1918use rustc_data_structures:: indexed_vec:: IndexVec ;
2019use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
2120use std:: collections:: VecDeque ;
@@ -29,19 +28,6 @@ mod var_name;
2928
3029use self :: region_name:: RegionName ;
3130
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-
4531impl fmt:: Display for ConstraintCategory {
4632 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
4733 // Must end with a space. Allows for empty names to be provided.
@@ -50,7 +36,14 @@ impl fmt::Display for ConstraintCategory {
5036 ConstraintCategory :: Return => write ! ( f, "returning this value " ) ,
5137 ConstraintCategory :: Cast => write ! ( f, "cast " ) ,
5238 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, "" ) ,
5447 }
5548 }
5649}
@@ -72,7 +65,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7265 fn best_blame_constraint (
7366 & self ,
7467 mir : & Mir < ' tcx > ,
75- tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
7668 from_region : RegionVid ,
7769 target_test : impl Fn ( RegionVid ) -> bool ,
7870 ) -> ( ConstraintCategory , Span , RegionVid ) {
@@ -97,7 +89,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9789 // Classify each of the constraints along the path.
9890 let mut categorized_path: Vec < ( ConstraintCategory , Span ) > = path
9991 . iter ( )
100- . map ( |& index| self . classify_constraint ( index , mir, tcx ) )
92+ . map ( |constraint| ( constraint . category , constraint . locations . span ( mir) ) )
10193 . collect ( ) ;
10294 debug ! (
10395 "best_blame_constraint: categorized_path={:#?}" ,
@@ -130,12 +122,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
130122 let constraint_sup_scc = self . constraint_sccs . scc ( constraint. sup ) ;
131123
132124 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 ,
139129 _ => constraint_sup_scc != target_scc,
140130 }
141131 } ) ;
@@ -221,106 +211,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
221211 None
222212 }
223213
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-
324214 /// Report an error because the universal region `fr` was required to outlive
325215 /// `outlived_fr` but it is not known to do so. For example:
326216 ///
@@ -342,7 +232,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
342232
343233 let ( category, span, _) = self . best_blame_constraint (
344234 mir,
345- infcx. tcx ,
346235 fr,
347236 |r| r == outlived_fr
348237 ) ;
@@ -392,7 +281,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
392281
393282 let escapes_from = if infcx. tcx . is_closure ( mir_def_id) { "closure" } else { "function" } ;
394283
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+ {
396289 return self . report_general_error ( mir, infcx, mir_def_id,
397290 fr, true , outlived_fr, false ,
398291 category, span, errors_buffer) ;
@@ -572,11 +465,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
572465 crate fn find_outlives_blame_span (
573466 & self ,
574467 mir : & Mir < ' tcx > ,
575- tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
576468 fr1 : RegionVid ,
577469 fr2 : RegionVid ,
578470 ) -> 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) ;
580472 span
581473 }
582474}
0 commit comments