@@ -28,26 +28,32 @@ tag valid { valid; overwritten(span, ast::path); val_taken(span, ast::path); }
28
28
29
29
type restrict =
30
30
@{ root_vars: [ node_id] ,
31
- block_defnum : node_id ,
31
+ local_id : uint ,
32
32
bindings: [ node_id] ,
33
33
tys: [ ty:: t] ,
34
34
depends_on: [ uint] ,
35
35
mutable ok: valid} ;
36
36
37
37
type scope = @[ restrict ] ;
38
38
39
- tag local_info { arg( ast:: mode) ; objfield ( ast:: mutability) ; }
39
+ tag local_info {
40
+ arg( ast:: mode) ;
41
+ objfield ( ast:: mutability) ;
42
+ local ( uint) ;
43
+ }
40
44
41
45
type mut_map = std:: map:: hashmap < node_id , ( ) > ;
42
46
type ctx = { tcx : ty:: ctxt ,
43
47
local_map : std:: map:: hashmap < node_id , local_info > ,
48
+ mutable next_local: uint ,
44
49
mut_map : mut_map } ;
45
50
46
51
fn check_crate ( tcx : ty:: ctxt , crate : & @ast:: crate ) -> mut_map {
47
52
// Stores information about object fields and function
48
53
// arguments that's otherwise not easily available.
49
54
let cx = @{ tcx: tcx,
50
55
local_map: std:: map:: new_int_hash ( ) ,
56
+ mutable next_local: 0 u,
51
57
mut_map: std:: map:: new_int_hash ( ) } ;
52
58
let v = @{ visit_fn: bind visit_fn ( cx, _, _, _, _, _, _, _) ,
53
59
visit_item: bind visit_item ( cx, _, _, _) ,
@@ -83,7 +89,7 @@ fn visit_fn(cx: &@ctx, f: &ast::_fn, _tp: &[ast::ty_param], _sp: &span,
83
89
@[
84
90
// I'm not sure if there is anything sensical to put here
85
91
@{ root_vars: [ ] ,
86
- block_defnum : 0 ,
92
+ local_id : cx . next_local ,
87
93
bindings: dnums,
88
94
tys: [ ] ,
89
95
depends_on: [ ] ,
@@ -162,6 +168,13 @@ fn visit_expr(cx: &@ctx, ex: &@ast::expr, sc: &scope, v: &vt<scope>) {
162
168
if !handled { visit:: visit_expr ( ex, sc, v) ; }
163
169
}
164
170
171
+ fn register_locals ( cx : & ctx , pat : & @ast:: pat ) {
172
+ for each pat in ast_util:: pat_bindings ( pat) {
173
+ cx. local_map . insert ( pat. id , local ( cx. next_local ) ) ;
174
+ cx. next_local += 1 u;
175
+ }
176
+ }
177
+
165
178
fn visit_decl ( cx : & @ctx , d : & @ast:: decl , sc : & scope , v : & vt < scope > ) {
166
179
visit:: visit_decl ( d, sc, v) ;
167
180
alt d. node {
@@ -175,6 +188,7 @@ fn visit_decl(cx: &@ctx, d: &@ast::decl, sc: &scope, v: &vt<scope>) {
175
188
}
176
189
none. { }
177
190
}
191
+ register_locals ( * cx, loc. node . pat ) ;
178
192
}
179
193
}
180
194
_ { }
@@ -331,55 +345,51 @@ fn check_tail_call(cx: &ctx, call: &@ast::expr) {
331
345
332
346
fn check_alt ( cx : & ctx , input : & @ast:: expr , arms : & [ ast:: arm ] , sc : & scope ,
333
347
v : & vt < scope > ) {
334
- visit :: visit_expr ( input, sc, v) ;
348
+ v . visit_expr ( input, sc, v) ;
335
349
let root = expr_root ( cx, input, true ) ;
336
350
let roots =
337
351
alt path_def_id ( cx, root. ex ) { some ( did) { [ did. node ] } _ { [ ] } } ;
338
352
let forbidden_tp: [ ty:: t ] =
339
353
alt inner_mut ( root. ds ) { some ( t) { [ t] } _ { [ ] } } ;
340
354
for a: ast:: arm in arms {
341
- let dnums = arm_defnums ( a ) ;
355
+ let dnums = ast_util :: pat_binding_ids ( a . pats [ 0 ] ) ;
342
356
let new_sc = sc;
343
357
if vec:: len ( dnums) > 0 u {
344
- new_sc =
345
- @( * sc +
346
- [ @{ root_vars: roots,
347
- block_defnum: dnums[ vec:: len ( dnums) - 1 u] ,
348
- bindings: dnums,
349
- tys: forbidden_tp,
350
- depends_on: deps ( sc, roots) ,
351
- mutable ok: valid} ] ) ;
358
+ new_sc = @( * sc + [ @{ root_vars: roots,
359
+ local_id: cx. next_local ,
360
+ bindings: dnums,
361
+ tys: forbidden_tp,
362
+ depends_on: deps ( sc, roots) ,
363
+ mutable ok: valid} ] ) ;
352
364
}
365
+ register_locals ( cx, a. pats [ 0 ] ) ;
353
366
visit:: visit_arm ( a, new_sc, v) ;
354
367
}
355
368
}
356
369
357
- fn arm_defnums ( arm : & ast:: arm ) -> [ node_id ] {
358
- ret ast_util:: pat_binding_ids ( arm. pats [ 0 ] ) ;
359
- }
360
-
361
370
fn check_for_each ( cx : & ctx , local : & @ast:: local , call : & @ast:: expr ,
362
371
blk : & ast:: blk , sc : & scope , v : & vt < scope > ) {
363
- visit :: visit_expr ( call, sc, v) ;
372
+ v . visit_expr ( call, sc, v) ;
364
373
alt call. node {
365
374
ast:: expr_call ( f, args) {
366
375
let data = check_call ( cx, f, args, sc) ;
367
376
let bindings = ast_util:: pat_binding_ids ( local. node . pat ) ;
368
377
let new_sc =
369
378
@{ root_vars: data. root_vars ,
370
- block_defnum : bindings [ vec :: len ( bindings ) - 1 u ] ,
379
+ local_id : cx . next_local ,
371
380
bindings: bindings,
372
381
tys: data. unsafe_ts ,
373
382
depends_on: deps ( sc, data. root_vars ) ,
374
383
mutable ok: valid} ;
384
+ register_locals ( cx, local. node . pat ) ;
375
385
visit:: visit_block ( blk, @( * sc + [ new_sc] ) , v) ;
376
386
}
377
387
}
378
388
}
379
389
380
390
fn check_for ( cx : & ctx , local : & @ast:: local , seq : & @ast:: expr , blk : & ast:: blk ,
381
391
sc : & scope , v : & vt < scope > ) {
382
- visit :: visit_expr ( seq, sc, v) ;
392
+ v . visit_expr ( seq, sc, v) ;
383
393
let root = expr_root ( cx, seq, false ) ;
384
394
let root_def =
385
395
alt path_def_id ( cx, root. ex ) { some ( did) { [ did. node ] } _ { [ ] } } ;
@@ -400,11 +410,12 @@ fn check_for(cx: &ctx, local: &@ast::local, seq: &@ast::expr, blk: &ast::blk,
400
410
let bindings = ast_util::pat_binding_ids(local.node.pat);
401
411
let new_sc =
402
412
@{root_vars: root_def,
403
- block_defnum: bindings[vec::len(bindings) - 1u] ,
413
+ local_id: cx.next_local ,
404
414
bindings: bindings,
405
415
tys: unsafe,
406
416
depends_on: deps(sc, root_def),
407
417
mutable ok: valid};
418
+ register_locals(cx, local.node.pat);
408
419
visit::visit_block(blk, @(*sc + [new_sc]), v);
409
420
}
410
421
@@ -413,12 +424,14 @@ fn check_var(cx: &ctx, ex: &@ast::expr, p: &ast::path, id: ast::node_id,
413
424
let def = cx.tcx.def_map.get(id);
414
425
if !def_is_local(def, true) { ret; }
415
426
let my_defnum = ast_util::def_id_of_def(def).node;
427
+ let my_local_id = alt cx.local_map.find(my_defnum) {
428
+ some(local(id)) { id }
429
+ _ { 0u }
430
+ };
416
431
let var_t = ty::expr_ty(cx.tcx, ex);
417
432
for r: restrict in *sc {
418
-
419
433
// excludes variables introduced since the alias was made
420
- // FIXME This does not work anymore, now that we have macros.
421
- if my_defnum < r.block_defnum {
434
+ if my_local_id < r.local_id {
422
435
for t: ty::t in r.tys {
423
436
if ty_can_unsafely_include(cx, t, var_t, assign) {
424
437
r.ok = val_taken(ex.span, p);
0 commit comments