Properly take mutable object fields into account during alias analysis

Closes #1055
This commit is contained in:
Marijn Haverbeke 2011-10-25 17:57:26 +02:00
parent cfdf193c46
commit 013107a25c
4 changed files with 36 additions and 30 deletions

View File

@ -551,6 +551,7 @@ fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t,
for t in ts { if helper(tcx, needle, t, mut) { ret true; } }
ret false;
}
ty::ty_fn(ast::proto_bare., _, _, _, _) { ret false; }
// These may contain anything.
ty::ty_fn(_, _, _, _, _) | ty::ty_obj(_) { ret true; }
// A type param may include everything, but can only be
@ -665,26 +666,32 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool)
for d in *base_root.ds {
if d.mut { unsafe_ty = some(contains(d.outer_t)); break; }
}
if is_none(path_def_id(cx, base_root.ex)) {
alt base_root.ex.node {
ast::expr_call(f, args, _) {
let fty = ty::expr_ty(cx.tcx, f);
alt ty::ty_fn_ret_style(cx.tcx, fty) {
ast::return_ref(mut, arg_n) {
let arg = args[arg_n - 1u];
let arg_root = expr_root(cx, arg, false);
if mut {
let ret_ty = ty::expr_ty(cx.tcx, base_root.ex);
unsafe_ty = some(mut_contains(ret_ty));
}
if !is_none(arg_root.mut) { unsafe_ty = arg_root.mut; }
ret {ex: arg_root.ex, mut: unsafe_ty};
}
_ {}
}
alt base_root.ex.node {
ast::expr_path(_) {
alt cx.tcx.def_map.get(base_root.ex.id) {
ast::def_obj_field(_, ast::mut.) {
unsafe_ty = some(mut_contains(ty::expr_ty(cx.tcx, base_root.ex)));
}
_ {}
}
}
ast::expr_call(f, args, _) {
let fty = ty::expr_ty(cx.tcx, f);
alt ty::ty_fn_ret_style(cx.tcx, fty) {
ast::return_ref(mut, arg_n) {
let arg = args[arg_n - 1u];
let arg_root = expr_root(cx, arg, false);
if mut {
let ret_ty = ty::expr_ty(cx.tcx, base_root.ex);
unsafe_ty = some(mut_contains(ret_ty));
}
if !is_none(arg_root.mut) { unsafe_ty = arg_root.mut; }
ret {ex: arg_root.ex, mut: unsafe_ty};
}
_ {}
}
}
_ {}
}
ret {ex: base_root.ex, mut: unsafe_ty};
}

View File

@ -1,9 +1,9 @@
/**
* Hashmap implementation.
*/
type hashfn<K> = fn@(K) -> uint;
type hashfn<K> = fn(K) -> uint;
type eqfn<K> = fn@(K, K) -> bool;
type eqfn<K> = fn(K, K) -> bool;
type hashmap<K, V> =
obj {

View File

@ -6,15 +6,10 @@ import std::uint;
fn main() {
let count = @mutable 0u;
let hash = bind fn (&&_s: [@str], count: @mutable uint) -> uint {
*count += 1u;
if *count == 10u {
fail;
} else {
ret *count;
}
} (_, count);
fn hash(&&s: [@str]) -> uint {
if (std::vec::len(s) > 0u && std::str::eq(*s[0], "boom")) { fail; }
ret 10u;
}
fn eq(&&s: [@str], &&t: [@str]) -> bool {
ret s == t;
}
@ -25,4 +20,5 @@ fn main() {
arr += [@"key stuff"];
map.insert(arr, arr + [@"value stuff"]);
}
map.insert([@"boom"], []);
}

View File

@ -8,11 +8,13 @@ import std::uint;
import std::util;
import std::option;
#[test]
fn test_simple() {
log "*** starting test_simple";
fn eq_uint(&&x: uint, &&y: uint) -> bool { ret x == y; }
let hasher_uint: map::hashfn<uint> = bind util::id(_);
fn uint_id(&&x: uint) -> uint { x }
let hasher_uint: map::hashfn<uint> = uint_id;
let eqer_uint: map::eqfn<uint> = eq_uint;
let hasher_str: map::hashfn<str> = str::hash;
let eqer_str: map::eqfn<str> = str::eq;
@ -84,8 +86,9 @@ fn test_growth() {
log "*** starting test_growth";
let num_to_insert: uint = 64u;
fn eq_uint(&&x: uint, &&y: uint) -> bool { ret x == y; }
fn uint_id(&&x: uint) -> uint { x }
log "uint -> uint";
let hasher_uint: map::hashfn<uint> = bind util::id(_);
let hasher_uint: map::hashfn<uint> = uint_id;
let eqer_uint: map::eqfn<uint> = eq_uint;
let hm_uu: map::hashmap<uint, uint> =
map::mk_hashmap::<uint, uint>(hasher_uint, eqer_uint);