8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use rustc:: hir;
12
+ use rustc:: hir:: def_id:: DefId ;
13
+ use rustc:: middle:: region;
11
14
use rustc:: mir:: { self , Location , Mir } ;
12
15
use rustc:: mir:: visit:: Visitor ;
13
16
use rustc:: ty:: { self , Region , TyCtxt } ;
@@ -27,13 +30,16 @@ use borrow_check::nll::ToRegionVid;
27
30
use syntax_pos:: Span ;
28
31
29
32
use std:: fmt;
33
+ use std:: rc:: Rc ;
30
34
31
35
// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
32
36
// uniquely identified in the MIR by the `Location` of the assigment
33
37
// statement in which it appears on the right hand side.
34
38
pub struct Borrows < ' a , ' gcx : ' tcx , ' tcx : ' a > {
35
39
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
36
40
mir : & ' a Mir < ' tcx > ,
41
+ scope_tree : Rc < region:: ScopeTree > ,
42
+ root_scope : Option < region:: Scope > ,
37
43
borrows : IndexVec < BorrowIndex , BorrowData < ' tcx > > ,
38
44
location_map : FxHashMap < Location , BorrowIndex > ,
39
45
region_map : FxHashMap < Region < ' tcx > , FxHashSet < BorrowIndex > > ,
@@ -69,8 +75,14 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
69
75
impl < ' a , ' gcx , ' tcx > Borrows < ' a , ' gcx , ' tcx > {
70
76
pub fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
71
77
mir : & ' a Mir < ' tcx > ,
72
- nonlexical_regioncx : Option < RegionInferenceContext < ' tcx > > )
78
+ nonlexical_regioncx : Option < RegionInferenceContext < ' tcx > > ,
79
+ def_id : DefId ,
80
+ body_id : Option < hir:: BodyId > )
73
81
-> Self {
82
+ let scope_tree = tcx. region_scope_tree ( def_id) ;
83
+ let root_scope = body_id. map ( |body_id| {
84
+ region:: Scope :: CallSite ( tcx. hir . body ( body_id) . value . hir_id . local_id )
85
+ } ) ;
74
86
let mut visitor = GatherBorrows {
75
87
tcx,
76
88
mir,
@@ -83,6 +95,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
83
95
return Borrows { tcx : tcx,
84
96
mir : mir,
85
97
borrows : visitor. idx_vec ,
98
+ scope_tree,
99
+ root_scope,
86
100
location_map : visitor. location_map ,
87
101
region_map : visitor. region_map ,
88
102
region_span_map : visitor. region_span_map ,
@@ -253,8 +267,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
253
267
// like unwind paths, we do not always emit `EndRegion` statements, so we
254
268
// add some kills here as a "backup" and to avoid spurious error messages.
255
269
for ( borrow_index, borrow_data) in self . borrows . iter_enumerated ( ) {
256
- if let ReScope ( ..) = borrow_data. region {
257
- sets. kill ( & borrow_index) ;
270
+ if let ReScope ( scope) = borrow_data. region {
271
+ // Check that the scope is not actually a scope from a function that is
272
+ // a parent of our closure. Note that the CallSite scope itself is
273
+ // *outside* of the closure, for some weird reason.
274
+ if let Some ( root_scope) = self . root_scope {
275
+ if * scope != root_scope &&
276
+ self . scope_tree . is_subscope_of ( * scope, root_scope)
277
+ {
278
+ sets. kill ( & borrow_index) ;
279
+ }
280
+ }
258
281
}
259
282
}
260
283
}
0 commit comments