10
10
11
11
use borrow_check:: nll:: region_infer:: RegionInferenceContext ;
12
12
use borrow_check:: nll:: ToRegionVid ;
13
+ use borrow_check:: nll:: universal_regions:: DefiningTy ;
13
14
use rustc:: hir;
14
15
use rustc:: hir:: def_id:: DefId ;
15
16
use rustc:: infer:: InferCtxt ;
@@ -72,7 +73,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
72
73
} )
73
74
. or_else ( || {
74
75
self . give_name_if_anonymous_region_appears_in_output (
75
- infcx. tcx , mir, fr, counter, diag)
76
+ infcx. tcx , mir, mir_def_id , fr, counter, diag)
76
77
} )
77
78
. unwrap_or_else ( || span_bug ! ( mir. span, "can't make a name for free region {:?}" , fr) )
78
79
}
@@ -107,13 +108,46 @@ impl<'tcx> RegionInferenceContext<'tcx> {
107
108
} ,
108
109
109
110
ty:: BoundRegion :: BrEnv => {
110
- let closure_span = tcx. hir . span_if_local ( mir_def_id) . unwrap ( ) ;
111
- let region_name = self . synthesize_region_name ( counter) ;
112
- diag. span_label (
113
- closure_span,
114
- format ! ( "lifetime `{}` represents the closure body" , region_name) ,
115
- ) ;
116
- Some ( region_name)
111
+ let mir_node_id = tcx. hir . as_local_node_id ( mir_def_id) . expect ( "non-local mir" ) ;
112
+ let def_ty = self . universal_regions . defining_ty ;
113
+
114
+ if let DefiningTy :: Closure ( def_id, substs) = def_ty {
115
+ let args_span = if let hir:: ExprKind :: Closure ( _, _, _, span, _)
116
+ = tcx. hir . expect_expr ( mir_node_id) . node
117
+ {
118
+ span
119
+ } else {
120
+ bug ! ( "Closure is not defined by a closure expr" ) ;
121
+ } ;
122
+ let region_name = self . synthesize_region_name ( counter) ;
123
+ diag. span_label (
124
+ args_span,
125
+ format ! ( "lifetime `{}` represents this closure's body" , region_name) ,
126
+ ) ;
127
+
128
+ let closure_kind_ty = substs. closure_kind_ty ( def_id, tcx) ;
129
+ let note = match closure_kind_ty. to_opt_closure_kind ( ) {
130
+ Some ( ty:: ClosureKind :: Fn ) => {
131
+ "closure implements `Fn`, so references to captured variables \
132
+ can't escape the closure"
133
+ }
134
+ Some ( ty:: ClosureKind :: FnMut ) => {
135
+ "closure implements `FnMut`, so references to captured variables \
136
+ can't escape the closure"
137
+ }
138
+ Some ( ty:: ClosureKind :: FnOnce ) => {
139
+ bug ! ( "BrEnv in a `FnOnce` closure" ) ;
140
+ }
141
+ None => bug ! ( "Closure kind not inferred in borrow check" ) ,
142
+ } ;
143
+
144
+ diag. note ( note) ;
145
+
146
+ Some ( region_name)
147
+ } else {
148
+ // Can't have BrEnv in functions, constants or generators.
149
+ bug ! ( "BrEnv outside of closure." ) ;
150
+ }
117
151
}
118
152
119
153
ty:: BoundRegion :: BrAnon ( _) | ty:: BoundRegion :: BrFresh ( _) => None ,
@@ -545,6 +579,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
545
579
& self ,
546
580
tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
547
581
mir : & Mir < ' tcx > ,
582
+ mir_def_id : DefId ,
548
583
fr : RegionVid ,
549
584
counter : & mut usize ,
550
585
diag : & mut DiagnosticBuilder < ' _ > ,
@@ -558,9 +593,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
558
593
return None ;
559
594
}
560
595
596
+ let mir_node_id = tcx. hir . as_local_node_id ( mir_def_id) . expect ( "non-local mir" ) ;
597
+ let args_span = if let hir:: ExprKind :: Closure ( _, _, _, span, _)
598
+ = tcx. hir . expect_expr ( mir_node_id) . node
599
+ {
600
+ span
601
+ } else {
602
+ mir. span
603
+ } ;
604
+
561
605
let region_name = self . synthesize_region_name ( counter) ;
562
606
diag. span_label (
563
- mir . span ,
607
+ args_span ,
564
608
format ! ( "lifetime `{}` appears in return type" , region_name) ,
565
609
) ;
566
610
0 commit comments