@@ -22,6 +22,7 @@ type binding = @{node_id: node_id,
22
22
unsafe_tys: [ ty:: t] ,
23
23
mutable ok: valid,
24
24
mutable copied: copied} ;
25
+ // FIXME it may be worthwhile to use a linked list of bindings instead
25
26
type scope = { bs : [ binding ] , ret_style : ast:: ret_style } ;
26
27
27
28
fn mk_binding ( cx : ctx , id : node_id , span : span , root_var : option:: t < node_id > ,
@@ -46,7 +47,8 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> copy_map {
46
47
copy_map: std:: map:: new_int_hash ( ) } ;
47
48
let v = @{ visit_fn: bind visit_fn ( cx, _, _, _, _, _, _, _) ,
48
49
visit_expr: bind visit_expr ( cx, _, _, _) ,
49
- visit_decl: bind visit_decl ( cx, _, _, _)
50
+ visit_decl: bind visit_decl ( cx, _, _, _) ,
51
+ visit_block: bind visit_block ( cx, _, _, _)
50
52
with * visit:: default_visitor :: < scope > ( ) } ;
51
53
visit:: visit_crate ( * crate , { bs: [ ] , ret_style: ast:: return_val} ,
52
54
visit:: mk_vt ( v) ) ;
@@ -134,8 +136,7 @@ fn visit_decl(cx: @ctx, d: @ast::decl, sc: scope, v: vt<scope>) {
134
136
visit:: visit_decl ( d, sc, v) ;
135
137
alt d. node {
136
138
ast:: decl_local ( locs) {
137
- // FIXME check that init is lvalue
138
- for ( style, loc) in locs {
139
+ for ( _, loc) in locs {
139
140
alt loc. node . init {
140
141
some ( init) {
141
142
if init. op == ast:: init_move {
@@ -150,6 +151,59 @@ fn visit_decl(cx: @ctx, d: @ast::decl, sc: scope, v: vt<scope>) {
150
151
}
151
152
}
152
153
154
+ fn visit_block ( cx : @ctx , b : ast:: blk , sc : scope , v : vt < scope > ) {
155
+ let ref_locs = [ ] ;
156
+ for stmt in b. node . stmts {
157
+ alt stmt. node {
158
+ ast:: stmt_decl ( @{ node: ast:: decl_local ( ls) , _} , _) {
159
+ for ( st, loc) in ls {
160
+ if st == ast:: let_ref {
161
+ ref_locs += [ loc] ;
162
+ }
163
+ }
164
+ }
165
+ _ { }
166
+ }
167
+ }
168
+ if vec:: len ( ref_locs) > 0 u {
169
+ let bindings = sc. bs ;
170
+ for loc in ref_locs { add_bindings_for_let ( * cx, bindings, loc) ; }
171
+ visit:: visit_block ( b, { bs: bindings with sc} , v) ;
172
+ } else {
173
+ visit:: visit_block ( b, sc, v) ;
174
+ }
175
+ }
176
+
177
+ fn add_bindings_for_let ( cx : ctx , & bs: [ binding ] , loc : @ast:: local ) {
178
+ alt loc. node . init {
179
+ some ( init) {
180
+ if init. op == ast:: init_move {
181
+ cx. tcx . sess . span_err
182
+ ( loc. span , "can not move into a by-reference binding" ) ;
183
+ }
184
+ let root = expr_root ( cx. tcx , init. expr , false ) ;
185
+ let root_var = path_def_id ( cx, root. ex ) ;
186
+ // FIXME also allow by-ref function calls
187
+ if is_none ( root_var) {
188
+ cx. tcx . sess . span_err ( loc. span , "a reference binding can't be \
189
+ rooted in a temporary") ;
190
+ }
191
+ for proot in * pattern_roots ( cx. tcx , * root. ds , loc. node . pat ) {
192
+ let bnd = mk_binding ( cx, proot. id , proot. span , root_var,
193
+ inner_mut ( proot. ds ) ) ;
194
+ // Don't implicitly copy explicit references
195
+ bnd. copied = not_allowed;
196
+ bs += [ bnd] ;
197
+ }
198
+ }
199
+ _ {
200
+ cx. tcx . sess . span_err
201
+ ( loc. span , "by-reference bindings must be initialized" ) ;
202
+ }
203
+ }
204
+ }
205
+
206
+
153
207
fn cant_copy ( cx : ctx , b : binding ) -> bool {
154
208
alt b. copied {
155
209
not_allowed. { ret true ; }
0 commit comments