Skip to content

Commit 0ddade3

Browse files
committed
Extend alias analysis to check assignments
This is a somewhat odd place to put these checks, but the data tracked by that pass, and the available functions, make it trivial to do such a check there.
1 parent 5fb518a commit 0ddade3

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

src/comp/middle/alias.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import std::option::some;
1010
import std::option::none;
1111
import std::option::is_none;
1212

13+
// This is not an alias-analyser (though it would merit from becoming one, or
14+
// at getting input from one, to be more precise). It is a pass that checks
15+
// whether aliases are used in a safe way. Beyond that, though it doesn't have
16+
// a lot to do with aliases, it also checks whether assignments are valid
17+
// (using an lval, which is actually mutable), since it already has all the
18+
// information needed to do that (and the typechecker, which would be a
19+
// logical place for such a check, doesn't).
20+
1321
tag valid {
1422
valid;
1523
overwritten(span, ast::path);
@@ -318,6 +326,7 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
318326
}
319327
}
320328

329+
// FIXME does not catch assigning to immutable object fields yet
321330
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
322331
&scope sc, &vt[scope] v) {
323332
visit_expr(cx, src, sc, v);
@@ -339,6 +348,18 @@ fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
339348
check_var(*cx, dest, p, ann, true, sc);
340349
}
341350
case (_) {
351+
auto root = expr_root(*cx, dest, false);
352+
if (vec::len(root.ds) == 0u) {
353+
cx.tcx.sess.span_err(dest.span, "assignment to non-lvalue");
354+
} else if (!root.ds.(0).mut) {
355+
auto name = alt (root.ds.(0).kind) {
356+
case (unbox) { "box" }
357+
case (field) { "field" }
358+
case (index) { "vec content" }
359+
};
360+
cx.tcx.sess.span_err
361+
(dest.span, "assignment to immutable " + name);
362+
}
342363
visit_expr(cx, dest, sc, v);
343364
}
344365
}
@@ -391,7 +412,7 @@ fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
391412

392413
tag deref_t {
393414
unbox;
394-
field(ident);
415+
field;
395416
index;
396417
}
397418
type deref = rec(bool mut, deref_t kind, ty::t outer_t);
@@ -446,7 +467,7 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef)
446467
case (ty::ty_obj(_)) {}
447468
}
448469
vec::push(ds, rec(mut=mut,
449-
kind=field(ident),
470+
kind=field,
450471
outer_t=auto_unbox.t));
451472
maybe_push_auto_unbox(auto_unbox.d, ds);
452473
ex = base;

src/test/compile-fail/assign-alias.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// xfail-stage0
2-
// xfail-stage1
31
// error-pattern:assigning to immutable alias
42

53
fn f(&int i) {

src/test/compile-fail/writing-through-read-alias.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// xfail-stage0
2-
// xfail-stage1
3-
// xfail-stage2
42
// -*- rust -*-
53

6-
// error-pattern: writing to immutable type
4+
// error-pattern:assignment to immutable field
75

86
type point = rec(int x, int y, int z);
97

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// xfail-stage0
2-
// xfail-stage1
3-
// xfail-stage2
4-
// error-pattern: writing to immutable type
2+
// error-pattern:assignment to immutable vec content
53
fn main() {
64
let vec[int] v = [1, 2, 3];
75
v.(1) = 4;
8-
}
6+
}

0 commit comments

Comments
 (0)