@@ -27,10 +27,10 @@ import std::option::is_none;
27
27
tag valid { valid; overwritten ( span, ast:: path) ; val_taken ( span, ast:: path) ; }
28
28
29
29
type restrict =
30
- @{ root_vars : [ node_id] ,
30
+ @{ root_var : option :: t< node_id> ,
31
31
local_id: uint,
32
32
bindings: [ node_id] ,
33
- tys : [ ty:: t] ,
33
+ unsafe_ty : option :: t< ty:: t> ,
34
34
depends_on: [ uint] ,
35
35
mutable ok: valid} ;
36
36
@@ -86,12 +86,11 @@ fn visit_fn(cx: &@ctx, f: &ast::_fn, _tp: &[ast::ty_param], _sp: &span,
86
86
for each nid in freevars:: get_freevar_defs ( cx. tcx , id) . keys ( ) {
87
87
dnums += [ nid] ;
88
88
} ;
89
- @[
90
- // I'm not sure if there is anything sensical to put here
91
- @{ root_vars: [ ] ,
89
+ // I'm not sure if there is anything sensical to put here
90
+ @[ @{ root_var: none,
92
91
local_id: cx. next_local ,
93
92
bindings: dnums,
94
- tys : [ ] ,
93
+ unsafe_ty : none ,
95
94
depends_on: [ ] ,
96
95
mutable ok: valid} ]
97
96
}
@@ -195,14 +194,12 @@ fn visit_decl(cx: &@ctx, d: &@ast::decl, sc: &scope, v: &vt<scope>) {
195
194
}
196
195
}
197
196
198
- fn check_call ( cx : & ctx , f : & @ast:: expr , args : & [ @ast:: expr ] , sc : & scope ) ->
199
- { root_vars : [ node_id ] , unsafe_ts : [ ty :: t ] } {
197
+ fn check_call ( cx : & ctx , f : & @ast:: expr , args : & [ @ast:: expr ] , sc : & scope )
198
+ -> [ restrict ] {
200
199
let fty = ty:: expr_ty ( cx. tcx , f) ;
201
200
let arg_ts = fty_args ( cx, fty) ;
202
- let roots: [ node_id ] = [ ] ;
203
201
let mut_roots: [ { arg : uint , node : node_id } ] = [ ] ;
204
- let unsafe_ts: [ ty:: t ] = [ ] ;
205
- let unsafe_t_offsets: [ uint ] = [ ] ;
202
+ let restricts = [ ] ;
206
203
let i = 0 u;
207
204
for arg_t: ty:: arg in arg_ts {
208
205
if arg_t. mode != ty:: mo_val {
@@ -242,70 +239,83 @@ fn check_call(cx: &ctx, f: &@ast::expr, args: &[@ast::expr], sc: &scope) ->
242
239
}
243
240
}
244
241
}
245
- alt path_def_id ( cx, root. ex ) {
246
- some ( did) { roots += [ did. node ] ; }
247
- _ { }
248
- }
249
- alt inner_mut( root. ds ) {
250
- some ( t) { unsafe_ts += [ t] ; unsafe_t_offsets += [ i] ; }
251
- _ { }
252
- }
242
+ let root_var = path_def_id ( cx, root. ex ) ;
243
+ let unsafe_t = alt inner_mut ( root. ds ) {
244
+ some ( t) { some ( t) }
245
+ _ { none }
246
+ } ;
247
+ restricts += [ @{ root_var: root_var,
248
+ local_id: cx. next_local ,
249
+ bindings: [ arg. id ] ,
250
+ unsafe_ty: unsafe_t,
251
+ depends_on: deps ( sc, root_var) ,
252
+ mutable ok: valid} ] ;
253
253
}
254
254
i += 1 u;
255
255
}
256
- if vec:: len ( unsafe_ts) > 0 u {
257
- alt f. node {
258
- ast:: expr_path ( _) {
259
- if def_is_local ( cx. tcx . def_map . get ( f. id ) , true ) {
256
+ let f_may_close = alt f. node {
257
+ ast:: expr_path ( _) { def_is_local ( cx. tcx . def_map . get ( f. id ) , true ) }
258
+ _ { false } // FIXME should be true!
259
+ } ;
260
+ if f_may_close {
261
+ let i = 0 u;
262
+ for r in restricts {
263
+ if !option:: is_none ( r. unsafe_ty ) {
260
264
cx. tcx . sess . span_err ( f. span ,
261
- #ifmt[ "function may alias with \
262
- argument %u, which is not immutably rooted",
263
- unsafe_t_offsets [ 0 ] ] ) ;
265
+ #ifmt[ "function may alias with argument \
266
+ %u, which is not immutably rooted",
267
+ i ] ) ;
264
268
}
265
- }
266
- _ { }
269
+ i += 1 u;
267
270
}
268
271
}
269
272
let j = 0 u;
270
- for unsafe: ty:: t in unsafe_ts {
271
- let offset = unsafe_t_offsets[ j] ;
272
- j += 1 u;
273
- let i = 0 u;
274
- for arg_t: ty:: arg in arg_ts {
275
- let mut_alias = arg_t. mode == ty:: mo_alias ( true ) ;
276
- if i != offset &&
277
- ty_can_unsafely_include ( cx, unsafe , arg_t. ty , mut_alias) {
278
- cx. tcx . sess . span_err ( args[ i] . span ,
279
- #ifmt[ "argument %u may alias with \
280
- argument %u, which is not immutably rooted",
281
- i, offset] ) ;
273
+ for @{ unsafe_ty, _} in restricts {
274
+ alt unsafe_ty {
275
+ some( ty) {
276
+ let i = 0 u;
277
+ for arg_t: ty:: arg in arg_ts {
278
+ let mut_alias = arg_t. mode == ty:: mo_alias ( true ) ;
279
+ if i != j &&
280
+ ty_can_unsafely_include ( cx, ty, arg_t. ty , mut_alias) {
281
+ cx. tcx . sess . span_err ( args[ i] . span ,
282
+ #ifmt[ "argument %u may alias with argument %u, \
283
+ which is not immutably rooted", i, j] ) ;
284
+ }
285
+ i += 1 u;
282
286
}
283
- i += 1 u;
287
+ }
288
+ _ { }
284
289
}
290
+ j += 1 u;
285
291
}
286
292
// Ensure we're not passing a root by mutable alias.
287
293
288
- for root : { arg : uint , node : node_id } in mut_roots {
294
+ for { node , arg } in mut_roots {
289
295
let mut_alias_to_root = false ;
290
296
let mut_alias_to_root_count = 0 u;
291
- for r: node_id in roots {
292
- if root. node == r {
293
- mut_alias_to_root_count += 1 u;
294
- if mut_alias_to_root_count > 1 u {
295
- mut_alias_to_root = true ;
296
- break ;
297
+ for @{ root_var, _} in restricts {
298
+ alt root_var {
299
+ some( root) {
300
+ if node == root {
301
+ mut_alias_to_root_count += 1 u;
302
+ if mut_alias_to_root_count > 1 u {
303
+ mut_alias_to_root = true ;
304
+ break ;
305
+ }
297
306
}
307
+ }
308
+ none. { }
298
309
}
299
310
}
300
311
301
-
302
312
if mut_alias_to_root {
303
- cx. tcx . sess . span_err ( args[ root . arg ] . span ,
304
- ~"passing a mutable alias to a \
305
- variable that roots another alias") ;
313
+ cx. tcx . sess . span_err ( args[ arg] . span ,
314
+ ~"passing a mutable alias to a variable \
315
+ that roots another alias") ;
306
316
}
307
317
}
308
- ret { root_vars : roots , unsafe_ts : unsafe_ts } ;
318
+ ret restricts ;
309
319
}
310
320
311
321
fn check_tail_call ( cx : & ctx , call : & @ast:: expr ) {
@@ -347,19 +357,16 @@ fn check_alt(cx: &ctx, input: &@ast::expr, arms: &[ast::arm], sc: &scope,
347
357
v : & vt < scope > ) {
348
358
v. visit_expr ( input, sc, v) ;
349
359
let root = expr_root ( cx, input, true ) ;
350
- let roots =
351
- alt path_def_id ( cx, root. ex ) { some ( did) { [ did. node ] } _ { [ ] } } ;
352
- let forbidden_tp: [ ty:: t ] =
353
- alt inner_mut ( root. ds ) { some ( t) { [ t] } _ { [ ] } } ;
354
360
for a: ast:: arm in arms {
355
361
let dnums = ast_util:: pat_binding_ids ( a. pats [ 0 ] ) ;
356
362
let new_sc = sc;
357
363
if vec:: len ( dnums) > 0 u {
358
- new_sc = @( * sc + [ @{ root_vars: roots,
364
+ let root_var = path_def_id ( cx, root. ex ) ;
365
+ new_sc = @( * sc + [ @{ root_var: root_var,
359
366
local_id: cx. next_local ,
360
367
bindings: dnums,
361
- tys : forbidden_tp ,
362
- depends_on: deps ( sc, roots ) ,
368
+ unsafe_ty : inner_mut ( root . ds ) ,
369
+ depends_on: deps ( sc, root_var ) ,
363
370
mutable ok: valid} ] ) ;
364
371
}
365
372
register_locals ( cx, a. pats [ 0 ] ) ;
@@ -372,17 +379,9 @@ fn check_for_each(cx: &ctx, local: &@ast::local, call: &@ast::expr,
372
379
v. visit_expr ( call, sc, v) ;
373
380
alt call. node {
374
381
ast:: expr_call ( f, args) {
375
- let data = check_call ( cx, f, args, sc) ;
376
- let bindings = ast_util:: pat_binding_ids ( local. node . pat ) ;
377
- let new_sc =
378
- @{ root_vars: data. root_vars ,
379
- local_id: cx. next_local ,
380
- bindings: bindings,
381
- tys: data. unsafe_ts ,
382
- depends_on: deps ( sc, data. root_vars ) ,
383
- mutable ok: valid} ;
382
+ let restricts = check_call ( cx, f, args, sc) ;
384
383
register_locals ( cx, local. node . pat ) ;
385
- visit:: visit_block ( blk, @( * sc + [ new_sc ] ) , v) ;
384
+ visit:: visit_block ( blk, @( * sc + restricts ) , v) ;
386
385
}
387
386
}
388
387
}
@@ -391,29 +390,25 @@ fn check_for(cx: &ctx, local: &@ast::local, seq: &@ast::expr, blk: &ast::blk,
391
390
sc : & scope , v : & vt < scope > ) {
392
391
v. visit_expr ( seq, sc, v) ;
393
392
let root = expr_root ( cx, seq, false ) ;
394
- let root_def =
395
- alt path_def_id ( cx, root. ex ) { some ( did) { [ did. node ] } _ { [ ] } } ;
396
- let unsafe = alt inner_mut ( root. ds ) { some ( t) { [ t] } _ { [ ] } } ;
393
+ let unsafe = inner_mut ( root. ds ) ;
397
394
398
395
// If this is a mutable vector, don't allow it to be touched.
399
396
let seq_t = ty:: expr_ty ( cx. tcx , seq) ;
400
397
alt ty:: struct ( cx. tcx , seq_t) {
401
- ty:: ty_vec ( mt) { if mt. mut != ast:: imm { unsafe = [ seq_t] ; } }
398
+ ty:: ty_vec ( mt) { if mt. mut != ast:: imm { unsafe = some ( seq_t) ; } }
402
399
ty:: ty_str. | ty:: ty_istr. { /* no-op */ }
403
400
_ {
404
- cx. tcx . sess . span_unimpl (
405
- seq. span ,
406
- ~"unknown seq type " +
407
- util::ppaux::ty_to_str(cx.tcx, seq_t));
401
+ cx. tcx . sess . span_unimpl ( seq. span , ~"unknown seq type " +
402
+ util::ppaux::ty_to_str(cx.tcx, seq_t));
408
403
}
409
404
}
410
- let bindings = ast_util::pat_binding_ids(local.node.pat );
405
+ let root_var = path_def_id(cx, root.ex );
411
406
let new_sc =
412
- @{root_vars: root_def ,
407
+ @{root_var: root_var ,
413
408
local_id: cx.next_local,
414
- bindings: bindings ,
415
- tys : unsafe,
416
- depends_on: deps(sc, root_def ),
409
+ bindings: ast_util::pat_binding_ids(local.node.pat) ,
410
+ unsafe_ty : unsafe,
411
+ depends_on: deps(sc, root_var ),
417
412
mutable ok: valid};
418
413
register_locals(cx, local.node.pat);
419
414
visit::visit_block(blk, @(*sc + [new_sc]), v);
@@ -432,10 +427,13 @@ fn check_var(cx: &ctx, ex: &@ast::expr, p: &ast::path, id: ast::node_id,
432
427
for r: restrict in *sc {
433
428
// excludes variables introduced since the alias was made
434
429
if my_local_id < r.local_id {
435
- for t: ty::t in r.tys {
436
- if ty_can_unsafely_include(cx, t, var_t, assign) {
430
+ alt r.unsafe_ty {
431
+ some(ty) {
432
+ if ty_can_unsafely_include(cx, ty, var_t, assign) {
437
433
r.ok = val_taken(ex.span, p);
438
434
}
435
+ }
436
+ _ {}
439
437
}
440
438
} else if vec::member(my_defnum, r.bindings) {
441
439
test_scope(cx, sc, r, p);
@@ -455,7 +453,7 @@ fn check_lval(cx: &@ctx, dest: &@ast::expr, sc: &scope, v: &vt<scope>) {
455
453
~"assigning to immutable obj field") ;
456
454
}
457
455
for r: restrict in * sc {
458
- if vec :: member ( dnum , r . root_vars ) {
456
+ if r . root_var == some ( dnum ) {
459
457
r. ok = overwritten ( dest. span , p) ;
460
458
}
461
459
}
@@ -548,14 +546,17 @@ fn test_scope(cx: &ctx, sc: &scope, r: &restrict, p: &ast::path) {
548
546
}
549
547
}
550
548
551
- fn deps ( sc : & scope , roots : & [ node_id ] ) -> [ uint ] {
552
- let i = 0 u;
549
+ fn deps ( sc : & scope , root : & option:: t < node_id > ) -> [ uint ] {
553
550
let result = [ ] ;
554
- for r: restrict in * sc {
555
- for dn: node_id in roots {
551
+ alt root {
552
+ some( dn) {
553
+ let i = 0 u;
554
+ for r: restrict in * sc {
556
555
if vec:: member ( dn, r. bindings ) { result += [ i] ; }
556
+ i += 1 u;
557
557
}
558
- i += 1 u;
558
+ }
559
+ _ { }
559
560
}
560
561
ret result;
561
562
}
@@ -678,10 +679,10 @@ fn path_def(cx: &ctx, ex: &@ast::expr) -> option::t<ast::def> {
678
679
}
679
680
}
680
681
681
- fn path_def_id ( cx : & ctx , ex : & @ast:: expr ) -> option:: t < ast:: def_id > {
682
+ fn path_def_id ( cx : & ctx , ex : & @ast:: expr ) -> option:: t < ast:: node_id > {
682
683
alt ex. node {
683
684
ast:: expr_path ( _) {
684
- ret some ( ast_util:: def_id_of_def ( cx. tcx . def_map . get ( ex. id ) ) ) ;
685
+ ret some ( ast_util:: def_id_of_def ( cx. tcx . def_map . get ( ex. id ) ) . node ) ;
685
686
}
686
687
_ { ret none; }
687
688
}
0 commit comments