diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2013-01-10 06:29:26 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2013-01-10 13:17:25 -0800 |
| commit | 737e115646ec79dac05d61232d89e59d8da751a9 (patch) | |
| tree | 174f3520372763ff341d9ea9a55a61874250fd04 /src | |
| parent | eaa256509ede9d1277e7b498fdea4548e1851647 (diff) | |
| download | rust-737e115646ec79dac05d61232d89e59d8da751a9.tar.gz rust-737e115646ec79dac05d61232d89e59d8da751a9.zip | |
mode: reset mode on entry to fn body.
This is an interim fix to address the "Beware!" unsoundness. I have a more comprehensive rewrite of mode.rs in the pipeline. r=pcwalton
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/condition.rs | 2 | ||||
| -rw-r--r-- | src/librustc/driver/driver.rs | 4 | ||||
| -rw-r--r-- | src/librustc/metadata/creader.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/check_match.rs | 5 | ||||
| -rw-r--r-- | src/librustc/middle/mode.rs | 23 | ||||
| -rw-r--r-- | src/librustc/middle/trans/callee.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/trans/closure.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/common.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/inline.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/trans/meth.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/trans/monomorphize.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/ty.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 32 | ||||
| -rw-r--r-- | src/test/compile-fail/access-mode-in-closures.rs | 10 | ||||
| -rw-r--r-- | src/test/run-fail/unwind-lambda.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/last-use-corner-cases.rs | 4 | ||||
| -rw-r--r-- | src/test/run-pass/monad.rs | 4 |
17 files changed, 69 insertions, 41 deletions
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index a40121445fa..c4001717ca1 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -37,7 +37,7 @@ impl<T, U> Condition<T, U> { fn raise(t: T) -> U { let msg = fmt!("Unhandled condition: %s: %?", self.name, t); - self.raise_default(t, || fail msg) + self.raise_default(t, || fail copy msg) } fn raise_default(t: T, default: &fn() -> U) -> U { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index b4a9a83992d..b4366428a90 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -188,7 +188,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg, -> {crate: @ast::crate, tcx: Option<ty::ctxt>} { let time_passes = sess.time_passes(); let mut crate = time(time_passes, ~"parsing", - ||parse_input(sess, cfg, input) ); + || parse_input(sess, copy cfg, input) ); if upto == cu_parse { return {crate: crate, tcx: None}; } sess.building_library = session::building_library( @@ -201,7 +201,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg, front::test::modify_for_testing(sess, crate)); crate = time(time_passes, ~"expansion", || - syntax::ext::expand::expand_crate(sess.parse_sess, cfg, + syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg, crate)); if upto == cu_expand { return {crate: crate, tcx: None}; } diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index a731aa8db97..608f2b5c233 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -86,7 +86,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler, /*bad*/copy *crate_cache.last().metas); let (matches, non_matches) = partition(crate_cache.map_to_vec(|&entry| { - let othername = loader::crate_name_from_metas(*entry.metas); + let othername = loader::crate_name_from_metas( + copy *entry.metas); if name == othername { Left(entry) } else { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index c99b5757baa..0a063d115e1 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -275,7 +275,7 @@ fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful { } } Some(ref ctor) => { - match is_useful(cx, vec::filter_map(m, |r| default(cx, *r)), + match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)), vec::tail(v)) { useful_ => useful(left_ty, (/*bad*/copy *ctor)), ref u => (/*bad*/copy *u) @@ -292,7 +292,8 @@ fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful { fn is_useful_specialized(cx: @MatchCheckCtxt, m: matrix, +v: ~[@pat], +ctor: ctor, arity: uint, lty: ty::t) -> useful { - let ms = vec::filter_map(m, |r| specialize(cx, *r, ctor, arity, lty)); + let ms = vec::filter_map(m, |r| specialize(cx, copy *r, + ctor, arity, lty)); let could_be_useful = is_useful( cx, ms, specialize(cx, v, ctor, arity, lty).get()); match could_be_useful { diff --git a/src/librustc/middle/mode.rs b/src/librustc/middle/mode.rs index 1e24ff9f5e4..7c2b518dbe9 100644 --- a/src/librustc/middle/mode.rs +++ b/src/librustc/middle/mode.rs @@ -23,8 +23,11 @@ use syntax::ast::{expr_binary, expr_call, expr_copy, expr_field, expr_index}; use syntax::ast::{expr_match, expr_method_call, expr_paren, expr_path}; use syntax::ast::{expr_swap, expr_unary, neg, node_id, not, pat, pat_ident}; use syntax::ast::{sty_uniq, sty_value, uniq}; +use syntax::ast::{fn_decl, blk}; use syntax::visit; -use syntax::visit::vt; +use syntax::visit::{fn_kind, vt}; +use syntax::print::pprust; +use syntax::codemap::span; struct VisitContext { tcx: ctxt, @@ -32,6 +35,17 @@ struct VisitContext { mode: ValueMode, } +fn compute_modes_for_fn(fk: fn_kind, + decl: fn_decl, + body: blk, + sp: span, + id: node_id, + &&cx: VisitContext, + v: vt<VisitContext>) { + let body_cx = VisitContext { mode: MoveValue, ..cx }; + visit::visit_fn(fk, decl, body, sp, id, body_cx, v); +} + fn compute_modes_for_fn_args(callee_id: node_id, args: &[@expr], last_arg_is_block: bool, @@ -79,6 +93,10 @@ fn record_mode_for_expr(expr: @expr, &&cx: VisitContext) { fn compute_modes_for_expr(expr: @expr, &&cx: VisitContext, v: vt<VisitContext>) { + debug!("compute_modes_for_expr(expr=%?/%s, mode=%?)", + expr.id, pprust::expr_to_str(expr, cx.tcx.sess.intr()), + cx.mode); + // Adjust the mode if there was an implicit reference here. let cx = match cx.tcx.adjustments.find(expr.id) { None => cx, @@ -91,7 +109,7 @@ fn compute_modes_for_expr(expr: @expr, } }; - match /*bad*/copy expr.node { + match copy expr.node { expr_call(callee, args, is_block) => { let callee_cx = VisitContext { mode: ReadValue, ..cx }; compute_modes_for_expr(callee, callee_cx, v); @@ -235,6 +253,7 @@ fn compute_modes_for_pat(pat: @pat, pub fn compute_modes(tcx: ctxt, method_map: method_map, crate: @crate) { let visitor = visit::mk_vt(@visit::Visitor { + visit_fn: compute_modes_for_fn, visit_expr: compute_modes_for_expr, visit_pat: compute_modes_for_pat, .. *visit::default_visitor() diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index d90673b31bc..9b9d3467934 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -366,7 +366,8 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block, bcx, None, fty, rty, |bcx| { let callee = - trans_fn_ref_with_vtables_to_callee(bcx, did, 0, type_params, + trans_fn_ref_with_vtables_to_callee(bcx, did, 0, + copy type_params, None); let new_llval; diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 63287055685..846c5d8edb2 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -413,7 +413,7 @@ fn trans_expr_fn(bcx: block, ret_handle); trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self, /*bad*/copy bcx.fcx.param_substs, id, None, |fcx| { - load_environment(fcx, cdata_ty, cap_vars, + load_environment(fcx, cdata_ty, copy cap_vars, ret_handle.is_some(), proto); }, |bcx| { if is_loop_body.is_some() { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 3bec973fc90..85f4389b0c4 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1309,7 +1309,7 @@ fn node_vtables(bcx: block, id: ast::node_id) -> Option<typeck::vtable_res> { fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res) -> typeck::vtable_res { - @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, *d)) + @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d)) } // Apply the typaram substitutions in the fn_ctxt to a vtable. This should diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 447b4455adf..98842f8b073 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -43,7 +43,8 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, match csearch::maybe_get_item_ast( ccx.tcx, fn_id, |a,b,c,d| { - astencode::decode_inlined_item(a, b, ccx.maps, c, d) + astencode::decode_inlined_item(a, b, ccx.maps, + /*bad*/ copy c, d) }) { csearch::not_found => { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 9631fd8b389..53ed1cf02ff 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -780,7 +780,8 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t], let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| { - let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty)); + let fty = ty::subst_tps(tcx, substs, None, + ty::mk_fn(tcx, copy im.fty)); if (*im.tps).len() > 0u || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", tcx.sess.str_of(im.ident)); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 60ad1b83807..6ead78a28dd 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -335,7 +335,7 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], Some(ref uses) => { vec::map2(precise_param_ids, *uses, |id, uses| { if ccx.sess.no_monomorphic_collapse() { - match *id { + match copy *id { (a, b) => mono_precise(a, b) } } else { @@ -379,7 +379,7 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], } None => { precise_param_ids.map(|x| { - let (a, b) = *x; + let (a, b) = copy *x; mono_precise(a, b) }) } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b4cbc6c3f0e..04085a2c047 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3905,10 +3905,10 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { let mut disr_val = -1; @vec::map(variants, |variant| { match variant.node.kind { - ast::tuple_variant_kind(args) => { + ast::tuple_variant_kind(ref args) => { let ctor_ty = node_id_to_type(cx, variant.node.id); let arg_tys = { - if vec::len(args) > 0u { + if args.len() > 0u { ty_fn_args(ctor_ty).map(|a| a.ty) } else { ~[] diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index ff99ee8590a..ae39c674030 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1507,12 +1507,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // resolution is not possible (e.g., no constraints yet present), just // returns `none`. fn unpack_expected<O: Copy>(fcx: @fn_ctxt, expected: Option<ty::t>, - unpack: fn(ty::sty) -> Option<O>) + unpack: fn(&ty::sty) -> Option<O>) -> Option<O> { match expected { Some(t) => { match resolve_type(fcx.infcx(), t, force_tvar) { - Ok(t) => unpack(ty::get(t).sty), + Ok(t) => unpack(&ty::get(t).sty), _ => None } } @@ -1537,7 +1537,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // to impure and block. Note that we only will use those for // block syntax lambdas; that is, lambdas without explicit // protos. - let expected_sty = unpack_expected(fcx, expected, |x| Some(x)); + let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let (expected_tys, expected_purity, expected_proto, @@ -1969,8 +1969,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, ast::expr_unary(unop, oprnd) => { let exp_inner = do unpack_expected(fcx, expected) |sty| { match unop { - ast::box(_) | ast::uniq(_) => match sty { - ty::ty_box(mt) | ty::ty_uniq(mt) => Some(mt.ty), + ast::box(_) | ast::uniq(_) => match *sty { + ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => Some(mt.ty), _ => None }, ast::not | ast::neg => expected, @@ -2050,8 +2050,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fcx.write_ty(id, oprnd_t); } ast::expr_addr_of(mutbl, oprnd) => { - bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |ty| - match ty { ty::ty_rptr(_, mt) => Some(mt.ty), _ => None } + bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |sty| + match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty), _ => None } )); // Note: at this point, we cannot say what the best lifetime @@ -2177,7 +2177,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // 1. a closure that returns a bool is expected // 2. the closure that was given returns unit let mut err_happened = false; - let expected_sty = unpack_expected(fcx, expected, |x| Some(x)); + let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let inner_ty = match expected_sty { Some(ty::ty_fn(ref fty)) => { match fcx.mk_subty(false, expr.span, @@ -2240,7 +2240,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } } ast::expr_do_body(b) => { - let expected_sty = unpack_expected(fcx, expected, |x| Some(x)); + let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let inner_ty = match expected_sty { Some(ty::ty_fn(ref fty)) => { ty::mk_fn(tcx, (/*bad*/copy *fty)) @@ -2349,11 +2349,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } ast::expr_tup(elts) => { let flds = unpack_expected(fcx, expected, |sty| { - // XXX: Beware! If you remove `copy` below, the borrow checker - // will NOT complain, but you will get a segfault at runtime! This - // is because the mode computation is currently unaware of - // argument modes. - match copy sty { ty::ty_tup(flds) => Some(flds), _ => None } + match *sty { ty::ty_tup(ref flds) => Some(copy *flds), _ => None } }); let elt_ts = do elts.mapi |i, e| { check_expr(fcx, *e, flds.map(|fs| fs[i])); @@ -2368,12 +2364,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, Some(fcx.expr_ty(base.get())) } else { expected }; let flds = unpack_expected(fcx, expected, |sty| - // XXX: Beware! If you remove `copy` below, the borrow checker - // will NOT complain, but you will get a segfault at runtime! This - // is because the mode computation is currently unaware of - // argument modes. - match copy sty { - ty::ty_rec(flds) => Some(flds), + match *sty { + ty::ty_rec(ref flds) => Some(copy *flds), _ => None } ); diff --git a/src/test/compile-fail/access-mode-in-closures.rs b/src/test/compile-fail/access-mode-in-closures.rs new file mode 100644 index 00000000000..32ac756aaff --- /dev/null +++ b/src/test/compile-fail/access-mode-in-closures.rs @@ -0,0 +1,10 @@ +enum sty = ~[int]; + +fn unpack(unpack: &fn(v: &sty) -> ~[int]) {} + +fn main() { + let foo = unpack(|s| { + // Test that `s` is moved here. + match *s { sty(v) => v } //~ ERROR moving out of dereference of immutable & pointer + }); +} diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs index 08457f07143..aee6f4e480c 100644 --- a/src/test/run-fail/unwind-lambda.rs +++ b/src/test/run-fail/unwind-lambda.rs @@ -15,7 +15,7 @@ fn main() { let carrots = @~"crunchy"; fn@(tasties: @~str, macerate: fn(~str)) { - macerate(*tasties); + macerate(copy *tasties); } (carrots, |food| { let mush = food + cheese; let f = fn@() { diff --git a/src/test/run-pass/last-use-corner-cases.rs b/src/test/run-pass/last-use-corner-cases.rs index b4077863852..1dfccac8bce 100644 --- a/src/test/run-pass/last-use-corner-cases.rs +++ b/src/test/run-pass/last-use-corner-cases.rs @@ -39,6 +39,6 @@ fn main() { // Verify that blocks can't interfere with each other. fn two_blocks(a: fn(), b: fn()) { a(); b(); a(); b(); } let q = ~50; - two_blocks(|| { let a = q; assert *a == 50;}, - || { let a = q; assert *a == 50;}); + two_blocks(|| { let a = copy q; assert *a == 50;}, + || { let a = copy q; assert *a == 50;}); } diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 8abc8236b65..210defa5789 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -43,6 +43,8 @@ fn transform(x: Option<int>) -> Option<~str> { fn main() { assert transform(Some(10)) == Some(~"11"); assert transform(None) == None; - assert (~[~"hi"]).bind(|x| ~[x, x + ~"!"] ).bind(|x| ~[x, x + ~"?"] ) == + assert (~[~"hi"]) + .bind(|x| ~[copy x, x + ~"!"] ) + .bind(|x| ~[copy x, x + ~"?"] ) == ~[~"hi", ~"hi?", ~"hi!", ~"hi!?"]; } |
