@@ -77,12 +77,18 @@ fn visit_item(@ctx cx, &@ast::item i, &scope sc, &vt[scope] v) {
77
77
}
78
78
79
79
fn visit_expr ( @ctx cx , & @ast:: expr ex, & scope sc, & vt[ scope] v ) {
80
- auto handled = false ;
80
+ auto handled = true ;
81
81
alt ( ex. node ) {
82
- case ( ast:: expr_call ( ?f, ?args, _) ) { check_call ( * cx, f, args, sc) ; }
82
+ case ( ast:: expr_call ( ?f, ?args, _) ) {
83
+ check_call ( * cx, f, args, sc) ;
84
+ handled = false ;
85
+ }
86
+ case ( ast:: expr_be ( ?cl, _) ) {
87
+ check_tail_call ( * cx, cl) ;
88
+ visit:: visit_expr ( cl, sc, v) ;
89
+ }
83
90
case ( ast:: expr_alt ( ?input, ?arms, _) ) {
84
91
check_alt ( * cx, input, arms, sc, v) ;
85
- handled = true ;
86
92
}
87
93
case ( ast:: expr_put ( ?val, _) ) {
88
94
alt ( val) {
@@ -97,44 +103,36 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
97
103
}
98
104
case ( _) { }
99
105
}
100
- handled = true ;
101
106
}
102
107
case ( ast:: expr_for_each ( ?decl, ?call, ?block, _) ) {
103
108
check_for_each ( * cx, decl, call, block, sc, v) ;
104
- handled = true ;
105
109
}
106
110
case ( ast:: expr_for ( ?decl, ?seq, ?block, _) ) {
107
111
check_for ( * cx, decl, seq, block, sc, v) ;
108
- handled = true ;
109
112
}
110
113
case ( ast:: expr_path ( ?pt, ?ann) ) {
111
114
check_var ( * cx, ex, pt, ann, false , sc) ;
115
+ handled = false ;
112
116
}
113
117
case ( ast:: expr_move ( ?dest, ?src, _) ) {
114
118
check_assign ( cx, dest, src, sc, v) ;
115
- handled = true ;
116
119
}
117
120
case ( ast:: expr_assign ( ?dest, ?src, _) ) {
118
121
check_assign ( cx, dest, src, sc, v) ;
119
- handled = true ;
120
122
}
121
123
case ( ast:: expr_assign_op ( _, ?dest, ?src, _) ) {
122
124
check_assign ( cx, dest, src, sc, v) ;
123
- handled = true ;
124
125
}
125
- case ( _) { }
126
+ case ( _) { handled = false ; }
126
127
}
127
128
if ( !handled) { visit:: visit_expr ( ex, sc, v) ; }
128
129
}
129
130
130
131
fn check_call ( & ctx cx, & @ast:: expr f, & vec[ @ast:: expr] args, & scope sc) ->
131
132
rec ( vec[ def_num] root_vars , vec[ ty:: t ] unsafe_ts ) {
132
133
auto fty = ty:: expr_ty ( * cx. tcx , f) ;
133
- auto arg_ts =
134
- alt ( ty:: struct ( * cx. tcx , fty) ) {
135
- case ( ty:: ty_fn ( _, ?args, _, _, _) ) { args }
136
- case ( ty:: ty_native_fn ( _, ?args, _) ) { args }
137
- } ;
134
+ auto arg_ts = fty_args ( cx, fty) ;
135
+
138
136
let vec[ def_num] roots = [ ] ;
139
137
let vec[ tup( uint, def_num) ] mut_roots = [ ] ;
140
138
let vec[ ty:: t] unsafe_ts = [ ] ;
@@ -175,11 +173,11 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
175
173
if ( vec:: len ( unsafe_ts) > 0 u) {
176
174
alt ( f. node ) {
177
175
case ( ast:: expr_path ( _, ?ann) ) {
178
- if ( def_is_local ( cx. dm . get ( ann. id ) ) ) {
179
- cx. tcx . sess . span_err ( f . span ,
180
- #fmt ( "function may alias with \
181
- argument %u, which is not immutably rooted",
182
- unsafe_t_offsets. ( 0 ) ) ) ;
176
+ if ( def_is_local ( cx. dm . get ( ann. id ) , true ) ) {
177
+ cx. tcx . sess . span_err
178
+ ( f . span , #fmt ( "function may alias with argument \
179
+ %u, which is not immutably rooted",
180
+ unsafe_t_offsets. ( 0 ) ) ) ;
183
181
}
184
182
}
185
183
case ( _) { }
@@ -221,8 +219,47 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
221
219
ret rec( root_vars=roots, unsafe_ts=unsafe_ts) ;
222
220
}
223
221
224
- fn check_alt( & ctx cx, & @ast:: expr input, & vec[ ast:: arm] arms, & scope sc,
225
- & vt[ scope] v) {
222
+ fn check_tail_call( & ctx cx, & @ast:: expr call) {
223
+ auto args;
224
+ auto f = alt ( call. node) {
225
+ case ( ast:: expr_call( ?f, ?args_, _) ) { args = args_; f }
226
+ } ;
227
+ auto i = 0 u;
228
+ for ( ty:: arg arg_t in fty_args( cx, ty:: expr_ty( * cx. tcx, f) ) ) {
229
+ if ( arg_t. mode != ty:: mo_val) {
230
+ auto mut_a = arg_t. mode == ty:: mo_alias( true ) ;
231
+ auto ok = true ;
232
+ alt ( args. ( i) . node) {
233
+ case ( ast:: expr_path( _, ?ann) ) {
234
+ auto def = cx. dm. get( ann. id) ;
235
+ auto dnum = ast:: def_id_of_def( def) . _1;
236
+ alt ( cx. local_map. find( dnum) ) {
237
+ case ( some( arg( ast:: alias( ?mut ) ) ) ) {
238
+ if ( mut_a && !mut) {
239
+ cx. tcx. sess. span_warn
240
+ ( args. ( i) . span, "passing an immutable \
241
+ alias by mutable alias") ;
242
+ }
243
+ }
244
+ case ( _) {
245
+ ok = !def_is_local( def, false ) ;
246
+ }
247
+ }
248
+ }
249
+ case ( _) { ok = false ; }
250
+ }
251
+ if ( !ok) {
252
+ cx. tcx. sess. span_warn
253
+ ( args. ( i) . span, "can not pass a local value by alias to \
254
+ a tail call") ;
255
+ }
256
+ }
257
+ i += 1 u;
258
+ }
259
+ }
260
+
261
+ fn check_alt( & ctx cx, & @ast:: expr input, & vec[ ast:: arm] arms,
262
+ & scope sc, & vt[ scope] v) {
226
263
visit:: visit_expr( input, sc, v) ;
227
264
auto root = expr_root( cx, input, true ) ;
228
265
auto roots =
@@ -317,7 +354,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
317
354
fn check_var( & ctx cx, & @ast:: expr ex, & ast:: path p, ast:: ann ann, bool assign,
318
355
& scope sc) {
319
356
auto def = cx. dm. get( ann. id) ;
320
- if ( !def_is_local( def) ) { ret; }
357
+ if ( !def_is_local( def, true ) ) { ret; }
321
358
auto my_defnum = ast:: def_id_of_def( def) . _1;
322
359
auto var_t = ty:: expr_ty( * cx. tcx, ex) ;
323
360
for ( restrict r in sc) {
@@ -594,15 +631,23 @@ fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut) ->
594
631
ret helper( * cx. tcx , needle, haystack, mut) ;
595
632
}
596
633
597
- fn def_is_local ( & ast:: def d) -> bool {
634
+ fn def_is_local ( & ast:: def d, bool objfields_count ) -> bool {
598
635
ret alt ( d) {
599
- case ( ast:: def_local ( _) ) { true }
600
- case ( ast:: def_arg ( _) ) { true }
601
- case ( ast:: def_obj_field ( _) ) { true }
602
- case ( ast:: def_binding ( _) ) { true }
603
- case ( _) { false }
604
- } ;
636
+ case ( ast:: def_local ( _) ) { true }
637
+ case ( ast:: def_arg ( _) ) { true }
638
+ case ( ast:: def_obj_field ( _) ) { objfields_count }
639
+ case ( ast:: def_binding ( _) ) { true }
640
+ case ( _) { false }
641
+ } ;
605
642
}
643
+
644
+ fn fty_args ( & ctx cx, ty:: t fty ) -> vec[ ty:: arg ] {
645
+ ret alt ( ty:: struct ( * cx. tcx , fty) ) {
646
+ case ( ty:: ty_fn ( _, ?args, _, _, _) ) { args }
647
+ case ( ty:: ty_native_fn ( _, ?args, _) ) { args }
648
+ } ;
649
+ }
650
+
606
651
// Local Variables:
607
652
// mode: rust
608
653
// fill-column: 78;
0 commit comments