@@ -64,7 +64,7 @@ fn visit_expr(&@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
64
64
alt ( val) {
65
65
case ( some ( ?ex) ) {
66
66
auto root = expr_root ( * cx, ex, false ) ;
67
- if ( ! is_none ( root. inner_mut ) ) {
67
+ if ( mut_field ( root. ds ) ) {
68
68
cx. tcx . sess . span_err
69
69
( ex. span ,
70
70
"result of put must be immutably rooted" ) ;
@@ -129,7 +129,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
129
129
vec:: push ( mut_roots, tup ( i, did. _1 ) ) ;
130
130
}
131
131
case ( _) {
132
- if ( !root. mut_field ) {
132
+ if ( !mut_field ( root. ds ) ) {
133
133
cx. tcx . sess . span_err
134
134
( arg. span , "passing a temporary value or \
135
135
immutable field by mutable alias") ;
@@ -141,7 +141,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
141
141
case ( some ( ?did) ) { vec:: push ( roots, did. _1 ) ; }
142
142
case ( _) { }
143
143
}
144
- alt ( root. inner_mut ) {
144
+ alt ( inner_mut ( root. ds ) ) {
145
145
case ( some ( ?t) ) {
146
146
vec:: push ( unsafe_ts, t) ;
147
147
vec:: push ( unsafe_t_offsets, i) ;
@@ -208,7 +208,7 @@ fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms,
208
208
case ( some( ?did) ) { [ did. _1] }
209
209
case ( _) { [ ] }
210
210
} ;
211
- let vec[ ty:: t] forbidden_tp = alt ( root. inner_mut ) {
211
+ let vec[ ty:: t] forbidden_tp = alt ( inner_mut ( root. ds ) ) {
212
212
case ( some( ?t) ) { [ t] }
213
213
case ( _) { [ ] }
214
214
} ;
@@ -276,7 +276,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq,
276
276
case ( some( ?did) ) { [ did. _1] }
277
277
case ( _) { [ ] }
278
278
} ;
279
- auto unsafe = alt ( root. inner_mut ) {
279
+ auto unsafe = alt ( inner_mut ( root. ds ) ) {
280
280
case ( some( ?t) ) { [ t] }
281
281
case ( _) { [ ] }
282
282
} ;
@@ -389,82 +389,89 @@ fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
389
389
ret result;
390
390
}
391
391
392
+ tag deref_t {
393
+ unbox;
394
+ field ( ident) ;
395
+ index;
396
+ }
397
+ type deref = rec ( bool mut, deref_t kind, ty:: t outer_t ) ;
398
+
399
+ // Finds the root (the thing that is dereferenced) for the given expr, and a
400
+ // vec of dereferences that were used on this root. Note that, in this vec,
401
+ // the inner derefs come in front, so foo.bar.baz becomes rec(ex=foo,
402
+ // ds=[field(baz),field(bar)])
392
403
fn expr_root ( & ctx cx, @ast:: expr ex, bool autoderef )
393
- -> rec ( @ast:: expr ex,
394
- option:: t[ ty:: t ] inner_mut ,
395
- bool mut_in_box ,
396
- bool mut_field ) {
397
- let option:: t[ ty:: t] mut = none;
398
- // This is not currently used but would make it possible to be more
399
- // liberal -- only stuff in a mutable box needs full type-inclusion
400
- // checking, things that aren't in a box need only be checked against
401
- // locally live aliases and their root.
402
- auto mut_in_box = false ;
403
- auto mut_fld = false ;
404
- auto depth = 0 ;
404
+ -> rec ( @ast:: expr ex, vec[ deref] ds ) {
405
+
406
+ fn maybe_auto_unbox ( & ctx cx, & ty:: t t)
407
+ -> rec ( ty:: t t, option:: t[ deref] d ) {
408
+ alt ( ty:: struct ( * cx. tcx , t) ) {
409
+ case ( ty:: ty_box ( ?mt) ) {
410
+ ret rec ( t=mt. ty , d=some ( rec ( mut=mt. mut != ast:: imm,
411
+ kind=unbox,
412
+ outer_t=t) ) ) ;
413
+ }
414
+ case ( _) {
415
+ ret rec ( t=t, d=none) ;
416
+ }
417
+ }
418
+ }
419
+ fn maybe_push_auto_unbox ( & option:: t[ deref] d , & mutable vec[ deref] ds ) {
420
+ alt ( d) {
421
+ case ( some ( ?d) ) { vec:: push ( ds, d) ; }
422
+ case ( none) { }
423
+ }
424
+ }
425
+
426
+ let vec[ deref] ds = [ ] ;
405
427
while ( true ) {
406
428
alt ( { ex. node } ) {
407
429
case ( ast:: expr_field ( ?base, ?ident, _) ) {
408
- auto base_t = ty:: expr_ty ( * cx. tcx , base) ;
409
- auto auto_unbox = maybe_auto_unbox ( cx, base_t) ;
430
+ auto auto_unbox = maybe_auto_unbox
431
+ ( cx, ty:: expr_ty ( * cx. tcx , base) ) ;
432
+ auto mut = false ;
410
433
alt ( ty:: struct ( * cx. tcx , auto_unbox. t ) ) {
411
434
case ( ty:: ty_tup ( ?fields) ) {
412
435
auto fnm = ty:: field_num ( cx. tcx . sess , ex. span , ident) ;
413
- if ( fields. ( fnm) . mut != ast:: imm) {
414
- if ( is_none ( mut) ) { mut = some ( auto_unbox. t ) ; }
415
- if ( depth == 0 ) { mut_fld = true ; }
416
- }
436
+ mut = fields. ( fnm) . mut != ast:: imm;
417
437
}
418
438
case ( ty:: ty_rec ( ?fields) ) {
419
439
for ( ty:: field fld in fields) {
420
440
if ( str:: eq ( ident, fld. ident ) ) {
421
- if ( fld. mt . mut != ast:: imm) {
422
- if ( is_none ( mut) ) {
423
- mut = some ( auto_unbox. t ) ;
424
- }
425
- if ( depth == 0 ) { mut_fld = true ; }
426
- }
441
+ mut = fld. mt . mut != ast:: imm;
427
442
break ;
428
443
}
429
444
}
430
445
}
431
446
case ( ty:: ty_obj ( _) ) { }
432
447
}
433
- if ( auto_unbox . done ) {
434
- if ( ! is_none ( mut ) ) { mut_in_box = true ; }
435
- else if ( auto_unbox . mut ) { mut = some ( base_t ) ; }
436
- }
448
+ vec :: push ( ds , rec ( mut=mut ,
449
+ kind= field ( ident ) ,
450
+ outer_t=auto_unbox . t ) ) ;
451
+ maybe_push_auto_unbox ( auto_unbox . d , ds ) ;
437
452
ex = base;
438
453
}
439
454
case ( ast:: expr_index ( ?base, _, _) ) {
440
- auto base_t = ty :: expr_ty ( * cx . tcx , base ) ;
441
- auto auto_unbox = maybe_auto_unbox ( cx, base_t ) ;
455
+ auto auto_unbox = maybe_auto_unbox
456
+ ( cx, ty :: expr_ty ( * cx . tcx , base ) ) ;
442
457
alt ( ty:: struct ( * cx. tcx , auto_unbox. t ) ) {
443
458
case ( ty:: ty_vec ( ?mt) ) {
444
- if ( mt. mut != ast:: imm) {
445
- if ( is_none ( mut) ) { mut = some ( auto_unbox. t ) ; }
446
- if ( depth == 0 ) { mut_fld = true ; }
447
- }
459
+ vec:: push ( ds, rec ( mut=mt. mut != ast:: imm,
460
+ kind=index,
461
+ outer_t=auto_unbox. t ) ) ;
448
462
}
449
463
}
450
- if ( auto_unbox. done ) {
451
- if ( !is_none ( mut) ) { mut_in_box = true ; }
452
- else if ( auto_unbox. mut ) { mut = some ( base_t) ; }
453
- }
464
+ maybe_push_auto_unbox ( auto_unbox. d , ds) ;
454
465
ex = base;
455
466
}
456
467
case ( ast:: expr_unary ( ?op, ?base, _) ) {
457
468
if ( op == ast:: deref) {
458
469
auto base_t = ty:: expr_ty ( * cx. tcx , base) ;
459
470
alt ( ty:: struct ( * cx. tcx , base_t) ) {
460
471
case ( ty:: ty_box ( ?mt) ) {
461
- if ( mt. mut != ast:: imm) {
462
- if ( is_none ( mut) ) { mut = some ( base_t) ; }
463
- if ( depth == 0 ) { mut_fld = true ; }
464
- }
465
- if ( !is_none ( mut) ) {
466
- mut_in_box = true ;
467
- }
472
+ vec:: push ( ds, rec ( mut=mt. mut != ast:: imm,
473
+ kind=unbox,
474
+ outer_t=base_t) ) ;
468
475
}
469
476
}
470
477
ex = base;
@@ -474,35 +481,26 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
474
481
}
475
482
case ( _) { break ; }
476
483
}
477
- depth += 1 ;
478
484
}
479
485
if ( autoderef) {
480
- auto ex_t = ty:: expr_ty ( * cx. tcx , ex) ;
481
- auto auto_unbox = maybe_auto_unbox ( cx, ex_t) ;
482
- if ( auto_unbox. done ) {
483
- if ( !is_none ( mut) ) { mut_in_box = true ; }
484
- else if ( auto_unbox. mut ) {
485
- mut = some ( ex_t) ;
486
- if ( depth == 0 ) { mut_fld = true ; }
487
- }
488
- }
486
+ auto auto_unbox = maybe_auto_unbox ( cx, ty:: expr_ty ( * cx. tcx , ex) ) ;
487
+ maybe_push_auto_unbox ( auto_unbox. d , ds) ;
489
488
}
490
- ret rec( ex = ex,
491
- inner_mut = mut,
492
- mut_in_box = mut_in_box,
493
- mut_field = mut_fld) ;
489
+ ret rec( ex=ex, ds=ds) ;
494
490
}
495
491
496
- fn maybe_auto_unbox ( & ctx cx, & ty:: t t)
497
- -> rec ( ty:: t t, bool done, bool mut) {
498
- alt ( ty:: struct ( * cx. tcx , t) ) {
499
- case ( ty:: ty_box ( ?mt) ) {
500
- ret rec ( t=mt. ty , done=true , mut=mt. mut != ast:: imm) ;
501
- }
502
- case ( _) {
503
- ret rec ( t=t, done=false , mut=false ) ;
504
- }
492
+ fn mut_field ( & vec[ deref] ds) -> bool {
493
+ for ( deref d in ds) {
494
+ if ( d. mut ) { ret true ; }
495
+ }
496
+ ret false ;
497
+ }
498
+
499
+ fn inner_mut ( & vec[ deref] ds) -> option:: t[ ty:: t] {
500
+ for ( deref d in ds) {
501
+ if ( d. mut ) { ret some ( d. outer_t ) ; }
505
502
}
503
+ ret none;
506
504
}
507
505
508
506
fn path_def_id ( & ctx cx, & @ast:: expr ex) -> option:: t [ ast:: def_id ] {
0 commit comments