diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-06-08 07:46:14 -0700 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-06-08 20:39:11 -0700 |
| commit | 013fc924236976c5dad9c77ed8adb41b58ebcf03 (patch) | |
| tree | 95420d15ae429b9f9959de0a773f9d3e1b2ca30d | |
| parent | 1351117aa859f44789e5bee15add4ceb71db613c (diff) | |
| download | rust-013fc924236976c5dad9c77ed8adb41b58ebcf03.tar.gz rust-013fc924236976c5dad9c77ed8adb41b58ebcf03.zip | |
remove alias analysis and replace with borrowck
This reverts commit 7ef825bb607c4e934c92bd0b73ecbc4c24f3286b.
50 files changed, 27 insertions, 1133 deletions
diff --git a/doc/tutorial.md b/doc/tutorial.md index c7b94c8e155..804cf39d640 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1382,83 +1382,7 @@ gets access to them. ## Safe references -There is one catch with this approach: sometimes the compiler can -*not* statically guarantee that the argument value at the caller side -will survive to the end of the call. Another argument might indirectly -refer to it and be used to overwrite it, or a closure might assign a -new value to it. - -Fortunately, Rust tasks are single-threaded worlds, which share no -data with other tasks, and most data is immutable. This allows most -argument-passing situations to be proved safe without further -difficulty. - -Take the following program: - -~~~~ -# fn get_really_big_record() -> int { 1 } -# fn myfunc(a: int) {} -fn main() { - let x = get_really_big_record(); - myfunc(x); -} -~~~~ - -Here we know for sure that no one else has access to the `x` variable -in `main`, so we're good. But the call could also look like this: - -~~~~ -# fn myfunc(a: int, b: fn()) {} -# fn get_another_record() -> int { 1 } -# let mut x = 1; -myfunc(x, {|| x = get_another_record(); }); -~~~~ - -Now, if `myfunc` first calls its second argument and then accesses its -first argument, it will see a different value from the one that was -passed to it. - -In such a case, the compiler will insert an implicit copy of `x`, -*except* if `x` contains something mutable, in which case a copy would -result in code that behaves differently. If copying `x` might be -expensive (for example, if it holds a vector), the compiler will emit -a warning. - -There are even more tricky cases, in which the Rust compiler is forced -to pessimistically assume a value will get mutated, even though it is -not sure. - -~~~~ -fn for_each(v: [mut @int], iter: fn(@int)) { - for v.each {|elt| iter(elt); } -} -~~~~ - -For all this function knows, calling `iter` (which is a closure that -might have access to the vector that's passed as `v`) could cause the -elements in the vector to be mutated, with the effect that it can not -guarantee that the boxes will live for the duration of the call. So it -has to copy them. In this case, this will happen implicitly (bumping a -reference count is considered cheap enough to not warn about it). - -## The copy operator - -If the `for_each` function given above were to take a vector of -`{mut a: int}` instead of `@int`, it would not be able to -implicitly copy, since if the `iter` function changes a copy of a -mutable record, the changes won't be visible in the record itself. If -we *do* want to allow copies there, we have to explicitly allow it -with the `copy` operator: - -~~~~ -type mutrec = {mut x: int}; -fn for_each(v: [mut mutrec], iter: fn(mutrec)) { - for v.each {|elt| iter(copy elt); } -} -~~~~ - -Adding a `copy` operator is also the way to muffle warnings about -implicit copies. +*This system has recently changed. An explanantion is forthcoming.* ## Other uses of safe references diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 672a950f42b..769f3c40e25 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -204,9 +204,6 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let (root_map, mutbl_map) = time( time_passes, "borrow checking", bind middle::borrowck::check_crate(ty_cx, method_map, crate)); - let (copy_map, _ref_map) = - time(time_passes, "alias checking", - bind middle::alias::check_crate(ty_cx, crate)); time(time_passes, "kind checking", bind kind::check_crate(ty_cx, method_map, last_use_map, crate)); time(time_passes, "lint checking", @@ -216,7 +213,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let outputs = option::get(outputs); let maps = {mutbl_map: mutbl_map, root_map: root_map, - copy_map: copy_map, last_use_map: last_use_map, + last_use_map: last_use_map, impl_map: impl_map, method_map: method_map, vtable_map: vtable_map}; @@ -448,14 +445,6 @@ fn build_session_options(match: getopts::match, let sysroot_opt = getopts::opt_maybe_str(match, "sysroot"); let target_opt = getopts::opt_maybe_str(match, "target"); let save_temps = getopts::opt_present(match, "save-temps"); - let borrowck = alt getopts::opt_maybe_str(match, "borrowck") { - none { 0u } - some("warn") { 1u } - some("err") { 2u } - some(_) { - early_error(demitter, "borrowck may be warn or err") - } - }; alt output_type { // unless we're emitting huamn-readable assembly, omit comments. link::output_type_llvm_assembly | link::output_type_assembly {} @@ -504,8 +493,7 @@ fn build_session_options(match: getopts::match, test: test, parse_only: parse_only, no_trans: no_trans, - debugging_opts: debugging_opts, - borrowck: borrowck}; + debugging_opts: debugging_opts}; ret sopts; } @@ -582,8 +570,7 @@ fn opts() -> [getopts::opt] { optmulti("Z"), optmulti("cfg"), optflag("test"), - optflag("lib"), optflag("bin"), optflag("static"), optflag("gc"), - optopt("borrowck")]; + optflag("lib"), optflag("bin"), optflag("static"), optflag("gc")]; } type output_filenames = @{out_filename: str, obj_filename:str}; diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index 97e2d0ec4db..07f42a0d269 100644 --- a/src/rustc/driver/session.rs +++ b/src/rustc/driver/session.rs @@ -66,9 +66,6 @@ type options = no_trans: bool, debugging_opts: uint, - - // temporary hack: 0=off,1=warn,2=err --> if 2, alias is disabled - borrowck: uint, }; type crate_metadata = {name: str, data: [u8]}; @@ -181,8 +178,7 @@ fn basic_options() -> @options { test: false, parse_only: false, no_trans: false, - debugging_opts: 0u, - borrowck: 0u, + debugging_opts: 0u } } diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index a754d4c11a2..ba23dd24baa 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -116,7 +116,6 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_param_bounds, tag_table_inferred_modes, tag_table_mutbl, - tag_table_copy, tag_table_last_use, tag_table_spill, tag_table_method_map, diff --git a/src/rustc/middle/alias.rs b/src/rustc/middle/alias.rs deleted file mode 100644 index 7b25a0955f3..00000000000 --- a/src/rustc/middle/alias.rs +++ /dev/null @@ -1,848 +0,0 @@ -import syntax::{ast, ast_util, ast_map}; -import ast_util::path_to_ident; -import ast::{ident, fn_ident, node_id}; -import syntax::codemap::span; -import syntax::print::pprust::expr_to_str; -import syntax::visit; -import visit::vt; -import std::list; -import std::map::hashmap; -import core::unreachable; -import option::is_none; -import list::list; -import driver::session::session; -import pat_util::*; -import util::ppaux::ty_to_str; - -// This is not an alias-analyser (though it would merit from becoming one, or -// getting input from one, to be more precise). It is a pass that checks -// whether aliases are used in a safe way. - -enum copied { not_allowed, copied, not_copied, } -enum invalid_reason { overwritten, val_taken, } -type invalid = {reason: invalid_reason, - node_id: node_id, - sp: span, path: @ast::path}; - -enum unsafe_ty { contains(ty::t), mutbl_contains(ty::t), } - -type binding = @{node_id: node_id, - span: span, - root_var: option<node_id>, - local_id: uint, - unsafe_tys: [unsafe_ty], - mut copied: copied}; - -// FIXME it may be worthwhile to use a linked list of bindings instead -type scope = {bs: [binding], - invalid: @mut @list<@invalid>}; - -fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option<node_id>, - unsafe_tys: [unsafe_ty]) -> binding { - alt root_var { - some(r_id) { cx.ref_map.insert(id, r_id); } - _ {} - } - ret @{node_id: id, span: span, root_var: root_var, - local_id: local_id_of_node(cx, id), - unsafe_tys: unsafe_tys, - mut copied: not_copied}; -} - -enum local_info { local(uint), } - -type copy_map = std::map::hashmap<node_id, ()>; -type ref_map = std::map::hashmap<node_id, node_id>; - -type ctx = {tcx: ty::ctxt, - copy_map: copy_map, - ref_map: ref_map, - mut silent: bool}; - -fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) { - // Stores information about function arguments that's otherwise not easily - // available. - let cx = @{tcx: tcx, - copy_map: std::map::int_hash(), - ref_map: std::map::int_hash(), - mut silent: false}; - let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _), - visit_expr: bind visit_expr(cx, _, _, _), - visit_block: bind visit_block(cx, _, _, _) - with *visit::default_visitor::<scope>()}; - let sc = {bs: [], invalid: @mut @list::nil}; - visit::visit_crate(*crate, sc, visit::mk_vt(v)); - tcx.sess.abort_if_errors(); - ret (cx.copy_map, cx.ref_map); -} - -fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl, - body: ast::blk, _sp: span, - id: ast::node_id, sc: scope, v: vt<scope>) { - visit::visit_fn_decl(decl, sc, v); - let fty = ty::node_id_to_type(cx.tcx, id); - - // Blocks need to obey any restrictions from the enclosing scope, and may - // be called multiple times. - let proto = ty::ty_fn_proto(fty); - alt proto { - ast::proto_block | ast::proto_any { - check_loop(*cx, sc) {|| v.visit_block(body, sc, v);} - } - ast::proto_box | ast::proto_uniq | ast::proto_bare { - let sc = {bs: [], invalid: @mut @list::nil}; - v.visit_block(body, sc, v); - } - } -} - -fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) { - let mut handled = true; - alt ex.node { - ast::expr_call(f, args, _) { - check_call(cx, sc, f, args, v); - visit_expr(cx, f, sc, v); - } - ast::expr_alt(input, arms, _) { check_alt(*cx, input, arms, sc, v); } - ast::expr_path(pt) { - check_var(*cx, ex, pt, ex.id, false, sc); - handled = false; - } - ast::expr_swap(lhs, rhs) { - check_lval(cx, lhs, sc, v); - check_lval(cx, rhs, sc, v); - handled = false; - } - ast::expr_move(dest, src) { - visit_expr(cx, src, sc, v); - check_lval(cx, dest, sc, v); - check_lval(cx, src, sc, v); - } - ast::expr_assign(dest, src) | ast::expr_assign_op(_, dest, src) { - visit_expr(cx, src, sc, v); - check_lval(cx, dest, sc, v); - } - ast::expr_if(c, then, els) { check_if(c, then, els, sc, v); } - ast::expr_while(_, _) { - check_loop(*cx, sc) {|| visit::visit_expr(ex, sc, v); } - } - _ { handled = false; } - } - if !handled { visit::visit_expr(ex, sc, v); } -} - -fn visit_block(cx: @ctx, b: ast::blk, sc: scope, v: vt<scope>) { - let sc = sc; - for b.node.stmts.each {|stmt| - alt stmt.node { - ast::stmt_decl(@{node: ast::decl_item(it), _}, _) { - v.visit_item(it, sc, v); - } - ast::stmt_decl(@{node: ast::decl_local(locs), _}, _) { - for locs.each {|loc| - alt loc.node.init { - some(init) { - if init.op == ast::init_move { - check_lval(cx, init.expr, sc, v); - } else { - visit_expr(cx, init.expr, sc, v); - } - } - none { } - } - } - } - ast::stmt_expr(ex, _) | ast::stmt_semi(ex, _) { - v.visit_expr(ex, sc, v); - } - } - } - visit::visit_expr_opt(b.node.expr, sc, v); -} - -fn cant_copy(cx: ctx, b: binding) -> bool { - - if cx.tcx.sess.opts.borrowck == 2u { - // borrowck is enabled. disable alias analysis. - ret false; - } - - alt b.copied { - not_allowed { ret true; } - copied { ret false; } - not_copied {} - } - let ty = ty::node_id_to_type(cx.tcx, b.node_id); - if ty::type_allows_implicit_copy(cx.tcx, ty) { - b.copied = copied; - cx.copy_map.insert(b.node_id, ()); - if copy_is_expensive(cx.tcx, ty) { - cx.tcx.sess.span_warn(b.span, - "inserting an implicit copy for type " + - util::ppaux::ty_to_str(cx.tcx, ty)); - } - ret false; - } else { ret true; } -} - -// FIXME this is a really awful hack -fn local_id_for_args(cx: ctx, args: [@ast::expr]) -> uint { - for vec::each(args) {|arg| - alt arg.node { - ast::expr_fn_block(decl, _, _) | ast::expr_fn(_, decl, _, _) | - ast::expr_loop_body(@{node: ast::expr_fn_block(decl, _, _), _}) { - if decl.inputs.len() > 0u { - ret local_id_of_node(cx, decl.inputs[0].id); - } - } - _ {} - } - } - 0xFFFFFFFFu -} - -fn check_call(cx: @ctx, sc: scope, f: @ast::expr, args: [@ast::expr], - v: vt<scope>) { - let fty = ty::expr_ty(cx.tcx, f); - let arg_ts = ty::ty_fn_args(fty); - let mut mut_roots: [{arg: @ast::expr, node: node_id}] = []; - let mut bindings = []; - let mut blocks = [], loc_id = local_id_for_args(*cx, args); - vec::iter2(args, arg_ts) {|arg, arg_t| - let root = expr_root(*cx, arg, false); - alt ty::resolved_mode(cx.tcx, arg_t.mode) { - ast::by_mutbl_ref { - alt path_def(*cx, arg) { - some(def) { - let dnum = ast_util::def_id_of_def(def).node; - mut_roots += [{arg: arg, node: dnum}]; - } - _ { } - } - } - ast::by_ref | ast::by_val | ast::by_move | ast::by_copy {} - } - alt arg.node { - ast::expr_fn_block(*) { blocks += [arg]; } - ast::expr_loop_body(b) { blocks += [b]; } - _ { - let root_var = path_def_id(*cx, root.ex); - let arg_copied = alt ty::resolved_mode(cx.tcx, arg_t.mode) { - ast::by_move | ast::by_copy { copied } - ast::by_mutbl_ref { not_allowed } - ast::by_ref | ast::by_val { not_copied } - }; - visit_expr(cx, arg, sc, v); - bindings += [@{node_id: arg.id, - span: arg.span, - root_var: root_var, - local_id: loc_id, - unsafe_tys: unsafe_set(root.mutbl), - mut copied: arg_copied}]; - } - } - } - let f_may_close = alt f.node { - ast::expr_path(_) { def_is_local_or_self(cx.tcx.def_map.get(f.id)) } - _ { true } - }; - if f_may_close { - let mut i = 0u; - for bindings.each {|b| - let mut unsfe = vec::len(b.unsafe_tys) > 0u; - alt b.root_var { - some(rid) { - for sc.bs.each {|o| - if o.node_id == rid && vec::len(o.unsafe_tys) > 0u { - unsfe = true; break; - } - } - } - _ {} - } - if unsfe && cant_copy(*cx, b) { - err(*cx, f.span, #fmt["function may alias with argument \ - %u, which is not immutably rooted", i]); - } - i += 1u; - } - } - let mut j = 0u; - for bindings.each {|b| - for b.unsafe_tys.each {|unsafe_ty| - vec::iteri(arg_ts) {|i, arg_t| - let mut_alias = - (ast::by_mutbl_ref == ty::arg_mode(cx.tcx, arg_t)); - alt args[i].node { - ast::expr_fn_block(*) | ast::expr_loop_body(_) {} - _ { - if i != j && ty_can_unsafely_include( - *cx, unsafe_ty, arg_t.ty, mut_alias) && - cant_copy(*cx, b) { - err(*cx, args[i].span, - #fmt["argument %u may alias with argument %u, \ - which is not immutably rooted", i, j]); - } - } - } - } - } - j += 1u; - } - - // Ensure we're not passing a root by mut alias. - for mut_roots.each {|mroot| - for bindings.each {|b| - if b.node_id != mroot.arg.id { - alt b.root_var { - some(root) { - if mroot.node == root && cant_copy(*cx, b) { - err(*cx, mroot.arg.span, - "passing a mut reference to a \ - variable that roots another reference"); - break; - } - } - none { } - } - } - } - } - // Check the bodies of block arguments against the current scope - if blocks.len() > 0u { - let inner_sc = {bs: bindings + sc.bs, invalid: sc.invalid}; - for blocks.each {|blk| - alt check blk.node { - ast::expr_fn_block(_, body, _) { - v.visit_block(body, inner_sc, v); - } - } - } - for bindings.each {|binding| - test_scope(*cx, sc, binding, none); - } - } -} - -#[warn(no_non_implicitly_copyable_typarams)] -fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope, - v: vt<scope>) { - v.visit_expr(input, sc, v); - let orig_invalid = *sc.invalid; - let mut all_invalid = orig_invalid; - let root = expr_root(cx, input, true); - for arms.each {|a| - let mut new_bs = sc.bs; - let root_var = path_def_id(cx, root.ex); - let pat_id_map = pat_util::pat_id_map(cx.tcx.def_map, a.pats[0]); - type info = { - id: node_id, - mut unsafe_tys: [unsafe_ty], - span: span}; - let mut binding_info: [info] = []; - for a.pats.each {|pat| - for pattern_roots(cx.tcx, root.mutbl, pat).each {|proot| - let canon_id = pat_id_map.get(proot.name); - alt vec::find(binding_info, {|x| x.id == canon_id}) { - some(s) { s.unsafe_tys += unsafe_set(proot.mutbl); } - none { - binding_info += [ - {id: canon_id, - mut unsafe_tys: unsafe_set(proot.mutbl), - span: proot.span}]; - } - } - } - } - for binding_info.each {|info| - new_bs += [mk_binding(cx, info.id, info.span, root_var, - copy info.unsafe_tys)]; - }; - *sc.invalid = orig_invalid; - visit::visit_arm(a, {bs: new_bs with sc}, v); - all_invalid = join_invalid(all_invalid, *sc.invalid); - }; - *sc.invalid = all_invalid; -} - -fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk, - sc: scope, v: vt<scope>) { - let root = expr_root(cx, seq, false); - - // If this is a mut vector, don't allow it to be touched. - let seq_t = ty::expr_ty(cx.tcx, seq); - let mut cur_mutbl = root.mutbl; - alt ty::get(seq_t).struct { - ty::ty_vec(mt) { - if mt.mutbl != ast::m_imm { - cur_mutbl = some(contains(seq_t)); - } - } - _ {} - } - let root_var = path_def_id(cx, root.ex); - let mut new_bs = sc.bs; - for pattern_roots(cx.tcx, cur_mutbl, local.node.pat).each {|proot| - new_bs += [mk_binding(cx, proot.id, proot.span, root_var, - unsafe_set(proot.mutbl))]; - } - visit::visit_block(blk, {bs: new_bs with sc}, v); -} - -fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id, - assign: bool, sc: scope) { - let def = cx.tcx.def_map.get(id); - if !def_is_local_or_self(def) { ret; } - let my_defnum = ast_util::def_id_of_def(def).node; - let my_local_id = local_id_of_node(cx, my_defnum); - let var_t = ty::expr_ty(cx.tcx, ex); - for sc.bs.each {|b| - // excludes variables introduced since the alias was made - if my_local_id < b.local_id { - for b.unsafe_tys.each {|unsafe_ty| - if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) { - let inv = @{reason: val_taken, node_id: b.node_id, - sp: ex.span, path: p}; - *sc.invalid = @list::cons(inv, *sc.invalid); - } - } - } else if b.node_id == my_defnum { - test_scope(cx, sc, b, some(p)); - } - } -} - -fn check_lval(cx: @ctx, dest: @ast::expr, sc: scope, v: vt<scope>) { - alt dest.node { - ast::expr_path(p) { - let def = cx.tcx.def_map.get(dest.id); - let dnum = ast_util::def_id_of_def(def).node; - for sc.bs.each {|b| - if b.root_var == some(dnum) { - let inv = @{reason: overwritten, node_id: b.node_id, - sp: dest.span, path: p}; - *sc.invalid = @list::cons(inv, *sc.invalid); - } - } - } - _ { visit_expr(cx, dest, sc, v); } - } -} - -fn check_if(c: @ast::expr, then: ast::blk, els: option<@ast::expr>, - sc: scope, v: vt<scope>) { - v.visit_expr(c, sc, v); - let orig_invalid = *sc.invalid; - v.visit_block(then, sc, v); - let then_invalid = *sc.invalid; - *sc.invalid = orig_invalid; - visit::visit_expr_opt(els, sc, v); - *sc.invalid = join_invalid(*sc.invalid, then_invalid); -} - -fn check_loop(cx: ctx, sc: scope, checker: fn()) { - let orig_invalid = filter_invalid(*sc.invalid, sc.bs); - checker(); - let new_invalid = filter_invalid(*sc.invalid, sc.bs); - // Have to check contents of loop again if it invalidated an alias - if list::len(orig_invalid) < list::len(new_invalid) { - let old_silent = cx.silent; - cx.silent = true; - checker(); - cx.silent = old_silent; - } - *sc.invalid = new_invalid; -} - -fn test_scope(cx: ctx, sc: scope, b: binding, p: option<@ast::path>) { - let mut prob = find_invalid(b.node_id, *sc.invalid); - alt b.root_var { - some(dn) { - for sc.bs.each {|other| - if !is_none(prob) { break; } - if other.node_id == dn { - prob = find_invalid(other.node_id, *sc.invalid); - } - } - } - _ {} - } - if !is_none(prob) && cant_copy(cx, b) { - let i = option::get(prob); - let msg = alt i.reason { - overwritten { "overwriting " + ast_util::path_name(i.path) } - val_taken { "taking the value of " + ast_util::path_name(i.path) } - }; - let refname = alt p { - some(pt) { "reference " + ast_util::path_name(pt) + - ", which is still used" } - none { "an argument" } - }; - err(cx, i.sp, msg + " will invalidate " + refname); - } -} - -fn path_def(cx: ctx, ex: @ast::expr) -> option<ast::def> { - ret alt ex.node { - ast::expr_path(_) { some(cx.tcx.def_map.get(ex.id)) } - _ { none } - } -} - -fn path_def_id(cx: ctx, ex: @ast::expr) -> option<ast::node_id> { - alt ex.node { - ast::expr_path(_) { - ret some(ast_util::def_id_of_def(cx.tcx.def_map.get(ex.id)).node); - } - _ { ret none; } - } -} - -fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t, - mutbl: bool) -> bool { - fn get_mutbl(cur: bool, mt: ty::mt) -> bool { - ret cur || mt.mutbl != ast::m_imm; - } - fn helper(tcx: ty::ctxt, needle: unsafe_ty, haystack: ty::t, mutbl: bool) - -> bool { - if alt needle { - contains(ty) { ty == haystack } - mutbl_contains(ty) { mutbl && ty == haystack } - } { ret true; } - alt ty::get(haystack).struct { - ty::ty_enum(_, ts) { - for ts.tps.each {|t| - if helper(tcx, needle, t, mutbl) { ret true; } - } - ret false; - } - ty::ty_box(mt) | ty::ty_ptr(mt) | ty::ty_uniq(mt) { - ret helper(tcx, needle, mt.ty, get_mutbl(mutbl, mt)); - } - ty::ty_rec(fields) { - for fields.each {|f| - if helper(tcx, needle, f.mt.ty, get_mutbl(mutbl, f.mt)) { - ret true; - } - } - ret false; - } - ty::ty_tup(ts) { - for ts.each {|t| if helper(tcx, needle, t, mutbl) { ret true; } } - ret false; - } - ty::ty_fn({proto: ast::proto_bare, _}) { ret false; } - // These may contain anything. - ty::ty_fn(_) | ty::ty_iface(_, _) { ret true; } - // A type param may include everything, but can only be - // treated as opaque downstream, and is thus safe unless we - // saw mut fields, in which case the whole thing can be - // overwritten. - ty::ty_param(_, _) { ret mutbl; } - _ { ret false; } - } - } - ret helper(cx.tcx, needle, haystack, mutbl); -} - -fn def_is_local_or_self(d: ast::def) -> bool { - alt d { - ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) | - ast::def_upvar(_, _, _) | ast::def_self(_) { true } - _ { false } - } -} - -fn local_id_of_node(cx: ctx, id: node_id) -> uint { - alt cx.tcx.items.find(id) { - some(ast_map::node_arg(_, id)) | some(ast_map::node_local(id)) { id } - _ { 0u } - } -} - -// Heuristic, somewhat random way to decide whether to warn when inserting an -// implicit copy. -fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool { - fn score_ty(tcx: ty::ctxt, ty: ty::t) -> uint { - ret alt ty::get(ty).struct { - ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | - ty::ty_uint(_) | ty::ty_float(_) | ty::ty_type | - ty::ty_ptr(_) { 1u } - ty::ty_box(_) | ty::ty_iface(_, _) { 3u } - ty::ty_constr(t, _) | ty::ty_res(_, t, _) { score_ty(tcx, t) } - ty::ty_fn(_) { 4u } - ty::ty_str | ty::ty_vec(_) | ty::ty_param(_, _) { 50u } - ty::ty_uniq(mt) { 1u + score_ty(tcx, mt.ty) } - ty::ty_enum(_, substs) { - substs.tps.foldl(0u) { |sum, t| sum + score_ty(tcx, t) } - } - ty::ty_tup(ts) { - ts.foldl(0u) { |sum, t| sum + score_ty(tcx, t) } - } - ty::ty_rec(fs) { - let mut sum = 0u; - for fs.each {|f| sum += score_ty(tcx, f.mt.ty); } - sum - } - _ { - tcx.sess.warn(#fmt("score_ty: unexpected type %s", - ty_to_str(tcx, ty))); - 1u // ??? - } - }; - } - ret score_ty(tcx, ty) > 8u; -} - -type pattern_root = {id: node_id, - name: ident, - mutbl: option<unsafe_ty>, - span: span}; - -fn pattern_roots(tcx: ty::ctxt, mutbl: option<unsafe_ty>, pat: @ast::pat) - -> [pattern_root] { - fn walk(tcx: ty::ctxt, mutbl: option<unsafe_ty>, pat: @ast::pat, - &set: [pattern_root]) { - alt pat.node { - ast::pat_ident(nm, sub) - if !pat_util::pat_is_variant(tcx.def_map, pat) { - set += [{id: pat.id, name: path_to_ident(nm), mutbl: mutbl, - span: pat.span}]; - option::iter(sub) {|p| walk(tcx, mutbl, p, set); }; - } - ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) | - ast::pat_ident(_, _) | ast::pat_enum(_, none) {} - ast::pat_enum(_, some(ps)) | ast::pat_tup(ps) { - for ps.each {|p| walk(tcx, mutbl, p, set); } - } - ast::pat_rec(fs, _) { - let ty = ty::node_id_to_type(tcx, pat.id); - for fs.each {|f| - let m = ty::get_field(ty, f.ident).mt.mutbl != ast::m_imm, - c = if m { some(contains(ty)) } else { mutbl }; - walk(tcx, c, f.pat, set); - } - } - ast::pat_box(p) { - let ty = ty::node_id_to_type(tcx, pat.id); - let m = alt ty::get(ty).struct { - ty::ty_box(mt) { mt.mutbl != ast::m_imm } - _ { tcx.sess.span_bug(pat.span, "box pat has non-box type"); } - }, - c = if m {some(contains(ty)) } else { mutbl }; - walk(tcx, c, p, set); - } - ast::pat_uniq(p) { - let ty = ty::node_id_to_type(tcx, pat.id); - let m = alt ty::get(ty).struct { - ty::ty_uniq(mt) { mt.mutbl != ast::m_imm } - _ { tcx.sess.span_bug(pat.span, "uniq pat has non-uniq type"); } - }, - c = if m { some(contains(ty)) } else { mutbl }; - walk(tcx, c, p, set); - } - } - } - let mut set = []; - walk(tcx, mutbl, pat, set); - ret set; -} - -enum deref_t { unbox(bool), field, index, } - -type deref = @{mutbl: bool, kind: deref_t, outer_t: ty::t}; - -fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) - -> {ex: @ast::expr, mutbl: option<unsafe_ty>} { - - fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} { - let mut ds = [], t = t; - loop { - alt ty::get(t).struct { - ty::ty_box(mt) | ty::ty_uniq(mt) | ty::ty_rptr(_, mt) { - ds += [@{mutbl: mt.mutbl == ast::m_mutbl, - kind: unbox(false), - outer_t: t}]; - t = mt.ty; - } - ty::ty_res(_, inner, substs) { - ds += [@{mutbl: false, kind: unbox(false), outer_t: t}]; - t = ty::subst(tcx, substs, inner); - } - ty::ty_enum(did, substs) { - let variants = ty::enum_variants(tcx, did); - if vec::len(*variants) != 1u || - vec::len(variants[0].args) != 1u { - break; - } - ds += [@{mutbl: false, kind: unbox(false), outer_t: t}]; - t = ty::subst(tcx, substs, variants[0].args[0]); - } - _ { break; } - } - } - ret {t: t, ds: ds}; - } - - fn expr_root_(tcx: ty::ctxt, ctor_self: option<node_id>, - ex: @ast::expr, autoderef: bool) -> {ex: @ast::expr, - ds: @[deref]} { - let mut ds: [deref] = [], ex = ex; - loop { - alt copy ex.node { - ast::expr_field(base, ident, _) { - let auto_unbox = - maybe_auto_unbox(tcx, ty::expr_ty(tcx, base)); - let mut is_mutbl = false; - alt ty::get(auto_unbox.t).struct { - ty::ty_rec(fields) { - for fields.each {|fld| - if str::eq(ident, fld.ident) { - is_mutbl = fld.mt.mutbl == ast::m_mutbl; - break; - } - } - } - ty::ty_class(did, _) { - #debug["base: %s", expr_to_str(base)]; - let in_self = alt ctor_self { - some(selfid) { - alt tcx.def_map.find(base.id) { - some(ast::def_self(slfid)) { slfid == selfid } - _ { false } - } - } - none { false } - }; - for ty::lookup_class_fields(tcx, did).each {|fld| - if str::eq(ident, fld.ident) { - is_mutbl = fld.mutability == ast::class_mutable - || in_self; // all fields can be mutated - // in the ctor - break; - } - } - } - _ {} - } - ds += [@{mutbl:is_mutbl, kind:field, outer_t:auto_unbox.t}]; - ds += auto_unbox.ds; - ex = base; - } - ast::expr_index(base, _) { - let auto_unbox = - maybe_auto_unbox(tcx, ty::expr_ty(tcx, base)); - alt ty::get(auto_unbox.t).struct { - ty::ty_evec(mt, _) | - ty::ty_vec(mt) { - ds += - [@{mutbl: mt.mutbl == ast::m_mutbl, - kind: index, - outer_t: auto_unbox.t}]; - } - ty::ty_estr(_) | - ty::ty_str { - ds += [@{mutbl:false, kind:index, outer_t:auto_unbox.t}]; - } - _ { break; } - } - ds += auto_unbox.ds; - ex = base; - } - ast::expr_unary(op, base) { - if op == ast::deref { - let base_t = ty::expr_ty(tcx, base); - let mut is_mutbl = false, ptr = false; - alt ty::get(base_t).struct { - ty::ty_box(mt) { is_mutbl = mt.mutbl==ast::m_mutbl; } - ty::ty_uniq(mt) { is_mutbl = mt.mutbl==ast::m_mutbl; } - ty::ty_res(_, _, _) { } - ty::ty_enum(_, _) { } - ty::ty_ptr(mt) | ty::ty_rptr(_, mt) { - is_mutbl = mt.mutbl==ast::m_mutbl; - ptr = true; - } - _ { - tcx.sess.span_bug( - base.span, - "ill-typed base expression in deref"); } - } - ds += [@{mutbl: is_mutbl, kind: unbox(ptr && is_mutbl), - outer_t: base_t}]; - ex = base; - } else { break; } - } - _ { break; } - } - } - if autoderef { - let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex)); - ds += auto_unbox.ds; - } - ret {ex: ex, ds: @ds}; - } - - let base_root = expr_root_(cx.tcx, none, ex, autoderef); - let mut unsafe_ty = none; - for vec::each(*base_root.ds) {|d| - if d.mutbl { unsafe_ty = some(contains(d.outer_t)); break; } - } - ret {ex: base_root.ex, mutbl: unsafe_ty}; -} - -fn unsafe_set(from: option<unsafe_ty>) -> [unsafe_ty] { - alt from { some(t) { [t] } _ { [] } } -} - -fn find_invalid(id: node_id, lst: @list<@invalid>) -> option<@invalid> { - let mut cur = lst; - loop { - alt *cur { - list::nil { ret none; } - list::cons(head, tail) { - if head.node_id == id { ret some(head); } - cur = tail; - } - } - }; -} - -fn join_invalid(a: @list<@invalid>, b: @list<@invalid>) -> @list<@invalid> { - let mut result = a; - list::iter(b) {|elt| - let mut found = false; - list::iter(a) {|e| if e == elt { found = true; } } - if !found { result = @list::cons(elt, result); } - } - result -} - -fn filter_invalid(src: @list<@invalid>, bs: [binding]) -> @list<@invalid> { - let mut out = @list::nil, cur = src; - loop { - alt *cur { - list::cons(head, tail) { - let p = vec::position(bs, {|b| b.node_id == head.node_id}); - if !is_none(p) { out = @list::cons(head, out); } - cur = tail; - } - list::nil { - ret out; - } - } - } -} - -fn err(cx: ctx, sp: span, err: str) { - if !cx.silent || !cx.tcx.sess.has_errors() { - cx.tcx.sess.span_err(sp, err); - } -} - -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index bcf6c799739..d604505455c 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -52,7 +52,6 @@ export decode_inlined_item; type maps = { mutbl_map: middle::borrowck::mutbl_map, root_map: middle::borrowck::root_map, - copy_map: middle::alias::copy_map, last_use_map: middle::liveness::last_use_map, impl_map: middle::resolve::impl_map, method_map: middle::typeck::method_map, @@ -831,12 +830,6 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, } } - option::iter(maps.copy_map.find(id)) {|_m| - ebml_w.tag(c::tag_table_copy) {|| - ebml_w.id(id); - } - } - option::iter(maps.last_use_map.find(id)) {|m| ebml_w.tag(c::tag_table_last_use) {|| ebml_w.id(id); @@ -943,8 +936,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt, if tag == (c::tag_table_mutbl as uint) { dcx.maps.mutbl_map.insert(id, ()); - } else if tag == (c::tag_table_copy as uint) { - dcx.maps.copy_map.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val]; let val_dsr = ebml::ebml_deserializer(val_doc); diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index d106c2b23d8..06714050010 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -171,28 +171,12 @@ export check_crate, root_map, mutbl_map; fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, crate: @ast::crate) -> (root_map, mutbl_map) { - - // big hack to keep this off except when I want it on - let msg_level = if tcx.sess.opts.borrowck != 0u { - tcx.sess.opts.borrowck - } else { - os::getenv("RUST_BORROWCK").map_default(0u) { |v| - option::get(uint::from_str(v)) - } - }; - let bccx = @{tcx: tcx, method_map: method_map, - msg_level: msg_level, root_map: root_map(), mutbl_map: int_hash()}; - let req_maps = if msg_level > 0u { - gather_loans::gather_loans(bccx, crate) - } else { - {req_loan_map: int_hash(), - pure_map: int_hash()} - }; + let req_maps = gather_loans::gather_loans(bccx, crate); check_loans::check_loans(bccx, req_maps, crate); ret (bccx.root_map, bccx.mutbl_map); } @@ -202,7 +186,6 @@ fn check_crate(tcx: ty::ctxt, type borrowck_ctxt = @{tcx: ty::ctxt, method_map: typeck::method_map, - msg_level: uint, root_map: root_map, mutbl_map: mutbl_map}; @@ -363,11 +346,7 @@ impl error_methods for borrowck_ctxt { } fn span_err(s: span, m: str) { - if self.msg_level == 1u { - self.tcx.sess.span_warn(s, m); - } else { - self.tcx.sess.span_err(s, m); - } + self.tcx.sess.span_err(s, m); } fn span_note(s: span, m: str) { diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index f31f3a209bc..44f26ad6947 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -614,25 +614,7 @@ fn make_phi_bindings(bcx: block, map: [exit_node], bcx.fcx.lllocals.insert(node_id, local_mem(local)); } else { success = false; } }; - if success { - // Copy references that the alias analysis considered unsafe - for ids.each_value {|node_id| - if bcx.ccx().maps.copy_map.contains_key(node_id) { - let local = alt bcx.fcx.lllocals.find(node_id) { - some(local_mem(x)) { x } - _ { bcx.tcx().sess.bug("someone \ - forgot to document an invariant in \ - make_phi_bindings"); } - }; - let e_ty = node_id_type(bcx, node_id); - let alloc = alloc_ty(bcx, e_ty); - bcx = copy_val(bcx, INIT, alloc, - load_if_immediate(bcx, local, e_ty), e_ty); - add_clean(bcx, alloc, e_ty); - bcx.fcx.lllocals.insert(node_id, local_mem(alloc)); - } - }; - } else { + if !success { Unreachable(bcx); } ret success; @@ -719,7 +701,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef, alt pat.node { ast::pat_ident(_,inner) { if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; } - if make_copy || ccx.maps.copy_map.contains_key(pat.id) { + if make_copy { let ty = node_id_type(bcx, pat.id); let llty = type_of::type_of(ccx, ty); let alloc = alloca(bcx, llty); diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 61d0786b215..84fd0f1947e 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2891,22 +2891,11 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr, // to have type lldestty (the callee's expected type). val = llvm::LLVMGetUndef(lldestty); } else if arg_mode == ast::by_ref || arg_mode == ast::by_val { - let mut copied = false; let imm = ty::type_is_immediate(arg.ty); #debug[" arg.ty=%s, imm=%b, arg_mode=%?, lv.kind=%?", ty_to_str(bcx.tcx(), arg.ty), imm, arg_mode, lv.kind]; if arg_mode == ast::by_ref && lv.kind != owned && imm { val = do_spill_noroot(bcx, val); - copied = true; - } - if ccx.maps.copy_map.contains_key(e.id) && lv.kind != temporary { - if !copied { - let alloc = alloc_ty(bcx, arg.ty); - bcx = copy_val(bcx, INIT, alloc, - load_if_immediate(bcx, val, arg.ty), arg.ty); - val = alloc; - } else { bcx = take_ty(bcx, val, arg.ty); } - add_clean(bcx, val, arg.ty); } if arg_mode == ast::by_val && (lv.kind == owned || !imm) { val = Load(bcx, val); diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc index 7cdaeb9273b..7d112ae7146 100644 --- a/src/rustc/rustc.rc +++ b/src/rustc/rustc.rc @@ -78,7 +78,6 @@ mod middle { mod loan; mod preserve; } - mod alias; mod liveness; mod block_use; mod kind; diff --git a/src/test/compile-fail/borrowck-assign-comp-idx.rs b/src/test/compile-fail/borrowck-assign-comp-idx.rs index c418c855237..a83f727369e 100644 --- a/src/test/compile-fail/borrowck-assign-comp-idx.rs +++ b/src/test/compile-fail/borrowck-assign-comp-idx.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - type point = { x: int, y: int }; fn a() { diff --git a/src/test/compile-fail/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck-assign-comp.rs index c8830957c76..2e045b84c60 100644 --- a/src/test/compile-fail/borrowck-assign-comp.rs +++ b/src/test/compile-fail/borrowck-assign-comp.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - type point = { x: int, y: int }; fn a() { diff --git a/src/test/compile-fail/borrowck-lend-args.rs b/src/test/compile-fail/borrowck-lend-args.rs index aa2358121e2..ef8914b134f 100644 --- a/src/test/compile-fail/borrowck-lend-args.rs +++ b/src/test/compile-fail/borrowck-lend-args.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn borrow(_v: &int) {} fn borrow_from_arg_imm_ref(&&v: ~int) { diff --git a/src/test/compile-fail/borrowck-lend-flow.rs b/src/test/compile-fail/borrowck-lend-flow.rs index def99033e5e..e3916867412 100644 --- a/src/test/compile-fail/borrowck-lend-flow.rs +++ b/src/test/compile-fail/borrowck-lend-flow.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - // Note: the borrowck analysis is currently flow-insensitive. // Therefore, some of these errors are marked as spurious and could be // corrected by a simple change to the analysis. The others are diff --git a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs index d9f3bd05676..0862af2e6fa 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn borrow(v: &int, f: fn(x: &int)) { f(v); } diff --git a/src/test/compile-fail/borrowck-loan-blocks-move.rs b/src/test/compile-fail/borrowck-loan-blocks-move.rs index 6c26aafd425..b5044754ac0 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn take(-_v: ~int) { } diff --git a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs index d7538f168ab..186229f39bd 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn borrow(v: &int, f: fn(x: &int)) { f(v); } diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index 7f45a50cbf4..a268b37ca72 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - type point = { x: int, y: int }; impl foo for point { diff --git a/src/test/compile-fail/borrowck-loan-rcvr.rs b/src/test/compile-fail/borrowck-loan-rcvr.rs index 1fba825d5ab..ec543bfc4f9 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - type point = { x: int, y: int }; impl foo for point { diff --git a/src/test/compile-fail/borrowck-loan-vec-content.rs b/src/test/compile-fail/borrowck-loan-vec-content.rs index c3d0a62f05e..80e23570a0d 100644 --- a/src/test/compile-fail/borrowck-loan-vec-content.rs +++ b/src/test/compile-fail/borrowck-loan-vec-content.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - // Here we check that it is allowed to lend out an element of a // (locally rooted) mutable, unique vector, and that we then prevent // modifications to the contents. diff --git a/src/test/compile-fail/borrowck-mut-vec-as-imm-slice-bad.rs b/src/test/compile-fail/borrowck-mut-vec-as-imm-slice-bad.rs index 803f30f8e33..c14c35189b5 100644 --- a/src/test/compile-fail/borrowck-mut-vec-as-imm-slice-bad.rs +++ b/src/test/compile-fail/borrowck-mut-vec-as-imm-slice-bad.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn want_slice(v: [int]/&) -> int { let mut sum = 0; for vec::each(v) { |i| sum += i; } diff --git a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs new file mode 100644 index 00000000000..a546ef867e1 --- /dev/null +++ b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs @@ -0,0 +1,13 @@ +enum cycle { + node({mut a: ~cycle}), + empty +} +fn main() { + let x = ~node({mut a: ~empty}); + // Create a cycle! + alt check *x { //! NOTE loan of immutable local variable granted here + node(y) { + y.a <- x; //! ERROR moving out of immutable local variable prohibited due to outstanding loan + } + }; +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-pat-enum-in-box.rs b/src/test/compile-fail/borrowck-pat-enum-in-box.rs index 32135b5ad8f..29de06a1104 100644 --- a/src/test/compile-fail/borrowck-pat-enum-in-box.rs +++ b/src/test/compile-fail/borrowck-pat-enum-in-box.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn match_imm_box(v: &const @option<int>) -> int { alt *v { @some(i) {i} diff --git a/src/test/compile-fail/borrowck-pat-enum.rs b/src/test/compile-fail/borrowck-pat-enum.rs index 753b51b0251..8e87e5d7420 100644 --- a/src/test/compile-fail/borrowck-pat-enum.rs +++ b/src/test/compile-fail/borrowck-pat-enum.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn match_ref(&&v: option<int>) -> int { alt v { some(i) { diff --git a/src/test/compile-fail/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck-pat-reassign-binding.rs index 5018d4835ae..cf1199557bd 100644 --- a/src/test/compile-fail/borrowck-pat-reassign-binding.rs +++ b/src/test/compile-fail/borrowck-pat-reassign-binding.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // xfail-pretty -- comments are infaithfully preserved fn main() { diff --git a/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs b/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs index bf28af2db4d..db8129d005a 100644 --- a/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs +++ b/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // xfail-pretty -- comments are infaithfully preserved fn main() { diff --git a/src/test/compile-fail/borrowck-pure-scope-in-call.rs b/src/test/compile-fail/borrowck-pure-scope-in-call.rs index 9e83fd4be35..4469dca3620 100644 --- a/src/test/compile-fail/borrowck-pure-scope-in-call.rs +++ b/src/test/compile-fail/borrowck-pure-scope-in-call.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - pure fn pure_borrow(_x: &int, _y: ()) {} fn test1(x: @mut ~int) { diff --git a/src/test/compile-fail/borrowck-unchecked-with-borrow.rs b/src/test/compile-fail/borrowck-unchecked-with-borrow.rs index cefe3ba0553..a5f8b947bf2 100644 --- a/src/test/compile-fail/borrowck-unchecked-with-borrow.rs +++ b/src/test/compile-fail/borrowck-unchecked-with-borrow.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn impure(_i: int) {} // check that unchecked alone does not override borrowck: diff --git a/src/test/compile-fail/borrowck-uniq-via-box.rs b/src/test/compile-fail/borrowck-uniq-via-box.rs index 4433dba0c19..cf0f5439afc 100644 --- a/src/test/compile-fail/borrowck-uniq-via-box.rs +++ b/src/test/compile-fail/borrowck-uniq-via-box.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn borrow(_v: &int) {} fn box_mut(v: @mut ~int) { diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck-uniq-via-lend.rs index 787285e7bf5..78bba1576e8 100644 --- a/src/test/compile-fail/borrowck-uniq-via-lend.rs +++ b/src/test/compile-fail/borrowck-uniq-via-lend.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn borrow(_v: &int) {} fn local() { diff --git a/src/test/compile-fail/borrowck-uniq-via-ref.rs b/src/test/compile-fail/borrowck-uniq-via-ref.rs index b0fae6622d0..156106b880c 100644 --- a/src/test/compile-fail/borrowck-uniq-via-ref.rs +++ b/src/test/compile-fail/borrowck-uniq-via-ref.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err fn borrow(_v: &int) {} fn box_mut(v: &mut ~int) { diff --git a/src/test/compile-fail/issue-511.rs b/src/test/compile-fail/issue-511.rs index 40d25a37566..793bb48c79a 100644 --- a/src/test/compile-fail/issue-511.rs +++ b/src/test/compile-fail/issue-511.rs @@ -8,8 +8,6 @@ fn f<T>(&o: option<T>) { fn main() { f::<int>(option::none); //!^ ERROR taking mut reference to static item - - // Additional errors reported by borrowck: - //^^ ERROR illegal borrow unless pure: creating mutable alias to aliasable, immutable memory - //^^^ NOTE impure due to access to impure function + //!^^ ERROR illegal borrow unless pure: creating mutable alias to aliasable, immutable memory + //!^^^ NOTE impure due to access to impure function } \ No newline at end of file diff --git a/src/test/compile-fail/unsafe-alias-2.rs b/src/test/compile-fail/unsafe-alias-2.rs deleted file mode 100644 index ac20aeec931..00000000000 --- a/src/test/compile-fail/unsafe-alias-2.rs +++ /dev/null @@ -1,8 +0,0 @@ -// error-pattern:invalidate reference x - -fn whoknows(x: @mut {mut x: int}) { x.x = 10; } - -fn main() { - let box = @mut {mut x: 1}; - alt *box { x { whoknows(box); log(error, x); } } -} diff --git a/src/test/compile-fail/unsafe-alias.rs b/src/test/compile-fail/unsafe-alias.rs deleted file mode 100644 index 0b13c5b5305..00000000000 --- a/src/test/compile-fail/unsafe-alias.rs +++ /dev/null @@ -1,10 +0,0 @@ -// error-pattern:may alias with argument - -fn foo(x: {mut x: int}, f: fn@()) { log(debug, x); } - -fn whoknows(x: @mut {mut x: int}) { *x = {mut x: 10}; } - -fn main() { - let box = @mut {mut x: 1}; - foo(*box, bind whoknows(box)); -} diff --git a/src/test/compile-fail/unsafe-alt.rs b/src/test/compile-fail/unsafe-alt.rs deleted file mode 100644 index 498508d8980..00000000000 --- a/src/test/compile-fail/unsafe-alt.rs +++ /dev/null @@ -1,8 +0,0 @@ -// error-pattern:invalidate reference i - -enum foo { left({mut x: int}), right(bool) } - -fn main() { - let mut x = left({mut x: 10}); - alt x { left(i) { x = right(false); copy x; log(debug, i); } _ { } } -} diff --git a/src/test/compile-fail/unsafe-mutable-alias.rs b/src/test/compile-fail/unsafe-mutable-alias.rs deleted file mode 100644 index 1767eb3983c..00000000000 --- a/src/test/compile-fail/unsafe-mutable-alias.rs +++ /dev/null @@ -1,8 +0,0 @@ -// error-pattern:mut reference to a variable that roots another reference - -fn f(a: {mut x: int}, &b: {mut x: int}) -> int { - b.x += 1; - ret a.x + b.x; -} - -fn main() { let i = {mut x: 4}; log(debug, f(i, i)); } diff --git a/src/test/run-pass/alt-implicit-copy-unique.rs b/src/test/run-pass/alt-implicit-copy-unique.rs index bffa76efa30..bef4af11be4 100644 --- a/src/test/run-pass/alt-implicit-copy-unique.rs +++ b/src/test/run-pass/alt-implicit-copy-unique.rs @@ -1,6 +1,6 @@ fn main() { let x = ~{mut a: ~10, b: ~20}; alt x { - ~{a, b} { assert *a == 10; (*x).a = ~30; assert *a == 10; } + ~{a, b} { assert *a == 10; (*x).a = ~30; assert *a == 30; } } } diff --git a/src/test/run-pass/alt-implicit-copy.rs b/src/test/run-pass/alt-implicit-copy.rs index 43de34e87a8..63cbdf6ca79 100644 --- a/src/test/run-pass/alt-implicit-copy.rs +++ b/src/test/run-pass/alt-implicit-copy.rs @@ -1,6 +1,6 @@ fn main() { let x = @{mut a: @10, b: @20}; alt x { - @{a, b} { assert *a == 10; (*x).a = @30; assert *a == 10; } + @{a, b} { assert *a == 10; (*x).a = @30; assert *a == 30; } } } diff --git a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs index e6e4c36db35..a6279d12ab8 100644 --- a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs +++ b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn want_slice(v: [int]/&) -> int { let mut sum = 0; for vec::each(v) { |i| sum += i; } diff --git a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs b/src/test/run-pass/borrowck-pat-reassign-no-binding.rs index e5dd8a1756c..73a7085d865 100644 --- a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs +++ b/src/test/run-pass/borrowck-pat-reassign-no-binding.rs @@ -1,6 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err - fn main() { let mut x = none; alt x { diff --git a/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs b/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs index 5241848131d..9b49e3cd044 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn main() { diff --git a/src/test/run-pass/borrowck-preserve-box-in-discr.rs b/src/test/run-pass/borrowck-preserve-box-in-discr.rs index 044db44595d..f486ffe557d 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-discr.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-discr.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn main() { diff --git a/src/test/run-pass/borrowck-preserve-box-in-field.rs b/src/test/run-pass/borrowck-preserve-box-in-field.rs index 06260dbe5d2..09353e3d39f 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-field.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-field.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn borrow(x: &int, f: fn(x: &int)) { diff --git a/src/test/run-pass/borrowck-preserve-box-in-pat.rs b/src/test/run-pass/borrowck-preserve-box-in-pat.rs index 718507d1efc..0bad47642a0 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-pat.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-pat.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn main() { diff --git a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs b/src/test/run-pass/borrowck-preserve-box-in-uniq.rs index 3bec4fb083a..475e5eaea8c 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-uniq.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn borrow(x: &int, f: fn(x: &int)) { diff --git a/src/test/run-pass/borrowck-preserve-box-sometimes-needed.rs b/src/test/run-pass/borrowck-preserve-box-sometimes-needed.rs index ed6e0b19e01..285b3ad8e0f 100644 --- a/src/test/run-pass/borrowck-preserve-box-sometimes-needed.rs +++ b/src/test/run-pass/borrowck-preserve-box-sometimes-needed.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn switcher(x: option<@int>) { diff --git a/src/test/run-pass/borrowck-preserve-box.rs b/src/test/run-pass/borrowck-preserve-box.rs index ebc1c1ab70d..d4d2f5a2055 100644 --- a/src/test/run-pass/borrowck-preserve-box.rs +++ b/src/test/run-pass/borrowck-preserve-box.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn borrow(x: &int, f: fn(x: &int)) { diff --git a/src/test/run-pass/borrowck-preserve-cond-box.rs b/src/test/run-pass/borrowck-preserve-cond-box.rs index d1098a04d01..0ee7ce18761 100644 --- a/src/test/run-pass/borrowck-preserve-cond-box.rs +++ b/src/test/run-pass/borrowck-preserve-cond-box.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn testfn(cond: bool) { diff --git a/src/test/run-pass/borrowck-preserve-expl-deref.rs b/src/test/run-pass/borrowck-preserve-expl-deref.rs index c50afeeaa90..0778b895137 100644 --- a/src/test/run-pass/borrowck-preserve-expl-deref.rs +++ b/src/test/run-pass/borrowck-preserve-expl-deref.rs @@ -1,5 +1,3 @@ -// xfail-fast (compile-flags unsupported on windows) -// compile-flags:--borrowck=err // exec-env:RUST_POISON_ON_FREE=1 fn borrow(x: &int, f: fn(x: &int)) { diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index a9ec335e5f0..ea817e0e0f7 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -145,7 +145,7 @@ fn main() { intrinsic::visit_ty::<i16>(vv); intrinsic::visit_ty::<[int]>(vv); - for v.types.each {|s| + for (copy v.types).each {|s| io::println(#fmt("type: %s", s)); } assert v.types == ["bool", "int", "i8", "i16", |
