@@ -26,7 +26,7 @@ use syntax::visit;
2626
2727#[ deriving( Clone , Decodable , Encodable , Show ) ]
2828pub enum CaptureMode {
29- /// Copy/move the value from this llvm ValueRef into the environment.
29+ /// Copy/move the value into the environment.
3030 CaptureByValue ,
3131
3232 /// Access by reference (used for stack closures).
@@ -45,23 +45,22 @@ pub type freevar_map = NodeMap<Vec<freevar_entry>>;
4545
4646pub type CaptureModeMap = NodeMap < CaptureMode > ;
4747
48- struct CollectFreevarsVisitor < ' a > {
48+ struct CollectFreevarsVisitor < ' a , ' b : ' a > {
49+ node_id : ast:: NodeId ,
4950 seen : NodeSet ,
50- refs : Vec < freevar_entry > ,
51- def_map : & ' a resolve:: DefMap ,
52- capture_mode_map : & ' a mut CaptureModeMap ,
53- depth : uint
51+ cx : & ' a mut AnnotateFreevarsVisitor < ' b > ,
52+ depth : u32
5453}
5554
56- impl < ' a , ' v > Visitor < ' v > for CollectFreevarsVisitor < ' a > {
55+ impl < ' a , ' b , ' v > Visitor < ' v > for CollectFreevarsVisitor < ' a , ' b > {
5756 fn visit_item ( & mut self , _: & ast:: Item ) {
5857 // ignore_item
5958 }
6059
6160 fn visit_expr ( & mut self , expr : & ast:: Expr ) {
6261 match expr. node {
6362 ast:: ExprProc ( ..) => {
64- self . capture_mode_map . insert ( expr. id , CaptureByValue ) ;
63+ self . cx . capture_mode_map . insert ( expr. id , CaptureByValue ) ;
6564 self . depth += 1 ;
6665 visit:: walk_expr ( self , expr) ;
6766 self . depth -= 1 ;
@@ -74,7 +73,7 @@ impl<'a, 'v> Visitor<'v> for CollectFreevarsVisitor<'a> {
7473 // ast::CaptureByRef => CaptureByRef,
7574 //};
7675 let capture_mode = CaptureByRef ;
77- self . capture_mode_map . insert ( expr. id , capture_mode) ;
76+ self . cx . capture_mode_map . insert ( expr. id , capture_mode) ;
7877 self . depth += 1 ;
7978 visit:: walk_expr ( self , expr) ;
8079 self . depth -= 1 ;
@@ -84,60 +83,45 @@ impl<'a, 'v> Visitor<'v> for CollectFreevarsVisitor<'a> {
8483 ast:: CaptureByValue => CaptureByValue ,
8584 ast:: CaptureByRef => CaptureByRef ,
8685 } ;
87- self . capture_mode_map . insert ( expr. id , capture_mode) ;
86+ self . cx . capture_mode_map . insert ( expr. id , capture_mode) ;
8887 self . depth += 1 ;
8988 visit:: walk_expr ( self , expr) ;
9089 self . depth -= 1 ;
9190 }
9291 ast:: ExprPath ( ..) => {
93- let mut def = * self . def_map . borrow ( ) . find ( & expr. id )
94- . expect ( "path not found" ) ;
95- let mut i = 0 ;
96- while i < self . depth {
97- match def {
98- def:: DefUpvar ( _, inner, _, _) => { def = * inner; }
99- _ => break
100- }
101- i += 1 ;
102- }
103- if i == self . depth { // Made it to end of loop
104- let dnum = def. def_id ( ) . node ;
105- if !self . seen . contains ( & dnum) {
106- self . refs . push ( freevar_entry {
107- def : def,
108- span : expr. span ,
109- } ) ;
110- self . seen . insert ( dnum) ;
111- }
92+ let def = * self . cx . def_map . borrow ( ) . find ( & expr. id )
93+ . expect ( "path not found" ) ;
94+ let dnum = def. def_id ( ) . node ;
95+ if self . seen . contains ( & dnum) {
96+ return ;
11297 }
98+ let def = match def {
99+ def:: DefUpvar ( _, _, depth, _, _) => {
100+ if depth < self . depth {
101+ return ;
102+ }
103+ let mut def = def;
104+ for _ in range ( 0 , depth - self . depth ) {
105+ match def {
106+ def:: DefUpvar ( _, inner, _, _, _) => { def = * inner; }
107+ _ => unreachable ! ( )
108+ }
109+ }
110+ def
111+ } ,
112+ _ => return
113+ } ;
114+ self . cx . freevars . find_or_insert ( self . node_id , vec ! [ ] ) . push ( freevar_entry {
115+ def : def,
116+ span : expr. span ,
117+ } ) ;
118+ self . seen . insert ( dnum) ;
113119 }
114120 _ => visit:: walk_expr ( self , expr)
115121 }
116122 }
117123}
118124
119- // Searches through part of the AST for all references to locals or
120- // upvars in this frame and returns the list of definition IDs thus found.
121- // Since we want to be able to collect upvars in some arbitrary piece
122- // of the AST, we take a walker function that we invoke with a visitor
123- // in order to start the search.
124- fn collect_freevars ( def_map : & resolve:: DefMap ,
125- blk : & ast:: Block ,
126- capture_mode_map : & mut CaptureModeMap )
127- -> Vec < freevar_entry > {
128- let mut v = CollectFreevarsVisitor {
129- seen : NodeSet :: new ( ) ,
130- refs : Vec :: new ( ) ,
131- def_map : def_map,
132- capture_mode_map : & mut * capture_mode_map,
133- depth : 1
134- } ;
135-
136- v. visit_block ( blk) ;
137-
138- v. refs
139- }
140-
141125struct AnnotateFreevarsVisitor < ' a > {
142126 def_map : & ' a resolve:: DefMap ,
143127 freevars : freevar_map ,
@@ -147,10 +131,12 @@ struct AnnotateFreevarsVisitor<'a> {
147131impl < ' a , ' v > Visitor < ' v > for AnnotateFreevarsVisitor < ' a > {
148132 fn visit_fn ( & mut self , fk : visit:: FnKind < ' v > , fd : & ' v ast:: FnDecl ,
149133 blk : & ' v ast:: Block , s : Span , nid : ast:: NodeId ) {
150- let vars = collect_freevars ( self . def_map ,
151- blk,
152- & mut self . capture_mode_map ) ;
153- self . freevars . insert ( nid, vars) ;
134+ CollectFreevarsVisitor {
135+ node_id : nid,
136+ seen : NodeSet :: new ( ) ,
137+ cx : self ,
138+ depth : 0
139+ } . visit_block ( blk) ;
154140 visit:: walk_fn ( self , fk, fd, blk, s) ;
155141 }
156142}
@@ -168,13 +154,7 @@ pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate)
168154 capture_mode_map : NodeMap :: new ( ) ,
169155 } ;
170156 visit:: walk_crate ( & mut visitor, krate) ;
171-
172- let AnnotateFreevarsVisitor {
173- freevars,
174- capture_mode_map,
175- ..
176- } = visitor;
177- ( freevars, capture_mode_map)
157+ ( visitor. freevars , visitor. capture_mode_map )
178158}
179159
180160pub fn with_freevars < T > ( tcx : & ty:: ctxt , fid : ast:: NodeId , f: |& [ freevar_entry] | -> T ) -> T {
0 commit comments