17
17
*/
18
18
19
19
20
- use std:: cast;
21
20
use std:: io;
22
21
use std:: uint;
23
22
use std:: vec;
@@ -72,9 +71,6 @@ pub trait DataFlowOperator {
72
71
73
72
/// Joins two predecessor bits together, typically either `|` or `&`
74
73
fn join ( & self , succ : uint , pred : uint ) -> uint ;
75
-
76
- /// True if we should propagate through closures
77
- fn walk_closures ( & self ) -> bool ;
78
74
}
79
75
80
76
struct PropagationContext < ' a , O > {
@@ -373,8 +369,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
373
369
blk : & ast:: Block ,
374
370
in_out : & mut [ uint ] ,
375
371
loop_scopes : & mut ~[ LoopScope ] ) {
376
- debug ! ( "DataFlowContext::walk_block(blk.id={:? }, in_out={})" ,
377
- blk. id, bits_to_str( reslice ( in_out) ) ) ;
372
+ debug ! ( "DataFlowContext::walk_block(blk.id={}, in_out={})" ,
373
+ blk. id, bits_to_str( in_out) ) ;
378
374
379
375
self . merge_with_entry_set ( blk. id , in_out) ;
380
376
@@ -425,99 +421,12 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
425
421
in_out : & mut [ uint ] ,
426
422
loop_scopes : & mut ~[ LoopScope ] ) {
427
423
debug ! ( "DataFlowContext::walk_expr(expr={}, in_out={})" ,
428
- expr. repr( self . dfcx. tcx) , bits_to_str( reslice ( in_out) ) ) ;
424
+ expr. repr( self . dfcx. tcx) , bits_to_str( in_out) ) ;
429
425
430
426
self . merge_with_entry_set ( expr. id , in_out) ;
431
427
432
428
match expr. node {
433
- ast:: ExprFnBlock ( ref decl, body) |
434
- ast:: ExprProc ( ref decl, body) => {
435
- if self . dfcx . oper . walk_closures ( ) {
436
- // In the absence of once fns, we must assume that
437
- // every function body will execute more than
438
- // once. Thus we treat every function body like a
439
- // loop.
440
- //
441
- // What is subtle and a bit tricky, also, is how
442
- // to deal with the "output" bits---that is, what
443
- // do we consider to be the successor of a
444
- // function body, given that it could be called
445
- // from any point within its lifetime? What we do
446
- // is to add their effects immediately as of the
447
- // point of creation. Of course we have to ensure
448
- // that this is sound for the analyses which make
449
- // use of dataflow.
450
- //
451
- // In the case of the initedness checker (which
452
- // does not currently use dataflow, but I hope to
453
- // convert at some point), we will simply not walk
454
- // closures at all, so it's a moot point.
455
- //
456
- // In the case of the borrow checker, this means
457
- // the loans which would be created by calling a
458
- // function come into effect immediately when the
459
- // function is created. This is guaranteed to be
460
- // earlier than the point at which the loan
461
- // actually comes into scope (which is the point
462
- // at which the closure is *called*). Because
463
- // loans persist until the scope of the loans is
464
- // exited, it is always a safe approximation to
465
- // have a loan begin earlier than it actually will
466
- // at runtime, so this should be sound.
467
- //
468
- // We stil have to be careful in the region
469
- // checker and borrow checker to treat function
470
- // bodies like loops, which implies some
471
- // limitations. For example, a closure cannot root
472
- // a managed box for longer than its body.
473
- //
474
- // General control flow looks like this:
475
- //
476
- // +- (expr) <----------+
477
- // | | |
478
- // | v |
479
- // | (body) -----------+--> (exit)
480
- // | | |
481
- // | + (break/loop) -+
482
- // | |
483
- // +--------------------+
484
- //
485
- // This is a bit more conservative than a loop.
486
- // Note that we must assume that even after a
487
- // `break` occurs (e.g., in a `for` loop) that the
488
- // closure may be reinvoked.
489
- //
490
- // One difference from other loops is that `loop`
491
- // and `break` statements which target a closure
492
- // both simply add to the `break_bits`.
493
-
494
- // func_bits represents the state when the function
495
- // returns
496
- let mut func_bits = reslice ( in_out) . to_owned ( ) ;
497
-
498
- loop_scopes. push ( LoopScope {
499
- loop_id : expr. id ,
500
- break_bits : reslice ( in_out) . to_owned ( )
501
- } ) ;
502
- for input in decl. inputs . iter ( ) {
503
- self . walk_pat ( input. pat , func_bits, loop_scopes) ;
504
- }
505
- self . walk_block ( body, func_bits, loop_scopes) ;
506
-
507
- // add the bits from any early return via `break`,
508
- // `continue`, or `return` into `func_bits`
509
- let loop_scope = loop_scopes. pop ( ) . unwrap ( ) ;
510
- join_bits ( & self . dfcx . oper , loop_scope. break_bits , func_bits) ;
511
-
512
- // add `func_bits` to the entry bits for `expr`,
513
- // since we must assume the function may be called
514
- // more than once
515
- self . add_to_entry_set ( expr. id , reslice ( func_bits) ) ;
516
-
517
- // the final exit bits include whatever was present
518
- // in the original, joined with the bits from the function
519
- join_bits ( & self . dfcx . oper , func_bits, in_out) ;
520
- }
429
+ ast:: ExprFnBlock ( ..) | ast:: ExprProc ( ..) => {
521
430
}
522
431
523
432
ast:: ExprIf ( cond, then, els) => {
@@ -536,7 +445,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
536
445
//
537
446
self . walk_expr ( cond, in_out, loop_scopes) ;
538
447
539
- let mut then_bits = reslice ( in_out) . to_owned ( ) ;
448
+ let mut then_bits = in_out. to_owned ( ) ;
540
449
self . walk_block ( then, then_bits, loop_scopes) ;
541
450
542
451
self . walk_opt_expr ( els, in_out, loop_scopes) ;
@@ -558,10 +467,10 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
558
467
559
468
self . walk_expr ( cond, in_out, loop_scopes) ;
560
469
561
- let mut body_bits = reslice ( in_out) . to_owned ( ) ;
470
+ let mut body_bits = in_out. to_owned ( ) ;
562
471
loop_scopes. push ( LoopScope {
563
472
loop_id : expr. id ,
564
- break_bits : reslice ( in_out) . to_owned ( )
473
+ break_bits : in_out. to_owned ( )
565
474
} ) ;
566
475
self . walk_block ( blk, body_bits, loop_scopes) ;
567
476
self . add_to_entry_set ( expr. id , body_bits) ;
@@ -581,11 +490,11 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
581
490
// <--+ (break)
582
491
//
583
492
584
- let mut body_bits = reslice ( in_out) . to_owned ( ) ;
493
+ let mut body_bits = in_out. to_owned ( ) ;
585
494
self . reset ( in_out) ;
586
495
loop_scopes. push ( LoopScope {
587
496
loop_id : expr. id ,
588
- break_bits : reslice ( in_out) . to_owned ( )
497
+ break_bits : in_out. to_owned ( )
589
498
} ) ;
590
499
self . walk_block ( blk, body_bits, loop_scopes) ;
591
500
self . add_to_entry_set ( expr. id , body_bits) ;
@@ -609,7 +518,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
609
518
//
610
519
self . walk_expr ( discr, in_out, loop_scopes) ;
611
520
612
- let mut guards = reslice ( in_out) . to_owned ( ) ;
521
+ let mut guards = in_out. to_owned ( ) ;
613
522
614
523
// We know that exactly one arm will be taken, so we
615
524
// can start out with a blank slate and just union
@@ -622,7 +531,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
622
531
623
532
// determine the bits for the body and then union
624
533
// them into `in_out`, which reflects all bodies to date
625
- let mut body = reslice ( guards) . to_owned ( ) ;
534
+ let mut body = guards. to_owned ( ) ;
626
535
self . walk_pat_alternatives ( arm. pats , body, loop_scopes) ;
627
536
self . walk_block ( arm. body , body, loop_scopes) ;
628
537
join_bits ( & self . dfcx . oper , body, in_out) ;
@@ -643,7 +552,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
643
552
ast:: ExprAgain ( label) => {
644
553
let scope = self . find_scope ( expr, label, loop_scopes) ;
645
554
self . pop_scopes ( expr, scope, in_out) ;
646
- self . add_to_entry_set ( scope. loop_id , reslice ( in_out) ) ;
555
+ self . add_to_entry_set ( scope. loop_id , in_out) ;
647
556
self . reset ( in_out) ;
648
557
}
649
558
@@ -693,7 +602,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
693
602
694
603
ast:: ExprBinary ( _, op, l, r) if ast_util:: lazy_binop ( op) => {
695
604
self . walk_expr ( l, in_out, loop_scopes) ;
696
- let temp = reslice ( in_out) . to_owned ( ) ;
605
+ let temp = in_out. to_owned ( ) ;
697
606
self . walk_expr ( r, in_out, loop_scopes) ;
698
607
join_bits ( & self . dfcx . oper , temp, in_out) ;
699
608
}
@@ -756,7 +665,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
756
665
757
666
debug ! ( "pop_scopes(from_expr={}, to_scope={:?}, in_out={})" ,
758
667
from_expr. repr( tcx) , to_scope. loop_id,
759
- bits_to_str( reslice ( in_out) ) ) ;
668
+ bits_to_str( in_out) ) ;
760
669
761
670
let mut id = from_expr. id ;
762
671
while id != to_scope. loop_id {
@@ -781,11 +690,11 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
781
690
in_out : & mut [ uint ] ) {
782
691
self . pop_scopes ( from_expr, to_scope, in_out) ;
783
692
self . dfcx . apply_kill ( from_expr. id , in_out) ;
784
- join_bits ( & self . dfcx . oper , reslice ( in_out) , to_scope. break_bits ) ;
785
- debug ! ( "break_from_to(from_expr={}, to_scope={:? }) final break_bits={}" ,
693
+ join_bits ( & self . dfcx . oper , in_out, to_scope. break_bits ) ;
694
+ debug ! ( "break_from_to(from_expr={}, to_scope={}) final break_bits={}" ,
786
695
from_expr. repr( self . tcx( ) ) ,
787
696
to_scope. loop_id,
788
- bits_to_str( reslice ( in_out) ) ) ;
697
+ bits_to_str( in_out) ) ;
789
698
}
790
699
791
700
fn walk_exprs ( & mut self ,
@@ -830,10 +739,10 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
830
739
in_out : & mut [ uint ] ,
831
740
_loop_scopes : & mut ~[ LoopScope ] ) {
832
741
debug ! ( "DataFlowContext::walk_pat(pat={}, in_out={})" ,
833
- pat. repr( self . dfcx. tcx) , bits_to_str( reslice ( in_out) ) ) ;
742
+ pat. repr( self . dfcx. tcx) , bits_to_str( in_out) ) ;
834
743
835
744
ast_util:: walk_pat ( pat, |p| {
836
- debug ! ( " p.id={:? } in_out={}" , p. id, bits_to_str( reslice ( in_out) ) ) ;
745
+ debug ! ( " p.id={} in_out={}" , p. id, bits_to_str( in_out) ) ;
837
746
self . merge_with_entry_set ( p. id , in_out) ;
838
747
self . dfcx . apply_gen_kill ( p. id , in_out) ;
839
748
true
@@ -852,7 +761,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
852
761
// In the general case, the patterns in `pats` are
853
762
// alternatives, so we must treat this like an N-way select
854
763
// statement.
855
- let initial_state = reslice ( in_out) . to_owned ( ) ;
764
+ let initial_state = in_out. to_owned ( ) ;
856
765
for & pat in pats. iter ( ) {
857
766
let mut temp = initial_state. clone ( ) ;
858
767
self . walk_pat ( pat, temp, loop_scopes) ;
@@ -929,8 +838,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
929
838
let ( start, end) = self . dfcx . compute_id_range ( id) ;
930
839
let changed = { // FIXME(#5074) awkward construction
931
840
let on_entry = self . dfcx . on_entry . mut_slice ( start, end) ;
932
- let changed = join_bits ( & self . dfcx . oper , reslice ( pred_bits) , on_entry) ;
933
- copy_bits ( reslice ( on_entry) , pred_bits) ;
841
+ let changed = join_bits ( & self . dfcx . oper , pred_bits, on_entry) ;
842
+ copy_bits ( on_entry, pred_bits) ;
934
843
changed
935
844
} ;
936
845
if changed {
@@ -942,7 +851,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
942
851
}
943
852
944
853
fn mut_bits_to_str ( words : & mut [ uint ] ) -> ~str {
945
- bits_to_str ( reslice ( words) )
854
+ bits_to_str ( words)
946
855
}
947
856
948
857
fn bits_to_str ( words : & [ uint ] ) -> ~str {
@@ -1007,9 +916,3 @@ fn bit_str(bit: uint) -> ~str {
1007
916
format ! ( "[{}:{}-{:02x}]" , bit, byte, lobits)
1008
917
}
1009
918
1010
- fn reslice < ' a > ( v : & ' a mut [ uint ] ) -> & ' a [ uint ] {
1011
- // bFIXME(#5074) this function should not be necessary at all
1012
- unsafe {
1013
- cast:: transmute ( v)
1014
- }
1015
- }
0 commit comments