diff options
| author | bors <bors@rust-lang.org> | 2013-05-30 19:04:52 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-05-30 19:04:52 -0700 |
| commit | 3869f7a99c54f00d69b19298f215cbc4a84ce5a8 (patch) | |
| tree | fca2b9d8c111e40604460dedc696cbe0a47b58c7 | |
| parent | 237dce12c934287abd0bbe5a35309b1dc4f0d2c0 (diff) | |
| parent | ce5fd302702a76e4b65a94128189b0f2d3a22c32 (diff) | |
auto merge of #6818 : nikomatsakis/rust/irrefut-patterns-refactoring, r=graydon
Various bug fixes and simplifications I did as part of a patch to fix `let` patterns. r? @catamorphism
49 files changed, 408 insertions, 450 deletions
diff --git a/src/libextra/fun_treemap.rs b/src/libextra/fun_treemap.rs index fb9bb0740c5..eb8c27e9902 100644 --- a/src/libextra/fun_treemap.rs +++ b/src/libextra/fun_treemap.rs @@ -35,13 +35,13 @@ enum TreeNode<K, V> { pub fn init<K, V>() -> Treemap<K, V> { @Empty } /// Insert a value into the map -pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> { +pub fn insert<K:Eq + Ord,V>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> { @match m { @Empty => Node(@k, @v, @Empty, @Empty), - @Node(@copy kk, vv, left, right) => cond!( - (k < kk) { Node(@kk, vv, insert(left, k, v), right) } - (k == kk) { Node(@kk, @v, left, right) } - _ { Node(@kk, vv, left, insert(right, k, v)) } + @Node(kk, vv, left, right) => cond!( + (k < *kk) { Node(kk, vv, insert(left, k, v), right) } + (k == *kk) { Node(kk, @v, left, right) } + _ { Node(kk, vv, left, insert(right, k, v)) } ) } } @@ -50,8 +50,8 @@ pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> { match *m { Empty => None, - Node(@ref kk, @copy v, left, right) => cond!( - (k == *kk) { Some(v) } + Node(kk, v, left, right) => cond!( + (k == *kk) { Some(copy *v) } (k < *kk) { find(left, k) } _ { find(right, k) } ) diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 678d795d8f8..eb5699df77f 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -171,7 +171,7 @@ fn is_arg(arg: &str) -> bool { fn name_str(nm: &Name) -> ~str { return match *nm { Short(ch) => str::from_char(ch), - Long(copy s) => s + Long(ref s) => copy *s }; } @@ -390,7 +390,7 @@ pub fn opts_present(mm: &Matches, names: &[~str]) -> bool { * argument */ pub fn opt_str(mm: &Matches, nm: &str) -> ~str { - return match opt_val(mm, nm) { Val(copy s) => s, _ => fail!() }; + return match opt_val(mm, nm) { Val(s) => s, _ => fail!() }; } /** @@ -402,7 +402,7 @@ pub fn opt_str(mm: &Matches, nm: &str) -> ~str { pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str { for names.each |nm| { match opt_val(mm, *nm) { - Val(copy s) => return s, + Val(ref s) => return copy *s, _ => () } } @@ -419,7 +419,7 @@ pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str { pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] { let mut acc: ~[~str] = ~[]; for vec::each(opt_vals(mm, nm)) |v| { - match *v { Val(copy s) => acc.push(s), _ => () } + match *v { Val(ref s) => acc.push(copy *s), _ => () } } return acc; } @@ -429,7 +429,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> { let vals = opt_vals(mm, nm); if vec::len::<Optval>(vals) == 0u { return None::<~str>; } return match vals[0] { - Val(copy s) => Some(s), + Val(ref s) => Some(copy *s), _ => None }; } @@ -445,7 +445,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> { pub fn opt_default(mm: &Matches, nm: &str, def: &str) -> Option<~str> { let vals = opt_vals(mm, nm); if vec::len::<Optval>(vals) == 0u { return None::<~str>; } - return match vals[0] { Val(copy s) => Some::<~str>(s), + return match vals[0] { Val(ref s) => Some::<~str>(copy *s), _ => Some::<~str>(str::to_owned(def)) } } @@ -701,7 +701,7 @@ mod tests { let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionMissing_), + Err(f) => check_fail_type(f, OptionMissing_), _ => fail!() } } @@ -712,7 +712,7 @@ mod tests { let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -723,7 +723,7 @@ mod tests { let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -748,7 +748,7 @@ mod tests { let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionMissing_), + Err(f) => check_fail_type(f, OptionMissing_), _ => fail!() } } @@ -759,7 +759,7 @@ mod tests { let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -770,7 +770,7 @@ mod tests { let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -808,7 +808,7 @@ mod tests { let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -819,7 +819,7 @@ mod tests { let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -855,7 +855,7 @@ mod tests { let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -866,7 +866,7 @@ mod tests { let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -901,7 +901,7 @@ mod tests { let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => { + Err(f) => { error!(fail_str(copy f)); check_fail_type(f, UnexpectedArgument_); } @@ -915,7 +915,7 @@ mod tests { let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -963,7 +963,7 @@ mod tests { let opts = ~[optflag("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -1066,7 +1066,7 @@ mod tests { let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -1119,7 +1119,7 @@ mod tests { let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -1147,7 +1147,7 @@ mod tests { let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, UnrecognizedOption_), + Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } } @@ -1158,7 +1158,7 @@ mod tests { let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, UnrecognizedOption_), + Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } } diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 48a3288f809..d69548c6f9d 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -1384,7 +1384,7 @@ mod tests { for items.each |item| { match *item { - (copy key, copy value) => { d.insert(key, value); }, + (ref key, ref value) => { d.insert(copy *key, copy *value); }, } }; diff --git a/src/libextra/list.rs b/src/libextra/list.rs index 6f2c8447eca..7a38be8944f 100644 --- a/src/libextra/list.rs +++ b/src/libextra/list.rs @@ -104,7 +104,7 @@ pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> { /// Returns the first element of a list pub fn head<T:Copy>(ls: @List<T>) -> T { match *ls { - Cons(copy hd, _) => hd, + Cons(ref hd, _) => copy *hd, // makes me sad _ => fail!("head invoked on empty list") } @@ -114,9 +114,9 @@ pub fn head<T:Copy>(ls: @List<T>) -> T { pub fn append<T:Copy>(l: @List<T>, m: @List<T>) -> @List<T> { match *l { Nil => return m, - Cons(copy x, xs) => { + Cons(ref x, xs) => { let rest = append(xs, m); - return @Cons(x, rest); + return @Cons(copy *x, rest); } } } diff --git a/src/libextra/net_ip.rs b/src/libextra/net_ip.rs index 160d06ec20d..ddbf09e40eb 100644 --- a/src/libextra/net_ip.rs +++ b/src/libextra/net_ip.rs @@ -278,7 +278,7 @@ pub mod v6 { pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { result::Ok(addr) => addr, - result::Err(copy err_data) => fail!(copy err_data.err_msg) + result::Err(err_data) => fail!(copy err_data.err_msg) } } pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> { diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs index c3a0463c2fc..d658ad6551f 100644 --- a/src/libextra/net_tcp.rs +++ b/src/libextra/net_tcp.rs @@ -595,7 +595,7 @@ pub fn accept(new_conn: TcpNewConnection) } // UNSAFE LIBUV INTERACTION END match result_po.recv() { - Some(copy err_data) => result::Err(err_data), + Some(err_data) => result::Err(err_data), None => result::Ok(TcpSocket(client_socket_data)) } } diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 59c6a12e036..375b4cd5fb5 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -223,7 +223,7 @@ pub fn run_tests_console(opts: &TestOpts, } TeWait(ref test) => st.out.write_str( fmt!("test %s ... ", test.name.to_str())), - TeResult(copy test, result) => { + TeResult(test, result) => { match st.log_out { Some(f) => write_log(f, copy result, &test), None => () @@ -504,9 +504,8 @@ pub fn filter_tests( filtered = if opts.filter.is_none() { filtered } else { - let filter_str = - match opts.filter { - option::Some(copy f) => f, + let filter_str = match opts.filter { + option::Some(ref f) => copy *f, option::None => ~"" }; @@ -866,7 +865,7 @@ mod tests { fn first_free_arg_should_be_a_filter() { let args = ~[~"progname", ~"filter"]; let opts = match parse_opts(args) { - either::Left(copy o) => o, + either::Left(o) => o, _ => fail!("Malformed arg in first_free_arg_should_be_a_filter") }; assert!("filter" == (copy opts.filter).get()); @@ -876,7 +875,7 @@ mod tests { fn parse_ignored_flag() { let args = ~[~"progname", ~"filter", ~"--ignored"]; let opts = match parse_opts(args) { - either::Left(copy o) => o, + either::Left(o) => o, _ => fail!("Malformed arg in parse_ignored_flag") }; assert!((opts.run_ignored)); diff --git a/src/libextra/time.rs b/src/libextra/time.rs index e3289d01750..1a3a5db66ae 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -275,10 +275,12 @@ priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> { let mut i = 0u; let len = strs.len(); while i < len { - let &(needle, value) = &strs[i]; - - if match_str(ss, pos, needle) { - return Some((value, pos + str::len(needle))); + match strs[i] { // can't use let due to stage0 bugs + (ref needle, value) => { + if match_str(ss, pos, *needle) { + return Some((value, pos + str::len(*needle))); + } + } } i += 1u; } @@ -1007,7 +1009,7 @@ mod tests { == Err(~"Invalid time")); match strptime("Fri Feb 13 15:31:30 2009", format) { - Err(copy e) => fail!(e), + Err(e) => fail!(e), Ok(ref tm) => { assert!(tm.tm_sec == 30_i32); assert!(tm.tm_min == 31_i32); @@ -1027,7 +1029,7 @@ mod tests { fn test(s: &str, format: &str) -> bool { match strptime(s, format) { Ok(ref tm) => tm.strftime(format) == str::to_owned(s), - Err(copy e) => fail!(e) + Err(e) => fail!(e) } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 02c0b19e565..472ce5c926e 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -375,8 +375,8 @@ pub mod write { pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) { let cc_prog: ~str = match &sess.opts.android_cross_path { - &Some(copy path) => { - fmt!("%s/bin/arm-linux-androideabi-gcc", path) + &Some(ref path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", *path) } &None => { sess.fatal("need Android NDK path for building \ @@ -763,12 +763,12 @@ pub fn link_binary(sess: Session, // For win32, there is no cc command, // so we add a condition to make it use gcc. let cc_prog: ~str = match sess.opts.linker { - Some(copy linker) => linker, + Some(ref linker) => copy *linker, None => { if sess.targ_cfg.os == session::os_android { match &sess.opts.android_cross_path { - &Some(copy path) => { - fmt!("%s/bin/arm-linux-androideabi-gcc", path) + &Some(ref path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", *path) } &None => { sess.fatal("need Android NDK path for linking \ diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index b56699927e4..5e33a8f78fe 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -956,8 +956,8 @@ mod test { fn test_switch_implies_cfg_test() { let matches = &match getopts([~"--test"], optgroups()) { - Ok(copy m) => m, - Err(copy f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f)) + Ok(m) => m, + Err(f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f)) }; let sessopts = build_session_options( @~"rustc", matches, diagnostic::emit); @@ -972,8 +972,8 @@ mod test { fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = &match getopts([~"--test", ~"--cfg=test"], optgroups()) { - Ok(copy m) => m, - Err(copy f) => { + Ok(m) => m, + Err(f) => { fail!("test_switch_implies_cfg_test_unless_cfg_test: %s", getopts::fail_str(f)); } }; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 2c9b3c3a4ef..0e263c78bfe 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -141,10 +141,10 @@ fn visit_crate(e: @mut Env, c: &ast::crate) { fn visit_view_item(e: @mut Env, i: @ast::view_item) { match i.node { - ast::view_item_extern_mod(ident, /*bad*/copy meta_items, id) => { + ast::view_item_extern_mod(ident, ref meta_items, id) => { debug!("resolving extern mod stmt. ident: %?, meta: %?", - ident, meta_items); - let cnum = resolve_crate(e, ident, meta_items, @~"", i.span); + ident, *meta_items); + let cnum = resolve_crate(e, ident, copy *meta_items, @~"", i.span); cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum); } _ => () diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index c2ae364e54c..552476d25d6 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -623,7 +623,7 @@ pub impl GatherLoanCtxt { cmt, mutbl, scope_r); } } - ast::bind_by_copy | ast::bind_infer => { + ast::bind_infer => { // No borrows here, but there may be moves if self.bccx.is_move(pat.id) { gather_moves::gather_move_from_pat( diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 58c5ce6f2b5..035d6a5cc45 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -827,7 +827,6 @@ pub fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, for pats.each |pat| { do pat_bindings(def_map, *pat) |bm, id, span, _path| { match bm { - bind_by_copy => {} bind_by_ref(_) => { by_ref_span = Some(span); } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 6315986d1a6..8493965049e 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -71,7 +71,6 @@ pub fn check_crate(tcx: ty::ctxt, current_item: -1 }; let visit = visit::mk_vt(@visit::Visitor { - visit_arm: check_arm, visit_expr: check_expr, visit_fn: check_fn, visit_ty: check_ty, @@ -238,19 +237,6 @@ fn check_fn( visit::visit_fn(fk, decl, body, sp, fn_id, cx, v); } -fn check_arm(a: &arm, cx: Context, v: visit::vt<Context>) { - for a.pats.each |p| { - do pat_util::pat_bindings(cx.tcx.def_map, *p) |mode, id, span, _pth| { - if mode == bind_by_copy { - let t = ty::node_id_to_type(cx.tcx, id); - let reason = "consider binding with `ref` or `move` instead"; - check_copy(cx, t, span, reason); - } - } - } - visit::visit_arm(a, cx, v); -} - pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) { debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr())); diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index c58ebcd1ee4..d2f6d652773 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -576,14 +576,18 @@ pub impl VisitContext { do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, _path| { let binding_moves = match bm { - bind_by_copy => false, bind_by_ref(_) => false, bind_infer => { let pat_ty = ty::node_id_to_type(self.tcx, id); + debug!("pattern %? type is %s", + id, pat_ty.repr(self.tcx)); ty::type_moves_by_default(self.tcx, pat_ty) } }; + debug!("pattern binding %?: bm=%?, binding_moves=%b", + id, bm, binding_moves); + if binding_moves { self.move_maps.moves_map.insert(id); } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index fa17fa04ed8..23645f7f04a 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -520,12 +520,12 @@ pub impl NameBindings { type_span: Some(sp) }); } - Some(copy type_def) => { + Some(type_def) => { self.type_def = Some(TypeNsDef { privacy: privacy, module_def: Some(module_), type_span: Some(sp), - .. type_def + type_def: type_def.type_def }); } } @@ -577,12 +577,12 @@ pub impl NameBindings { type_span: Some(sp) }); } - Some(copy type_def) => { + Some(type_def) => { self.type_def = Some(TypeNsDef { privacy: privacy, type_def: Some(def), type_span: Some(sp), - .. type_def + module_def: type_def.module_def }); } } @@ -1566,7 +1566,7 @@ pub impl Resolver { match def { def_mod(def_id) | def_foreign_mod(def_id) => { match child_name_bindings.type_def { - Some(TypeNsDef { module_def: Some(copy module_def), _ }) => { + Some(TypeNsDef { module_def: Some(module_def), _ }) => { debug!("(building reduced graph for external crate) \ already created module"); module_def.def_id = Some(def_id); @@ -1745,7 +1745,7 @@ pub impl Resolver { NormalModuleKind, dummy_sp()); } - Some(copy type_ns_def) + Some(type_ns_def) if type_ns_def.module_def.is_none() => { debug!("(building reduced graph for external crate) \ autovivifying missing module def %s", @@ -1812,7 +1812,7 @@ pub impl Resolver { let type_module; match child_name_bindings.type_def { Some(TypeNsDef { - module_def: Some(copy module_def), + module_def: Some(module_def), _ }) => { // We already have a module. This @@ -2445,7 +2445,7 @@ pub impl Resolver { None => { // Continue. } - Some(copy value_target) => { + Some(value_target) => { dest_import_resolution.value_target = Some(value_target); } @@ -2454,7 +2454,7 @@ pub impl Resolver { None => { // Continue. } - Some(copy type_target) => { + Some(type_target) => { dest_import_resolution.type_target = Some(type_target); } @@ -2566,7 +2566,7 @@ pub impl Resolver { // Check to see whether there are type bindings, and, if // so, whether there is a module within. match target.bindings.type_def { - Some(copy type_def) => { + Some(type_def) => { match type_def.module_def { None => { // Not a module. @@ -5170,12 +5170,6 @@ pub impl Resolver { descr: &str) { match pat_binding_mode { bind_infer => {} - bind_by_copy => { - self.session.span_err( - pat.span, - fmt!("cannot use `copy` binding mode with %s", - descr)); - } bind_by_ref(*) => { self.session.span_err( pat.span, @@ -5316,7 +5310,7 @@ pub fn resolve_crate(session: Session, -> CrateMap { let resolver = @mut Resolver(session, lang_items, crate); resolver.resolve(); - let @Resolver{def_map, export_map2, trait_map, _} = resolver; + let Resolver{def_map, export_map2, trait_map, _} = copy *resolver; CrateMap { def_map: def_map, exp_map2: export_map2, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index ca7ce9c02d1..b142dc1ef28 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -140,6 +140,11 @@ * the various values we copied explicitly. Note that guards and moves are * just plain incompatible. * + * Some relevant helper functions that manage bindings: + * - `create_bindings_map()` + * - `store_non_ref_bindings()` + * - `insert_lllocals()` + * */ use core::prelude::*; @@ -314,7 +319,6 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id) pub enum TransBindingMode { TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef), TrByRef, - TrByImplicitRef } /** @@ -670,8 +674,8 @@ pub fn enter_tup<'r>(bcx: block, let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { match p.node { - ast::pat_tup(/*bad*/copy elts) => { - Some(elts) + ast::pat_tup(ref elts) => { + Some(copy *elts) } _ => { assert_is_binding_or_wild(bcx, p); @@ -698,7 +702,7 @@ pub fn enter_tuple_struct<'r>(bcx: block, let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { match p.node { - ast::pat_enum(_, Some(/*bad*/copy elts)) => Some(elts), + ast::pat_enum(_, Some(ref elts)) => Some(copy *elts), _ => { assert_is_binding_or_wild(bcx, p); Some(vec::from_elem(n_elts, dummy)) @@ -881,7 +885,7 @@ fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum { //! we should just pass around a Datum and be done with it. let ty = node_id_type(bcx, pat_id); - Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean} + Datum {val: val, ty: ty, mode: datum::ByRef(RevokeClean)} } @@ -988,7 +992,7 @@ pub fn root_pats_as_necessary(mut bcx: block, let pat_id = br.pats[col].id; if pat_id != 0 { let datum = Datum {val: val, ty: node_id_type(bcx, pat_id), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; bcx = datum.root_and_write_guard(bcx, br.pats[col].span, pat_id, 0); } } @@ -1125,10 +1129,10 @@ pub fn compare_values(cx: block, } } -pub fn store_non_ref_bindings(bcx: block, - data: &ArmData, - opt_temp_cleanups: Option<&mut ~[ValueRef]>) - -> block +fn store_non_ref_bindings(bcx: block, + bindings_map: &BindingsMap, + mut opt_temp_cleanups: Option<&mut ~[ValueRef]>) + -> block { /*! * @@ -1140,13 +1144,12 @@ pub fn store_non_ref_bindings(bcx: block, */ let mut bcx = bcx; - let mut opt_temp_cleanups = opt_temp_cleanups; - for data.bindings_map.each_value |&binding_info| { + for bindings_map.each_value |&binding_info| { match binding_info.trmode { TrByValue(is_move, lldest) => { let llval = Load(bcx, binding_info.llmatch); // get a T* let datum = Datum {val: llval, ty: binding_info.ty, - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; bcx = { if is_move { datum.move_to(bcx, INIT, lldest) @@ -1161,22 +1164,28 @@ pub fn store_non_ref_bindings(bcx: block, temp_cleanups } } - TrByRef | TrByImplicitRef => {} + TrByRef => {} } } return bcx; } -pub fn insert_lllocals(bcx: block, - data: &ArmData, - add_cleans: bool) -> block { +fn insert_lllocals(bcx: block, + bindings_map: &BindingsMap, + binding_mode: IrrefutablePatternBindingMode, + add_cleans: bool) -> block { /*! - * * For each binding in `data.bindings_map`, adds an appropriate entry into * the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for - * the bindings. */ + * the bindings. + */ - for data.bindings_map.each_value |&binding_info| { + let llmap = match binding_mode { + BindLocal => bcx.fcx.lllocals, + BindArgument => bcx.fcx.llargs + }; + + for bindings_map.each_value |&binding_info| { let llval = match binding_info.trmode { // By value bindings: use the stack slot that we // copied/moved the value into @@ -1192,17 +1201,12 @@ pub fn insert_lllocals(bcx: block, TrByRef => { binding_info.llmatch } - - // Ugly: for implicit ref, we actually want a T*, but - // we have a T**, so we had to load. This will go away - // once implicit refs go away. - TrByImplicitRef => { - Load(bcx, binding_info.llmatch) - } }; - bcx.fcx.lllocals.insert(binding_info.id, - local_mem(llval)); + debug!("binding %? to %s", + binding_info.id, + val_str(bcx.ccx().tn, llval)); + llmap.insert(binding_info.id, llval); } return bcx; } @@ -1223,8 +1227,8 @@ pub fn compile_guard(bcx: block, let mut bcx = bcx; let mut temp_cleanups = ~[]; - bcx = store_non_ref_bindings(bcx, data, Some(&mut temp_cleanups)); - bcx = insert_lllocals(bcx, data, false); + bcx = store_non_ref_bindings(bcx, &data.bindings_map, Some(&mut temp_cleanups)); + bcx = insert_lllocals(bcx, &data.bindings_map, BindLocal, false); let val = unpack_result!(bcx, { do with_scope_result(bcx, guard_expr.info(), @@ -1254,7 +1258,7 @@ pub fn compile_guard(bcx: block, TrByValue(_, llval) => { bcx = glue::drop_ty(bcx, llval, binding_info.ty); } - TrByRef | TrByImplicitRef => {} + TrByRef => {} } bcx.fcx.lllocals.remove(&binding_info.id); } @@ -1621,6 +1625,42 @@ pub fn trans_match(bcx: block, } } +fn create_bindings_map(bcx: block, pat: @ast::pat) -> BindingsMap { + // Create the bindings map, which is a mapping from each binding name + // to an alloca() that will be the value for that local variable. + // Note that we use the names because each binding will have many ids + // from the various alternatives. + let ccx = bcx.ccx(); + let tcx = bcx.tcx(); + let mut bindings_map = HashMap::new(); + do pat_bindings(tcx.def_map, pat) |bm, p_id, _s, path| { + let ident = path_to_ident(path); + let variable_ty = node_id_type(bcx, p_id); + let llvariable_ty = type_of::type_of(ccx, variable_ty); + + let llmatch, trmode; + match bm { + ast::bind_infer => { + // in this case, the final type of the variable will be T, + // but during matching we need to store a *T as explained + // above + let is_move = ccx.maps.moves_map.contains(&p_id); + llmatch = alloca(bcx, T_ptr(llvariable_ty)); + trmode = TrByValue(is_move, alloca(bcx, llvariable_ty)); + } + ast::bind_by_ref(_) => { + llmatch = alloca(bcx, llvariable_ty); + trmode = TrByRef; + } + }; + bindings_map.insert(ident, BindingInfo { + llmatch: llmatch, trmode: trmode, + id: p_id, ty: variable_ty + }); + } + return bindings_map; +} + pub fn trans_match_inner(scope_cx: block, discr_expr: @ast::expr, arms: &[ast::arm], @@ -1637,41 +1677,9 @@ pub fn trans_match_inner(scope_cx: block, } let mut arm_datas = ~[], matches = ~[]; - for arms.each |arm| { + for vec::each(arms) |arm| { let body = scope_block(bcx, arm.body.info(), "case_body"); - - // Create the bindings map, which is a mapping from each binding name - // to an alloca() that will be the value for that local variable. - // Note that we use the names because each binding will have many ids - // from the various alternatives. - let mut bindings_map = HashMap::new(); - do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, _s, path| { - let ident = path_to_ident(path); - let variable_ty = node_id_type(bcx, p_id); - let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty); - - let llmatch, trmode; - match bm { - ast::bind_by_copy | ast::bind_infer => { - // in this case, the final type of the variable will be T, - // but during matching we need to store a *T as explained - // above - let is_move = - scope_cx.ccx().maps.moves_map.contains(&p_id); - llmatch = alloca(bcx, T_ptr(llvariable_ty)); - trmode = TrByValue(is_move, alloca(bcx, llvariable_ty)); - } - ast::bind_by_ref(_) => { - llmatch = alloca(bcx, llvariable_ty); - trmode = TrByRef; - } - }; - bindings_map.insert(ident, BindingInfo { - llmatch: llmatch, trmode: trmode, - id: p_id, ty: variable_ty - }); - } - + let bindings_map = create_bindings_map(bcx, arm.pats[0]); let arm_data = @ArmData {bodycx: body, arm: arm, bindings_map: bindings_map}; @@ -1693,7 +1701,7 @@ pub fn trans_match_inner(scope_cx: block, None } }; - let lldiscr = discr_datum.to_ref_llval(bcx); + let lldiscr = discr_datum.to_zeroable_ref_llval(bcx); compile_submatch(bcx, matches, [lldiscr], chk); let mut arm_cxs = ~[]; @@ -1705,11 +1713,11 @@ pub fn trans_match_inner(scope_cx: block, // is just to reduce code space. See extensive comment at the start // of the file for more details. if arm_data.arm.guard.is_none() { - bcx = store_non_ref_bindings(bcx, *arm_data, None); + bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None); } // insert bindings into the lllocals map and add cleanups - bcx = insert_lllocals(bcx, *arm_data, true); + bcx = insert_lllocals(bcx, &arm_data.bindings_map, BindLocal, true); bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest); bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx)); @@ -1757,27 +1765,25 @@ pub fn bind_irrefutable_pat(bcx: block, if make_copy { let binding_ty = node_id_type(bcx, pat.id); let datum = Datum {val: val, ty: binding_ty, - mode: ByRef, source: RevokeClean}; + mode: ByRef(RevokeClean)}; let scratch = scratch_datum(bcx, binding_ty, false); datum.copy_to_datum(bcx, INIT, scratch); match binding_mode { BindLocal => { - bcx.fcx.lllocals.insert(pat.id, - local_mem(scratch.val)); + bcx.fcx.lllocals.insert(pat.id, scratch.val); } BindArgument => { - bcx.fcx.llargs.insert(pat.id, - local_mem(scratch.val)); + bcx.fcx.llargs.insert(pat.id, scratch.val); } } add_clean(bcx, scratch.val, binding_ty); } else { match binding_mode { BindLocal => { - bcx.fcx.lllocals.insert(pat.id, local_mem(val)); + bcx.fcx.lllocals.insert(pat.id, val); } BindArgument => { - bcx.fcx.llargs.insert(pat.id, local_mem(val)); + bcx.fcx.llargs.insert(pat.id, val); } } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 6a49ae4cbc6..539dc3e1f00 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1105,8 +1105,8 @@ pub fn init_local(bcx: block, local: @ast::local) -> block { } } - let llptr = match bcx.fcx.lllocals.find(&local.node.id) { - Some(&local_mem(v)) => v, + let llptr = match bcx.fcx.lllocals.find_copy(&local.node.id) { + Some(v) => v, _ => { bcx.tcx().sess.span_bug(local.span, "init_local: Someone forgot to document why it's\ @@ -1432,7 +1432,7 @@ pub fn alloc_local(cx: block, local: @ast::local) -> block { }); } } - cx.fcx.lllocals.insert(local.node.id, local_mem(val)); + cx.fcx.lllocals.insert(local.node.id, val); cx } @@ -1726,7 +1726,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, let mut bcx = bcx; match fcx.llself { - Some(copy slf) => { + Some(slf) => { // We really should do this regardless of whether self is owned, but // it doesn't work right with default method impls yet. (FIXME: #2794) if slf.is_owned { @@ -1768,7 +1768,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, false, _match::BindArgument); - fcx.llargs.insert(arg_id, local_mem(llarg)); + fcx.llargs.insert(arg_id, llarg); if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span); @@ -1801,7 +1801,7 @@ pub fn build_return_block(fcx: fn_ctxt) { pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) { let _icx = fcx.insn_ctxt("tie_up_header_blocks"); match fcx.llloadenv { - Some(copy ll) => { + Some(ll) => { Br(raw_block(fcx, false, fcx.llstaticallocas), ll); Br(raw_block(fcx, false, ll), lltop); } @@ -2004,7 +2004,7 @@ pub fn trans_enum_variant(ccx: @CrateContext, // this function as an opaque blob due to the way that type_of() // works. So we have to cast to the destination's view of the type. let llarg = match fcx.llargs.find(&va.id) { - Some(&local_mem(x)) => x, + Some(&x) => x, _ => fail!("trans_enum_variant: how do we know this works?"), }; let arg_ty = arg_tys[i]; @@ -2074,12 +2074,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext, fcx.llretptr.get(), 0, i); - let llarg = match fcx.llargs.get_copy(&field.node.id) { - local_mem(x) => x, - _ => { - ccx.tcx.sess.bug("trans_tuple_struct: llarg wasn't local_mem") - } - }; + let llarg = fcx.llargs.get_copy(&field.node.id); let arg_ty = arg_tys[i]; memcpy_ty(bcx, lldestptr, llarg, arg_ty); } diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 1e6e31e4277..557388cf11c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -711,8 +711,7 @@ pub fn trans_arg_expr(bcx: block, DatumBlock {bcx: bcx, datum: Datum {val: scratch, ty: scratch_ty, - mode: ByRef, - source: RevokeClean}} + mode: ByRef(RevokeClean)}} } _ => { bcx.sess().impossible_case( @@ -775,7 +774,7 @@ pub fn trans_arg_expr(bcx: block, match arg_datum.appropriate_mode() { ByValue => val = Load(bcx, scratch.val), - ByRef => val = scratch.val, + ByRef(_) => val = scratch.val, } } } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index fa3e6eeb0b6..1a78019f289 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -287,7 +287,7 @@ pub fn build_closure(bcx0: block, for include_ret_handle.each |flagptr| { // Flag indicating we have returned (a by-ref bool): let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; env_vals.push(EnvValue {action: EnvRef, datum: flag_datum}); @@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block, }; let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil())); let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; env_vals.push(EnvValue {action: EnvRef, datum: ret_datum}); } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index d148dbd2183..a2fa840ad79 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -240,8 +240,6 @@ pub struct ValSelfData { is_owned: bool } -pub enum local_val { local_mem(ValueRef), local_imm(ValueRef), } - // Here `self_ty` is the real type of the self parameter to this method. It // will only be set in the case of default methods. pub struct param_substs { @@ -328,10 +326,10 @@ pub struct fn_ctxt_ { has_immediate_return_value: bool, // Maps arguments to allocas created for them in llallocas. - llargs: @mut HashMap<ast::node_id, local_val>, + llargs: @mut HashMap<ast::node_id, ValueRef>, // Maps the def_ids for local variables to the allocas created for // them in llallocas. - lllocals: @mut HashMap<ast::node_id, local_val>, + lllocals: @mut HashMap<ast::node_id, ValueRef>, // Same as above, but for closure upvars llupvars: @mut HashMap<ast::node_id, ValueRef>, diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index c8b9e3f8f0e..c0403083ce1 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -44,15 +44,17 @@ * # Datum cleanup styles * * Each datum carries with it an idea of how its value will be cleaned - * up. This is important after a move, because we need to know how to - * cancel the cleanup (since the value has been moved and therefore does - * not need to be freed). There are two options: - * - * 1. `RevokeClean`: To cancel the cleanup, we invoke `revoke_clean()`. - * This is used for temporary rvalues. - * - * 2. `ZeroMem`: To cancel the cleanup, we zero out the memory where - * the value resides. This is used for lvalues. + * up. This is primarily determined by the mode: a `ByValue` datum + * will always be cleaned up by revoking cleanup using + * `revoke_clean()`, because there is no other option. By ref datums + * can sometimes be cleaned up via `revoke_clean` (in particular, + * by-ref datums that originated from rvalues), but sometimes they + * must be zeroed. This is indicated by the `DatumCleanup` + * parameter. Note that zeroing a by-ref datum *always works* to + * cancel the cleanup, but using `revoke_clean` is preferable since + * there is no runtime cost. Some older parts of the code (notably + * `match_`, at least at the time of this writing) rely on this and + * only use zeroing. * * # Copying, moving, and storing * @@ -103,7 +105,6 @@ use middle::ty; use util::common::indenter; use util::ppaux::ty_to_str; -use core::to_bytes; use core::uint; use syntax::ast; use syntax::codemap::span; @@ -125,12 +126,6 @@ pub struct Datum { /// Indicates whether this is by-ref or by-value. mode: DatumMode, - - /// How did this value originate? This is particularly important - /// if the value is MOVED or prematurely DROPPED, because it - /// describes how to cancel the cleanup that was scheduled before. - /// See the def'n of the `DatumCleanup` type. - source: DatumCleanup } pub struct DatumBlock { @@ -138,10 +133,13 @@ pub struct DatumBlock { datum: Datum, } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum DatumMode { - /// `val` is a pointer to the actual value (and thus has type *T) - ByRef, + /// `val` is a pointer to the actual value (and thus has type *T). + /// The argument indicates how to cancel cleanup of this datum if + /// the value is moved elsewhere, which can either be by zeroing + /// the memory or by canceling a registered cleanup. + ByRef(DatumCleanup), /// `val` is the actual value (*only used for immediates* like ints, ptrs) ByValue, @@ -149,30 +147,23 @@ pub enum DatumMode { pub impl DatumMode { fn is_by_ref(&self) -> bool { - match *self { ByRef => true, ByValue => false } + match *self { ByRef(_) => true, ByValue => false } } fn is_by_value(&self) -> bool { - match *self { ByRef => false, ByValue => true } - } -} - -impl to_bytes::IterBytes for DatumMode { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - (*self as uint).iter_bytes(lsb0, f) + match *self { ByRef(_) => false, ByValue => true } } } /// See `Datum cleanup styles` section at the head of this module. -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum DatumCleanup { RevokeClean, ZeroMem } pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum { - return Datum {val: val, ty: ty, - mode: ByValue, source: RevokeClean}; + return Datum {val: val, ty: ty, mode: ByValue}; } pub fn immediate_rvalue_bcx(bcx: block, @@ -195,7 +186,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum { let llty = type_of::type_of(bcx.ccx(), ty); let scratch = alloca_maybe_zeroed(bcx, llty, zero); - Datum { val: scratch, ty: ty, mode: ByRef, source: RevokeClean } + Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) } } pub fn appropriate_mode(ty: ty::t) -> DatumMode { @@ -210,7 +201,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode { } else if ty::type_is_immediate(ty) { ByValue } else { - ByRef + ByRef(RevokeClean) } } @@ -289,7 +280,7 @@ pub impl Datum { ty::type_needs_drop(bcx.tcx(), self.ty) { match self.mode { - ByRef => { + ByRef(_) => { let cast = PointerCast(bcx, dst, val_ty(self.val)); let cmp = ICmp(bcx, lib::llvm::IntNE, cast, self.val); do with_cond(bcx, cmp) |bcx| { @@ -324,7 +315,7 @@ pub impl Datum { ByValue => { Store(bcx, self.val, dst); } - ByRef => { + ByRef(_) => { memcpy_ty(bcx, dst, self.val, self.ty); } } @@ -352,7 +343,7 @@ pub impl Datum { } match self.mode { - ByRef => { + ByRef(_) => { memcpy_ty(bcx, dst, self.val, self.ty); } ByValue => { @@ -367,28 +358,32 @@ pub impl Datum { fn add_clean(&self, bcx: block) { /*! - * * Schedules this datum for cleanup in `bcx`. The datum - * must be an rvalue. */ + * must be an rvalue. + */ - assert_eq!(self.source, RevokeClean); match self.mode { ByValue => { add_clean_temp_immediate(bcx, self.val, self.ty); } - ByRef => { + ByRef(RevokeClean) => { add_clean_temp_mem(bcx, self.val, self.ty); } + ByRef(ZeroMem) => { + bcx.tcx().sess.bug( + fmt!("Cannot add clean to a 'zero-mem' datum")); + } } } fn cancel_clean(&self, bcx: block) { if ty::type_needs_drop(bcx.tcx(), self.ty) { - match self.source { - RevokeClean => { + match self.mode { + ByValue | + ByRef(RevokeClean) => { revoke_clean(bcx, self.val); } - ZeroMem => { + ByRef(ZeroMem) => { // Lvalues which potentially need to be dropped // must be passed by ref, so that we can zero them // out. @@ -400,11 +395,10 @@ pub impl Datum { } fn to_str(&self, ccx: &CrateContext) -> ~str { - fmt!("Datum { val=%s, ty=%s, mode=%?, source=%? }", + fmt!("Datum { val=%s, ty=%s, mode=%? }", val_str(ccx.tn, self.val), ty_to_str(ccx.tcx, self.ty), - self.mode, - self.source) + self.mode) } fn to_value_datum(&self, bcx: block) -> Datum { @@ -417,9 +411,9 @@ pub impl Datum { match self.mode { ByValue => *self, - ByRef => { + ByRef(_) => { Datum {val: self.to_value_llval(bcx), mode: ByValue, - ty: self.ty, source: RevokeClean} + ty: self.ty} } } } @@ -434,7 +428,7 @@ pub impl Datum { } else { match self.mode { ByValue => self.val, - ByRef => { + ByRef(_) => { if ty::type_is_bool(self.ty) { LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True) } else { @@ -447,24 +441,24 @@ pub impl Datum { fn to_ref_datum(&self, bcx: block) -> Datum { /*! - * * Yields a by-ref form of this datum. This may involve * creation of a temporary stack slot. The value returned by * this function is not separately rooted from this datum, so - * it will not live longer than the current datum. */ + * it will not live longer than the current datum. + */ match self.mode { - ByRef => *self, + ByRef(_) => *self, ByValue => { - Datum {val: self.to_ref_llval(bcx), mode: ByRef, - ty: self.ty, source: RevokeClean} + Datum {val: self.to_ref_llval(bcx), mode: ByRef(RevokeClean), + ty: self.ty} } } } fn to_ref_llval(&self, bcx: block) -> ValueRef { match self.mode { - ByRef => self.val, + ByRef(_) => self.val, ByValue => { if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) { C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty))) @@ -477,6 +471,31 @@ pub impl Datum { } } + fn to_zeroable_ref_llval(&self, bcx: block) -> ValueRef { + /*! + * Returns a by-ref llvalue that can be zeroed in order to + * cancel cleanup. This is a kind of hokey bridge used + * to adapt to the match code. Please don't use it for new code. + */ + + match self.mode { + // All by-ref datums are zeroable, even if we *could* just + // cancel the cleanup. + ByRef(_) => self.val, + + // By value datums can't be zeroed (where would you store + // the zero?) so we have to spill them. Add a temp cleanup + // for this spilled value and cancel the cleanup on this + // current value. + ByValue => { + let slot = self.to_ref_llval(bcx); + self.cancel_clean(bcx); + add_clean_temp_mem(bcx, slot, self.ty); + slot + } + } + } + fn appropriate_mode(&self) -> DatumMode { /*! See the `appropriate_mode()` function */ @@ -490,7 +509,7 @@ pub impl Datum { match self.appropriate_mode() { ByValue => self.to_value_llval(bcx), - ByRef => self.to_ref_llval(bcx) + ByRef(_) => self.to_ref_llval(bcx) } } @@ -501,7 +520,7 @@ pub impl Datum { match self.appropriate_mode() { ByValue => self.to_value_datum(bcx), - ByRef => self.to_ref_datum(bcx) + ByRef(_) => self.to_ref_datum(bcx) } } @@ -512,9 +531,8 @@ pub impl Datum { let base_val = self.to_ref_llval(bcx); Datum { val: gep(base_val), - mode: ByRef, + mode: ByRef(source), ty: ty, - source: source } } @@ -524,7 +542,7 @@ pub impl Datum { } return match self.mode { - ByRef => glue::drop_ty(bcx, self.val, self.ty), + ByRef(_) => glue::drop_ty(bcx, self.val, self.ty), ByValue => glue::drop_ty_immediate(bcx, self.val, self.ty) }; } @@ -546,7 +564,7 @@ pub impl Datum { let ptr = self.to_value_llval(bcx); let body = opaque_box_body(bcx, content_ty, ptr); - Datum {val: body, ty: content_ty, mode: ByRef, source: ZeroMem} + Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)} } fn to_rptr(&self, bcx: block) -> Datum { @@ -561,8 +579,7 @@ pub impl Datum { let llval = self.to_ref_llval(bcx); let rptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::re_static, self.ty); - Datum {val: llval, ty: rptr_ty, - mode: ByValue, source: RevokeClean} + Datum {val: llval, ty: rptr_ty, mode: ByValue} } fn try_deref(&self, @@ -606,7 +623,7 @@ pub impl Datum { let repr = adt::represent_type(ccx, self.ty); let ty = ty::subst(ccx.tcx, substs, variants[0].args[0]); return match self.mode { - ByRef => { + ByRef(_) => { // Recast lv.val as a pointer to the newtype // rather than a ptr to the enum type. ( @@ -614,8 +631,7 @@ pub impl Datum { val: adt::trans_field_ptr(bcx, repr, self.val, 0, 0), ty: ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) }), bcx ) @@ -645,7 +661,7 @@ pub impl Datum { let repr = adt::represent_type(ccx, self.ty); let ty = fields[0].mt.ty; return match self.mode { - ByRef => { + ByRef(_) => { // Recast lv.val as a pointer to the newtype rather // than a pointer to the struct type. // FIXME #6572: This isn't correct for structs with @@ -655,8 +671,7 @@ pub impl Datum { val: adt::trans_field_ptr(bcx, repr, self.val, 0, 0), ty: ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) }), bcx ) @@ -683,8 +698,7 @@ pub impl Datum { Datum { val: lv.to_value_llval(bcx), ty: ty, - mode: ByRef, - source: ZeroMem // *p is an lvalue + mode: ByRef(ZeroMem) } } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index c1661b80cf8..6d78e8e0379 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -864,17 +864,14 @@ pub fn create_local_var(bcx: block, local: @ast::local) }; update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); - let llptr = match bcx.fcx.lllocals.find(&local.node.id) { - option::Some(&local_mem(v)) => v, - option::Some(_) => { - bcx.tcx().sess.span_bug(local.span, "local is bound to something weird"); - } - option::None => { - match bcx.fcx.lllocals.get_copy(&local.node.pat.id) { - local_imm(v) => v, - _ => bcx.tcx().sess.span_bug(local.span, "local is bound to something weird") + // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc + let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug( + local.span, + fmt!("No entry in lllocals table for %?", local.node.id)); } - } }; let declargs = ~[llmdnode([llptr]), mdnode]; trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), @@ -922,9 +919,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span) }; update_cache(cache, tg, argument_metadata(mdval)); - let llptr = match fcx.llargs.get_copy(&arg.id) { - local_mem(v) | local_imm(v) => v, - }; + let llptr = fcx.llargs.get_copy(&arg.id); let declargs = ~[llmdnode([llptr]), mdnode]; trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 99860e60c6b..42ba06aad76 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -247,7 +247,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { // must patchup the type. DatumBlock {bcx: bcx, datum: Datum {val: datum.val, ty: adjusted_ty, - mode: datum.mode, source: datum.source}} + mode: datum.mode}} } fn auto_slice(bcx: block, @@ -793,8 +793,7 @@ fn trans_def_datum_unadjusted(bcx: block, bcx: bcx, datum: Datum {val: llval, ty: rust_ty, - mode: ByValue, - source: RevokeClean} + mode: ByValue} }; } } @@ -920,8 +919,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { bcx: bcx, datum: Datum {val: elt, ty: vt.unit_ty, - mode: ByRef, - source: ZeroMem} + mode: ByRef(ZeroMem)} }; } @@ -988,8 +986,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { bcx: bcx, datum: Datum {val: val, ty: const_ty, - mode: ByRef, - source: ZeroMem} + mode: ByRef(ZeroMem)} } } _ => { @@ -1014,8 +1011,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { Datum { val: val, ty: local_ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) } } None => { @@ -1052,8 +1048,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { Datum { val: casted_val, ty: self_info.t, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) } } _ => { @@ -1063,26 +1058,22 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { }; fn take_local(bcx: block, - table: &HashMap<ast::node_id, local_val>, + table: &HashMap<ast::node_id, ValueRef>, nid: ast::node_id) -> Datum { - let (v, mode) = match table.find(&nid) { - Some(&local_mem(v)) => (v, ByRef), - Some(&local_imm(v)) => (v, ByValue), + let v = match table.find(&nid) { + Some(&v) => v, None => { bcx.sess().bug(fmt!( "trans_local_var: no llval for local/arg %? found", nid)); } }; let ty = node_id_type(bcx, nid); - - debug!("take_local(nid=%?, v=%s, mode=%?, ty=%s)", - nid, bcx.val_str(v), mode, bcx.ty_to_str(ty)); - + debug!("take_local(nid=%?, v=%s, ty=%s)", + nid, bcx.val_str(v), bcx.ty_to_str(ty)); Datum { val: v, ty: ty, - mode: mode, - source: ZeroMem + mode: ByRef(ZeroMem) } } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index a7a8cd088d2..ae68a28de97 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -692,19 +692,15 @@ pub fn trans_intrinsic(ccx: @CrateContext, fcx.llretptr.get()); } ~"move_val" => { - // Create a datum reflecting the value being moved: - // - // - the datum will be by ref if the value is non-immediate; - // - // - the datum has a RevokeClean source because, that way, - // the `move_to()` method does not feel compelled to - // zero out the memory where the datum resides. Zeroing - // is not necessary since, for intrinsics, there is no - // cleanup to concern ourselves with. + // Create a datum reflecting the value being moved. + // Use `appropriate_mode` so that the datum is by ref + // if the value is non-immediate. Note that, with + // intrinsics, there are no argument cleanups to + // concern ourselves with. let tp_ty = substs.tys[0]; let mode = appropriate_mode(tp_ty); let src = Datum {val: get_param(decl, first_real_arg + 1u), - ty: tp_ty, mode: mode, source: RevokeClean}; + ty: tp_ty, mode: mode}; bcx = src.move_to(bcx, DROP_EXISTING, get_param(decl, first_real_arg)); } @@ -713,7 +709,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let tp_ty = substs.tys[0]; let mode = appropriate_mode(tp_ty); let src = Datum {val: get_param(decl, first_real_arg + 1u), - ty: tp_ty, mode: mode, source: RevokeClean}; + ty: tp_ty, mode: mode}; bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg)); } ~"min_align_of" => { @@ -832,7 +828,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, } }); let datum = Datum {val: get_param(decl, first_real_arg), - mode: ByRef, ty: fty, source: ZeroMem}; + mode: ByRef(ZeroMem), ty: fty}; let arg_vals = ~[frameaddress_val]; bcx = trans_call_inner( bcx, None, fty, ty::mk_nil(), diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 1e43a3c502b..023d931a60b 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -197,7 +197,7 @@ pub fn trans_method_callee(bcx: block, // Replace method_self with method_static here. let mut origin = mentry.origin; match origin { - typeck::method_self(copy trait_id, copy method_index) => { + typeck::method_self(trait_id, method_index) => { // Get the ID of the impl we're inside. let impl_def_id = bcx.fcx.impl_id.get(); @@ -445,7 +445,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id, _, _)) => { m.generics.ty_params.len() } - copy e => fail!("method_ty_param_count %?", e) + ref e => fail!("method_ty_param_count %?", *e) } } else { csearch::get_type_param_count(ccx.sess.cstore, m_id) - diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index ceb229c79bd..77b2586781f 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -85,8 +85,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) } if fn_id_loc.crate != local_crate { - let Context { uses: @uses, _ } = cx; - let uses = @uses; // mutability + let Context { uses, _ } = cx; + let uses = @copy *uses; // freeze ccx.type_use_cache.insert(fn_id, uses); return uses; } @@ -173,8 +173,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) ccx.tcx.sess.parse_sess.interner))); } } - let Context { uses: @uses, _ } = cx; - let uses = @uses; // mutability + let Context { uses, _ } = cx; + let uses = @copy *uses; // freeze ccx.type_use_cache.insert(fn_id, uses); uses } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index e469856f08f..13102093cd6 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -450,7 +450,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { demand::eqtype(fcx, pat.span, region_ty, typ); } // otherwise the type of x is the expected type T - ast::bind_by_copy | ast::bind_infer => { + ast::bind_infer => { demand::eqtype(fcx, pat.span, expected, typ); } } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index f9aa01c0956..3cb028b811e 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -308,7 +308,7 @@ pub impl CoherenceChecker { implementation = self.create_impl_from_item(item); } - Some(copy existing_implementation) => { + Some(existing_implementation) => { implementation = existing_implementation; } } diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 011c56ac7c1..bfe82a015cd 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1933,7 +1933,7 @@ mod tests { #[test] fn file_reader_not_exist() { match io::file_reader(&Path("not a file")) { - result::Err(copy e) => { + result::Err(e) => { assert_eq!(e, ~"error opening not a file"); } result::Ok(_) => fail!() @@ -1974,7 +1974,7 @@ mod tests { #[test] fn file_writer_bad_name() { match io::file_writer(&Path("?/?"), []) { - result::Err(copy e) => { + result::Err(e) => { assert!(str::starts_with(e, "error opening")); } result::Ok(_) => fail!() @@ -1984,7 +1984,7 @@ mod tests { #[test] fn buffered_file_writer_bad_name() { match io::buffered_file_writer(&Path("?/?")) { - result::Err(copy e) => { + result::Err(e) => { assert!(str::starts_with(e, "error opening")); } result::Ok(_) => fail!() diff --git a/src/libstd/option.rs b/src/libstd/option.rs index be6ec8c8518..ee6e37aeb78 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -341,7 +341,7 @@ pub impl<T:Copy> Option<T> { #[inline(always)] fn get(self) -> T { match self { - Some(copy x) => return x, + Some(x) => return x, None => fail!("option::get none") } } @@ -349,7 +349,7 @@ pub impl<T:Copy> Option<T> { /// Returns the contained value or a default #[inline(always)] fn get_or_default(self, def: T) -> T { - match self { Some(copy x) => x, None => def } + match self { Some(x) => x, None => def } } /// Applies a function zero or more times until the result is none. @@ -366,7 +366,7 @@ pub impl<T:Copy + Zero> Option<T> { /// Returns the contained value or zero (for this type) #[inline(always)] fn get_or_zero(self) -> T { - match self { Some(copy x) => x, None => Zero::zero() } + match self { Some(x) => x, None => Zero::zero() } } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 39bd57b3c37..9eb7b54f009 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -774,9 +774,9 @@ impl GenericPath for WindowsPath { /* if rhs has a host set, then the whole thing wins */ match other.host { - Some(copy host) => { + Some(ref host) => { return WindowsPath { - host: Some(host), + host: Some(copy *host), device: copy other.device, is_absolute: true, components: copy other.components, @@ -787,10 +787,10 @@ impl GenericPath for WindowsPath { /* if rhs has a device set, then a part wins */ match other.device { - Some(copy device) => { + Some(ref device) => { return WindowsPath { host: None, - device: Some(device), + device: Some(copy *device), is_absolute: true, components: copy other.components, }; diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 4fe92ddb7b6..5b40b09e98e 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -40,7 +40,7 @@ pub enum Result<T, U> { #[inline(always)] pub fn get<T:Copy,U>(res: &Result<T, U>) -> T { match *res { - Ok(copy t) => t, + Ok(ref t) => copy *t, Err(ref the_err) => fail!("get called on error result: %?", *the_err) } @@ -72,7 +72,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T { #[inline(always)] pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U { match *res { - Err(copy u) => u, + Err(ref u) => copy *u, Ok(_) => fail!("get_err called on ok result") } } @@ -102,8 +102,8 @@ pub fn is_err<T, U>(res: &Result<T, U>) -> bool { pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>) -> Either<T, U> { match *res { - Ok(copy res) => either::Right(res), - Err(copy fail_) => either::Left(fail_) + Ok(ref res) => either::Right(copy *res), + Err(ref fail_) => either::Left(copy *fail_) } } @@ -206,7 +206,7 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U) -> Result<U, E> { match *res { Ok(ref t) => Ok(op(t)), - Err(copy e) => Err(e) + Err(ref e) => Err(copy *e) } } @@ -222,7 +222,7 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U) pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F) -> Result<T, F> { match *res { - Ok(copy t) => Ok(t), + Ok(ref t) => Ok(copy *t), Err(ref e) => Err(op(e)) } } @@ -304,8 +304,8 @@ pub fn map_vec<T,U:Copy,V:Copy>( let mut vs: ~[V] = vec::with_capacity(vec::len(ts)); for ts.each |t| { match op(t) { - Ok(copy v) => vs.push(v), - Err(copy u) => return Err(u) + Ok(v) => vs.push(v), + Err(u) => return Err(u) } } return Ok(vs); @@ -319,8 +319,8 @@ pub fn map_opt<T,U:Copy,V:Copy>( match *o_t { None => Ok(None), Some(ref t) => match op(t) { - Ok(copy v) => Ok(Some(v)), - Err(copy e) => Err(e) + Ok(v) => Ok(Some(v)), + Err(e) => Err(e) } } } @@ -344,8 +344,8 @@ pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T], let mut i = 0u; while i < n { match op(&ss[i],&ts[i]) { - Ok(copy v) => vs.push(v), - Err(copy u) => return Err(u) + Ok(v) => vs.push(v), + Err(u) => return Err(u) } i += 1u; } @@ -367,7 +367,7 @@ pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T], while i < n { match op(&ss[i],&ts[i]) { Ok(()) => (), - Err(copy u) => return Err(u) + Err(u) => return Err(u) } i += 1u; } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index cdd16e5d890..676a57e38da 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -257,7 +257,6 @@ pub struct field_pat { #[deriving(Eq, Encodable, Decodable)] pub enum binding_mode { - bind_by_copy, bind_by_ref(mutability), bind_infer } @@ -265,13 +264,13 @@ pub enum binding_mode { impl to_bytes::IterBytes for binding_mode { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - bind_by_copy => 0u8.iter_bytes(lsb0, f), - bind_by_ref(ref m) => { - 1u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f) + 0u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f) } - bind_infer => 2u8.iter_bytes(lsb0, f), + bind_infer => { + 1u8.iter_bytes(lsb0, f) + } } } } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index c8cac4ba2d7..deff6dc5ba9 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -233,7 +233,7 @@ pub fn ident_to_path(s: span, i: ident) -> @Path { pub fn ident_to_pat(id: node_id, s: span, i: ident) -> @pat { @ast::pat { id: id, - node: pat_ident(bind_by_copy, ident_to_path(s, i), None), + node: pat_ident(bind_infer, ident_to_path(s, i), None), span: s } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2a3c266cfa6..85bebebf0f6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -560,7 +560,7 @@ impl AstBuilder for @ExtCtxt { self.pat(span, ast::pat_lit(expr)) } fn pat_ident(&self, span: span, ident: ast::ident) -> @ast::pat { - self.pat_ident_binding_mode(span, ident, ast::bind_by_copy) + self.pat_ident_binding_mode(span, ident, ast::bind_infer) } fn pat_ident_binding_mode(&self, diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index 64ce6dfbc19..10fb4b8ecd4 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -62,11 +62,11 @@ fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @ Struct(ref fs) => { fields = fs } - EnumMatching(copy index, ref variant, ref fs) => { + EnumMatching(index, ref variant, ref fs) => { // Determine the discriminant. We will feed this value to the byte // iteration function. let discriminant = match variant.node.disr_expr { - Some(copy d)=> d, + Some(d)=> d, None => cx.expr_uint(span, index) }; diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index b2e039786ad..54d31de7c50 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -119,7 +119,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { summary: &Either<uint, ~[ident]>, rand_call: &fn() -> @expr) -> @expr { match *summary { - Left(copy count) => { + Left(count) => { if count == 0 { cx.expr_ident(span, ctor_ident) } else { diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 8a60b239b89..91fad0c22a6 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -58,8 +58,8 @@ pub fn expand_file(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) base::check_zero_tts(cx, sp, tts, "file!"); let topmost = topmost_expn_info(cx.backtrace().get()); - let Loc { file: @FileMap { name: filename, _ }, _ } = - cx.codemap().lookup_char_pos(topmost.call_site.lo); + let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); + let filename = copy loc.file.name; base::MRExpr(cx.expr_str(topmost.call_site, filename)) } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 183bc2a77c5..ec63b5a7f74 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -423,7 +423,7 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal { }, "block" => token::nt_block(p.parse_block()), "stmt" => token::nt_stmt(p.parse_stmt(~[])), - "pat" => token::nt_pat(p.parse_pat(true)), + "pat" => token::nt_pat(p.parse_pat()), "expr" => token::nt_expr(p.parse_expr()), "ty" => token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)), // this could be handled like a token, since it is one diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index cac963727e3..4a6a070df50 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -207,8 +207,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } else { /* repeat */ r.stack.idx = 0u; r.repeat_idx[r.repeat_idx.len() - 1u] += 1u; - match r.stack.sep { - Some(copy tk) => { + match copy r.stack.sep { + Some(tk) => { r.cur_tok = tk; /* repeat same span, I guess */ return ret_val; } @@ -218,8 +218,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } loop { /* because it's easiest, this handles `tt_delim` not starting with a `tt_tok`, even though it won't happen */ - match r.stack.forest[r.stack.idx] { - tt_delim(copy tts) => { + match copy r.stack.forest[r.stack.idx] { + tt_delim(tts) => { r.stack = @mut TtFrame { forest: @mut tts, idx: 0u, @@ -229,13 +229,13 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }; // if this could be 0-length, we'd need to potentially recur here } - tt_tok(sp, copy tok) => { + tt_tok(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; r.stack.idx += 1u; return ret_val; } - tt_seq(sp, copy tts, copy sep, zerok) => { + tt_seq(sp, tts, sep, zerok) => { let t = tt_seq(sp, copy tts, copy sep, zerok); match lockstep_iter_size(&t, r) { lis_unconstrained => { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index eca999231cd..9d5cb131fec 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -485,9 +485,9 @@ mod test { #[test] fn parse_ident_pat () { let parser = string_to_parser(@~"b"); - assert_eq!(parser.parse_pat(false), + assert_eq!(parser.parse_pat(), @ast::pat{id:1, // fixme - node: ast::pat_ident(ast::bind_by_copy, + node: ast::pat_ident(ast::bind_infer, @ast::Path{ span:sp(0,1), global:false, @@ -516,7 +516,7 @@ mod test { 2), span:sp(4,7)}, pat: @ast::pat{id:1, - node: ast::pat_ident(ast::bind_by_copy, + node: ast::pat_ident(ast::bind_infer, @ast::Path{ span:sp(0,1), global:false, @@ -553,7 +553,7 @@ mod test { span:sp(10,13)}, pat: @ast::pat{id:1, // fixme node: ast::pat_ident( - ast::bind_by_copy, + ast::bind_infer, @ast::Path{ span:sp(6,7), global:false, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 27dfc2c0a46..29f565851b4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -18,7 +18,7 @@ use ast::{TyBareFn, TyClosure}; use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{provided, public, purity}; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; -use ast::{bind_by_copy, bitand, bitor, bitxor, blk}; +use ast::{bitand, bitor, bitxor, blk}; use ast::{blk_check_mode, box}; use ast::{crate, crate_cfg, decl, decl_item}; use ast::{decl_local, default_blk, deref, div, enum_def, explicit_self}; @@ -131,11 +131,11 @@ at INTERPOLATED tokens */ macro_rules! maybe_whole_expr ( ($p:expr) => ( match *($p).token { - INTERPOLATED(token::nt_expr(copy e)) => { + INTERPOLATED(token::nt_expr(e)) => { $p.bump(); return e; } - INTERPOLATED(token::nt_path(copy pt)) => { + INTERPOLATED(token::nt_path(pt)) => { $p.bump(); return $p.mk_expr( ($p).span.lo, @@ -150,8 +150,8 @@ macro_rules! maybe_whole_expr ( macro_rules! maybe_whole ( ($p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return x; } @@ -159,8 +159,8 @@ macro_rules! maybe_whole ( } ); (deref $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return copy *x; } @@ -168,8 +168,8 @@ macro_rules! maybe_whole ( } ); (Some $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return Some(x); } @@ -177,8 +177,8 @@ macro_rules! maybe_whole ( } ); (iovi $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return iovi_item(x); } @@ -186,8 +186,8 @@ macro_rules! maybe_whole ( } ); (pair_empty $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return (~[], x); } @@ -825,7 +825,7 @@ pub impl Parser { let pat = if require_name || self.is_named_argument() { self.parse_arg_mode(); is_mutbl = self.eat_keyword(keywords::Mut); - let pat = self.parse_pat(false); + let pat = self.parse_pat(); self.expect(&token::COLON); pat } else { @@ -853,7 +853,7 @@ pub impl Parser { fn parse_fn_block_arg(&self) -> arg_or_capture_item { self.parse_arg_mode(); let is_mutbl = self.eat_keyword(keywords::Mut); - let pat = self.parse_pat(false); + let pat = self.parse_pat(); let t = if self.eat(&token::COLON) { self.parse_ty(false) } else { @@ -1992,28 +1992,29 @@ pub impl Parser { // them as the lambda arguments let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP); match e.node { - expr_call(f, /*bad*/ copy args, NoSugar) => { + expr_call(f, ref args, NoSugar) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); - let args = vec::append(args, [last_arg]); + let args = vec::append(copy *args, [last_arg]); self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar)) } - expr_method_call(f, i, /*bad*/ copy tps, - /*bad*/ copy args, NoSugar) => { + expr_method_call(f, i, ref tps, ref args, NoSugar) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); - let args = vec::append(args, [last_arg]); + let args = vec::append(copy *args, [last_arg]); self.mk_expr(lo.lo, block.span.hi, - expr_method_call(f, i, tps, args, sugar)) + expr_method_call(f, i, copy *tps, + args, sugar)) } - expr_field(f, i, /*bad*/ copy tps) => { + expr_field(f, i, ref tps) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); self.mk_expr(lo.lo, block.span.hi, - expr_method_call(f, i, tps, ~[last_arg], sugar)) + expr_method_call(f, i, + copy *tps, ~[last_arg], sugar)) } expr_path(*) | expr_call(*) | expr_method_call(*) | expr_paren(*) => { @@ -2162,7 +2163,7 @@ pub impl Parser { fn parse_pats(&self) -> ~[@pat] { let mut pats = ~[]; loop { - pats.push(self.parse_pat(true)); + pats.push(self.parse_pat()); if *self.token == token::BINOP(token::OR) { self.bump(); } else { return pats; } }; @@ -2170,7 +2171,6 @@ pub impl Parser { fn parse_pat_vec_elements( &self, - refutable: bool ) -> (~[@pat], Option<@pat>, ~[@pat]) { let mut before = ~[]; let mut slice = None; @@ -2191,7 +2191,7 @@ pub impl Parser { } } - let subpat = self.parse_pat(refutable); + let subpat = self.parse_pat(); if is_slice { match subpat { @ast::pat { node: pat_wild, _ } => (), @@ -2214,7 +2214,7 @@ pub impl Parser { } // parse the fields of a struct-like pattern - fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) { + fn parse_pat_fields(&self) -> (~[ast::field_pat], bool) { let mut fields = ~[]; let mut etc = false; let mut first = true; @@ -2244,7 +2244,7 @@ pub impl Parser { let subpat; if *self.token == token::COLON { self.bump(); - subpat = self.parse_pat(refutable); + subpat = self.parse_pat(); } else { subpat = @ast::pat { id: self.get_id(), @@ -2257,10 +2257,8 @@ pub impl Parser { return (fields, etc); } - // parse a pattern. The 'refutable' argument - // appears to control whether the binding_mode - // 'bind_infer' or 'bind_by_copy' is used. - fn parse_pat(&self, refutable: bool) -> @pat { + // parse a pattern. + fn parse_pat(&self) -> @pat { maybe_whole!(self, nt_pat); let lo = self.span.lo; @@ -2272,7 +2270,7 @@ pub impl Parser { // parse @pat token::AT => { self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse @"..." as a literal of a vstore @str pat = match sub.node { @@ -2295,7 +2293,7 @@ pub impl Parser { token::TILDE => { // parse ~pat self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse ~"..." as a literal of a vstore ~str pat = match sub.node { @@ -2319,7 +2317,7 @@ pub impl Parser { // parse &pat let lo = self.span.lo; self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse &"..." as a literal of a borrowed str pat = match sub.node { @@ -2340,7 +2338,7 @@ pub impl Parser { } token::LBRACE => { self.bump(); - let (_, _) = self.parse_pat_fields(refutable); + let (_, _) = self.parse_pat_fields(); hi = self.span.hi; self.bump(); self.obsolete(*self.span, ObsoleteRecordPattern); @@ -2358,11 +2356,11 @@ pub impl Parser { let expr = self.mk_expr(lo, hi, expr_lit(lit)); pat = pat_lit(expr); } else { - let mut fields = ~[self.parse_pat(refutable)]; + let mut fields = ~[self.parse_pat()]; if self.look_ahead(1) != token::RPAREN { while *self.token == token::COMMA { self.bump(); - fields.push(self.parse_pat(refutable)); + fields.push(self.parse_pat()); } } if fields.len() == 1 { self.expect(&token::COMMA); } @@ -2375,7 +2373,7 @@ pub impl Parser { // parse [pat,pat,...] as vector pattern self.bump(); let (before, slice, after) = - self.parse_pat_vec_elements(refutable); + self.parse_pat_vec_elements(); hi = self.span.hi; self.expect(&token::RBRACKET); pat = ast::pat_vec(before, slice, after); @@ -2405,15 +2403,13 @@ pub impl Parser { } else if self.eat_keyword(keywords::Ref) { // parse ref pat let mutbl = self.parse_mutability(); - pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl)); + pat = self.parse_pat_ident(bind_by_ref(mutbl)); } else if self.eat_keyword(keywords::Copy) { // parse copy pat - pat = self.parse_pat_ident(refutable, bind_by_copy); + self.warn("copy keyword in patterns no longer has any effect, \ + remove it"); + pat = self.parse_pat_ident(bind_infer); } else { - // XXX---refutable match bindings should work same as let - let binding_mode = - if refutable {bind_infer} else {bind_by_copy}; - let can_be_enum_or_struct; match self.look_ahead(1) { token::LPAREN | token::LBRACKET | token::LT | @@ -2434,12 +2430,12 @@ pub impl Parser { let sub; if self.eat(&token::AT) { // parse foo @ pat - sub = Some(self.parse_pat(refutable)); + sub = Some(self.parse_pat()); } else { // or just foo sub = None; } - pat = pat_ident(binding_mode, name, sub); + pat = pat_ident(bind_infer, name, sub); } else { // parse an enum pat let enum_path = self.parse_path_with_tps(true); @@ -2447,7 +2443,7 @@ pub impl Parser { token::LBRACE => { self.bump(); let (fields, etc) = - self.parse_pat_fields(refutable); + self.parse_pat_fields(); self.bump(); pat = pat_struct(enum_path, fields, etc); } @@ -2468,7 +2464,7 @@ pub impl Parser { seq_sep_trailing_disallowed( token::COMMA ), - |p| p.parse_pat(refutable) + |p| p.parse_pat() ); pat = pat_enum(enum_path, Some(args)); } @@ -2478,7 +2474,7 @@ pub impl Parser { // it could still be either an enum // or an identifier pattern, resolve // will sort it out: - pat = pat_ident(binding_mode, + pat = pat_ident(bind_infer, enum_path, None); } else { @@ -2500,7 +2496,6 @@ pub impl Parser { // used by the copy foo and ref foo patterns to give a good // error message when parsing mistakes like ref foo(a,b) fn parse_pat_ident(&self, - refutable: bool, binding_mode: ast::binding_mode) -> ast::pat_ { if !is_plain_ident(&*self.token) { @@ -2510,7 +2505,7 @@ pub impl Parser { // why a path here, and not just an identifier? let name = self.parse_path_without_tps(); let sub = if self.eat(&token::AT) { - Some(self.parse_pat(refutable)) + Some(self.parse_pat()) } else { None }; @@ -2533,7 +2528,7 @@ pub impl Parser { // parse a local variable declaration fn parse_local(&self, is_mutbl: bool) -> @local { let lo = self.span.lo; - let pat = self.parse_pat(false); + let pat = self.parse_pat(); let mut ty = @Ty { id: self.get_id(), node: ty_infer, @@ -2760,7 +2755,7 @@ pub impl Parser { match stmt.node { stmt_expr(e, stmt_id) => { // expression without semicolon - match *self.token { + match copy *self.token { token::SEMI => { self.bump(); stmts.push(@codemap::spanned { @@ -2770,7 +2765,7 @@ pub impl Parser { token::RBRACE => { expr = Some(e); } - copy t => { + t => { if classify::stmt_ends_with_semi(stmt) { self.fatal( fmt!( @@ -2880,7 +2875,7 @@ pub impl Parser { token::MOD_SEP | token::IDENT(*) => { let obsolete_bound = match *self.token { token::MOD_SEP => false, - token::IDENT(copy sid, _) => { + token::IDENT(sid, _) => { match *self.id_to_str(sid) { ~"send" | ~"copy" | diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6a32e535295..f29876b8708 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1537,9 +1537,6 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { word_nbsp(s, "ref"); print_mutability(s, mutbl); } - ast::bind_by_copy => { - word_nbsp(s, "copy"); - } ast::bind_infer => {} } } diff --git a/src/test/compile-fail/borrowck-pat-by-value-binding.rs b/src/test/compile-fail/borrowck-pat-by-value-binding.rs index d60ed3d0e37..e77f5245d7d 100644 --- a/src/test/compile-fail/borrowck-pat-by-value-binding.rs +++ b/src/test/compile-fail/borrowck-pat-by-value-binding.rs @@ -36,7 +36,7 @@ fn match_const_opt_by_imm_ref(v: &const Option<int>) { fn match_const_opt_by_value(v: &const Option<int>) { match *v { - Some(copy i) => process(i), + Some(i) => process(i), None => () } } diff --git a/src/test/compile-fail/noncopyable-match-pattern.rs b/src/test/compile-fail/noncopyable-match-pattern.rs deleted file mode 100644 index a7c8950486c..00000000000 --- a/src/test/compile-fail/noncopyable-match-pattern.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::unstable; - -fn main() { - unsafe { - let x = Some(unstable::sync::exclusive(false)); - match x { - Some(copy z) => { //~ ERROR copying a value of non-copyable type - do z.with |b| { assert!(!*b); } - } - None => fail!() - } - } -} diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs index 33cc934c7b3..65fbbfc6e19 100644 --- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs +++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs @@ -14,7 +14,7 @@ enum opts { fn matcher1(x: opts) { match x { - a(ref i) | b(copy i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 + a(ref i) | b(i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 c(_) => {} } } diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs index d42d0b5aac0..59ab5018c1d 100644 --- a/src/test/run-pass/issue-2804.rs +++ b/src/test/run-pass/issue-2804.rs @@ -25,9 +25,9 @@ fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str { match table.find(&key) { - option::Some(&extra::json::String(copy s)) => + option::Some(&extra::json::String(ref s)) => { - copy s + copy *s } option::Some(value) => { @@ -45,9 +45,9 @@ fn add_interface(store: int, managed_ip: ~str, data: extra::json::Json) -> (~str { match &data { - &extra::json::Object(copy interface) => + &extra::json::Object(ref interface) => { - let name = lookup(copy interface, ~"ifDescr", ~""); + let name = lookup(copy *interface, ~"ifDescr", ~""); let label = fmt!("%s-%s", managed_ip, name); (label, bool_value(false)) diff --git a/src/test/run-pass/match-vec-rvalue.rs b/src/test/run-pass/match-vec-rvalue.rs new file mode 100644 index 00000000000..5f68b0e9a69 --- /dev/null +++ b/src/test/run-pass/match-vec-rvalue.rs @@ -0,0 +1,12 @@ +// Tests that matching rvalues with drops does not crash. + +fn main() { + match ~[1, 2, 3] { + x => { + assert_eq!(x.len(), 3); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + } + } +} |
