@@ -14,7 +14,7 @@ use rustc::hir::def_id::DefId;
14
14
use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
15
15
use rustc:: infer:: InferCtxt ;
16
16
use rustc:: mir:: { self , Location , Mir , Place , Rvalue , StatementKind , TerminatorKind } ;
17
- use rustc:: ty:: RegionVid ;
17
+ use rustc:: ty:: { TyCtxt , RegionVid } ;
18
18
use rustc_data_structures:: indexed_vec:: IndexVec ;
19
19
use rustc_errors:: Diagnostic ;
20
20
use std:: collections:: VecDeque ;
@@ -67,6 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
67
67
fn best_blame_constraint (
68
68
& self ,
69
69
mir : & Mir < ' tcx > ,
70
+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
70
71
from_region : RegionVid ,
71
72
target_test : impl Fn ( RegionVid ) -> bool ,
72
73
) -> ( ConstraintCategory , Span , RegionVid ) {
@@ -92,7 +93,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
92
93
// Classify each of the constraints along the path.
93
94
let mut categorized_path: Vec < ( ConstraintCategory , Span ) > = path
94
95
. iter ( )
95
- . map ( |& index| self . classify_constraint ( index, mir) )
96
+ . map ( |& index| self . classify_constraint ( index, mir, tcx ) )
96
97
. collect ( ) ;
97
98
debug ! (
98
99
"best_blame_constraint: categorized_path={:#?}" ,
@@ -231,6 +232,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
231
232
& self ,
232
233
index : ConstraintIndex ,
233
234
mir : & Mir < ' tcx > ,
235
+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
234
236
) -> ( ConstraintCategory , Span ) {
235
237
let constraint = self . constraints [ index] ;
236
238
debug ! ( "classify_constraint: constraint={:?}" , constraint) ;
@@ -254,7 +256,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {
254
256
debug ! ( "classify_constraint: terminator.kind={:?}" , terminator. kind) ;
255
257
match terminator. kind {
256
258
TerminatorKind :: DropAndReplace { .. } => ConstraintCategory :: Assignment ,
257
- TerminatorKind :: Call { .. } => ConstraintCategory :: CallArgument ,
259
+ // Classify calls differently depending on whether or not
260
+ // the sub region appears in the destination type (so the
261
+ // sup region is in the return type). If the return type
262
+ // contains the sub-region, then this is either an
263
+ // assignment or a return, depending on whether we are
264
+ // writing to the RETURN_PLACE or not.
265
+ //
266
+ // The idea here is that the region is being propagated
267
+ // from an input into the output place, so it's a kind of
268
+ // assignment. Otherwise, if the sub-region only appears in
269
+ // the argument types, then use the CallArgument
270
+ // classification.
271
+ TerminatorKind :: Call { destination : Some ( ( ref place, _) ) , .. } => {
272
+ if tcx. any_free_region_meets (
273
+ & place. ty ( mir, tcx) . to_ty ( tcx) ,
274
+ |region| self . to_region_vid ( region) == constraint. sub ,
275
+ ) {
276
+ match place {
277
+ Place :: Local ( mir:: RETURN_PLACE ) => ConstraintCategory :: Return ,
278
+ _ => ConstraintCategory :: Assignment ,
279
+ }
280
+ } else {
281
+ ConstraintCategory :: CallArgument
282
+ }
283
+ }
284
+ TerminatorKind :: Call { destination : None , .. } => {
285
+ ConstraintCategory :: CallArgument
286
+ }
258
287
_ => ConstraintCategory :: Other ,
259
288
}
260
289
} else {
@@ -304,7 +333,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
304
333
) {
305
334
debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
306
335
307
- let ( category, span, _) = self . best_blame_constraint ( mir, fr, |r| r == outlived_fr) ;
336
+ let ( category, span, _) = self . best_blame_constraint (
337
+ mir,
338
+ infcx. tcx ,
339
+ fr,
340
+ |r| r == outlived_fr
341
+ ) ;
308
342
309
343
// Check if we can use one of the "nice region errors".
310
344
if let ( Some ( f) , Some ( o) ) = ( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) ) {
@@ -446,10 +480,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
446
480
crate fn find_outlives_blame_span (
447
481
& self ,
448
482
mir : & Mir < ' tcx > ,
483
+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
449
484
fr1 : RegionVid ,
450
485
fr2 : RegionVid ,
451
486
) -> Span {
452
- let ( _, span, _) = self . best_blame_constraint ( mir, fr1, |r| r == fr2) ;
487
+ let ( _, span, _) = self . best_blame_constraint ( mir, tcx , fr1, |r| r == fr2) ;
453
488
span
454
489
}
455
490
}
0 commit comments