Skip to content

Commit 737e115

Browse files
committed
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
1 parent eaa2565 commit 737e115

File tree

17 files changed

+69
-41
lines changed

17 files changed

+69
-41
lines changed

src/libcore/condition.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl<T, U> Condition<T, U> {
3737

3838
fn raise(t: T) -> U {
3939
let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
40-
self.raise_default(t, || fail msg)
40+
self.raise_default(t, || fail copy msg)
4141
}
4242

4343
fn raise_default(t: T, default: &fn() -> U) -> U {

src/librustc/driver/driver.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg,
188188
-> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
189189
let time_passes = sess.time_passes();
190190
let mut crate = time(time_passes, ~"parsing",
191-
||parse_input(sess, cfg, input) );
191+
|| parse_input(sess, copy cfg, input) );
192192
if upto == cu_parse { return {crate: crate, tcx: None}; }
193193

194194
sess.building_library = session::building_library(
@@ -201,7 +201,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg,
201201
front::test::modify_for_testing(sess, crate));
202202

203203
crate = time(time_passes, ~"expansion", ||
204-
syntax::ext::expand::expand_crate(sess.parse_sess, cfg,
204+
syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg,
205205
crate));
206206

207207
if upto == cu_expand { return {crate: crate, tcx: None}; }

src/librustc/metadata/creader.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler,
8686
/*bad*/copy *crate_cache.last().metas);
8787
let (matches, non_matches) =
8888
partition(crate_cache.map_to_vec(|&entry| {
89-
let othername = loader::crate_name_from_metas(*entry.metas);
89+
let othername = loader::crate_name_from_metas(
90+
copy *entry.metas);
9091
if name == othername {
9192
Left(entry)
9293
} else {

src/librustc/middle/check_match.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful {
275275
}
276276
}
277277
Some(ref ctor) => {
278-
match is_useful(cx, vec::filter_map(m, |r| default(cx, *r)),
278+
match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)),
279279
vec::tail(v)) {
280280
useful_ => useful(left_ty, (/*bad*/copy *ctor)),
281281
ref u => (/*bad*/copy *u)
@@ -292,7 +292,8 @@ fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful {
292292

293293
fn is_useful_specialized(cx: @MatchCheckCtxt, m: matrix, +v: ~[@pat],
294294
+ctor: ctor, arity: uint, lty: ty::t) -> useful {
295-
let ms = vec::filter_map(m, |r| specialize(cx, *r, ctor, arity, lty));
295+
let ms = vec::filter_map(m, |r| specialize(cx, copy *r,
296+
ctor, arity, lty));
296297
let could_be_useful = is_useful(
297298
cx, ms, specialize(cx, v, ctor, arity, lty).get());
298299
match could_be_useful {

src/librustc/middle/mode.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,29 @@ use syntax::ast::{expr_binary, expr_call, expr_copy, expr_field, expr_index};
2323
use syntax::ast::{expr_match, expr_method_call, expr_paren, expr_path};
2424
use syntax::ast::{expr_swap, expr_unary, neg, node_id, not, pat, pat_ident};
2525
use syntax::ast::{sty_uniq, sty_value, uniq};
26+
use syntax::ast::{fn_decl, blk};
2627
use syntax::visit;
27-
use syntax::visit::vt;
28+
use syntax::visit::{fn_kind, vt};
29+
use syntax::print::pprust;
30+
use syntax::codemap::span;
2831

2932
struct VisitContext {
3033
tcx: ctxt,
3134
method_map: HashMap<node_id,method_map_entry>,
3235
mode: ValueMode,
3336
}
3437

38+
fn compute_modes_for_fn(fk: fn_kind,
39+
decl: fn_decl,
40+
body: blk,
41+
sp: span,
42+
id: node_id,
43+
&&cx: VisitContext,
44+
v: vt<VisitContext>) {
45+
let body_cx = VisitContext { mode: MoveValue, ..cx };
46+
visit::visit_fn(fk, decl, body, sp, id, body_cx, v);
47+
}
48+
3549
fn compute_modes_for_fn_args(callee_id: node_id,
3650
args: &[@expr],
3751
last_arg_is_block: bool,
@@ -79,6 +93,10 @@ fn record_mode_for_expr(expr: @expr, &&cx: VisitContext) {
7993
fn compute_modes_for_expr(expr: @expr,
8094
&&cx: VisitContext,
8195
v: vt<VisitContext>) {
96+
debug!("compute_modes_for_expr(expr=%?/%s, mode=%?)",
97+
expr.id, pprust::expr_to_str(expr, cx.tcx.sess.intr()),
98+
cx.mode);
99+
82100
// Adjust the mode if there was an implicit reference here.
83101
let cx = match cx.tcx.adjustments.find(expr.id) {
84102
None => cx,
@@ -91,7 +109,7 @@ fn compute_modes_for_expr(expr: @expr,
91109
}
92110
};
93111

94-
match /*bad*/copy expr.node {
112+
match copy expr.node {
95113
expr_call(callee, args, is_block) => {
96114
let callee_cx = VisitContext { mode: ReadValue, ..cx };
97115
compute_modes_for_expr(callee, callee_cx, v);
@@ -235,6 +253,7 @@ fn compute_modes_for_pat(pat: @pat,
235253

236254
pub fn compute_modes(tcx: ctxt, method_map: method_map, crate: @crate) {
237255
let visitor = visit::mk_vt(@visit::Visitor {
256+
visit_fn: compute_modes_for_fn,
238257
visit_expr: compute_modes_for_expr,
239258
visit_pat: compute_modes_for_pat,
240259
.. *visit::default_visitor()

src/librustc/middle/trans/callee.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block,
366366
bcx, None, fty, rty,
367367
|bcx| {
368368
let callee =
369-
trans_fn_ref_with_vtables_to_callee(bcx, did, 0, type_params,
369+
trans_fn_ref_with_vtables_to_callee(bcx, did, 0,
370+
copy type_params,
370371
None);
371372

372373
let new_llval;

src/librustc/middle/trans/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ fn trans_expr_fn(bcx: block,
413413
ret_handle);
414414
trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self,
415415
/*bad*/copy bcx.fcx.param_substs, id, None, |fcx| {
416-
load_environment(fcx, cdata_ty, cap_vars,
416+
load_environment(fcx, cdata_ty, copy cap_vars,
417417
ret_handle.is_some(), proto);
418418
}, |bcx| {
419419
if is_loop_body.is_some() {

src/librustc/middle/trans/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ fn node_vtables(bcx: block, id: ast::node_id) -> Option<typeck::vtable_res> {
13091309
fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
13101310
-> typeck::vtable_res
13111311
{
1312-
@vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, *d))
1312+
@vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
13131313
}
13141314
13151315
// Apply the typaram substitutions in the fn_ctxt to a vtable. This should

src/librustc/middle/trans/inline.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id,
4343
match csearch::maybe_get_item_ast(
4444
ccx.tcx, fn_id,
4545
|a,b,c,d| {
46-
astencode::decode_inlined_item(a, b, ccx.maps, c, d)
46+
astencode::decode_inlined_item(a, b, ccx.maps,
47+
/*bad*/ copy c, d)
4748
}) {
4849

4950
csearch::not_found => {

src/librustc/middle/trans/meth.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,8 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
780780
781781
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
782782
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
783-
let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty));
783+
let fty = ty::subst_tps(tcx, substs, None,
784+
ty::mk_fn(tcx, copy im.fty));
784785
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
785786
debug!("(making impl vtable) method has self or type params: %s",
786787
tcx.sess.str_of(im.ident));

src/librustc/middle/trans/monomorphize.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t],
335335
Some(ref uses) => {
336336
vec::map2(precise_param_ids, *uses, |id, uses| {
337337
if ccx.sess.no_monomorphic_collapse() {
338-
match *id {
338+
match copy *id {
339339
(a, b) => mono_precise(a, b)
340340
}
341341
} else {
@@ -379,7 +379,7 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t],
379379
}
380380
None => {
381381
precise_param_ids.map(|x| {
382-
let (a, b) = *x;
382+
let (a, b) = copy *x;
383383
mono_precise(a, b)
384384
})
385385
}

src/librustc/middle/ty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3905,10 +3905,10 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
39053905
let mut disr_val = -1;
39063906
@vec::map(variants, |variant| {
39073907
match variant.node.kind {
3908-
ast::tuple_variant_kind(args) => {
3908+
ast::tuple_variant_kind(ref args) => {
39093909
let ctor_ty = node_id_to_type(cx, variant.node.id);
39103910
let arg_tys = {
3911-
if vec::len(args) > 0u {
3911+
if args.len() > 0u {
39123912
ty_fn_args(ctor_ty).map(|a| a.ty)
39133913
} else {
39143914
~[]

src/librustc/middle/typeck/check/mod.rs

+12-20
Original file line numberDiff line numberDiff line change
@@ -1507,12 +1507,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
15071507
// resolution is not possible (e.g., no constraints yet present), just
15081508
// returns `none`.
15091509
fn unpack_expected<O: Copy>(fcx: @fn_ctxt, expected: Option<ty::t>,
1510-
unpack: fn(ty::sty) -> Option<O>)
1510+
unpack: fn(&ty::sty) -> Option<O>)
15111511
-> Option<O> {
15121512
match expected {
15131513
Some(t) => {
15141514
match resolve_type(fcx.infcx(), t, force_tvar) {
1515-
Ok(t) => unpack(ty::get(t).sty),
1515+
Ok(t) => unpack(&ty::get(t).sty),
15161516
_ => None
15171517
}
15181518
}
@@ -1537,7 +1537,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
15371537
// to impure and block. Note that we only will use those for
15381538
// block syntax lambdas; that is, lambdas without explicit
15391539
// protos.
1540-
let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
1540+
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
15411541
let (expected_tys,
15421542
expected_purity,
15431543
expected_proto,
@@ -1969,8 +1969,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
19691969
ast::expr_unary(unop, oprnd) => {
19701970
let exp_inner = do unpack_expected(fcx, expected) |sty| {
19711971
match unop {
1972-
ast::box(_) | ast::uniq(_) => match sty {
1973-
ty::ty_box(mt) | ty::ty_uniq(mt) => Some(mt.ty),
1972+
ast::box(_) | ast::uniq(_) => match *sty {
1973+
ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => Some(mt.ty),
19741974
_ => None
19751975
},
19761976
ast::not | ast::neg => expected,
@@ -2050,8 +2050,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
20502050
fcx.write_ty(id, oprnd_t);
20512051
}
20522052
ast::expr_addr_of(mutbl, oprnd) => {
2053-
bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |ty|
2054-
match ty { ty::ty_rptr(_, mt) => Some(mt.ty), _ => None }
2053+
bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |sty|
2054+
match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty), _ => None }
20552055
));
20562056
20572057
// Note: at this point, we cannot say what the best lifetime
@@ -2177,7 +2177,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
21772177
// 1. a closure that returns a bool is expected
21782178
// 2. the closure that was given returns unit
21792179
let mut err_happened = false;
2180-
let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
2180+
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
21812181
let inner_ty = match expected_sty {
21822182
Some(ty::ty_fn(ref fty)) => {
21832183
match fcx.mk_subty(false, expr.span,
@@ -2240,7 +2240,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
22402240
}
22412241
}
22422242
ast::expr_do_body(b) => {
2243-
let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
2243+
let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
22442244
let inner_ty = match expected_sty {
22452245
Some(ty::ty_fn(ref fty)) => {
22462246
ty::mk_fn(tcx, (/*bad*/copy *fty))
@@ -2349,11 +2349,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
23492349
}
23502350
ast::expr_tup(elts) => {
23512351
let flds = unpack_expected(fcx, expected, |sty| {
2352-
// XXX: Beware! If you remove `copy` below, the borrow checker
2353-
// will NOT complain, but you will get a segfault at runtime! This
2354-
// is because the mode computation is currently unaware of
2355-
// argument modes.
2356-
match copy sty { ty::ty_tup(flds) => Some(flds), _ => None }
2352+
match *sty { ty::ty_tup(ref flds) => Some(copy *flds), _ => None }
23572353
});
23582354
let elt_ts = do elts.mapi |i, e| {
23592355
check_expr(fcx, *e, flds.map(|fs| fs[i]));
@@ -2368,12 +2364,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
23682364
Some(fcx.expr_ty(base.get()))
23692365
} else { expected };
23702366
let flds = unpack_expected(fcx, expected, |sty|
2371-
// XXX: Beware! If you remove `copy` below, the borrow checker
2372-
// will NOT complain, but you will get a segfault at runtime! This
2373-
// is because the mode computation is currently unaware of
2374-
// argument modes.
2375-
match copy sty {
2376-
ty::ty_rec(flds) => Some(flds),
2367+
match *sty {
2368+
ty::ty_rec(ref flds) => Some(copy *flds),
23772369
_ => None
23782370
}
23792371
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
enum sty = ~[int];
2+
3+
fn unpack(unpack: &fn(v: &sty) -> ~[int]) {}
4+
5+
fn main() {
6+
let foo = unpack(|s| {
7+
// Test that `s` is moved here.
8+
match *s { sty(v) => v } //~ ERROR moving out of dereference of immutable & pointer
9+
});
10+
}

src/test/run-fail/unwind-lambda.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() {
1515
let carrots = @~"crunchy";
1616

1717
fn@(tasties: @~str, macerate: fn(~str)) {
18-
macerate(*tasties);
18+
macerate(copy *tasties);
1919
} (carrots, |food| {
2020
let mush = food + cheese;
2121
let f = fn@() {

src/test/run-pass/last-use-corner-cases.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ fn main() {
3939
// Verify that blocks can't interfere with each other.
4040
fn two_blocks(a: fn(), b: fn()) { a(); b(); a(); b(); }
4141
let q = ~50;
42-
two_blocks(|| { let a = q; assert *a == 50;},
43-
|| { let a = q; assert *a == 50;});
42+
two_blocks(|| { let a = copy q; assert *a == 50;},
43+
|| { let a = copy q; assert *a == 50;});
4444
}

src/test/run-pass/monad.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ fn transform(x: Option<int>) -> Option<~str> {
4343
fn main() {
4444
assert transform(Some(10)) == Some(~"11");
4545
assert transform(None) == None;
46-
assert (~[~"hi"]).bind(|x| ~[x, x + ~"!"] ).bind(|x| ~[x, x + ~"?"] ) ==
46+
assert (~[~"hi"])
47+
.bind(|x| ~[copy x, x + ~"!"] )
48+
.bind(|x| ~[copy x, x + ~"?"] ) ==
4749
~[~"hi", ~"hi?", ~"hi!", ~"hi!?"];
4850
}

0 commit comments

Comments
 (0)