From 013107a25c92262f515b1da8a473c7fad32269df Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 25 Oct 2011 17:57:26 +0200 Subject: [PATCH] Properly take mutable object fields into account during alias analysis Closes #1055 --- src/comp/middle/alias.rs | 41 +++++++++++++++++------------- src/lib/map.rs | 4 +-- src/test/run-fail/unwind-misc-1.rs | 14 ++++------ src/test/stdtest/map.rs | 7 +++-- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 5b96bddfe3f..e98b5590f64 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -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}; } diff --git a/src/lib/map.rs b/src/lib/map.rs index 88d19092280..a3f5eb7d449 100644 --- a/src/lib/map.rs +++ b/src/lib/map.rs @@ -1,9 +1,9 @@ /** * Hashmap implementation. */ -type hashfn = fn@(K) -> uint; +type hashfn = fn(K) -> uint; -type eqfn = fn@(K, K) -> bool; +type eqfn = fn(K, K) -> bool; type hashmap = obj { diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs index c49b00599aa..811eff881ae 100644 --- a/src/test/run-fail/unwind-misc-1.rs +++ b/src/test/run-fail/unwind-misc-1.rs @@ -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"], []); } \ No newline at end of file diff --git a/src/test/stdtest/map.rs b/src/test/stdtest/map.rs index 45d1a535e02..32ecae5c6c8 100644 --- a/src/test/stdtest/map.rs +++ b/src/test/stdtest/map.rs @@ -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 = bind util::id(_); + fn uint_id(&&x: uint) -> uint { x } + let hasher_uint: map::hashfn = uint_id; let eqer_uint: map::eqfn = eq_uint; let hasher_str: map::hashfn = str::hash; let eqer_str: map::eqfn = 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 = bind util::id(_); + let hasher_uint: map::hashfn = uint_id; let eqer_uint: map::eqfn = eq_uint; let hm_uu: map::hashmap = map::mk_hashmap::(hasher_uint, eqer_uint);