From 0ddade3d7a668be0397a2a79c21f632ff6986031 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 15 Jun 2011 12:17:37 +0200 Subject: [PATCH] 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. --- src/comp/middle/alias.rs | 25 +++++++++++++++++-- src/test/compile-fail/assign-alias.rs | 2 -- .../writing-through-read-alias.rs | 4 +-- .../compile-fail/writing-to-immutable-vec.rs | 6 ++--- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 08ac6c303ccb..f7ea23317c33 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -10,6 +10,14 @@ import std::option::some; import std::option::none; import std::option::is_none; +// This is not an alias-analyser (though it would merit from becoming one, or +// at getting input from one, to be more precise). It is a pass that checks +// whether aliases are used in a safe way. Beyond that, though it doesn't have +// a lot to do with aliases, it also checks whether assignments are valid +// (using an lval, which is actually mutable), since it already has all the +// information needed to do that (and the typechecker, which would be a +// logical place for such a check, doesn't). + tag valid { valid; overwritten(span, ast::path); @@ -318,6 +326,7 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign, } } +// FIXME does not catch assigning to immutable object fields yet fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, &scope sc, &vt[scope] v) { visit_expr(cx, src, sc, v); @@ -339,6 +348,18 @@ fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, check_var(*cx, dest, p, ann, true, sc); } case (_) { + auto root = expr_root(*cx, dest, false); + if (vec::len(root.ds) == 0u) { + cx.tcx.sess.span_err(dest.span, "assignment to non-lvalue"); + } else if (!root.ds.(0).mut) { + auto name = alt (root.ds.(0).kind) { + case (unbox) { "box" } + case (field) { "field" } + case (index) { "vec content" } + }; + cx.tcx.sess.span_err + (dest.span, "assignment to immutable " + name); + } visit_expr(cx, dest, sc, v); } } @@ -391,7 +412,7 @@ fn deps(&scope sc, vec[def_num] roots) -> vec[uint] { tag deref_t { unbox; - field(ident); + field; index; } 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) case (ty::ty_obj(_)) {} } vec::push(ds, rec(mut=mut, - kind=field(ident), + kind=field, outer_t=auto_unbox.t)); maybe_push_auto_unbox(auto_unbox.d, ds); ex = base; diff --git a/src/test/compile-fail/assign-alias.rs b/src/test/compile-fail/assign-alias.rs index 2e1f88fcf375..5b10892ba7a8 100644 --- a/src/test/compile-fail/assign-alias.rs +++ b/src/test/compile-fail/assign-alias.rs @@ -1,5 +1,3 @@ -// xfail-stage0 -// xfail-stage1 // error-pattern:assigning to immutable alias fn f(&int i) { diff --git a/src/test/compile-fail/writing-through-read-alias.rs b/src/test/compile-fail/writing-through-read-alias.rs index b3aff12dfcc2..79bb37db0471 100644 --- a/src/test/compile-fail/writing-through-read-alias.rs +++ b/src/test/compile-fail/writing-through-read-alias.rs @@ -1,9 +1,7 @@ // xfail-stage0 -// xfail-stage1 -// xfail-stage2 // -*- rust -*- -// error-pattern: writing to immutable type +// error-pattern:assignment to immutable field type point = rec(int x, int y, int z); diff --git a/src/test/compile-fail/writing-to-immutable-vec.rs b/src/test/compile-fail/writing-to-immutable-vec.rs index 2872d11fc800..7f574ce3320e 100644 --- a/src/test/compile-fail/writing-to-immutable-vec.rs +++ b/src/test/compile-fail/writing-to-immutable-vec.rs @@ -1,8 +1,6 @@ // xfail-stage0 -// xfail-stage1 -// xfail-stage2 -// error-pattern: writing to immutable type +// error-pattern:assignment to immutable vec content fn main() { let vec[int] v = [1, 2, 3]; v.(1) = 4; -} \ No newline at end of file +}