@@ -98,6 +98,7 @@ state type fn_ctxt = rec(ValueRef llfn,
98
98
hashmap[ ast. def_id, ValueRef ] llargs ,
99
99
hashmap[ ast. def_id, ValueRef ] llobjfields ,
100
100
hashmap[ ast. def_id, ValueRef ] lllocals ,
101
+ hashmap[ ast. def_id, ValueRef ] llupvars ,
101
102
hashmap[ ast. def_id, ValueRef ] lltydescs ,
102
103
@crate_ctxt ccx ) ;
103
104
@@ -2897,6 +2898,62 @@ fn trans_for(@block_ctxt cx,
2897
2898
bind inner( _, local, _, _, body) ) ;
2898
2899
}
2899
2900
2901
+
2902
+ // Iterator translation
2903
+
2904
+ // Searches through a block for all references to locals or upvars in this
2905
+ // frame and returns the list of definition IDs thus found.
2906
+ fn collect_upvars( @block_ctxt cx, & ast. block bloc, & ast. def_id initial_decl)
2907
+ -> vec[ ast. def_id] {
2908
+ type env = @rec(
2909
+ mutable vec[ ast. def_id] refs,
2910
+ hashmap[ ast. def_id, ( ) ] decls
2911
+ ) ;
2912
+
2913
+ fn fold_expr_path( & env e, & common. span sp, & ast. path p,
2914
+ & option. t[ ast. def] d, ast. ann a) -> @ast. expr {
2915
+ alt ( option. get[ ast. def] ( d) ) {
2916
+ case ( ast. def_arg( ?did) ) { e. refs += vec( did) ; }
2917
+ case ( ast. def_local( ?did) ) { e. refs += vec( did) ; }
2918
+ case ( ast. def_upvar( ?did) ) { e. refs += vec( did) ; }
2919
+ case ( _) { /* ignore */ }
2920
+ }
2921
+
2922
+ ret @fold. respan[ ast. expr_] ( sp, ast. expr_path( p, d, a) ) ;
2923
+ }
2924
+
2925
+ fn fold_decl_local( & env e, & common. span sp, @ast. local local)
2926
+ -> @ast. decl {
2927
+ e. decls. insert( local. id, ( ) ) ;
2928
+ ret @fold. respan[ ast. decl_] ( sp, ast. decl_local( local) ) ;
2929
+ }
2930
+
2931
+ auto fep = fold_expr_path;
2932
+ auto fdl = fold_decl_local;
2933
+ auto fld = @rec(
2934
+ fold_expr_path=fep,
2935
+ fold_decl_local=fdl
2936
+ with * fold. new_identity_fold[ env] ( )
2937
+ ) ;
2938
+
2939
+ let vec[ ast. def_id] refs = vec( ) ;
2940
+ let hashmap[ ast. def_id, ( ) ] decls = new_def_hash[ ( ) ] ( ) ;
2941
+ decls. insert( initial_decl, ( ) ) ;
2942
+ let env e = @rec( mutable refs=refs, decls=decls) ;
2943
+
2944
+ fold. fold_block[ env] ( e, fld, bloc) ;
2945
+
2946
+ // Calculate (refs - decls). This is the set of captured upvars.
2947
+ let vec[ ast. def_id] result = vec( ) ;
2948
+ for ( ast. def_id ref_id in e. refs) {
2949
+ if ( !decls. contains_key( ref_id) ) {
2950
+ result += vec( ref_id) ;
2951
+ }
2952
+ }
2953
+
2954
+ ret result;
2955
+ }
2956
+
2900
2957
fn trans_for_each( @block_ctxt cx,
2901
2958
@ast. decl decl,
2902
2959
@ast. expr seq,
@@ -2928,19 +2985,26 @@ fn trans_for_each(@block_ctxt cx,
2928
2985
// escape. This could be determined upstream, and probably ought
2929
2986
// to be so, eventualy. For first cut, skip this. Null env.
2930
2987
2931
- auto env_ty = T_opaque_closure_ptr ( cx. fcx. ccx. tn) ;
2932
-
2933
-
2934
- // Step 2: Declare foreach body function.
2935
-
2936
2988
// FIXME: possibly support alias-mode here?
2937
2989
auto decl_ty = plain_ty( ty. ty_nil) ;
2990
+ auto decl_id;
2938
2991
alt ( decl. node) {
2939
2992
case ( ast. decl_local( ?local) ) {
2940
2993
decl_ty = node_ann_type( cx. fcx. ccx, local. ann) ;
2994
+ decl_id = local. id;
2941
2995
}
2942
2996
}
2943
2997
2998
+ auto upvars = collect_upvars( cx, body, decl_id) ;
2999
+ if ( _vec. len[ ast. def_id] ( upvars) > 0 u) {
3000
+ cx. fcx. ccx. sess. unimpl( "upvars in for each") ;
3001
+ fail;
3002
+ }
3003
+
3004
+ auto env_ty = T_opaque_closure_ptr ( cx. fcx. ccx. tn) ;
3005
+
3006
+ // Step 2: Declare foreach body function.
3007
+
2944
3008
let str s =
2945
3009
cx. fcx. ccx. names. next( "_rust_foreach")
2946
3010
+ sep( ) + cx. fcx. ccx. path;
@@ -4624,6 +4688,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
4624
4688
let hashmap[ ast. def_id, ValueRef ] llargs = new_def_hash[ ValueRef ] ( ) ;
4625
4689
let hashmap[ ast. def_id, ValueRef ] llobjfields = new_def_hash[ ValueRef ] ( ) ;
4626
4690
let hashmap[ ast. def_id, ValueRef ] lllocals = new_def_hash[ ValueRef ] ( ) ;
4691
+ let hashmap[ ast. def_id, ValueRef ] llupvars = new_def_hash[ ValueRef ] ( ) ;
4627
4692
let hashmap[ ast. def_id, ValueRef ] lltydescs = new_def_hash[ ValueRef ] ( ) ;
4628
4693
4629
4694
ret @rec( llfn=llfndecl,
@@ -4635,6 +4700,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
4635
4700
llargs=llargs,
4636
4701
llobjfields=llobjfields,
4637
4702
lllocals=lllocals,
4703
+ llupvars=llupvars,
4638
4704
lltydescs=lltydescs,
4639
4705
ccx=cx) ;
4640
4706
}
@@ -5486,6 +5552,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
5486
5552
llargs=new_def_hash[ ValueRef ] ( ) ,
5487
5553
llobjfields=new_def_hash[ ValueRef ] ( ) ,
5488
5554
lllocals=new_def_hash[ ValueRef ] ( ) ,
5555
+ llupvars=new_def_hash[ ValueRef ] ( ) ,
5489
5556
lltydescs=new_def_hash[ ValueRef ] ( ) ,
5490
5557
ccx=cx) ;
5491
5558
@@ -5819,6 +5886,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
5819
5886
llargs=new_def_hash[ ValueRef ] ( ) ,
5820
5887
llobjfields=new_def_hash[ ValueRef ] ( ) ,
5821
5888
lllocals=new_def_hash[ ValueRef ] ( ) ,
5889
+ llupvars=new_def_hash[ ValueRef ] ( ) ,
5822
5890
lltydescs=new_def_hash[ ValueRef ] ( ) ,
5823
5891
ccx=cx) ;
5824
5892
0 commit comments