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 , ConstraintCategory } ;
11
+ use borrow_check:: nll:: constraints:: { OutlivesConstraint } ;
12
12
use borrow_check:: nll:: region_infer:: RegionInferenceContext ;
13
+ use borrow_check:: nll:: type_check:: Locations ;
13
14
use rustc:: hir:: def_id:: DefId ;
14
15
use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
15
16
use rustc:: infer:: InferCtxt ;
16
- use rustc:: mir:: { Location , Mir } ;
17
+ use rustc:: mir:: { ConstraintCategory , Location , Mir } ;
17
18
use rustc:: ty:: { self , RegionVid } ;
18
19
use rustc_data_structures:: indexed_vec:: IndexVec ;
19
20
use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
20
21
use std:: collections:: VecDeque ;
21
- use std:: fmt;
22
22
use syntax:: symbol:: keywords;
23
23
use syntax_pos:: Span ;
24
24
use syntax:: errors:: Applicability ;
@@ -28,22 +28,26 @@ mod var_name;
28
28
29
29
use self :: region_name:: RegionName ;
30
30
31
- impl fmt:: Display for ConstraintCategory {
32
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
31
+ trait ConstraintDescription {
32
+ fn description ( & self ) -> & ' static str ;
33
+ }
34
+
35
+ impl ConstraintDescription for ConstraintCategory {
36
+ fn description ( & self ) -> & ' static str {
33
37
// Must end with a space. Allows for empty names to be provided.
34
38
match self {
35
- ConstraintCategory :: Assignment => write ! ( f , "assignment " ) ,
36
- ConstraintCategory :: Return => write ! ( f , "returning this value " ) ,
37
- ConstraintCategory :: Cast => write ! ( f , "cast " ) ,
38
- ConstraintCategory :: CallArgument => write ! ( f , "argument " ) ,
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 " ) ,
39
+ ConstraintCategory :: Assignment => "assignment " ,
40
+ ConstraintCategory :: Return => "returning this value " ,
41
+ ConstraintCategory :: Cast => "cast " ,
42
+ ConstraintCategory :: CallArgument => "argument " ,
43
+ ConstraintCategory :: TypeAnnotation => "type annotation " ,
44
+ ConstraintCategory :: ClosureBounds => "closure body " ,
45
+ ConstraintCategory :: SizedBound => "proving this value is `Sized` " ,
46
+ ConstraintCategory :: CopyBound => "copying this value " ,
47
+ ConstraintCategory :: OpaqueType => "opaque type " ,
44
48
ConstraintCategory :: Boring
45
49
| ConstraintCategory :: BoringNoLocation
46
- | ConstraintCategory :: Internal => write ! ( f , "" ) ,
50
+ | ConstraintCategory :: Internal => "" ,
47
51
}
48
52
}
49
53
}
@@ -89,7 +93,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
89
93
// Classify each of the constraints along the path.
90
94
let mut categorized_path: Vec < ( ConstraintCategory , Span ) > = path
91
95
. iter ( )
92
- . map ( |constraint| ( constraint. category , constraint. locations . span ( mir) ) )
96
+ . map ( |constraint| {
97
+ if constraint. category == ConstraintCategory :: ClosureBounds {
98
+ self . retrieve_closure_constraint_info ( mir, & constraint)
99
+ } else {
100
+ ( constraint. category , constraint. locations . span ( mir) )
101
+ }
102
+ } )
93
103
. collect ( ) ;
94
104
debug ! (
95
105
"best_blame_constraint: categorized_path={:#?}" ,
@@ -358,7 +368,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
358
368
_ => {
359
369
diag. span_label ( span, format ! (
360
370
"{}requires that `{}` must outlive `{}`" ,
361
- category, fr_name, outlived_fr_name,
371
+ category. description ( ) , fr_name, outlived_fr_name,
362
372
) ) ;
363
373
} ,
364
374
}
@@ -470,8 +480,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
470
480
mir : & Mir < ' tcx > ,
471
481
fr1 : RegionVid ,
472
482
fr2 : RegionVid ,
473
- ) -> Span {
474
- let ( _, span, _) = self . best_blame_constraint ( mir, fr1, |r| r == fr2) ;
475
- span
483
+ ) -> ( ConstraintCategory , Span ) {
484
+ let ( category, span, _) = self . best_blame_constraint ( mir, fr1, |r| r == fr2) ;
485
+ ( category, span)
486
+ }
487
+
488
+ fn retrieve_closure_constraint_info (
489
+ & self ,
490
+ mir : & Mir < ' tcx > ,
491
+ constraint : & OutlivesConstraint
492
+ ) -> ( ConstraintCategory , Span ) {
493
+ let loc = match constraint. locations {
494
+ Locations :: All ( span) => return ( constraint. category , span) ,
495
+ Locations :: Single ( loc) => loc,
496
+ } ;
497
+
498
+ let opt_span_category = self
499
+ . closure_bounds_mapping [ & loc]
500
+ . get ( & ( constraint. sup , constraint. sub ) ) ;
501
+ * opt_span_category. unwrap_or ( & ( constraint. category , mir. source_info ( loc) . span ) )
476
502
}
477
503
}
0 commit comments