@@ -17,14 +17,14 @@ use middle::def;
17
17
use middle:: mem_categorization:: Typer ;
18
18
use middle:: resolve;
19
19
use middle:: ty;
20
- use util:: nodemap:: { DefIdSet , NodeMap , NodeSet } ;
20
+ use util:: nodemap:: { NodeMap , NodeSet } ;
21
21
22
+ use syntax:: ast;
22
23
use syntax:: codemap:: Span ;
23
- use syntax:: { ast} ;
24
- use syntax:: visit;
25
24
use syntax:: visit:: Visitor ;
25
+ use syntax:: visit;
26
26
27
- #[ deriving( Show ) ]
27
+ #[ deriving( Clone , Decodable , Encodable , Show ) ]
28
28
pub enum CaptureMode {
29
29
/// Copy/move the value from this llvm ValueRef into the environment.
30
30
CaptureByValue ,
@@ -43,12 +43,13 @@ pub struct freevar_entry {
43
43
44
44
pub type freevar_map = NodeMap < Vec < freevar_entry > > ;
45
45
46
- pub type UnboxedClosureList = DefIdSet ;
46
+ pub type CaptureModeMap = NodeMap < CaptureMode > ;
47
47
48
48
struct CollectFreevarsVisitor < ' a > {
49
49
seen : NodeSet ,
50
50
refs : Vec < freevar_entry > ,
51
51
def_map : & ' a resolve:: DefMap ,
52
+ capture_mode_map : & ' a mut CaptureModeMap ,
52
53
}
53
54
54
55
impl < ' a > Visitor < int > for CollectFreevarsVisitor < ' a > {
@@ -58,8 +59,27 @@ impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
58
59
59
60
fn visit_expr ( & mut self , expr : & ast:: Expr , depth : int ) {
60
61
match expr. node {
61
- ast:: ExprFnBlock ( ..) | ast:: ExprProc ( ..) |
62
- ast:: ExprUnboxedFn ( ..) => {
62
+ ast:: ExprProc ( ..) => {
63
+ self . capture_mode_map . insert ( expr. id , CaptureByValue ) ;
64
+ visit:: walk_expr ( self , expr, depth + 1 )
65
+ }
66
+ ast:: ExprFnBlock ( _, _, _) => {
67
+ // NOTE(stage0): After snapshot, change to:
68
+ //
69
+ //let capture_mode = match capture_clause {
70
+ // ast::CaptureByValue => CaptureByValue,
71
+ // ast::CaptureByRef => CaptureByRef,
72
+ //};
73
+ let capture_mode = CaptureByRef ;
74
+ self . capture_mode_map . insert ( expr. id , capture_mode) ;
75
+ visit:: walk_expr ( self , expr, depth + 1 )
76
+ }
77
+ ast:: ExprUnboxedFn ( capture_clause, _, _) => {
78
+ let capture_mode = match capture_clause {
79
+ ast:: CaptureByValue => CaptureByValue ,
80
+ ast:: CaptureByRef => CaptureByRef ,
81
+ } ;
82
+ self . capture_mode_map . insert ( expr. id , capture_mode) ;
63
83
visit:: walk_expr ( self , expr, depth + 1 )
64
84
}
65
85
ast:: ExprPath ( ..) => {
@@ -91,35 +111,41 @@ impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
91
111
_ => visit:: walk_expr ( self , expr, depth)
92
112
}
93
113
}
94
-
95
-
96
114
}
97
115
98
116
// Searches through part of the AST for all references to locals or
99
117
// upvars in this frame and returns the list of definition IDs thus found.
100
118
// Since we want to be able to collect upvars in some arbitrary piece
101
119
// of the AST, we take a walker function that we invoke with a visitor
102
120
// in order to start the search.
103
- fn collect_freevars ( def_map : & resolve:: DefMap , blk : & ast:: Block ) -> Vec < freevar_entry > {
121
+ fn collect_freevars ( def_map : & resolve:: DefMap ,
122
+ blk : & ast:: Block ,
123
+ capture_mode_map : & mut CaptureModeMap )
124
+ -> Vec < freevar_entry > {
104
125
let mut v = CollectFreevarsVisitor {
105
126
seen : NodeSet :: new ( ) ,
106
127
refs : Vec :: new ( ) ,
107
128
def_map : def_map,
129
+ capture_mode_map : & mut * capture_mode_map,
108
130
} ;
109
131
110
132
v. visit_block ( blk, 1 ) ;
133
+
111
134
v. refs
112
135
}
113
136
114
137
struct AnnotateFreevarsVisitor < ' a > {
115
138
def_map : & ' a resolve:: DefMap ,
116
139
freevars : freevar_map ,
140
+ capture_mode_map : CaptureModeMap ,
117
141
}
118
142
119
143
impl < ' a > Visitor < ( ) > for AnnotateFreevarsVisitor < ' a > {
120
144
fn visit_fn ( & mut self , fk : & visit:: FnKind , fd : & ast:: FnDecl ,
121
145
blk : & ast:: Block , s : Span , nid : ast:: NodeId , _: ( ) ) {
122
- let vars = collect_freevars ( self . def_map , blk) ;
146
+ let vars = collect_freevars ( self . def_map ,
147
+ blk,
148
+ & mut self . capture_mode_map ) ;
123
149
self . freevars . insert ( nid, vars) ;
124
150
visit:: walk_fn ( self , fk, fd, blk, s, ( ) ) ;
125
151
}
@@ -131,14 +157,20 @@ impl<'a> Visitor<()> for AnnotateFreevarsVisitor<'a> {
131
157
// node of interest rather than building up the free variables in
132
158
// one pass. This could be improved upon if it turns out to matter.
133
159
pub fn annotate_freevars ( def_map : & resolve:: DefMap , krate : & ast:: Crate )
134
- -> freevar_map {
160
+ -> ( freevar_map , CaptureModeMap ) {
135
161
let mut visitor = AnnotateFreevarsVisitor {
136
162
def_map : def_map,
137
163
freevars : NodeMap :: new ( ) ,
164
+ capture_mode_map : NodeMap :: new ( ) ,
138
165
} ;
139
166
visit:: walk_crate ( & mut visitor, krate, ( ) ) ;
140
167
141
- visitor. freevars
168
+ let AnnotateFreevarsVisitor {
169
+ freevars,
170
+ capture_mode_map,
171
+ ..
172
+ } = visitor;
173
+ ( freevars, capture_mode_map)
142
174
}
143
175
144
176
pub fn with_freevars < T > ( tcx : & ty:: ctxt , fid : ast:: NodeId , f: |& [ freevar_entry] | -> T ) -> T {
@@ -148,10 +180,7 @@ pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]|
148
180
}
149
181
}
150
182
151
- pub fn get_capture_mode < T : Typer > ( tcx : & T , closure_expr_id : ast:: NodeId ) -> CaptureMode {
152
- let fn_ty = tcx. node_ty ( closure_expr_id) . ok ( ) . expect ( "couldn't find closure ty?" ) ;
153
- match ty:: ty_closure_store ( fn_ty) {
154
- ty:: RegionTraitStore ( ..) => CaptureByRef ,
155
- ty:: UniqTraitStore => CaptureByValue
156
- }
183
+ pub fn get_capture_mode < T : Typer > ( tcx : & T , closure_expr_id : ast:: NodeId )
184
+ -> CaptureMode {
185
+ tcx. capture_mode ( closure_expr_id)
157
186
}
0 commit comments