Skip to content

Commit 007a736

Browse files
committed
Improve handling of move and swap by alias checker
Closes issue #541. Closes issue #591
1 parent 130006c commit 007a736

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

src/comp/middle/alias.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ import std::option::some;
1414
import std::option::none;
1515
import std::option::is_none;
1616

17-
1817
// This is not an alias-analyser (though it would merit from becoming one, or
19-
// at getting input from one, to be more precise). It is a pass that checks
18+
// getting input from one, to be more precise). It is a pass that checks
2019
// whether aliases are used in a safe way. Beyond that, though it doesn't have
2120
// a lot to do with aliases, it also checks whether assignments are valid
2221
// (using an lval, which is actually mutable), since it already has all the
2322
// information needed to do that (and the typechecker, which would be a
2423
// logical place for such a check, doesn't).
24+
2525
tag valid { valid; overwritten(span, ast::path); val_taken(span, ast::path); }
2626

2727
type restrict =
@@ -40,12 +40,10 @@ type ctx = rec(@ty::ctxt tcx,
4040
std::map::hashmap[node_id, local_info] local_map);
4141

4242
fn check_crate(@ty::ctxt tcx, &@ast::crate crate) {
43-
auto cx =
44-
@rec(tcx=tcx,
45-
46-
// Stores information about object fields and function
47-
// arguments that's otherwise not easily available.
48-
local_map=std::map::new_int_hash());
43+
auto cx = @rec(tcx=tcx,
44+
// Stores information about object fields and function
45+
// arguments that's otherwise not easily available.
46+
local_map=std::map::new_int_hash());
4947
auto v =
5048
@rec(visit_fn=bind visit_fn(cx, _, _, _, _, _, _, _),
5149
visit_item=bind visit_item(cx, _, _, _),
@@ -117,9 +115,11 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
117115
case (ast::expr_swap(?lhs, ?rhs)) {
118116
check_lval(cx, lhs, sc, v);
119117
check_lval(cx, rhs, sc, v);
118+
handled = false;
120119
}
121120
case (ast::expr_move(?dest, ?src)) {
122121
check_assign(cx, dest, src, sc, v);
122+
check_move_rhs(cx, src, sc, v);
123123
}
124124
case (ast::expr_assign(?dest, ?src)) {
125125
check_assign(cx, dest, src, sc, v);
@@ -369,7 +369,6 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::node_id id,
369369
auto my_defnum = ast::def_id_of_def(def)._1;
370370
auto var_t = ty::expr_ty(*cx.tcx, ex);
371371
for (restrict r in sc) {
372-
373372
// excludes variables introduced since the alias was made
374373
if (my_defnum < r.block_defnum) {
375374
for (ty::t t in r.tys) {
@@ -399,7 +398,6 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
399398
r.ok = overwritten(dest.span, p);
400399
}
401400
}
402-
check_var(*cx, dest, p, dest.id, true, sc);
403401
}
404402
case (_) {
405403
auto root = expr_root(*cx, dest, false);
@@ -420,6 +418,22 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
420418
}
421419
}
422420

421+
fn check_move_rhs(&@ctx cx, &@ast::expr src, &scope sc, &vt[scope] v) {
422+
alt (src.node) {
423+
case (ast::expr_path(?p)) {
424+
check_lval(cx, src, sc, v);
425+
}
426+
case (_) {
427+
auto root = expr_root(*cx, src, false);
428+
// Not a path and no-derefs means this is a temporary.
429+
if (vec::len(root.ds) != 0u) {
430+
cx.tcx.sess.span_err
431+
(src.span, "moving out of a data structure");
432+
}
433+
}
434+
}
435+
}
436+
423437
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, &scope sc,
424438
&vt[scope] v) {
425439
visit_expr(cx, src, sc, v);

0 commit comments

Comments
 (0)