Skip to content

Commit d60588a

Browse files
committed
---
yaml --- r: 3123 b: refs/heads/master c: 9b5ebe7 h: refs/heads/master i: 3121: 91d1549 3119: 4f2b971 v: v3
1 parent 232a9bd commit d60588a

File tree

2 files changed

+76
-31
lines changed

2 files changed

+76
-31
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: b2b8002fd325aa5a6f79d0306f508b4c17cd90af
2+
refs/heads/master: 9b5ebe726c1f9dc83b11fb3b77dd24f201d7b777

trunk/src/comp/middle/alias.rs

Lines changed: 75 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,18 @@ fn visit_item(@ctx cx, &@ast::item i, &scope sc, &vt[scope] v) {
7777
}
7878

7979
fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
80-
auto handled = false;
80+
auto handled = true;
8181
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+
}
8390
case (ast::expr_alt(?input, ?arms, _)) {
8491
check_alt(*cx, input, arms, sc, v);
85-
handled = true;
8692
}
8793
case (ast::expr_put(?val, _)) {
8894
alt (val) {
@@ -97,44 +103,36 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
97103
}
98104
case (_) { }
99105
}
100-
handled = true;
101106
}
102107
case (ast::expr_for_each(?decl, ?call, ?block, _)) {
103108
check_for_each(*cx, decl, call, block, sc, v);
104-
handled = true;
105109
}
106110
case (ast::expr_for(?decl, ?seq, ?block, _)) {
107111
check_for(*cx, decl, seq, block, sc, v);
108-
handled = true;
109112
}
110113
case (ast::expr_path(?pt, ?ann)) {
111114
check_var(*cx, ex, pt, ann, false, sc);
115+
handled = false;
112116
}
113117
case (ast::expr_move(?dest, ?src, _)) {
114118
check_assign(cx, dest, src, sc, v);
115-
handled = true;
116119
}
117120
case (ast::expr_assign(?dest, ?src, _)) {
118121
check_assign(cx, dest, src, sc, v);
119-
handled = true;
120122
}
121123
case (ast::expr_assign_op(_, ?dest, ?src, _)) {
122124
check_assign(cx, dest, src, sc, v);
123-
handled = true;
124125
}
125-
case (_) { }
126+
case (_) { handled = false; }
126127
}
127128
if (!handled) { visit::visit_expr(ex, sc, v); }
128129
}
129130

130131
fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
131132
rec(vec[def_num] root_vars, vec[ty::t] unsafe_ts) {
132133
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+
138136
let vec[def_num] roots = [];
139137
let vec[tup(uint, def_num)] mut_roots = [];
140138
let vec[ty::t] unsafe_ts = [];
@@ -175,11 +173,11 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
175173
if (vec::len(unsafe_ts) > 0u) {
176174
alt (f.node) {
177175
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)));
183181
}
184182
}
185183
case (_) { }
@@ -221,8 +219,47 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
221219
ret rec(root_vars=roots, unsafe_ts=unsafe_ts);
222220
}
223221

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 = 0u;
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 += 1u;
258+
}
259+
}
260+
261+
fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms,
262+
&scope sc, &vt[scope] v) {
226263
visit::visit_expr(input, sc, v);
227264
auto root = expr_root(cx, input, true);
228265
auto roots =
@@ -317,7 +354,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
317354
fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
318355
&scope sc) {
319356
auto def = cx.dm.get(ann.id);
320-
if (!def_is_local(def)) { ret; }
357+
if (!def_is_local(def, true)) { ret; }
321358
auto my_defnum = ast::def_id_of_def(def)._1;
322359
auto var_t = ty::expr_ty(*cx.tcx, ex);
323360
for (restrict r in sc) {
@@ -594,15 +631,23 @@ fn ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut) ->
594631
ret helper(*cx.tcx, needle, haystack, mut);
595632
}
596633

597-
fn def_is_local(&ast::def d) -> bool {
634+
fn def_is_local(&ast::def d, bool objfields_count) -> bool {
598635
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+
};
605642
}
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+
606651
// Local Variables:
607652
// mode: rust
608653
// fill-column: 78;

0 commit comments

Comments
 (0)