diff --git a/mk/crates.mk b/mk/crates.mk index 80231ad2ba4..8af8f966e30 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -60,9 +60,9 @@ DEPS_extra := std term sync serialize getopts collections DEPS_green := std native:context_switch DEPS_rustuv := std native:uv native:uv_support DEPS_native := std -DEPS_syntax := std extra term serialize collections +DEPS_syntax := std term serialize collections DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \ - collections + collections extra DEPS_rustdoc := rustc native:sundown serialize sync getopts collections DEPS_flate := std native:miniz DEPS_arena := std collections diff --git a/mk/rt.mk b/mk/rt.mk index 10b73c6b395..673e6684f69 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -236,7 +236,7 @@ COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1)) COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt -$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) +$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) @$$(call E, make: compiler-rt) $$(Q)$$(MAKE) -C "$(S)src/compiler-rt" \ ProjSrcRoot="$(S)src/compiler-rt" \ diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 0c965b7c6c3..38c1162f636 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -30,6 +30,8 @@ pub struct TestProps { check_lines: ~[~str], // Flag to force a crate to be built with the host architecture force_host: bool, + // Check stdout for error-pattern output as well as stderr + check_stdout: bool, } // Load any test directives embedded in the file @@ -42,6 +44,7 @@ pub fn load_props(testfile: &Path) -> TestProps { let mut debugger_cmds = ~[]; let mut check_lines = ~[]; let mut force_host = false; + let mut check_stdout = false; iter_header(testfile, |ln| { match parse_error_pattern(ln) { Some(ep) => error_patterns.push(ep), @@ -60,6 +63,10 @@ pub fn load_props(testfile: &Path) -> TestProps { force_host = parse_force_host(ln); } + if !check_stdout { + check_stdout = parse_check_stdout(ln); + } + match parse_aux_build(ln) { Some(ab) => { aux_builds.push(ab); } None => {} @@ -91,6 +98,7 @@ pub fn load_props(testfile: &Path) -> TestProps { debugger_cmds: debugger_cmds, check_lines: check_lines, force_host: force_host, + check_stdout: check_stdout, }; } @@ -155,6 +163,10 @@ fn parse_force_host(line: &str) -> bool { parse_name_directive(line, "force-host") } +fn parse_check_stdout(line: &str) -> bool { + parse_name_directive(line, "check-stdout") +} + fn parse_exec_env(line: &str) -> Option<(~str, ~str)> { parse_name_value_directive(line, ~"exec-env").map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index a2c61352e6f..8b45d987864 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -452,7 +452,12 @@ fn check_error_patterns(props: &TestProps, let mut next_err_idx = 0u; let mut next_err_pat = &props.error_patterns[next_err_idx]; let mut done = false; - for line in ProcRes.stderr.lines() { + let output_to_check = if props.check_stdout { + ProcRes.stdout + ProcRes.stderr + } else { + ProcRes.stderr.clone() + }; + for line in output_to_check.lines() { if line.contains(*next_err_pat) { debug!("found error pattern {}", *next_err_pat); next_err_idx += 1u; diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 61eccb52055..d620ed0b54f 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -57,8 +57,8 @@ they don't contain references to names that aren't actually defined. # Getting started -> **NOTE**: The tarball and installer links are for the most recent release, -> not master. +> **WARNING**: The tarball and installer links are for the most recent +> release, not master. To use master, you **must** build from [git]. The Rust compiler currently must be built from a [tarball] or [git], unless you are on Windows, in which case using the [installer][win-exe] is diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 1ff868dced2..bee9ec6240b 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -1561,6 +1561,7 @@ mod tests { let mut bitv = 0 as uint; b.iter(|| { bitv |= (1 << ((r.next_u32() as uint) % uint::BITS)); + &bitv }) } @@ -1570,6 +1571,7 @@ mod tests { let mut bitv = SmallBitv::new(uint::BITS); b.iter(|| { bitv.set((r.next_u32() as uint) % uint::BITS, true); + &bitv }) } @@ -1579,6 +1581,7 @@ mod tests { let mut bitv = BigBitv::new(~[0]); b.iter(|| { bitv.set((r.next_u32() as uint) % uint::BITS, true); + &bitv }) } @@ -1590,6 +1593,7 @@ mod tests { let mut bitv = BigBitv::new(storage); b.iter(|| { bitv.set((r.next_u32() as uint) % BENCH_BITS, true); + &bitv }) } @@ -1599,6 +1603,7 @@ mod tests { let mut bitv = Bitv::new(BENCH_BITS, false); b.iter(|| { bitv.set((r.next_u32() as uint) % BENCH_BITS, true); + &bitv }) } @@ -1608,6 +1613,7 @@ mod tests { let mut bitv = Bitv::new(uint::BITS, false); b.iter(|| { bitv.set((r.next_u32() as uint) % uint::BITS, true); + &bitv }) } @@ -1617,6 +1623,7 @@ mod tests { let mut bitv = BitvSet::new(); b.iter(|| { bitv.insert((r.next_u32() as uint) % uint::BITS); + &bitv }) } @@ -1626,6 +1633,7 @@ mod tests { let mut bitv = BitvSet::new(); b.iter(|| { bitv.insert((r.next_u32() as uint) % BENCH_BITS); + &bitv }) } diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs index 325f0ee4edb..14c6bc5ce28 100644 --- a/src/libcollections/deque.rs +++ b/src/libcollections/deque.rs @@ -115,8 +115,9 @@ pub mod bench { // measure let mut i = 0; bh.iter(|| { - map.find(&i); + let x = map.find(&i); i = (i + 1) % n; + x }) } } diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 85da41911c9..df13538b4bc 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -26,12 +26,11 @@ use stats; use time::precise_time_ns; use collections::TreeMap; -use std::clone::Clone; use std::cmp; use std::io; -use std::io::File; -use std::io::Writer; +use std::io::{File, PortReader, ChanWriter}; use std::io::stdio::StdWriter; +use std::str; use std::task; use std::to_str::ToStr; use std::f64; @@ -358,7 +357,7 @@ struct ConsoleTestState { ignored: uint, measured: uint, metrics: MetricMap, - failures: ~[TestDesc], + failures: ~[(TestDesc, ~[u8])], max_name_len: uint, // number of columns to fill when aligning names } @@ -498,9 +497,23 @@ impl ConsoleTestState { pub fn write_failures(&mut self) -> io::IoResult<()> { if_ok!(self.write_plain("\nfailures:\n")); let mut failures = ~[]; - for f in self.failures.iter() { + let mut fail_out = ~""; + for &(ref f, ref stdout) in self.failures.iter() { failures.push(f.name.to_str()); + if stdout.len() > 0 { + fail_out.push_str(format!("---- {} stdout ----\n\t", + f.name.to_str())); + let output = str::from_utf8_lossy(*stdout); + fail_out.push_str(output.as_slice().replace("\n", "\n\t")); + fail_out.push_str("\n"); + } } + if fail_out.len() > 0 { + if_ok!(self.write_plain("\n")); + if_ok!(self.write_plain(fail_out)); + } + + if_ok!(self.write_plain("\nfailures:\n")); failures.sort(); for name in failures.iter() { if_ok!(self.write_plain(format!(" {}\n", name.to_str()))); @@ -632,7 +645,7 @@ pub fn run_tests_console(opts: &TestOpts, match (*event).clone() { TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()), TeWait(ref test, padding) => st.write_test_start(test, padding), - TeResult(test, result) => { + TeResult(test, result, stdout) => { if_ok!(st.write_log(&test, &result)); if_ok!(st.write_result(&result)); match result { @@ -655,7 +668,7 @@ pub fn run_tests_console(opts: &TestOpts, } TrFailed => { st.failed += 1; - st.failures.push(test); + st.failures.push((test, stdout)); } } Ok(()) @@ -717,17 +730,17 @@ fn should_sort_failures_before_printing_them() { measured: 0u, max_name_len: 10u, metrics: MetricMap::new(), - failures: ~[test_b, test_a] + failures: ~[(test_b, ~[]), (test_a, ~[])] }; st.write_failures().unwrap(); let s = match st.out { - Raw(ref m) => str::from_utf8(m.get_ref()).unwrap(), + Raw(ref m) => str::from_utf8_lossy(m.get_ref()), Pretty(_) => unreachable!() }; - let apos = s.find_str("a").unwrap(); - let bpos = s.find_str("b").unwrap(); + let apos = s.as_slice().find_str("a").unwrap(); + let bpos = s.as_slice().find_str("b").unwrap(); assert!(apos < bpos); } @@ -737,11 +750,10 @@ fn use_color() -> bool { return get_concurrency() == 1; } enum TestEvent { TeFiltered(~[TestDesc]), TeWait(TestDesc, NamePadding), - TeResult(TestDesc, TestResult), + TeResult(TestDesc, TestResult, ~[u8] /* stdout */), } -/// The message sent to the test monitor from the individual runners. -pub type MonitorMsg = (TestDesc, TestResult); +pub type MonitorMsg = (TestDesc, TestResult, ~[u8] /* stdout */); fn run_tests(opts: &TestOpts, tests: ~[TestDescAndFn], @@ -783,11 +795,11 @@ fn run_tests(opts: &TestOpts, pending += 1; } - let (desc, result) = p.recv(); + let (desc, result, stdout) = p.recv(); if concurrency != 1 { if_ok!(callback(TeWait(desc.clone(), PadNone))); } - if_ok!(callback(TeResult(desc, result))); + if_ok!(callback(TeResult(desc, result, stdout))); pending -= 1; } @@ -796,8 +808,8 @@ fn run_tests(opts: &TestOpts, for b in filtered_benchs_and_metrics.move_iter() { if_ok!(callback(TeWait(b.desc.clone(), b.testfn.padding()))); run_test(!opts.run_benchmarks, b, ch.clone()); - let (test, result) = p.recv(); - if_ok!(callback(TeResult(test, result))); + let (test, result, stdout) = p.recv(); + if_ok!(callback(TeResult(test, result, stdout))); } Ok(()) } @@ -884,7 +896,7 @@ pub fn run_test(force_ignore: bool, let TestDescAndFn {desc, testfn} = test; if force_ignore || desc.ignore { - monitor_ch.send((desc, TrIgnored)); + monitor_ch.send((desc, TrIgnored, ~[])); return; } @@ -893,40 +905,47 @@ pub fn run_test(force_ignore: bool, testfn: proc()) { spawn(proc() { let mut task = task::task(); - task.name(match desc.name { - DynTestName(ref name) => name.to_owned().into_maybe_owned(), - StaticTestName(name) => name.into_maybe_owned() - }); + let (p, c) = Chan::new(); + let mut reader = PortReader::new(p); + let stdout = ChanWriter::new(c.clone()); + let stderr = ChanWriter::new(c); + match desc.name { + DynTestName(ref name) => task.name(name.clone()), + StaticTestName(name) => task.name(name), + } + task.opts.stdout = Some(~stdout as ~Writer); + task.opts.stderr = Some(~stderr as ~Writer); let result_future = task.future_result(); task.spawn(testfn); + let stdout = reader.read_to_end().unwrap(); let task_result = result_future.recv(); let test_result = calc_result(&desc, task_result.is_ok()); - monitor_ch.send((desc.clone(), test_result)); - }); + monitor_ch.send((desc.clone(), test_result, stdout)); + }) } match testfn { DynBenchFn(bencher) => { let bs = ::test::bench::benchmark(|harness| bencher.run(harness)); - monitor_ch.send((desc, TrBench(bs))); + monitor_ch.send((desc, TrBench(bs), ~[])); return; } StaticBenchFn(benchfn) => { let bs = ::test::bench::benchmark(|harness| benchfn(harness)); - monitor_ch.send((desc, TrBench(bs))); + monitor_ch.send((desc, TrBench(bs), ~[])); return; } DynMetricFn(f) => { let mut mm = MetricMap::new(); f(&mut mm); - monitor_ch.send((desc, TrMetrics(mm))); + monitor_ch.send((desc, TrMetrics(mm), ~[])); return; } StaticMetricFn(f) => { let mut mm = MetricMap::new(); f(&mut mm); - monitor_ch.send((desc, TrMetrics(mm))); + monitor_ch.send((desc, TrMetrics(mm), ~[])); return; } DynTestFn(f) => run_test_inner(desc, monitor_ch, f), @@ -1264,7 +1283,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert!(res != TrOk); } @@ -1281,7 +1300,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrIgnored); } @@ -1298,7 +1317,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrOk); } @@ -1315,7 +1334,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrFailed); } diff --git a/src/libextra/url.rs b/src/libextra/url.rs index 6138c5416f2..c76c73dc432 100644 --- a/src/libextra/url.rs +++ b/src/libextra/url.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -139,10 +139,19 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { } /** - * Encodes a URI by replacing reserved characters with percent encoded + * Encodes a URI by replacing reserved characters with percent-encoded * character sequences. * * This function is compliant with RFC 3986. + * + * # Example + * + * ```rust + * use extra::url::encode; + * + * let url = encode(&"https://example.com/Rust (programming language)"); + * println!("{}", url); // https://example.com/Rust%20(programming%20language) + * ``` */ pub fn encode(s: &str) -> ~str { encode_inner(s, true) @@ -206,9 +215,18 @@ fn decode_inner(s: &str, full_url: bool) -> ~str { } /** - * Decode a string encoded with percent encoding. + * Decodes a percent-encoded string representing a URI. * - * This will only decode escape sequences generated by encode. + * This will only decode escape sequences generated by `encode`. + * + * # Example + * + * ```rust + * use extra::url::decode; + * + * let url = decode(&"https://example.com/Rust%20(programming%20language)"); + * println!("{}", url); // https://example.com/Rust (programming language) + * ``` */ pub fn decode(s: &str) -> ~str { decode_inner(s, true) @@ -410,7 +428,23 @@ pub fn query_to_str(query: &Query) -> ~str { return strvec.connect("&"); } -// returns the scheme and the rest of the url, or a parsing error +/** + * Returns a tuple of the URI scheme and the rest of the URI, or a parsing error. + * + * Does not include the separating `:` character. + * + * # Example + * + * ```rust + * use extra::url::get_scheme; + * + * let scheme = match get_scheme("https://example.com/") { + * Ok((sch, _)) => sch, + * Err(_) => ~"(None)", + * }; + * println!("Scheme in use: {}.", scheme); // Scheme in use: https. + * ``` + */ pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> { for (i,c) in rawurl.chars().enumerate() { match c { @@ -654,18 +688,16 @@ fn get_query_fragment(rawurl: &str) -> } /** - * Parse a `str` to a `url` + * Parses a URL, converting it from a string to `Url` representation. * * # Arguments * - * `rawurl` - a string representing a full url, including scheme. + * `rawurl` - a string representing the full URL, including scheme. * * # Returns * - * a `url` that contains the parsed representation of the url. - * + * A `Url` struct type representing the URL. */ - pub fn from_str(rawurl: &str) -> Result { // scheme let (scheme, rest) = match get_scheme(rawurl) { @@ -705,19 +737,18 @@ impl FromStr for Url { } /** - * Format a `url` as a string + * Converts a URL from `Url` to string representation. * * # Arguments * - * `url` - a url. + * `url` - a URL. * * # Returns * - * a `str` that contains the formatted url. Note that this will usually - * be an inverse of `from_str` but might strip out unneeded separators. + * A string that contains the formatted URL. Note that this will usually + * be an inverse of `from_str` but might strip out unneeded separators; * for example, "http://somehost.com?", when parsed and formatted, will * result in just "http://somehost.com". - * */ pub fn to_str(url: &Url) -> ~str { let user = match url.user { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 1f90d2d8f0f..590229a6652 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -831,10 +831,10 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>, ast::ExprAssignOp(_, _, dest, _) => { this.check_assignment(dest); } - ast::ExprCall(f, ref args, _) => { + ast::ExprCall(f, ref args) => { this.check_call(expr, Some(f), f.id, f.span, *args); } - ast::ExprMethodCall(callee_id, _, _, ref args, _) => { + ast::ExprMethodCall(callee_id, _, _, ref args) => { this.check_call(expr, None, callee_id, expr.span, *args); } ast::ExprIndex(callee_id, _, rval) | diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 9c213558d9c..6ca779906e2 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -351,11 +351,11 @@ impl CFGBuilder { self.straightline(expr, pred, *elems) } - ast::ExprCall(func, ref args, _) => { + ast::ExprCall(func, ref args) => { self.call(expr, pred, func, *args) } - ast::ExprMethodCall(_, _, _, ref args, _) => { + ast::ExprMethodCall(_, _, _, ref args) => { self.call(expr, pred, args[0], args.slice_from(1)) } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 88ade3e225a..75337a27a6c 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -160,7 +160,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor, } } } - ExprCall(callee, _, NoSugar) => { + ExprCall(callee, _) => { let def_map = def_map.borrow(); match def_map.get().find(&callee.id) { Some(&DefStruct(..)) => {} // OK. diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 4d22f541432..60d83d7559e 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -577,12 +577,12 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> { self.walk_opt_expr(with_expr, in_out, loop_scopes); } - ast::ExprCall(f, ref args, _) => { + ast::ExprCall(f, ref args) => { self.walk_expr(f, in_out, loop_scopes); self.walk_call(f.id, expr.id, *args, in_out, loop_scopes); } - ast::ExprMethodCall(callee_id, _, _, ref args, _) => { + ast::ExprMethodCall(callee_id, _, _, ref args) => { self.walk_call(callee_id, expr.id, *args, in_out, loop_scopes); } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 1445d5734ad..2a40c8148fd 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -120,7 +120,7 @@ impl Visitor<()> for EffectCheckVisitor { fn visit_expr(&mut self, expr: &ast::Expr, _:()) { match expr.node { - ast::ExprMethodCall(callee_id, _, _, _, _) => { + ast::ExprMethodCall(callee_id, _, _, _) => { let base_type = ty::node_id_to_type(self.tcx, callee_id); debug!("effect: method call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); @@ -129,7 +129,7 @@ impl Visitor<()> for EffectCheckVisitor { "invocation of unsafe method") } } - ast::ExprCall(base, _, _) => { + ast::ExprCall(base, _) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug!("effect: call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b7a89db4b9e..70b5aab4c93 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1205,7 +1205,7 @@ impl Liveness { }) } - ExprCall(f, ref args, _) => { + ExprCall(f, ref args) => { // calling a fn with bot return type means that the fn // will fail, and hence the successors can be ignored let t_ret = ty::ty_fn_ret(ty::expr_ty(self.tcx, f)); @@ -1215,7 +1215,7 @@ impl Liveness { self.propagate_through_expr(f, succ) } - ExprMethodCall(callee_id, _, _, ref args, _) => { + ExprMethodCall(callee_id, _, _, ref args) => { // calling a method with bot return type means that the method // will fail, and hence the successors can be ignored let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, callee_id)); diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index a0dc8634792..32cb7ca57da 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -382,7 +382,7 @@ impl VisitContext { } } - ExprCall(callee, ref args, _) => { // callee(args) + ExprCall(callee, ref args) => { // callee(args) // Figure out whether the called function is consumed. let mode = match ty::get(ty::expr_ty(self.tcx, callee)).sty { ty::ty_closure(ref cty) => { @@ -412,7 +412,7 @@ impl VisitContext { self.use_fn_args(callee.id, *args); } - ExprMethodCall(callee_id, _, _, ref args, _) => { // callee.m(args) + ExprMethodCall(callee_id, _, _, ref args) => { // callee.m(args) self.use_fn_args(callee_id, *args); } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 1f3bb2ba70d..8c5654d3fce 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -705,7 +705,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> { _ => {} } } - ast::ExprMethodCall(_, ident, _, ref args, _) => { + ast::ExprMethodCall(_, ident, _, ref args) => { // see above let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0])); match ty::get(t).sty { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index bedaff70121..cb9e772dcea 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5221,7 +5221,7 @@ impl Resolver { let traits = self.search_for_traits_containing_method(ident); self.trait_map.insert(expr.id, @RefCell::new(traits)); } - ExprMethodCall(_, ident, _, _, _) => { + ExprMethodCall(_, ident, _, _) => { debug!("(recording candidate traits for expr) recording \ traits for {}", expr.id); diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 9c04f6d9399..68be851449a 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -647,7 +647,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr, } } } - ast::ExprCall(callee, ref args, _) => { + ast::ExprCall(callee, ref args) => { let tcx = cx.tcx; let opt_def = { let def_map = tcx.def_map.borrow(); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 74450695ae7..86f4275cf98 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -2624,7 +2624,7 @@ fn populate_scope_map(cx: &CrateContext, }) } - ast::ExprCall(fn_exp, ref args, _) => { + ast::ExprCall(fn_exp, ref args) => { walk_expr(cx, fn_exp, scope_stack, scope_map); for arg_exp in args.iter() { @@ -2632,7 +2632,7 @@ fn populate_scope_map(cx: &CrateContext, } } - ast::ExprMethodCall(node_id, _, _, ref args, _) => { + ast::ExprMethodCall(node_id, _, _, ref args) => { scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata); for arg_exp in args.iter() { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 357e2e5e9ef..794964e1054 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -777,11 +777,11 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>, expr_to_str(expr), expr_ty.repr(tcx)); closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest) } - ast::ExprCall(f, ref args, _) => { + ast::ExprCall(f, ref args) => { callee::trans_call(bcx, expr, f, callee::ArgExprs(*args), expr.id, dest) } - ast::ExprMethodCall(callee_id, _, _, ref args, _) => { + ast::ExprMethodCall(callee_id, _, _, ref args) => { callee::trans_method_call(bcx, expr, callee_id, args[0], callee::ArgExprs(*args), dest) } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 6c23cfd8ccb..27fb9bdb0bb 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -353,17 +353,24 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>, // converting to an rvalue. let self_datum = unpack_datum!( bcx, expr::trans(bcx, self_expr)); - let self_datum = unpack_datum!( - bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); - // Convert to by-ref since `trans_trait_callee_from_llval` wants it - // that way. - let self_datum = unpack_datum!( - bcx, self_datum.to_ref_datum(bcx)); + let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) { + let self_datum = unpack_datum!( + bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); - // Arrange cleanup in case something should go wrong before the - // actual call occurs. - let llval = self_datum.add_clean(bcx.fcx, arg_cleanup_scope); + // Convert to by-ref since `trans_trait_callee_from_llval` wants it + // that way. + let self_datum = unpack_datum!( + bcx, self_datum.to_ref_datum(bcx)); + + // Arrange cleanup in case something should go wrong before the + // actual call occurs. + self_datum.add_clean(bcx.fcx, arg_cleanup_scope) + } else { + // We don't have to do anything about cleanups for &Trait and &mut Trait. + assert!(self_datum.kind.is_by_ref()); + self_datum.val + }; let callee_ty = node_id_type(bcx, callee_id); trans_trait_callee_from_llval(bcx, callee_ty, n_method, llval) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5d33f6d1722..177eba5aa1b 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1592,22 +1592,20 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, method_fn_ty: ty::t, callee_expr: &ast::Expr, args: &[@ast::Expr], - sugar: ast::CallSugar, - deref_args: DerefArgs) -> ty::t - { + deref_args: DerefArgs) -> ty::t { // HACK(eddyb) ignore provided self (it has special typeck rules). let args = args.slice_from(1); if ty::type_is_error(method_fn_ty) { let err_inputs = err_args(args.len()); check_argument_types(fcx, sp, err_inputs, callee_expr, - args, sugar, deref_args, false); + args, deref_args, false); method_fn_ty } else { match ty::get(method_fn_ty).sty { ty::ty_bare_fn(ref fty) => { // HACK(eddyb) ignore self in the definition (see above). check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1), - callee_expr, args, sugar, deref_args, + callee_expr, args, deref_args, fty.sig.variadic); fty.sig.output } @@ -1625,7 +1623,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, fn_inputs: &[ty::t], callee_expr: &ast::Expr, args: &[@ast::Expr], - sugar: ast::CallSugar, deref_args: DerefArgs, variadic: bool) { /*! @@ -1659,18 +1656,12 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, err_args(supplied_arg_count) } } else { - let suffix = match sugar { - ast::NoSugar => "", - ast::ForSugar => " (including the closure passed by \ - the `for` keyword)" - }; let msg = format!( "this function takes {} parameter{} \ - but {} parameter{} supplied{}", + but {} parameter{} supplied", expected_arg_count, if expected_arg_count == 1 {""} else {"s"}, supplied_arg_count, - if supplied_arg_count == 1 {" was"} else {"s were"}, - suffix); + if supplied_arg_count == 1 {" was"} else {"s were"}); tcx.sess.span_err(sp, msg); @@ -1783,24 +1774,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, // The callee checks for bot / err, we don't need to } - fn write_call(fcx: @FnCtxt, - call_expr: &ast::Expr, - output: ty::t, - sugar: ast::CallSugar) { - let ret_ty = match sugar { - ast::ForSugar => { - match ty::get(output).sty { - ty::ty_bool => {} - _ => fcx.type_error_message(call_expr.span, |actual| { - format!("expected `for` closure to return `bool`, \ - but found `{}`", actual) }, - output, None) - } - ty::mk_nil() - } - _ => output - }; - fcx.write_ty(call_expr.id, ret_ty); + fn write_call(fcx: @FnCtxt, call_expr: &ast::Expr, output: ty::t) { + fcx.write_ty(call_expr.id, output); } // A generic function for doing all of the checking for call expressions @@ -1808,8 +1783,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, callee_id: ast::NodeId, call_expr: &ast::Expr, f: &ast::Expr, - args: &[@ast::Expr], - sugar: ast::CallSugar) { + args: &[@ast::Expr]) { // Index expressions need to be handled separately, to inform them // that they appear in call position. check_expr(fcx, f); @@ -1857,9 +1831,9 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, // Call the generic checker. check_argument_types(fcx, call_expr.span, fn_sig.inputs, f, - args, sugar, DontDerefArgs, fn_sig.variadic); + args, DontDerefArgs, fn_sig.variadic); - write_call(fcx, call_expr, fn_sig.output, sugar); + write_call(fcx, call_expr, fn_sig.output); } // Checks a method call. @@ -1868,8 +1842,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, expr: &ast::Expr, method_name: ast::Ident, args: &[@ast::Expr], - tps: &[ast::P], - sugar: ast::CallSugar) { + tps: &[ast::P]) { let rcvr = args[0]; check_expr(fcx, rcvr); @@ -1915,10 +1888,10 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, // Call the generic checker. let fn_ty = fcx.node_ty(callee_id); let ret_ty = check_method_argument_types(fcx, expr.span, - fn_ty, expr, args, sugar, + fn_ty, expr, args, DontDerefArgs); - write_call(fcx, expr, ret_ty, sugar); + write_call(fcx, expr, ret_ty); } // A generic function for checking the then and else in an if @@ -1985,8 +1958,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, method_map.get().insert(op_ex.id, *origin); } check_method_argument_types(fcx, op_ex.span, - method_ty, op_ex, args, - ast::NoSugar, deref_args) + method_ty, op_ex, + args, deref_args) } _ => { unbound_method(); @@ -1994,8 +1967,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, // so we get all the error messages let expected_ty = ty::mk_err(); check_method_argument_types(fcx, op_ex.span, - expected_ty, op_ex, args, - ast::NoSugar, deref_args); + expected_ty, op_ex, + args, deref_args); ty::mk_err() } } @@ -2948,8 +2921,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, check_block_with_expected(fcx, b, expected); fcx.write_ty(id, fcx.node_ty(b.id)); } - ast::ExprCall(f, ref args, sugar) => { - check_call(fcx, expr.id, expr, f, *args, sugar); + ast::ExprCall(f, ref args) => { + check_call(fcx, expr.id, expr, f, *args); let f_ty = fcx.expr_ty(f); let (args_bot, args_err) = args.iter().fold((false, false), |(rest_bot, rest_err), a| { @@ -2964,8 +2937,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt, fcx.write_bot(id); } } - ast::ExprMethodCall(callee_id, ident, ref tps, ref args, sugar) => { - check_method_call(fcx, callee_id, expr, ident, *args, *tps, sugar); + ast::ExprMethodCall(callee_id, ident, ref tps, ref args) => { + check_method_call(fcx, callee_id, expr, ident, *args, *tps); let arg_tys = args.map(|a| fcx.expr_ty(*a)); let (args_bot, args_err) = arg_tys.iter().fold((false, false), |(rest_bot, rest_err), a| { diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index a015f43b230..38400772778 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -432,14 +432,14 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { } match expr.node { - ast::ExprCall(callee, ref args, _) => { + ast::ExprCall(callee, ref args) => { constrain_callee(rcx, callee.id, expr, callee); constrain_call(rcx, callee.id, expr, None, *args, false); visit::walk_expr(rcx, expr, ()); } - ast::ExprMethodCall(callee_id, _, _, ref args, _) => { + ast::ExprMethodCall(callee_id, _, _, ref args) => { constrain_call(rcx, callee_id, expr, Some(args[0]), args.slice_from(1), false); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 46e79f4d1d5..721672ab677 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -702,7 +702,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) { ast::ExprUnary(callee_id, _, _) | ast::ExprAssignOp(callee_id, _, _, _) | ast::ExprIndex(callee_id, _, _) | - ast::ExprMethodCall(callee_id, _, _, _, _) => { + ast::ExprMethodCall(callee_id, _, _, _) => { match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) { Some(type_param_defs) => { debug!("vtable resolution on parameter bounds for method call {}", diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 36abb7aa457..c05afcf859a 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -307,7 +307,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) { maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id); } - ast::ExprMethodCall(callee_id, _, _, _, _) => { + ast::ExprMethodCall(callee_id, _, _, _) => { // We must always have written in a callee ID type for these. resolve_type_vars_for_node(wbcx, e.span, callee_id); } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index e17a42d3494..0c3bf2e0135 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -15,7 +15,7 @@ use syntax::visit; use syntax::visit::Visitor; use std::local_data; -use extra; +use extra::time; pub fn time(do_it: bool, what: &str, u: U, f: |U| -> T) -> T { local_data_key!(depth: uint); @@ -24,9 +24,9 @@ pub fn time(do_it: bool, what: &str, u: U, f: |U| -> T) -> T { let old = local_data::get(depth, |d| d.map(|a| *a).unwrap_or(0)); local_data::set(depth, old + 1); - let start = extra::time::precise_time_s(); + let start = time::precise_time_s(); let rv = f(u); - let end = extra::time::precise_time_s(); + let end = time::precise_time_s(); println!("{}time: {:3.3f} s\t{}", " ".repeat(old), end - start, what); local_data::set(depth, old); diff --git a/src/librustuv/idle.rs b/src/librustuv/idle.rs index 30e02b168ca..46de70c1746 100644 --- a/src/librustuv/idle.rs +++ b/src/librustuv/idle.rs @@ -117,7 +117,10 @@ mod test { match *slot.get() { (ref mut task, ref mut val) => { *val = n; - task.take_unwrap() + match task.take() { + Some(t) => t, + None => return + } } } } diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 231cf6592eb..fbed53ee30d 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -565,14 +565,14 @@ mod test { #[bench] fn bench_buffered_reader(bh: &mut Harness) { bh.iter(|| { - BufferedReader::new(NullStream); + BufferedReader::new(NullStream) }); } #[bench] fn bench_buffered_writer(bh: &mut Harness) { bh.iter(|| { - BufferedWriter::new(NullStream); + BufferedWriter::new(NullStream) }); } diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 6ed588ac69f..bf2c6dbb623 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -96,6 +96,12 @@ impl ChanWriter { } } +impl Clone for ChanWriter { + fn clone(&self) -> ChanWriter { + ChanWriter { chan: self.chan.clone() } + } +} + impl Writer for ChanWriter { fn write(&mut self, buf: &[u8]) -> IoResult<()> { if !self.chan.try_send(buf.to_owned()) { diff --git a/src/libstd/mem.rs b/src/libstd/mem.rs index 09d2db329ca..ee05d6a704b 100644 --- a/src/libstd/mem.rs +++ b/src/libstd/mem.rs @@ -292,7 +292,7 @@ mod bench { let s = Struct { field: 10 }; let t = &s as &Trait; bh.iter(|| { - t.method(); + t.method() }); } @@ -300,7 +300,7 @@ mod bench { fn trait_static_method_call(bh: &mut BenchHarness) { let s = Struct { field: 10 }; bh.iter(|| { - s.method(); + s.method() }); } @@ -310,10 +310,10 @@ mod bench { fn match_option_some(bh: &mut BenchHarness) { let x = Some(10); bh.iter(|| { - let _q = match x { + match x { Some(y) => y, None => 11 - }; + } }); } @@ -321,10 +321,10 @@ mod bench { fn match_vec_pattern(bh: &mut BenchHarness) { let x = [1,2,3,4,5,6]; bh.iter(|| { - let _q = match x { + match x { [1,2,3,..] => 10, _ => 11 - }; + } }); } } diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 4bce16706ee..ab279fd3102 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -112,14 +112,14 @@ mod bench { #[bench] fn alloc_owned_small(bh: &mut BenchHarness) { bh.iter(|| { - ~10; + ~10 }) } #[bench] fn alloc_owned_big(bh: &mut BenchHarness) { bh.iter(|| { - ~[10, ..1000]; + ~[10, ..1000] }) } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 0d263d94ccf..063182ff0e1 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -4357,7 +4357,7 @@ mod bench { assert_eq!(100, s.len()); bh.iter(|| { - let _ = is_utf8(s); + is_utf8(s) }); } @@ -4366,7 +4366,7 @@ mod bench { let s = bytes!("πŒ€πŒ–πŒ‹πŒ„πŒ‘πŒ‰ΰΈ›ΰΈ£Ψ―ΩˆΩ„Ψ© Ψ§Ω„ΩƒΩˆΩŠΨͺΰΈ—ΰΈ¨ΰΉ„ΰΈ—ΰΈ’δΈ­εŽπ…πŒΏπŒ»π†πŒΉπŒ»πŒ°"); assert_eq!(100, s.len()); bh.iter(|| { - let _ = is_utf8(s); + is_utf8(s) }); } @@ -4409,7 +4409,7 @@ mod bench { #[bench] fn bench_with_capacity(bh: &mut BenchHarness) { bh.iter(|| { - let _ = with_capacity(100); + with_capacity(100) }); } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index c67b19933d3..cfe2ad5a08a 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -4428,6 +4428,7 @@ mod bench { let mut vec: ~[uint] = ~[0u]; bh.iter(|| { vec.push(0); + &vec }) } @@ -4435,7 +4436,7 @@ mod bench { fn starts_with_same_vector(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.starts_with(vec); + vec.starts_with(vec) }) } @@ -4443,7 +4444,7 @@ mod bench { fn starts_with_single_element(bh: &mut BenchHarness) { let vec: ~[uint] = ~[0u]; bh.iter(|| { - vec.starts_with(vec); + vec.starts_with(vec) }) } @@ -4453,7 +4454,7 @@ mod bench { let mut match_vec: ~[uint] = vec::from_fn(99, |i| i); match_vec.push(0); bh.iter(|| { - vec.starts_with(match_vec); + vec.starts_with(match_vec) }) } @@ -4461,7 +4462,7 @@ mod bench { fn ends_with_same_vector(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.ends_with(vec); + vec.ends_with(vec) }) } @@ -4469,7 +4470,7 @@ mod bench { fn ends_with_single_element(bh: &mut BenchHarness) { let vec: ~[uint] = ~[0u]; bh.iter(|| { - vec.ends_with(vec); + vec.ends_with(vec) }) } @@ -4479,7 +4480,7 @@ mod bench { let mut match_vec: ~[uint] = vec::from_fn(100, |i| i); match_vec[0] = 200; bh.iter(|| { - vec.starts_with(match_vec); + vec.starts_with(match_vec) }) } @@ -4487,7 +4488,7 @@ mod bench { fn contains_last_element(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.contains(&99u); + vec.contains(&99u) }) } @@ -4507,13 +4508,14 @@ mod bench { ptr::set_memory(vp, 0, 1024); v.set_len(1024); } + v }); } #[bench] fn zero_1kb_fixed_repeat(bh: &mut BenchHarness) { bh.iter(|| { - let _v: ~[u8] = ~[0u8, ..1024]; + ~[0u8, ..1024] }); } @@ -4542,6 +4544,7 @@ mod bench { for x in v.mut_iter() { *x = 0; } + v }); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 72330bb7f31..132cb396ddd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -519,7 +519,7 @@ pub struct Expr { impl Expr { pub fn get_callee_id(&self) -> Option { match self.node { - ExprMethodCall(callee_id, _, _, _, _) | + ExprMethodCall(callee_id, _, _, _) | ExprIndex(callee_id, _, _) | ExprBinary(callee_id, _, _, _) | ExprAssignOp(callee_id, _, _, _) | @@ -529,20 +529,14 @@ impl Expr { } } -#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] -pub enum CallSugar { - NoSugar, - ForSugar -} - #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum Expr_ { ExprVstore(@Expr, ExprVstore), // First expr is the place; second expr is the value. ExprBox(@Expr, @Expr), ExprVec(~[@Expr], Mutability), - ExprCall(@Expr, ~[@Expr], CallSugar), - ExprMethodCall(NodeId, Ident, ~[P], ~[@Expr], CallSugar), + ExprCall(@Expr, ~[@Expr]), + ExprMethodCall(NodeId, Ident, ~[P], ~[@Expr]), ExprTup(~[@Expr]), ExprBinary(NodeId, BinOp, @Expr, @Expr), ExprUnary(NodeId, UnOp, @Expr), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e41decbd8ef..d311a542ac6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -525,11 +525,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_call(&self, span: Span, expr: @ast::Expr, args: ~[@ast::Expr]) -> @ast::Expr { - self.expr(span, ast::ExprCall(expr, args, ast::NoSugar)) + self.expr(span, ast::ExprCall(expr, args)) } fn expr_call_ident(&self, span: Span, id: ast::Ident, args: ~[@ast::Expr]) -> @ast::Expr { - self.expr(span, - ast::ExprCall(self.expr_ident(span, id), args, ast::NoSugar)) + self.expr(span, ast::ExprCall(self.expr_ident(span, id), args)) } fn expr_call_global(&self, sp: Span, fn_path: ~[ast::Ident], args: ~[@ast::Expr]) -> @ast::Expr { @@ -541,7 +540,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ident: ast::Ident, mut args: ~[@ast::Expr]) -> @ast::Expr { args.unshift(expr); - self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args, ast::NoSugar)) + self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args)) } fn expr_block(&self, b: P) -> @ast::Expr { self.expr(b.span, ast::ExprBlock(b)) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e59afc6ffa6..97766e1a14b 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -203,52 +203,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { } } -// This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_encode]. These are invoked by an -// attribute prefixing an item, and are interpreted by feeding the item -// through the named attribute _as a syntax extension_ and splicing in the -// resulting item vec into place in favour of the decorator. Note that -// these do _not_ work for macro extensions, just ItemDecorator ones. -// -// NB: there is some redundancy between this and expand_item, below, and -// they might benefit from some amount of semantic and language-UI merger. -pub fn expand_mod_items(module_: &ast::Mod, fld: &mut MacroExpander) -> ast::Mod { - // Fold the contents first: - let module_ = noop_fold_mod(module_, fld); - - // For each item, look through the attributes. If any of them are - // decorated with "item decorators", then use that function to transform - // the item into a new set of items. - let mut new_items = module_.items.clone(); - for item in module_.items.iter() { - for attr in item.attrs.rev_iter() { - let mname = attr.name(); - - match fld.extsbox.find(&intern(mname.get())) { - Some(&ItemDecorator(dec_fn)) => { - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - name: mname.get().to_str(), - format: MacroAttribute, - span: None - } - }); - dec_fn(fld.cx, attr.span, attr.node.value, *item, - |item| new_items.push(item)); - fld.cx.bt_pop(); - }, - _ => {}, - } - } - } - - ast::Mod { - items: new_items, - ..module_ - } -} - // eval $e with a new exts frame: macro_rules! with_exts_frame ( ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => @@ -263,7 +217,35 @@ macro_rules! with_exts_frame ( // When we enter a module, record it, for the sake of `module!` pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) -> SmallVector<@ast::Item> { - match it.node { + let mut decorator_items = SmallVector::zero(); + for attr in it.attrs.rev_iter() { + let mname = attr.name(); + + match fld.extsbox.find(&intern(mname.get())) { + Some(&ItemDecorator(dec_fn)) => { + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.get().to_str(), + format: MacroAttribute, + span: None + } + }); + // we'd ideally decorator_items.push_all(expand_item(item, fld)), + // but that double-mut-borrows fld + dec_fn(fld.cx, attr.span, attr.node.value, it, + |item| decorator_items.push(item)); + fld.cx.bt_pop(); + } + _ => {} + } + } + + let decorator_items = decorator_items.move_iter() + .flat_map(|item| expand_item(item, fld).move_iter()) + .collect(); + + let mut new_items = match it.node { ast::ItemMac(..) => expand_item_mac(it, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { fld.cx.mod_push(it.ident); @@ -275,7 +257,10 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) result }, _ => noop_fold_item(it, fld) - } + }; + + new_items.push_all(decorator_items); + new_items } // does this attribute list contain "macro_escape" ? @@ -778,10 +763,6 @@ impl<'a> Folder for MacroExpander<'a> { expand_expr(expr, self) } - fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod { - expand_mod_items(module, self) - } - fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> { expand_item(item, self) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6fb66a66f18..e150d1685de 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -727,19 +727,16 @@ pub fn noop_fold_expr(e: @Expr, folder: &mut T) -> @Expr { ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count), mutt) } ExprTup(ref elts) => ExprTup(elts.map(|x| folder.fold_expr(*x))), - ExprCall(f, ref args, blk) => { + ExprCall(f, ref args) => { ExprCall(folder.fold_expr(f), - args.map(|&x| folder.fold_expr(x)), - blk) + args.map(|&x| folder.fold_expr(x))) } - ExprMethodCall(callee_id, i, ref tps, ref args, blk) => { + ExprMethodCall(callee_id, i, ref tps, ref args) => { ExprMethodCall( folder.new_id(callee_id), folder.fold_ident(i), tps.map(|&x| folder.fold_ty(x)), - args.map(|&x| folder.fold_expr(x)), - blk - ) + args.map(|&x| folder.fold_expr(x))) } ExprBinary(callee_id, binop, lhs, rhs) => { ExprBinary(folder.new_id(callee_id), diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 613416bed1c..78e40a795db 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -32,7 +32,7 @@ This API is completely unstable and subject to change. #[deny(non_camel_case_types)]; -extern mod extra; +#[cfg(test)] extern mod extra; extern mod serialize; extern mod term; extern mod collections; diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index accf5e73540..d6dcb956f25 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -23,15 +23,13 @@ use ast; // isn't parsed as (if true {...} else {...} | x) | 5 pub fn expr_requires_semi_to_be_stmt(e: @ast::Expr) -> bool { match e.node { - ast::ExprIf(..) - | ast::ExprMatch(..) - | ast::ExprBlock(_) - | ast::ExprWhile(..) - | ast::ExprLoop(..) - | ast::ExprForLoop(..) - | ast::ExprCall(_, _, ast::ForSugar) - | ast::ExprMethodCall(_, _, _, _, ast::ForSugar) => false, - _ => true + ast::ExprIf(..) + | ast::ExprMatch(..) + | ast::ExprBlock(_) + | ast::ExprWhile(..) + | ast::ExprLoop(..) + | ast::ExprForLoop(..) => false, + _ => true } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 674d41e9dbe..a02971ae8ea 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -13,7 +13,6 @@ use abi; use abi::AbiSet; use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil}; -use ast::{CallSugar, NoSugar}; use ast::{BareFnTy, ClosureTy}; use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{Provided, Public, Purity}; @@ -1690,13 +1689,12 @@ impl Parser { ExprBinary(ast::DUMMY_NODE_ID, binop, lhs, rhs) } - pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr], sugar: CallSugar) -> ast::Expr_ { - ExprCall(f, args, sugar) + pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr]) -> ast::Expr_ { + ExprCall(f, args) } - fn mk_method_call(&mut self, ident: Ident, tps: ~[P], args: ~[@Expr], - sugar: CallSugar) -> ast::Expr_ { - ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args, sugar) + fn mk_method_call(&mut self, ident: Ident, tps: ~[P], args: ~[@Expr]) -> ast::Expr_ { + ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args) } pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ { @@ -1997,7 +1995,7 @@ impl Parser { hi = self.last_span.hi; es.unshift(e); - let nd = self.mk_method_call(i, tys, es, NoSugar); + let nd = self.mk_method_call(i, tys, es); e = self.mk_expr(lo, hi, nd); } _ => { @@ -2022,7 +2020,7 @@ impl Parser { ); hi = self.last_span.hi; - let nd = self.mk_call(e, es, NoSugar); + let nd = self.mk_call(e, es); e = self.mk_expr(lo, hi, nd); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 85bc372b9c6..bb2f345ac28 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1141,33 +1141,10 @@ pub fn print_expr_vstore(s: &mut State, t: ast::ExprVstore) -> io::IoResult<()> } } -pub fn print_call_pre(s: &mut State, - sugar: ast::CallSugar, - base_args: &mut ~[@ast::Expr]) - -> io::IoResult> { - match sugar { - ast::ForSugar => { - if_ok!(head(s, "for")); - Ok(Some(base_args.pop().unwrap())) - } - ast::NoSugar => Ok(None) - } -} - -pub fn print_call_post(s: &mut State, - sugar: ast::CallSugar, - blk: &Option<@ast::Expr>, - base_args: &mut ~[@ast::Expr]) -> io::IoResult<()> { - if sugar == ast::NoSugar || !base_args.is_empty() { - if_ok!(popen(s)); - if_ok!(commasep_exprs(s, Inconsistent, *base_args)); - if_ok!(pclose(s)); - } - if sugar != ast::NoSugar { - if_ok!(nbsp(s)); - // not sure if this can happen - if_ok!(print_expr(s, blk.unwrap())); - } +fn print_call_post(s: &mut State, args: &[@ast::Expr]) -> io::IoResult<()> { + if_ok!(popen(s)); + if_ok!(commasep_exprs(s, Inconsistent, args)); + if_ok!(pclose(s)); Ok(()) } @@ -1254,15 +1231,12 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> { } if_ok!(pclose(s)); } - ast::ExprCall(func, ref args, sugar) => { - let mut base_args = (*args).clone(); - let blk = if_ok!(print_call_pre(s, sugar, &mut base_args)); + ast::ExprCall(func, ref args) => { if_ok!(print_expr(s, func)); - if_ok!(print_call_post(s, sugar, &blk, &mut base_args)); + if_ok!(print_call_post(s, *args)); } - ast::ExprMethodCall(_, ident, ref tys, ref args, sugar) => { - let mut base_args = args.slice_from(1).to_owned(); - let blk = if_ok!(print_call_pre(s, sugar, &mut base_args)); + ast::ExprMethodCall(_, ident, ref tys, ref args) => { + let base_args = args.slice_from(1); if_ok!(print_expr(s, args[0])); if_ok!(word(&mut s.s, ".")); if_ok!(print_ident(s, ident)); @@ -1271,7 +1245,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> { if_ok!(commasep(s, Inconsistent, *tys, print_type_ref)); if_ok!(word(&mut s.s, ">")); } - if_ok!(print_call_post(s, sugar, &blk, &mut base_args)); + if_ok!(print_call_post(s, base_args)); } ast::ExprBinary(_, op, lhs, rhs) => { if_ok!(print_expr(s, lhs)); diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index e0d7fdd8790..32e5b83ee04 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -64,6 +64,12 @@ impl SmallVector { } } + pub fn push_all(&mut self, other: SmallVector) { + for v in other.move_iter() { + self.push(v); + } + } + pub fn get<'a>(&'a self, idx: uint) -> &'a T { match *self { One(ref v) if idx == 0 => v, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ce87c3d7591..feab4e0e84d 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -652,13 +652,13 @@ pub fn walk_expr>(visitor: &mut V, expression: &Expr, en visitor.visit_expr(*subexpression, env.clone()) } } - ExprCall(callee_expression, ref arguments, _) => { + ExprCall(callee_expression, ref arguments) => { for argument in arguments.iter() { visitor.visit_expr(*argument, env.clone()) } visitor.visit_expr(callee_expression, env.clone()) } - ExprMethodCall(_, _, ref types, ref arguments, _) => { + ExprMethodCall(_, _, ref types, ref arguments) => { walk_exprs(visitor, *arguments, env.clone()); for &typ in types.iter() { visitor.visit_ty(typ, env.clone()) diff --git a/src/test/compile-fail/issue-8727.rs b/src/test/compile-fail/issue-8727.rs new file mode 100644 index 00000000000..003f1d67cdb --- /dev/null +++ b/src/test/compile-fail/issue-8727.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// Verify the compiler fails with an error on infinite function +// recursions. + +struct Data(~Option); + +fn generic( _ : ~[(Data,T)] ) { + //~^ ERROR overly deep expansion of inlined function + let rec : ~[(Data,(bool,T))] = ~[]; + generic( rec ); +} + + +fn main () { + // Use generic at least once to trigger instantiation. + let input : ~[(Data,())] = ~[]; + generic(input); +} diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs index e9d3c41faa6..427e606147d 100644 --- a/src/test/run-fail/run-unexported-tests.rs +++ b/src/test/run-fail/run-unexported-tests.rs @@ -10,6 +10,7 @@ // error-pattern:runned an unexported test // compile-flags:--test +// check-stdout extern mod extra; diff --git a/src/test/run-fail/test-fail.rs b/src/test/run-fail/test-fail.rs index ddd54f00159..77d87c22c6f 100644 --- a/src/test/run-fail/test-fail.rs +++ b/src/test/run-fail/test-fail.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// check-stdout // error-pattern:task 'test_foo' failed at // compile-flags: --test diff --git a/src/test/run-pass/deriving-in-fn.rs b/src/test/run-pass/deriving-in-fn.rs new file mode 100644 index 00000000000..7fb7d601b81 --- /dev/null +++ b/src/test/run-pass/deriving-in-fn.rs @@ -0,0 +1,19 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + #[deriving(ToStr)] + struct Foo { + foo: int, + } + + let f = Foo { foo: 10 }; + let _ = f.to_str(); +} diff --git a/src/test/run-pass/issue-8860.rs b/src/test/run-pass/issue-8860.rs new file mode 100644 index 00000000000..230dce16151 --- /dev/null +++ b/src/test/run-pass/issue-8860.rs @@ -0,0 +1,62 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-fast + +extern mod green; + +static mut DROP: int = 0i; +static mut DROP_S: int = 0i; +static mut DROP_T: int = 0i; + +#[start] +fn start(argc: int, argv: **u8) -> int { + let ret = green::start(argc, argv, main); + unsafe { + assert_eq!(2, DROP); + assert_eq!(1, DROP_S); + assert_eq!(1, DROP_T); + } + ret +} + +struct S; +impl Drop for S { + fn drop(&mut self) { + unsafe { + DROP_S += 1; + DROP += 1; + } + } +} +fn f(ref _s: S) {} + +struct T { i: int } +impl Drop for T { + fn drop(&mut self) { + unsafe { + DROP_T += 1; + DROP += 1; + } + } +} +fn g(ref _t: T) {} + +fn main() { + let s = S; + f(s); + unsafe { + assert_eq!(1, DROP); + assert_eq!(1, DROP_S); + } + let t = T { i: 1 }; + g(t); + unsafe { assert_eq!(1, DROP_T); } +}