From 4ee73a124c828831e97201649a6e71f6d5b4f83c Mon Sep 17 00:00:00 2001 From: th0114nd Date: Thu, 18 Dec 2014 18:27:50 -0500 Subject: [PATCH 001/106] =?UTF-8?q?Changed=20LaTex=20$\bot$s=20to=20?= =?UTF-8?q?=E2=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the HTML version of the documentation, it isn't rendered so might as well use the unicode representation. Part of the problem was that putting a math unicode character wasn't rendering properly in the pdf, so extra steps were needed to define the unicode charecter ⊥ in reference.tex closes #15285 --- mk/docs.mk | 11 ++++++++--- src/doc/reference.md | 4 ++-- src/doc/uptack.tex | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 src/doc/uptack.tex diff --git a/mk/docs.mk b/mk/docs.mk index 6d1a3bfa7a326..09f3580a3c8be 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -49,8 +49,10 @@ RUSTDOC_HTML_OPTS_NO_CSS = --html-before-content=doc/version_info.html \ RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css PANDOC_BASE_OPTS := --standalone --toc --number-sections -PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.tex \ - --from=markdown --include-before-body=doc/footer.tex --to=latex +PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --from=markdown --to=latex \ + --include-before-body=doc/version.tex \ + --include-before-body=doc/footer.tex \ + --include-in-header=doc/uptack.tex PANDOC_EPUB_OPTS = $(PANDOC_BASE_OPTS) --to=epub # The rustdoc executable... @@ -155,6 +157,9 @@ doc/footer.tex: $(D)/footer.inc | doc/ @$(call E, pandoc: $@) $(CFG_PANDOC) --from=html --to=latex $< --output=$@ +doc/uptack.tex: $(D)/uptack.tex | doc/ + $(Q)cp $< $@ + # HTML (rustdoc) DOC_TARGETS += doc/not_found.html doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/ @@ -180,7 +185,7 @@ doc/$(1).epub: $$(D)/$(1).md | doc/ # PDF (md =(pandoc)=> tex =(pdflatex)=> pdf) DOC_TARGETS += doc/$(1).tex -doc/$(1).tex: $$(D)/$(1).md doc/footer.tex doc/version.tex | doc/ +doc/$(1).tex: $$(D)/$(1).md doc/uptack.tex doc/footer.tex doc/version.tex | doc/ @$$(call E, pandoc: $$@) $$(CFG_PANDOC) $$(PANDOC_TEX_OPTS) $$< --output=$$@ diff --git a/src/doc/reference.md b/src/doc/reference.md index 3d4791e916e6a..cd1e6f74ee1d1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1259,8 +1259,8 @@ We call such functions "diverging" because they never return a value to the caller. Every control path in a diverging function must end with a `panic!()` or a call to another diverging function on every control path. The `!` annotation does *not* denote a type. Rather, the result type of a diverging function is a -special type called $\bot$ ("bottom") that unifies with any type. Rust has no -syntax for $\bot$. +special type called ⊥ ("bottom") that unifies with any type. Rust has no +syntax for ⊥. It might be necessary to declare a diverging function because as mentioned previously, the typechecker checks that every control path in a function ends diff --git a/src/doc/uptack.tex b/src/doc/uptack.tex new file mode 100644 index 0000000000000..32158ea549627 --- /dev/null +++ b/src/doc/uptack.tex @@ -0,0 +1,2 @@ +\usepackage{newunicodechar} +\newunicodechar⊥{{$\bot$}} From 9f244dc97a1ee0340d53de5faedb5a170fa8e6f2 Mon Sep 17 00:00:00 2001 From: Barosl Lee Date: Sat, 13 Dec 2014 23:54:06 +0900 Subject: [PATCH 002/106] Minor fix for the Rust language FAQ extra library -> standard library --- src/doc/complement-lang-faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/complement-lang-faq.md b/src/doc/complement-lang-faq.md index 9e73863239fbc..a9a9e0858ec6b 100644 --- a/src/doc/complement-lang-faq.md +++ b/src/doc/complement-lang-faq.md @@ -17,7 +17,7 @@ Some examples that demonstrate different aspects of the language: * [sprocketnes], an NES emulator with no GC, using modern Rust conventions * The language's general-purpose [hash] function, SipHash-2-4. Bit twiddling, OO, macros * The standard library's [HashMap], a sendable hash map in an OO style -* The extra library's [json] module. Enums and pattern matching +* The standard library's [json] module. Enums and pattern matching [sprocketnes]: https://github.com/pcwalton/sprocketnes [hash]: https://github.com/rust-lang/rust/blob/master/src/libstd/hash/mod.rs From 739f74bb156538880464b6e776048d02bf4c6adb Mon Sep 17 00:00:00 2001 From: Barosl Lee Date: Sat, 20 Dec 2014 03:56:47 +0900 Subject: [PATCH 003/106] Make the line numbers of the source code clickable --- src/librustdoc/html/render.rs | 4 ++-- src/librustdoc/html/static/main.css | 16 ++++++++++--- src/librustdoc/html/static/main.js | 37 ++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 304dbe201e8fd..bbd76adb5766b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2249,9 +2249,9 @@ impl<'a> fmt::Show for Source<'a> { cols += 1; tmp /= 10; } - try!(write!(fmt, "
"));
+        try!(write!(fmt, "
"));
         for i in range(1, lines + 1) {
-            try!(write!(fmt, "{0:1$}\n", i, cols));
+            try!(write!(fmt, "{0:1$}\n", i, cols));
         }
         try!(write!(fmt, "
")); try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None))); diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index dc62273364c20..c0d3e2c19eb51 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -157,6 +157,7 @@ nav.sub { left: 0; top: 0; min-height: 100%; + z-index: -1; } .content, nav { max-width: 960px; } @@ -217,10 +218,18 @@ nav.sub { overflow: auto; padding-left: 0; } -.content pre.line-numbers { float: left; border: none; } -.line-numbers span { color: #c67e2d; } +.content pre.line-numbers { + float: left; + border: none; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.line-numbers span { color: #c67e2d; cursor: pointer; } .line-numbers .line-highlighted { - background-color: #f6fdb0; + background-color: #f6fdb0 !important; } .content .highlighted { @@ -465,6 +474,7 @@ h1 .stability { .summary.Unmarked { background-color: #BBBBBB; } :target { background: #FDFFD3; } +.line-numbers :target { background-color: transparent; } /* Code highlighting */ pre.rust .kw { color: #8959A8; } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 978af31cdc689..2d575c226c5d0 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -50,7 +50,7 @@ resizeShortBlocks(); $(window).on('resize', resizeShortBlocks); - function highlightSourceLines() { + function highlightSourceLines(ev) { var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { from = parseInt(match[1], 10); @@ -59,14 +59,14 @@ if ($('#' + from).length === 0) { return; } - $('#' + from)[0].scrollIntoView(); + if (ev === null) $('#' + from)[0].scrollIntoView(); $('.line-numbers span').removeClass('line-highlighted'); for (i = from; i <= to; ++i) { $('#' + i).addClass('line-highlighted'); } } } - highlightSourceLines(); + highlightSourceLines(null); $(window).on('hashchange', highlightSourceLines); $(document).on('keyup', function(e) { @@ -778,4 +778,35 @@ $("#main > .docblock").before(wrapper); }); + $('pre.line-numbers').on('click', 'span', function() { + var prev_id = 0; + + function set_fragment(name) { + if (history.replaceState) { + history.replaceState(null, null, '#' + name); + $(window).trigger('hashchange'); + } else { + location.replace('#' + name); + } + } + + return function(ev) { + var cur_id = parseInt(ev.target.id); + + if (ev.shiftKey && prev_id) { + if (prev_id > cur_id) { + var tmp = prev_id; + prev_id = cur_id; + cur_id = tmp; + } + + set_fragment(prev_id + '-' + cur_id); + } else { + prev_id = cur_id; + + set_fragment(cur_id); + } + }; + }()); + }()); From 9554794d22840b5077aa4605fa49a587d3e018b6 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sat, 27 Dec 2014 18:19:27 +0900 Subject: [PATCH 004/106] Add unstable_options method --- src/librustc/session/mod.rs | 3 +++ src/librustc_driver/lib.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 37bdd1673e9ca..c120ac53b7811 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -202,6 +202,9 @@ impl Session { pub fn show_span(&self) -> bool { self.debugging_opt(config::SHOW_SPAN) } + pub fn unstable_options(&self) -> bool { + self.debugging_opt(config::UNSTABLE_OPTIONS) + } pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot { Some (ref sysroot) => sysroot, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e2791aff14e49..5cd87a1e4c080 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -143,7 +143,7 @@ fn run_compiler(args: &[String]) { pretty::parse_pretty(&sess, a.as_slice(), false) }); let pretty = if pretty.is_none() && - sess.debugging_opt(config::UNSTABLE_OPTIONS) { + sess.unstable_options() { matches.opt_str("xpretty").map(|a| { // extended with unstable pretty-print variants pretty::parse_pretty(&sess, a.as_slice(), true) From d4da75892219ee8fed5fc8801a37ffe82520083d Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sat, 27 Dec 2014 19:43:14 +0900 Subject: [PATCH 005/106] Use -Z unstable-options for span debugger --- src/librustc/session/config.rs | 6 ++++-- src/librustc/session/mod.rs | 3 --- src/librustc_driver/driver.rs | 4 ++-- src/librustc_driver/lib.rs | 6 +++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 6629f6620d484..61676407991fc 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -105,6 +105,7 @@ pub struct Options { pub prints: Vec, pub cg: CodegenOptions, pub color: ColorConfig, + pub show_span: Option, pub externs: HashMap>, pub crate_name: Option, /// An optional name to use as the crate for std during std injection, @@ -211,6 +212,7 @@ pub fn basic_options() -> Options { prints: Vec::new(), cg: basic_codegen_options(), color: Auto, + show_span: None, externs: HashMap::new(), crate_name: None, alt_std_name: None, @@ -259,7 +261,6 @@ debugging_opts! { BORROWCK_STATS, NO_LANDING_PADS, DEBUG_LLVM, - SHOW_SPAN, COUNT_TYPE_SIZES, META_STATS, GC, @@ -298,7 +299,6 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> { ("no-landing-pads", "omit landing pads for unwinding", NO_LANDING_PADS), ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM), - ("show-span", "show spans for compiler debugging", SHOW_SPAN), ("count-type-sizes", "count the sizes of aggregate types", COUNT_TYPE_SIZES), ("meta-stats", "gather metadata statistics", META_STATS), @@ -820,6 +820,7 @@ pub fn rustc_optgroups() -> Vec { `flowgraph=` (graphviz formatted flowgraph for node), or `everybody_loops` (all function bodies replaced with `loop {}`).", "TYPE"), + opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"), opt::flagopt("", "dep-info", "Output dependency info to after compiling, \ in a format suitable for use by Makefiles", "FILENAME"), @@ -1122,6 +1123,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { prints: prints, cg: cg, color: color, + show_span: None, externs: externs, crate_name: crate_name, alt_std_name: None, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index c120ac53b7811..9a6275401adc8 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -199,9 +199,6 @@ impl Session { pub fn no_landing_pads(&self) -> bool { self.debugging_opt(config::NO_LANDING_PADS) } - pub fn show_span(&self) -> bool { - self.debugging_opt(config::SHOW_SPAN) - } pub fn unstable_options(&self) -> bool { self.debugging_opt(config::UNSTABLE_OPTIONS) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 20bb9c2f4fd1c..69e439c1bbe27 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -138,7 +138,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) krate.encode(&mut json).unwrap(); } - if sess.show_span() { + if sess.opts.show_span.is_some() { syntax::show_span::run(sess.diagnostic(), &krate); } @@ -542,7 +542,7 @@ pub fn stop_after_phase_1(sess: &Session) -> bool { debug!("invoked with --parse-only, returning early from compile_input"); return true; } - if sess.show_span() { + if sess.opts.show_span.is_some() { return true; } return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5cd87a1e4c080..98d2b5eb67d3c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -132,7 +132,7 @@ fn run_compiler(args: &[String]) { _ => early_error("multiple input filenames provided") }; - let sess = build_session(sopts, input_file_path, descriptions); + let mut sess = build_session(sopts, input_file_path, descriptions); let cfg = config::build_configuration(&sess); if print_crate_info(&sess, Some(&input), &odir, &ofile) { return @@ -160,6 +160,10 @@ fn run_compiler(args: &[String]) { None => {/* continue */ } } + if sess.unstable_options() { + sess.opts.show_span = matches.opt_str("show-span"); + } + let r = matches.opt_strs("Z"); if r.contains(&("ls".to_string())) { match input { From 20fa7cbfc0b5143f6c88e288772fc0f65610c2ec Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 15 Dec 2014 13:51:04 -0500 Subject: [PATCH 006/106] Add header to optimizations section --- src/doc/guide-testing.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/guide-testing.md b/src/doc/guide-testing.md index 682c89fcc53fc..60ce71dac8454 100644 --- a/src/doc/guide-testing.md +++ b/src/doc/guide-testing.md @@ -503,6 +503,8 @@ Advice on writing benchmarks: * Make the code in the `iter` loop do something simple, to assist in pinpointing performance improvements (or regressions) +## Gotcha: optimizations + There's another tricky part to writing benchmarks: benchmarks compiled with optimizations activated can be dramatically changed by the optimizer so that the benchmark is no longer benchmarking what one expects. For example, the From cd85f0a56a790f24bb1c1928fbc37c9d24dd2937 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 15 Dec 2014 13:53:14 -0500 Subject: [PATCH 007/106] restore paragraph Fixes #19861 --- src/doc/guide-testing.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/doc/guide-testing.md b/src/doc/guide-testing.md index 60ce71dac8454..8d113bb931a09 100644 --- a/src/doc/guide-testing.md +++ b/src/doc/guide-testing.md @@ -556,8 +556,12 @@ extern crate test; # fn main() { # struct X; impl X { fn iter(&self, _: || -> T) {} } let b = X; b.iter(|| { - test::black_box(range(0u, 1000).fold(0, |old, new| old ^ new)); -}); + let mut n = 1000_u32; + + test::black_box(&mut n); // pretend to modify `n` + + range(0, n).fold(0, |a, b| a ^ b) +}) # } ``` @@ -573,3 +577,6 @@ test bench_xor_1000_ints ... bench: 1 ns/iter (+/- 0) test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured ``` + +However, the optimizer can still modify a testcase in an undesirable manner +even when using either of the above. From 98aeac2930dfd64ef1cb52c3a20e1f3609feee8e Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sat, 27 Dec 2014 21:00:48 +0900 Subject: [PATCH 008/106] Extend span debugger --- src/librustc_driver/driver.rs | 4 +-- src/libsyntax/show_span.rs | 52 +++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 69e439c1bbe27..5e563ae9d6dfa 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -138,8 +138,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) krate.encode(&mut json).unwrap(); } - if sess.opts.show_span.is_some() { - syntax::show_span::run(sess.diagnostic(), &krate); + if let Some(ref s) = sess.opts.show_span { + syntax::show_span::run(sess.diagnostic(), s.as_slice(), &krate); } krate diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 354ba854b101a..51d655ec0f2c5 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -13,27 +13,73 @@ //! This module shows spans for all expressions in the crate //! to help with compiler debugging. +use std::str::FromStr; + use ast; use diagnostic; use visit; use visit::Visitor; +enum Mode { + Expression, + Pattern, + Type, +} + +impl FromStr for Mode { + fn from_str(s: &str) -> Option { + let mode = match s { + "expr" => Mode::Expression, + "pat" => Mode::Pattern, + "ty" => Mode::Type, + _ => return None + }; + Some(mode) + } +} + struct ShowSpanVisitor<'a> { span_diagnostic: &'a diagnostic::SpanHandler, + mode: Mode, } impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> { fn visit_expr(&mut self, e: &ast::Expr) { - self.span_diagnostic.span_note(e.span, "expression"); + if let Mode::Expression = self.mode { + self.span_diagnostic.span_note(e.span, "expression"); + } visit::walk_expr(self, e); } + fn visit_pat(&mut self, p: &ast::Pat) { + if let Mode::Pattern = self.mode { + self.span_diagnostic.span_note(p.span, "pattern"); + } + visit::walk_pat(self, p); + } + + fn visit_ty(&mut self, t: &ast::Ty) { + if let Mode::Type = self.mode { + self.span_diagnostic.span_note(t.span, "type"); + } + visit::walk_ty(self, t); + } + fn visit_mac(&mut self, macro: &ast::Mac) { visit::walk_mac(self, macro); } } -pub fn run(span_diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate) { - let mut v = ShowSpanVisitor { span_diagnostic: span_diagnostic }; +pub fn run(span_diagnostic: &diagnostic::SpanHandler, + mode: &str, + krate: &ast::Crate) { + let mode = match mode.parse() { + Some(mode) => mode, + None => return + }; + let mut v = ShowSpanVisitor { + span_diagnostic: span_diagnostic, + mode: mode, + }; visit::walk_crate(&mut v, krate); } From 5cf72ff8988243814aed3f384ea272e2c3d85ee2 Mon Sep 17 00:00:00 2001 From: P1start Date: Sun, 21 Dec 2014 19:03:31 +1300 Subject: [PATCH 009/106] Parse arbitrary operators after expr-like macro invocations in statement position Closes #20093. --- src/libsyntax/parse/parser.rs | 15 ++++--- .../run-pass/parse-complex-macro-invoc-op.rs | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/parse-complex-macro-invoc-op.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2f43661eebeba..3acb74485f5ef 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2995,14 +2995,17 @@ impl<'a> Parser<'a> { /// actually, this seems to be the main entry point for /// parsing an arbitrary expression. pub fn parse_assign_expr(&mut self) -> P { - let lo = self.span.lo; let lhs = self.parse_binops(); + self.parse_assign_expr_with(lhs) + } + + pub fn parse_assign_expr_with(&mut self, lhs: P) -> P { let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL; match self.token { token::Eq => { self.bump(); let rhs = self.parse_expr_res(restrictions); - self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs)) + self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs)) } token::BinOpEq(op) => { self.bump(); @@ -3020,8 +3023,9 @@ impl<'a> Parser<'a> { token::Shr => BiShr }; let rhs_span = rhs.span; + let span = lhs.span; let assign_op = self.mk_assign_op(aop, lhs, rhs); - self.mk_expr(lo, rhs_span.hi, assign_op) + self.mk_expr(span.lo, rhs_span.hi, assign_op) } _ => { lhs @@ -3919,8 +3923,9 @@ impl<'a> Parser<'a> { let e = self.mk_mac_expr(span.lo, span.hi, macro.and_then(|m| m.node)); - let e = - self.parse_dot_or_call_expr_with(e); + let e = self.parse_dot_or_call_expr_with(e); + let e = self.parse_more_binops(e, 0); + let e = self.parse_assign_expr_with(e); self.handle_expression_like_statement( e, ast::DUMMY_NODE_ID, diff --git a/src/test/run-pass/parse-complex-macro-invoc-op.rs b/src/test/run-pass/parse-complex-macro-invoc-op.rs new file mode 100644 index 0000000000000..e9ec624c13edf --- /dev/null +++ b/src/test/run-pass/parse-complex-macro-invoc-op.rs @@ -0,0 +1,43 @@ +// 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. + +// Test parsing binary operators after macro invocations. + +#![feature(macro_rules)] + +macro_rules! id { + ($e: expr) => { $e } +} + +fn foo() { + id!(1i) + 1; + id![1i] - 1; + id!(1i) * 1; + id![1i] / 1; + id!(1i) % 1; + + id!(1i) & 1; + id![1i] | 1; + id!(1i) ^ 1; + + let mut x = 1i; + id![x] = 2; + id!(x) += 1; + + id!(1f64).clone(); + + id!([1i, 2, 3])[1]; + id![drop](1i); + + id!(true) && true; + id![true] || true; +} + +fn main() {} From 399579785cda1bceb1a0b0848dc1d713d948166d Mon Sep 17 00:00:00 2001 From: Sean T Allen Date: Sat, 3 Jan 2015 12:26:03 -0500 Subject: [PATCH 010/106] Minor documentation edit. Number of rustc calls would depending on various circumstances. Two is misleading. --- src/doc/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/guide.md b/src/doc/guide.md index 55465651cfb4b..ed49cc5bb39ce 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -354,7 +354,7 @@ Hello, world! Bam! We build our project with `cargo build`, and run it with `./target/hello_world`. This hasn't bought us a whole lot over our simple use of `rustc`, but think about the future: when our project has more than one -file, we would need to call `rustc` twice, and pass it a bunch of options to +file, we would need to call `rustc` more than once, and pass it a bunch of options to tell it to build everything together. With Cargo, as our project grows, we can just `cargo build` and it'll work the right way. From 053698686550852ffa6be622697baf314d2bb4b4 Mon Sep 17 00:00:00 2001 From: Sean T Allen Date: Sat, 3 Jan 2015 13:00:38 -0500 Subject: [PATCH 011/106] Minor documentation edit. A tuple could be more made up of more than 2 values. Update guide to reflect. --- src/doc/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/guide.md b/src/doc/guide.md index ed49cc5bb39ce..cde1167982ded 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -978,7 +978,7 @@ fn main() { ``` Even though Rust functions can only return one value, a tuple _is_ one value, -that happens to be made up of two. You can also see in this example how you +that happens to be made up of more than one value. You can also see in this example how you can destructure a pattern returned by a function, as well. Tuples are a very simple data structure, and so are not often what you want. From a2c2cb942ebb443bfbc864a4606cc2784c850882 Mon Sep 17 00:00:00 2001 From: ville-h Date: Sat, 3 Jan 2015 23:22:09 +0200 Subject: [PATCH 012/106] rename std::sync::RWLock to RwLock --- src/libstd/sync/rwlock.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 431aeb9cae9f8..af102fc74025a 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -59,13 +59,13 @@ use sys_common::rwlock as sys; /// } // write lock is dropped here /// ``` #[stable] -pub struct RWLock { +pub struct RwLock { inner: Box, data: UnsafeCell, } -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} /// Structure representing a statically allocated RWLock. /// @@ -127,11 +127,11 @@ pub struct RWLockWriteGuard<'a, T: 'a> { __marker: marker::NoSend, } -impl RWLock { +impl RwLock { /// Creates a new instance of an RWLock which is unlocked and read to go. #[stable] - pub fn new(t: T) -> RWLock { - RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } + pub fn new(t: T) -> RwLock { + RwLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } } /// Locks this rwlock with shared read access, blocking the current thread @@ -228,7 +228,7 @@ impl RWLock { } #[unsafe_destructor] -impl Drop for RWLock { +impl Drop for RwLock { fn drop(&mut self) { unsafe { self.inner.lock.destroy() } } From b2ab5d7658435f8710acc0b0a99ce858af36bd9a Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 01:58:35 +0200 Subject: [PATCH 013/106] fix code and comments referencing RwLock --- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/rwlock.rs | 62 +++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index c09c3b45d3e26..3410976a6e451 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -21,7 +21,7 @@ pub use alloc::arc::{Arc, Weak}; pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; -pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT}; +pub use self::rwlock::{RwLock, StaticRWLock, RWLOCK_INIT}; pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index af102fc74025a..087281d6ce6d6 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -31,17 +31,17 @@ use sys_common::rwlock as sys; /// /// # Poisoning /// -/// RWLocks, like Mutexes, will become poisoned on panics. Note, however, that -/// an RWLock may only be poisoned if a panic occurs while it is locked +/// RwLocks, like Mutexes, will become poisoned on panics. Note, however, that +/// an RwLock may only be poisoned if a panic occurs while it is locked /// exclusively (write mode). If a panic occurs in any reader, then the lock /// will not be poisoned. /// /// # Examples /// /// ``` -/// use std::sync::RWLock; +/// use std::sync::RwLock; /// -/// let lock = RWLock::new(5i); +/// let lock = RwLock::new(5i); /// /// // many reader locks can be held at once /// { @@ -67,11 +67,11 @@ pub struct RwLock { unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} -/// Structure representing a statically allocated RWLock. +/// Structure representing a statically allocated RwLock. /// /// This structure is intended to be used inside of a `static` and will provide /// automatic global access as well as lazy initialization. The internal -/// resources of this RWLock, however, must be manually deallocated. +/// resources of this RwLock, however, must be manually deallocated. /// /// # Example /// @@ -90,7 +90,7 @@ unsafe impl Sync for RwLock {} /// } /// unsafe { LOCK.destroy() } // free all resources /// ``` -#[unstable = "may be merged with RWLock in the future"] +#[unstable = "may be merged with RwLock in the future"] pub struct StaticRWLock { lock: sys::RWLock, poison: poison::Flag, @@ -100,7 +100,7 @@ unsafe impl Send for StaticRWLock {} unsafe impl Sync for StaticRWLock {} /// Constant initialization for a statically-initialized rwlock. -#[unstable = "may be merged with RWLock in the future"] +#[unstable = "may be merged with RwLock in the future"] pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { lock: sys::RWLOCK_INIT, poison: poison::FLAG_INIT, @@ -128,7 +128,7 @@ pub struct RWLockWriteGuard<'a, T: 'a> { } impl RwLock { - /// Creates a new instance of an RWLock which is unlocked and read to go. + /// Creates a new instance of an RwLock which is unlocked and read to go. #[stable] pub fn new(t: T) -> RwLock { RwLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } @@ -148,7 +148,7 @@ impl RwLock { /// /// # Failure /// - /// This function will return an error if the RWLock is poisoned. An RWLock + /// This function will return an error if the RwLock is poisoned. An RwLock /// is poisoned whenever a writer panics while holding an exclusive lock. /// The failure will occur immediately after the lock has been acquired. #[inline] @@ -169,7 +169,7 @@ impl RwLock { /// /// # Failure /// - /// This function will return an error if the RWLock is poisoned. An RWLock + /// This function will return an error if the RwLock is poisoned. An RwLock /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. @@ -194,7 +194,7 @@ impl RwLock { /// /// # Failure /// - /// This function will return an error if the RWLock is poisoned. An RWLock + /// This function will return an error if the RwLock is poisoned. An RwLock /// is poisoned whenever a writer panics while holding an exclusive lock. /// An error will be returned when the lock is acquired. #[inline] @@ -212,7 +212,7 @@ impl RwLock { /// /// # Failure /// - /// This function will return an error if the RWLock is poisoned. An RWLock + /// This function will return an error if the RwLock is poisoned. An RwLock /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. @@ -242,9 +242,9 @@ impl StaticRWLock { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. /// - /// See `RWLock::read`. + /// See `RwLock::read`. #[inline] - #[unstable = "may be merged with RWLock in the future"] + #[unstable = "may be merged with RwLock in the future"] pub fn read(&'static self) -> LockResult> { unsafe { self.lock.read() } RWLockReadGuard::new(self, &DUMMY.0) @@ -252,9 +252,9 @@ impl StaticRWLock { /// Attempt to acquire this lock with shared read access. /// - /// See `RWLock::try_read`. + /// See `RwLock::try_read`. #[inline] - #[unstable = "may be merged with RWLock in the future"] + #[unstable = "may be merged with RwLock in the future"] pub fn try_read(&'static self) -> TryLockResult> { if unsafe { self.lock.try_read() } { @@ -267,9 +267,9 @@ impl StaticRWLock { /// Lock this rwlock with exclusive write access, blocking the current /// thread until it can be acquired. /// - /// See `RWLock::write`. + /// See `RwLock::write`. #[inline] - #[unstable = "may be merged with RWLock in the future"] + #[unstable = "may be merged with RwLock in the future"] pub fn write(&'static self) -> LockResult> { unsafe { self.lock.write() } RWLockWriteGuard::new(self, &DUMMY.0) @@ -277,9 +277,9 @@ impl StaticRWLock { /// Attempt to lock this rwlock with exclusive write access. /// - /// See `RWLock::try_write`. + /// See `RwLock::try_write`. #[inline] - #[unstable = "may be merged with RWLock in the future"] + #[unstable = "may be merged with RwLock in the future"] pub fn try_write(&'static self) -> TryLockResult> { if unsafe { self.lock.try_write() } { @@ -295,7 +295,7 @@ impl StaticRWLock { /// active users of the lock, and this also doesn't prevent any future users /// of this lock. This method is required to be called to not leak memory on /// all platforms. - #[unstable = "may be merged with RWLock in the future"] + #[unstable = "may be merged with RwLock in the future"] pub unsafe fn destroy(&'static self) { self.lock.destroy() } @@ -365,11 +365,11 @@ mod tests { use rand::{mod, Rng}; use sync::mpsc::channel; use thread::Thread; - use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT}; + use sync::{Arc, RwLock, StaticRWLock, RWLOCK_INIT}; #[test] fn smoke() { - let l = RWLock::new(()); + let l = RwLock::new(()); drop(l.read().unwrap()); drop(l.write().unwrap()); drop((l.read().unwrap(), l.read().unwrap())); @@ -414,7 +414,7 @@ mod tests { #[test] fn test_rw_arc_poison_wr() { - let arc = Arc::new(RWLock::new(1i)); + let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); let _: Result = Thread::spawn(move|| { let _lock = arc2.write().unwrap(); @@ -425,7 +425,7 @@ mod tests { #[test] fn test_rw_arc_poison_ww() { - let arc = Arc::new(RWLock::new(1i)); + let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); let _: Result = Thread::spawn(move|| { let _lock = arc2.write().unwrap(); @@ -436,7 +436,7 @@ mod tests { #[test] fn test_rw_arc_no_poison_rr() { - let arc = Arc::new(RWLock::new(1i)); + let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); let _: Result = Thread::spawn(move|| { let _lock = arc2.read().unwrap(); @@ -447,7 +447,7 @@ mod tests { } #[test] fn test_rw_arc_no_poison_rw() { - let arc = Arc::new(RWLock::new(1i)); + let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); let _: Result = Thread::spawn(move|| { let _lock = arc2.read().unwrap(); @@ -459,7 +459,7 @@ mod tests { #[test] fn test_rw_arc() { - let arc = Arc::new(RWLock::new(0i)); + let arc = Arc::new(RwLock::new(0i)); let arc2 = arc.clone(); let (tx, rx) = channel(); @@ -497,11 +497,11 @@ mod tests { #[test] fn test_rw_arc_access_in_unwind() { - let arc = Arc::new(RWLock::new(1i)); + let arc = Arc::new(RwLock::new(1i)); let arc2 = arc.clone(); let _ = Thread::spawn(move|| -> () { struct Unwinder { - i: Arc>, + i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { From fedbde66239d4a7a7551938975d4e3894d778332 Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 02:03:09 +0200 Subject: [PATCH 014/106] rename std::sync::StaticRWLock to StaticRwLock --- src/libstd/sync/rwlock.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 087281d6ce6d6..5743386e055a6 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -91,13 +91,13 @@ unsafe impl Sync for RwLock {} /// unsafe { LOCK.destroy() } // free all resources /// ``` #[unstable = "may be merged with RwLock in the future"] -pub struct StaticRWLock { +pub struct StaticRwLock { lock: sys::RWLock, poison: poison::Flag, } -unsafe impl Send for StaticRWLock {} -unsafe impl Sync for StaticRWLock {} +unsafe impl Send for StaticRwLock {} +unsafe impl Sync for StaticRwLock {} /// Constant initialization for a statically-initialized rwlock. #[unstable = "may be merged with RwLock in the future"] @@ -238,7 +238,7 @@ struct Dummy(UnsafeCell<()>); unsafe impl Sync for Dummy {} static DUMMY: Dummy = Dummy(UnsafeCell { value: () }); -impl StaticRWLock { +impl StaticRwLock { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. /// From 144f4b88ac338add740009626b91f278030f660b Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sun, 23 Nov 2014 16:20:26 +1100 Subject: [PATCH 015/106] Update influence list --- src/doc/reference.md | 89 +++++++++++--------------------------------- 1 file changed, 22 insertions(+), 67 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 8c2c5ab7b8580..94207677dd3a9 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -4316,73 +4316,28 @@ fine-grained control is desired over the output format of a Rust crate. *TODO*. -# Appendix: Influences and further references - -## Influences - -> The essential problem that must be solved in making a fault-tolerant -> software system is therefore that of fault-isolation. Different programmers -> will write different modules, some modules will be correct, others will have -> errors. We do not want the errors in one module to adversely affect the -> behaviour of a module which does not have any errors. -> -> — Joe Armstrong - -> In our approach, all data is private to some process, and processes can -> only communicate through communications channels. *Security*, as used -> in this paper, is the property which guarantees that processes in a system -> cannot affect each other except by explicit communication. -> -> When security is absent, nothing which can be proven about a single module -> in isolation can be guaranteed to hold when that module is embedded in a -> system [...] -> -> — Robert Strom and Shaula Yemini - -> Concurrent and applicative programming complement each other. The -> ability to send messages on channels provides I/O without side effects, -> while the avoidance of shared data helps keep concurrent processes from -> colliding. -> -> — Rob Pike - -Rust is not a particularly original language. It may however appear unusual by -contemporary standards, as its design elements are drawn from a number of -"historical" languages that have, with a few exceptions, fallen out of favour. -Five prominent lineages contribute the most, though their influences have come -and gone during the course of Rust's development: - -* The NIL (1981) and Hermes (1990) family. These languages were developed by - Robert Strom, Shaula Yemini, David Bacon and others in their group at IBM - Watson Research Center (Yorktown Heights, NY, USA). - -* The Erlang (1987) language, developed by Joe Armstrong, Robert Virding, Claes - Wikström, Mike Williams and others in their group at the Ericsson Computer - Science Laboratory (Älvsjö, Stockholm, Sweden) . - -* The Sather (1990) language, developed by Stephen Omohundro, Chu-Cheow Lim, - Heinz Schmidt and others in their group at The International Computer - Science Institute of the University of California, Berkeley (Berkeley, CA, - USA). - -* The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These - languages were developed by Rob Pike, Phil Winterbottom, Sean Dorward and - others in their group at Bell Labs Computing Sciences Research Center - (Murray Hill, NJ, USA). - -* The Napier (1985) and Napier88 (1988) family. These languages were - developed by Malcolm Atkinson, Ron Morrison and others in their group at - the University of St. Andrews (St. Andrews, Fife, UK). - -Additional specific influences can be seen from the following languages: - -* The structural algebraic types and compilation manager of SML. -* The attribute and assembly systems of C#. -* The references and deterministic destructor system of C++. -* The memory region systems of the ML Kit and Cyclone. -* The typeclass system of Haskell. -* The lexical identifier rule of Python. -* The block syntax of Ruby. +# Appendix: Influences + +Rust is not a particularly original language, with design elements coming from +a wide range of sources. Some of these are listed below (including elements +that have since been removed): + +* SML, OCaml: algebraic datatypes, pattern matching, type inference, + semicolon statement separation +* C++: references, RAII, smart pointers, move semantics, monomorphisation, + memory model +* ML Kit, Cyclone: region based memory management +* Haskell (GHC): typeclasses, type families +* Newsqueak, Alef, Limbo: channels, concurrency +* Erlang: message passing, task failure, ~~linked task failure~~, + ~~lightweight concurrency~~ +* Swift: optional bindings +* Scheme: hygienic macros +* C#: attributes +* Ruby: ~~block syntax~~ +* NIL, Hermes: ~~typestate~~ +* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and + pattern syntax [ffi]: guide-ffi.html [plugin]: guide-plugin.html From 8cebb1f64498508e1fc940d885ad05d7a2fb4089 Mon Sep 17 00:00:00 2001 From: Chase Southwood Date: Sun, 4 Jan 2015 00:09:18 -0600 Subject: [PATCH 016/106] Rename `raw_pointer_deriving` lint to `raw_pointer_derive` Due to the `#[deriving]` -> `#[derive]` switch. --- src/librustc/lint/builtin.rs | 22 +++++++++---------- src/librustc/lint/context.rs | 3 ++- ...ptr-deriving.rs => lint-raw-ptr-derive.rs} | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) rename src/test/compile-fail/{lint-raw-ptr-deriving.rs => lint-raw-ptr-derive.rs} (97%) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 53249c724627e..e44e3154d3df1 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -550,20 +550,20 @@ impl LintPass for BoxPointers { } declare_lint! { - RAW_POINTER_DERIVING, + RAW_POINTER_DERIVE, Warn, "uses of #[derive] with raw pointers are rarely correct" } -struct RawPtrDerivingVisitor<'a, 'tcx: 'a> { +struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { cx: &'a Context<'a, 'tcx> } -impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDerivingVisitor<'a, 'tcx> { +impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { static MSG: &'static str = "use of `#[derive]` with a raw pointer"; if let ast::TyPtr(..) = ty.node { - self.cx.span_lint(RAW_POINTER_DERIVING, ty.span, MSG); + self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG); } visit::walk_ty(self, ty); } @@ -572,21 +572,21 @@ impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDerivingVisitor<'a, 'tcx> { fn visit_block(&mut self, _: &ast::Block) {} } -pub struct RawPointerDeriving { +pub struct RawPointerDerive { checked_raw_pointers: NodeSet, } -impl RawPointerDeriving { - pub fn new() -> RawPointerDeriving { - RawPointerDeriving { +impl RawPointerDerive { + pub fn new() -> RawPointerDerive { + RawPointerDerive { checked_raw_pointers: NodeSet::new(), } } } -impl LintPass for RawPointerDeriving { +impl LintPass for RawPointerDerive { fn get_lints(&self) -> LintArray { - lint_array!(RAW_POINTER_DERIVING) + lint_array!(RAW_POINTER_DERIVE) } fn check_item(&mut self, cx: &Context, item: &ast::Item) { @@ -611,7 +611,7 @@ impl LintPass for RawPointerDeriving { if !self.checked_raw_pointers.insert(item.id) { return } match item.node { ast::ItemStruct(..) | ast::ItemEnum(..) => { - let mut visitor = RawPtrDerivingVisitor { cx: cx }; + let mut visitor = RawPtrDeriveVisitor { cx: cx }; visit::walk_item(&mut visitor, &*item); } _ => {} diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index ffae485364a86..9cf4ae9d467b0 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -208,7 +208,7 @@ impl LintStore { add_builtin_with_new!(sess, TypeLimits, - RawPointerDeriving, + RawPointerDerive, MissingDoc, ); @@ -247,6 +247,7 @@ impl LintStore { self.register_renamed("unknown_crate_type", "unknown_crate_types"); self.register_renamed("variant_size_difference", "variant_size_differences"); self.register_renamed("transmute_fat_ptr", "fat_ptr_transmutes"); + self.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); } diff --git a/src/test/compile-fail/lint-raw-ptr-deriving.rs b/src/test/compile-fail/lint-raw-ptr-derive.rs similarity index 97% rename from src/test/compile-fail/lint-raw-ptr-deriving.rs rename to src/test/compile-fail/lint-raw-ptr-derive.rs index 6fe8862d77e58..3198e782df893 100644 --- a/src/test/compile-fail/lint-raw-ptr-deriving.rs +++ b/src/test/compile-fail/lint-raw-ptr-derive.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(dead_code)] -#![deny(raw_pointer_deriving)] +#![deny(raw_pointer_derive)] #[derive(Clone)] struct Foo { From 817f75d2fbc15dd152c9473e012ec5271cb5e94b Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 08:59:06 +0200 Subject: [PATCH 017/106] fix code and comments referencing StaticRwLock --- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/rwlock.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 3410976a6e451..0e2b0a441e69e 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -21,7 +21,7 @@ pub use alloc::arc::{Arc, Weak}; pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; -pub use self::rwlock::{RwLock, StaticRWLock, RWLOCK_INIT}; +pub use self::rwlock::{RwLock, StaticRwLock, RWLOCK_INIT}; pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 5743386e055a6..04efbf893ea02 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -60,7 +60,7 @@ use sys_common::rwlock as sys; /// ``` #[stable] pub struct RwLock { - inner: Box, + inner: Box, data: UnsafeCell, } @@ -76,9 +76,9 @@ unsafe impl Sync for RwLock {} /// # Example /// /// ``` -/// use std::sync::{StaticRWLock, RWLOCK_INIT}; +/// use std::sync::{StaticRwLock, RWLOCK_INIT}; /// -/// static LOCK: StaticRWLock = RWLOCK_INIT; +/// static LOCK: StaticRwLock = RWLOCK_INIT; /// /// { /// let _g = LOCK.read().unwrap(); @@ -101,7 +101,7 @@ unsafe impl Sync for StaticRwLock {} /// Constant initialization for a statically-initialized rwlock. #[unstable = "may be merged with RwLock in the future"] -pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { +pub const RWLOCK_INIT: StaticRwLock = StaticRwLock { lock: sys::RWLOCK_INIT, poison: poison::FLAG_INIT, }; @@ -111,7 +111,7 @@ pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { #[must_use] #[stable] pub struct RWLockReadGuard<'a, T: 'a> { - __lock: &'a StaticRWLock, + __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __marker: marker::NoSend, } @@ -121,7 +121,7 @@ pub struct RWLockReadGuard<'a, T: 'a> { #[must_use] #[stable] pub struct RWLockWriteGuard<'a, T: 'a> { - __lock: &'a StaticRWLock, + __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __poison: poison::Guard, __marker: marker::NoSend, @@ -302,7 +302,7 @@ impl StaticRwLock { } impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { - fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) + fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |_| { RWLockReadGuard { @@ -314,7 +314,7 @@ impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { } } impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { - fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) + fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { RWLockWriteGuard { @@ -365,7 +365,7 @@ mod tests { use rand::{mod, Rng}; use sync::mpsc::channel; use thread::Thread; - use sync::{Arc, RwLock, StaticRWLock, RWLOCK_INIT}; + use sync::{Arc, RwLock, StaticRwLock, RWLOCK_INIT}; #[test] fn smoke() { @@ -378,7 +378,7 @@ mod tests { #[test] fn static_smoke() { - static R: StaticRWLock = RWLOCK_INIT; + static R: StaticRwLock = RWLOCK_INIT; drop(R.read().unwrap()); drop(R.write().unwrap()); drop((R.read().unwrap(), R.read().unwrap())); @@ -388,7 +388,7 @@ mod tests { #[test] fn frob() { - static R: StaticRWLock = RWLOCK_INIT; + static R: StaticRwLock = RWLOCK_INIT; static N: uint = 10; static M: uint = 1000; From 5344ae2d4f66f5e8392b325320eeec0af29f503c Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 09:03:27 +0200 Subject: [PATCH 018/106] rename std::sync::RWLOCK_INIT to RW_LOCK_INIT --- src/libstd/sync/rwlock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 04efbf893ea02..7b67383833976 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -101,7 +101,7 @@ unsafe impl Sync for StaticRwLock {} /// Constant initialization for a statically-initialized rwlock. #[unstable = "may be merged with RwLock in the future"] -pub const RWLOCK_INIT: StaticRwLock = StaticRwLock { +pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock { lock: sys::RWLOCK_INIT, poison: poison::FLAG_INIT, }; From c3dcf9b6bf7b3de4b7b4f51725f2ab814cbdfd38 Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 10:57:05 +0200 Subject: [PATCH 019/106] fix code and comments referencing RW_LOCK_INIT --- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/rwlock.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 0e2b0a441e69e..3bb0e257577cf 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -21,7 +21,7 @@ pub use alloc::arc::{Arc, Weak}; pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; -pub use self::rwlock::{RwLock, StaticRwLock, RWLOCK_INIT}; +pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT}; pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 7b67383833976..f6fffd49deea0 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -76,9 +76,9 @@ unsafe impl Sync for RwLock {} /// # Example /// /// ``` -/// use std::sync::{StaticRwLock, RWLOCK_INIT}; +/// use std::sync::{StaticRwLock, RW_LOCK_INIT}; /// -/// static LOCK: StaticRwLock = RWLOCK_INIT; +/// static LOCK: StaticRwLock = RW_LOCK_INIT; /// /// { /// let _g = LOCK.read().unwrap(); @@ -131,7 +131,7 @@ impl RwLock { /// Creates a new instance of an RwLock which is unlocked and read to go. #[stable] pub fn new(t: T) -> RwLock { - RwLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } + RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) } } /// Locks this rwlock with shared read access, blocking the current thread @@ -365,7 +365,7 @@ mod tests { use rand::{mod, Rng}; use sync::mpsc::channel; use thread::Thread; - use sync::{Arc, RwLock, StaticRwLock, RWLOCK_INIT}; + use sync::{Arc, RwLock, StaticRwLock, RW_LOCK_INIT}; #[test] fn smoke() { @@ -378,7 +378,7 @@ mod tests { #[test] fn static_smoke() { - static R: StaticRwLock = RWLOCK_INIT; + static R: StaticRwLock = RW_LOCK_INIT; drop(R.read().unwrap()); drop(R.write().unwrap()); drop((R.read().unwrap(), R.read().unwrap())); @@ -388,7 +388,7 @@ mod tests { #[test] fn frob() { - static R: StaticRwLock = RWLOCK_INIT; + static R: StaticRwLock = RW_LOCK_INIT; static N: uint = 10; static M: uint = 1000; From 2dcbdc1edac50af0f1a2796b1dfe2dd082f8190c Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 11:43:14 +0200 Subject: [PATCH 020/106] rename std::sync::RWLockReadGuard to RwLockReadGuard --- src/libstd/sync/rwlock.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index f6fffd49deea0..37b9f5dc68dd3 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -110,7 +110,7 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock { /// dropped. #[must_use] #[stable] -pub struct RWLockReadGuard<'a, T: 'a> { +pub struct RwLockReadGuard<'a, T: 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __marker: marker::NoSend, @@ -301,11 +301,11 @@ impl StaticRwLock { } } -impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { +impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) - -> LockResult> { + -> LockResult> { poison::map_result(lock.poison.borrow(), |_| { - RWLockReadGuard { + RwLockReadGuard { __lock: lock, __data: data, __marker: marker::NoSend, @@ -327,7 +327,7 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { } } -impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } @@ -344,7 +344,7 @@ impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { } #[unsafe_destructor] -impl<'a, T> Drop for RWLockReadGuard<'a, T> { +impl<'a, T> Drop for RwLockReadGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.lock.read_unlock(); } } From 956cab6f97c1841e6f3f00acb6386f07eddfc25e Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 11:45:31 +0200 Subject: [PATCH 021/106] fix code referencing RwLockReadGuard --- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/rwlock.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 3bb0e257577cf..71ff3c7d17221 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -22,7 +22,7 @@ pub use alloc::arc::{Arc, Weak}; pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT}; -pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; +pub use self::rwlock::{RwLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 37b9f5dc68dd3..0a8bf6f0aa79e 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -153,9 +153,9 @@ impl RwLock { /// The failure will occur immediately after the lock has been acquired. #[inline] #[stable] - pub fn read(&self) -> LockResult> { + pub fn read(&self) -> LockResult> { unsafe { self.inner.lock.read() } - RWLockReadGuard::new(&*self.inner, &self.data) + RwLockReadGuard::new(&*self.inner, &self.data) } /// Attempt to acquire this lock with shared read access. @@ -175,9 +175,9 @@ impl RwLock { /// acquired. #[inline] #[stable] - pub fn try_read(&self) -> TryLockResult> { + pub fn try_read(&self) -> TryLockResult> { if unsafe { self.inner.lock.try_read() } { - Ok(try!(RWLockReadGuard::new(&*self.inner, &self.data))) + Ok(try!(RwLockReadGuard::new(&*self.inner, &self.data))) } else { Err(TryLockError::WouldBlock) } @@ -245,9 +245,9 @@ impl StaticRwLock { /// See `RwLock::read`. #[inline] #[unstable = "may be merged with RwLock in the future"] - pub fn read(&'static self) -> LockResult> { + pub fn read(&'static self) -> LockResult> { unsafe { self.lock.read() } - RWLockReadGuard::new(self, &DUMMY.0) + RwLockReadGuard::new(self, &DUMMY.0) } /// Attempt to acquire this lock with shared read access. @@ -256,9 +256,9 @@ impl StaticRwLock { #[inline] #[unstable = "may be merged with RwLock in the future"] pub fn try_read(&'static self) - -> TryLockResult> { + -> TryLockResult> { if unsafe { self.lock.try_read() } { - Ok(try!(RWLockReadGuard::new(self, &DUMMY.0))) + Ok(try!(RwLockReadGuard::new(self, &DUMMY.0))) } else { Err(TryLockError::WouldBlock) } From 98e6d12017da5e323612108c81accb1f437f7137 Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 12:36:27 +0200 Subject: [PATCH 022/106] rename std::sync::RWLockWriteGuard to RwLockWriteGuard --- src/libstd/sync/rwlock.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 0a8bf6f0aa79e..6c2def11ce519 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -120,7 +120,7 @@ pub struct RwLockReadGuard<'a, T: 'a> { /// dropped. #[must_use] #[stable] -pub struct RWLockWriteGuard<'a, T: 'a> { +pub struct RwLockWriteGuard<'a, T: 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __poison: poison::Guard, @@ -313,11 +313,11 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { }) } } -impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) - -> LockResult> { + -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { - RWLockWriteGuard { + RwLockWriteGuard { __lock: lock, __data: data, __poison: guard, @@ -332,12 +332,12 @@ impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> { fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> Deref for RwLockWriteGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { +impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } } @@ -351,7 +351,7 @@ impl<'a, T> Drop for RwLockReadGuard<'a, T> { } #[unsafe_destructor] -impl<'a, T> Drop for RWLockWriteGuard<'a, T> { +impl<'a, T> Drop for RwLockWriteGuard<'a, T> { fn drop(&mut self) { self.__lock.poison.done(&self.__poison); unsafe { self.__lock.lock.write_unlock(); } From 44b3ddef8df7fa5392ce3608cbe1977f119337ee Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 13:12:17 +0200 Subject: [PATCH 023/106] fix code referencing RwLockWriteGuard --- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/rwlock.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 71ff3c7d17221..a2e1eb6c65ace 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -22,7 +22,7 @@ pub use alloc::arc::{Arc, Weak}; pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; pub use self::mutex::MUTEX_INIT; pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT}; -pub use self::rwlock::{RwLockReadGuard, RWLockWriteGuard}; +pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 6c2def11ce519..bc068d0e63702 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -199,9 +199,9 @@ impl RwLock { /// An error will be returned when the lock is acquired. #[inline] #[stable] - pub fn write(&self) -> LockResult> { + pub fn write(&self) -> LockResult> { unsafe { self.inner.lock.write() } - RWLockWriteGuard::new(&*self.inner, &self.data) + RwLockWriteGuard::new(&*self.inner, &self.data) } /// Attempt to lock this rwlock with exclusive write access. @@ -218,9 +218,9 @@ impl RwLock { /// acquired. #[inline] #[stable] - pub fn try_write(&self) -> TryLockResult> { + pub fn try_write(&self) -> TryLockResult> { if unsafe { self.inner.lock.try_read() } { - Ok(try!(RWLockWriteGuard::new(&*self.inner, &self.data))) + Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data))) } else { Err(TryLockError::WouldBlock) } @@ -270,9 +270,9 @@ impl StaticRwLock { /// See `RwLock::write`. #[inline] #[unstable = "may be merged with RwLock in the future"] - pub fn write(&'static self) -> LockResult> { + pub fn write(&'static self) -> LockResult> { unsafe { self.lock.write() } - RWLockWriteGuard::new(self, &DUMMY.0) + RwLockWriteGuard::new(self, &DUMMY.0) } /// Attempt to lock this rwlock with exclusive write access. @@ -281,9 +281,9 @@ impl StaticRwLock { #[inline] #[unstable = "may be merged with RwLock in the future"] pub fn try_write(&'static self) - -> TryLockResult> { + -> TryLockResult> { if unsafe { self.lock.try_write() } { - Ok(try!(RWLockWriteGuard::new(self, &DUMMY.0))) + Ok(try!(RwLockWriteGuard::new(self, &DUMMY.0))) } else { Err(TryLockError::WouldBlock) } From fee1f2ade962c913ba2da81f7a97ab39c6f66989 Mon Sep 17 00:00:00 2001 From: ville-h Date: Sun, 4 Jan 2015 13:26:25 +0200 Subject: [PATCH 024/106] fix comment referencing RwLock --- src/libstd/sync/poison.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index 6e4df1182091f..385df45b400c4 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -49,7 +49,7 @@ pub struct Guard { /// A type of error which can be returned whenever a lock is acquired. /// -/// Both Mutexes and RWLocks are poisoned whenever a task fails while the lock +/// Both Mutexes and RwLocks are poisoned whenever a task fails while the lock /// is held. The precise semantics for when a lock is poisoned is documented on /// each lock, but once a lock is poisoned then all future acquisitions will /// return this error. From e723fe07783cd9b797c9f1456d359879bba44907 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 4 Jan 2015 14:58:08 +0200 Subject: [PATCH 025/106] Do not use entropy during gen_weighted_bool(1) 1 in 1 chance to return true always results in true. --- src/librand/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0f8dbc78cde32..18f508e816f2b 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -243,7 +243,7 @@ pub trait Rng : Sized { /// println!("{}", rng.gen_weighted_bool(3)); /// ``` fn gen_weighted_bool(&mut self, n: uint) -> bool { - n == 0 || self.gen_range(0, n) == 0 + n <= 1 || self.gen_range(0, n) == 0 } /// Return an iterator of random characters from the set A-Z,a-z,0-9. From 9b820d0d634483e5400b1da52340a0606a32c84a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 4 Jan 2015 05:22:59 -0500 Subject: [PATCH 026/106] Correct the subtyping relations created by the pattern typechecking code. Previously we were creating a subtyping relation in the wrong direction. We now just unify types, which is stronger than necessary but turns out fine. Fixes #19552. Fixes #19997. --- src/librustc_typeck/check/_match.rs | 108 ++++++++++++++++-- .../regions-pattern-typing-issue-19552.rs | 18 +++ .../regions-pattern-typing-issue-19997.rs | 20 ++++ .../regions-reassign-let-bound-pointer.rs | 23 ++++ .../regions-reassign-match-bound-pointer.rs | 26 +++++ ...ions-on-closures-to-inference-variables.rs | 65 +++++++++++ 6 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/regions-pattern-typing-issue-19552.rs create mode 100644 src/test/compile-fail/regions-pattern-typing-issue-19997.rs create mode 100644 src/test/run-pass/regions-reassign-let-bound-pointer.rs create mode 100644 src/test/run-pass/regions-reassign-match-bound-pointer.rs create mode 100644 src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 7c431b4fc0bd0..d0fd5732f233d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -46,6 +46,19 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_expr(fcx, &**lt); let expr_ty = fcx.expr_ty(&**lt); fcx.write_ty(pat.id, expr_ty); + + // somewhat surprising: in this case, the subtyping + // relation goes the opposite way as the other + // cases. Actually what we really want is not a subtyping + // relation at all but rather that there exists a LUB (so + // that they can be compared). However, in practice, + // constants are always scalars or strings. For scalars + // subtyping is irrelevant, and for strings `expr_ty` is + // type is `&'static str`, so if we say that + // + // &'static str <: expected + // + // that's equivalent to there existing a LUB. demand::suptype(fcx, pat.span, expected, expr_ty); } ast::PatRange(ref begin, ref end) => { @@ -54,10 +67,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let lhs_ty = fcx.expr_ty(&**begin); let rhs_ty = fcx.expr_ty(&**end); - if require_same_types( - tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty, - || "mismatched types in range".to_string()) - && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(rhs_ty)) { + + let lhs_eq_rhs = + require_same_types( + tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty, + || "mismatched types in range".to_string()); + + let numeric_or_char = + lhs_eq_rhs && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(lhs_ty)); + + if numeric_or_char { match valid_range_bounds(fcx.ccx, &**begin, &**end) { Some(false) => { span_err!(tcx.sess, begin.span, E0030, @@ -75,6 +94,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } fcx.write_ty(pat.id, lhs_ty); + + // subtyping doens't matter here, as the value is some kind of scalar demand::eqtype(fcx, pat.span, expected, lhs_ty); } ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => { @@ -89,20 +110,29 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ast::BindByRef(mutbl) => { // if the binding is like // ref x | ref const x | ref mut x - // then the type of x is &M T where M is the mutability - // and T is the expected type + // then `x` is assigned a value of type `&M T` where M is the mutability + // and T is the expected type. let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); let mt = ty::mt { ty: expected, mutbl: mutbl }; let region_ty = ty::mk_rptr(tcx, tcx.mk_region(region_var), mt); + + // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is + // required. However, we use equality, which is stronger. See (*) for + // an explanation. demand::eqtype(fcx, pat.span, region_ty, typ); } // otherwise the type of x is the expected type T ast::BindByValue(_) => { + // As above, `T <: typeof(x)` is required but we + // use equality, see (*) below. demand::eqtype(fcx, pat.span, expected, typ); } } + fcx.write_ty(pat.id, typ); + // if there are multiple arms, make sure they all agree on + // what the type of the binding `x` ought to be let canon_id = pcx.map[path.node]; if canon_id != pat.id { let ct = fcx.local_ty(pat.span, canon_id); @@ -138,7 +168,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let uniq_ty = ty::mk_uniq(tcx, inner_ty); if check_dereferencable(pcx, pat.span, expected, &**inner) { - demand::suptype(fcx, pat.span, expected, uniq_ty); + // Here, `demand::subtype` is good enough, but I don't + // think any errors can be introduced by using + // `demand::eqtype`. + demand::eqtype(fcx, pat.span, expected, uniq_ty); fcx.write_ty(pat.id, uniq_ty); check_pat(pcx, &**inner, inner_ty); } else { @@ -158,7 +191,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let rptr_ty = ty::mk_rptr(tcx, tcx.mk_region(region), mt); if check_dereferencable(pcx, pat.span, expected, &**inner) { - demand::suptype(fcx, pat.span, expected, rptr_ty); + // `demand::subtype` would be good enough, but using + // `eqtype` turns out to be equally general. See (*) + // below for details. + demand::eqtype(fcx, pat.span, expected, rptr_ty); fcx.write_ty(pat.id, rptr_ty); check_pat(pcx, &**inner, inner_ty); } else { @@ -188,7 +224,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, }; fcx.write_ty(pat.id, pat_ty); - demand::suptype(fcx, pat.span, expected, pat_ty); + + // `demand::subtype` would be good enough, but using + // `eqtype` turns out to be equally general. See (*) + // below for details. + demand::eqtype(fcx, pat.span, expected, pat_ty); for elt in before.iter() { check_pat(pcx, &**elt, inner_ty); @@ -210,6 +250,56 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } ast::PatMac(_) => tcx.sess.bug("unexpanded macro") } + + + // (*) In most of the cases above (literals and constants being + // the exception), we relate types using strict equality, evewn + // though subtyping would be sufficient. There are a few reasons + // for this, some of which are fairly subtle and which cost me + // (nmatsakis) an hour or two debugging to remember, so I thought + // I'd write them down this time. + // + // 1. Most importantly, there is no loss of expressiveness + // here. What we are saying is that the type of `x` + // becomes *exactly* what is expected. This might seem + // like it will cause errors in a case like this: + // + // ``` + // fn foo<'x>(x: &'x int) { + // let a = 1; + // let mut z = x; + // z = &a; + // } + // ``` + // + // The reason we might get an error is that `z` might be + // assigned a type like `&'x int`, and then we would have + // a problem when we try to assign `&a` to `z`, because + // the lifetime of `&a` (i.e., the enclosing block) is + // shorter than `'x`. + // + // HOWEVER, this code works fine. The reason is that the + // expected type here is whatever type the user wrote, not + // the initializer's type. In this case the user wrote + // nothing, so we are going to create a type variable `Z`. + // Then we will assign the type of the initializer (`&'x + // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we + // will instantiate `Z` as a type `&'0 int` where `'0` is + // a fresh region variable, with the constraint that `'x : + // '0`. So basically we're all set. + // + // Note that there are two tests to check that this remains true + // (`regions-reassign-{match,let}-bound-pointer.rs`). + // + // 2. Things go horribly wrong if we use subtype. The reason for + // THIS is a fairly subtle case involving bound regions. See the + // `givens` field in `region_inference`, as well as the test + // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, + // for details. Short version is that we must sometimes detect + // relationships between specific region variables and regions + // bound in a closure signature, and that detection gets thrown + // off when we substitute fresh region variables here to enable + // subtyping. } pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs new file mode 100644 index 0000000000000..3f722c9433bb2 --- /dev/null +++ b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs @@ -0,0 +1,18 @@ +// 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. + +fn assert_send(_t: T) {} + +fn main() { + let line = String::new(); + match [line.as_slice()] { //~ ERROR `line` does not live long enough + [ word ] => { assert_send(word); } + } +} diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs new file mode 100644 index 0000000000000..da839d7217261 --- /dev/null +++ b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs @@ -0,0 +1,20 @@ +// 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. + +fn main() { + let a0 = 0u8; + let f = 1u8; + let mut a1 = &a0; + match (&a1,) { + (&ref b0,) => { + a1 = &f; //~ ERROR cannot assign + } + } +} diff --git a/src/test/run-pass/regions-reassign-let-bound-pointer.rs b/src/test/run-pass/regions-reassign-let-bound-pointer.rs new file mode 100644 index 0000000000000..ecf79de622222 --- /dev/null +++ b/src/test/run-pass/regions-reassign-let-bound-pointer.rs @@ -0,0 +1,23 @@ +// 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. + +// Check that the type checker permits us to reassign `z` which +// started out with a longer lifetime and was reassigned to a shorter +// one (it should infer to be the intersection). + +fn foo(x: &int) { + let a = 1; + let mut z = x; + z = &a; +} + +pub fn main() { + foo(&1); +} diff --git a/src/test/run-pass/regions-reassign-match-bound-pointer.rs b/src/test/run-pass/regions-reassign-match-bound-pointer.rs new file mode 100644 index 0000000000000..18312b17339ce --- /dev/null +++ b/src/test/run-pass/regions-reassign-match-bound-pointer.rs @@ -0,0 +1,26 @@ +// 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. + +// Check that the type checker permits us to reassign `z` which +// started out with a longer lifetime and was reassigned to a shorter +// one (it should infer to be the intersection). + +fn foo(x: &int) { + let a = 1; + match x { + mut z => { + z = &a; + } + } +} + +pub fn main() { + foo(&1); +} diff --git a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs new file mode 100644 index 0000000000000..aa0ed023da3e2 --- /dev/null +++ b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs @@ -0,0 +1,65 @@ +// 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. + +// Test that this fairly specialized, but also reasonable, pattern +// typechecks. The pattern involves regions bound in closures that +// wind up related to inference variables. +// +// NB. Changes to the region implementatiosn have broken this pattern +// a few times, but it happens to be used in the compiler so those +// changes were caught. However, those uses in the compiler could +// easily get changed or refactored away in the future. + +struct Ctxt<'tcx> { + x: &'tcx Vec +} + +struct Foo<'a,'tcx:'a> { + cx: &'a Ctxt<'tcx>, +} + +impl<'a,'tcx> Foo<'a,'tcx> { + fn bother(&mut self) -> int { + self.elaborate_bounds(|this| { + // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`, + // where `'f0` and `'f1` are fresh, free regions that + // result from the bound regions on the closure, and `'2` + // is a region inference variable created by the call. Due + // to the constraints on the type, we find that `'_2 : 'f1 + // + 'f2` must hold (and can be assumed by the callee). + // Region inference has to do some clever stuff to avoid + // inferring `'_2` to be `'static` in this case, because + // it is created outside the closure but then related to + // regions bound by the closure itself. See the + // `region_inference.rs` file (and the `givens` field, in + // particular) for more details. + this.foo() + }) + } + + fn foo(&mut self) -> int { + 22 + } + + fn elaborate_bounds( + &mut self, + mk_cand: for<'b>|this: &mut Foo<'b, 'tcx>| -> int) + -> int + { + mk_cand(self) + } +} + +fn main() { + let v = vec!(); + let cx = Ctxt { x: &v }; + let mut foo = Foo { cx: &cx }; + assert_eq!(foo.bother(), 22); // just so the code is not dead, basically +} From a17a7c9f7572685df59e287c48450ccb09e8313a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 4 Jan 2015 05:23:29 -0500 Subject: [PATCH 027/106] Miscellaneous reformatting and commenting. --- src/librustc_typeck/check/_match.rs | 19 +++++++++++-------- src/librustc_typeck/check/demand.rs | 13 ++++++------- src/librustc_typeck/check/mod.rs | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d0fd5732f233d..7ff0e1758f526 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -30,7 +30,9 @@ use syntax::print::pprust; use syntax::ptr::P; pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, - pat: &ast::Pat, expected: Ty<'tcx>) { + pat: &ast::Pat, + expected: Ty<'tcx>) +{ let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; @@ -90,7 +92,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } } else { span_err!(tcx.sess, begin.span, E0029, - "only char and numeric types are allowed in range"); + "only char and numeric types are allowed in range"); } fcx.write_ty(pat.id, lhs_ty); @@ -154,8 +156,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected); } ast::PatTup(ref elements) => { - let element_tys: Vec<_> = range(0, elements.len()).map(|_| fcx.infcx() - .next_ty_var()).collect(); + let element_tys: Vec<_> = + range(0, elements.len()).map(|_| fcx.infcx().next_ty_var()) + .collect(); let pat_ty = ty::mk_tup(tcx, element_tys.clone()); fcx.write_ty(pat.id, pat_ty); demand::eqtype(fcx, pat.span, expected, pat_ty); @@ -183,8 +186,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let inner_ty = fcx.infcx().next_ty_var(); let mutbl = - ty::deref(fcx.infcx().shallow_resolve(expected), true) - .map_or(ast::MutImmutable, |mt| mt.mutbl); + ty::deref(fcx.infcx().shallow_resolve(expected), true).map(|mt| mt.mutbl) + .unwrap_or(ast::MutImmutable); let mt = ty::mt { ty: inner_ty, mutbl: mutbl }; let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); @@ -217,8 +220,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); ty::mk_slice(tcx, tcx.mk_region(region), ty::mt { ty: inner_ty, - mutbl: ty::deref(expected_ty, true) - .map_or(ast::MutImmutable, |mt| mt.mutbl) + mutbl: ty::deref(expected_ty, true).map(|mt| mt.mutbl) + .unwrap_or(ast::MutImmutable) }) } }; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9af9eaf75f5a5..565964012085a 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -18,14 +18,15 @@ use syntax::ast; use syntax::codemap::Span; use util::ppaux::Repr; -// Requires that the two types unify, and prints an error message if they -// don't. +// Requires that the two types unify, and prints an error message if +// they don't. pub fn suptype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, - expected: Ty<'tcx>, actual: Ty<'tcx>) { - suptype_with_fn(fcx, sp, false, expected, actual, + ty_expected: Ty<'tcx>, ty_actual: Ty<'tcx>) { + suptype_with_fn(fcx, sp, false, ty_expected, ty_actual, |sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) }) } +/// As `suptype`, but call `handle_err` if unification for subtyping fails. pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, b_is_expected: bool, @@ -48,9 +49,7 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) { Ok(()) => { /* ok */ } - Err(ref err) => { - fcx.report_mismatched_types(sp, expected, actual, err); - } + Err(ref err) => { fcx.report_mismatched_types(sp, expected, actual, err); } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 82525b71052d2..0a7c406e63172 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4683,7 +4683,7 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> { pub fn check_decl_initializer(fcx: &FnCtxt, nid: ast::NodeId, init: &ast::Expr) - { +{ let local_ty = fcx.local_ty(init.span, nid); check_expr_coercable_to_type(fcx, init, local_ty) } From dbfa05411bad5d31cb594a02ddbf5333dcb0ad5a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 4 Jan 2015 07:23:21 -0500 Subject: [PATCH 028/106] Cleanup type-checking of constants, but do not try to fix #20489. --- src/librustc/middle/ty.rs | 4 ++++ src/librustc_typeck/check/_match.rs | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c720032bef264..0d853295502dc 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1779,6 +1779,10 @@ impl<'tcx> Generics<'tcx> { !self.regions.is_empty_in(space) } + pub fn is_empty(&self) -> bool { + self.types.is_empty() && self.regions.is_empty() + } + pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) -> GenericBounds<'tcx> { GenericBounds { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 7ff0e1758f526..49627120d2291 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -103,8 +103,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => { let const_did = tcx.def_map.borrow()[pat.id].clone().def_id(); let const_scheme = ty::lookup_item_type(tcx, const_did); - fcx.write_ty(pat.id, const_scheme.ty); - demand::suptype(fcx, pat.span, expected, const_scheme.ty); + assert!(const_scheme.generics.is_empty()); + let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, + &Substs::empty(), + &const_scheme.ty); + fcx.write_ty(pat.id, const_ty); + + // FIXME(#20489) -- we should limit the types here to scalars or something! + + // As with PatLit, what we really want here is that there + // exist a LUB, but for the cases that can occur, subtype + // is good enough. + demand::suptype(fcx, pat.span, expected, const_ty); } ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => { let typ = fcx.local_ty(pat.span, pat.id); From cc18053d9c070a65b6b5f686968ebd901c1d60c3 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 5 Jan 2015 03:19:34 +0200 Subject: [PATCH 029/106] bench: do not quit rt-messaging-ping-pong.rs early --- src/test/bench/rt-messaging-ping-pong.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/test/bench/rt-messaging-ping-pong.rs b/src/test/bench/rt-messaging-ping-pong.rs index adf773a2f252c..5ecc580de08d5 100644 --- a/src/test/bench/rt-messaging-ping-pong.rs +++ b/src/test/bench/rt-messaging-ping-pong.rs @@ -35,21 +35,24 @@ fn ping_pong_bench(n: uint, m: uint) { // Create a channel: B->A let (btx, brx) = channel(); - Thread::spawn(move|| { + let guard_a = Thread::spawn(move|| { let (tx, rx) = (atx, brx); for _ in range(0, n) { tx.send(()).unwrap(); rx.recv().unwrap(); } - }).detach(); + }); - Thread::spawn(move|| { + let guard_b = Thread::spawn(move|| { let (tx, rx) = (btx, arx); for _ in range(0, n) { rx.recv().unwrap(); tx.send(()).unwrap(); } - }).detach(); + }); + + guard_a.join().ok(); + guard_b.join().ok(); } for _ in range(0, m) { From c54932cb12b8384060bfe132907ec42cc5c1bbd2 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Fri, 2 Jan 2015 04:02:50 -0800 Subject: [PATCH 030/106] Fix the parsing of where-clauses for structs --- src/libsyntax/parse/parser.rs | 24 +++++++++++++++++++++--- src/test/run-pass/issue-17904.rs | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/issue-17904.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 37ac86a33242e..570ef67bbccfd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4875,11 +4875,26 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "`virtual` structs have been removed from the language"); } - self.parse_where_clause(&mut generics); - let mut fields: Vec; let is_tuple_like; + // There is a special case worth noting here, as reported in issue #17904. + // If we are parsing a tuple struct it is the case that the where clause + // should follow the field list. Like so: + // + // struct Foo(T) where T: Copy; + // + // If we are parsing a normal record-style struct it is the case + // that the where clause comes before the body, and after the generics. + // So if we look ahead and see a brace or a where-clause we begin + // parsing a record style struct. + // + // Otherwise if we look ahead and see a paren we parse a tuple-style + // struct. + + // Will parse the where-clause if it precedes the brace. + self.parse_where_clause(&mut generics); + if self.eat(&token::OpenDelim(token::Brace)) { // It's a record-like struct. is_tuple_like = false; @@ -4916,8 +4931,11 @@ impl<'a> Parser<'a> { written as `struct {};`", token::get_ident(class_name))[]); } + self.parse_where_clause(&mut generics); self.expect(&token::Semi); - } else if self.eat(&token::Semi) { + } else if self.token.is_keyword(keywords::Where) || self.eat(&token::Semi) { + // We can find a where clause here. + self.parse_where_clause(&mut generics); // It's a unit-like struct. is_tuple_like = true; fields = Vec::new(); diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs new file mode 100644 index 0000000000000..c2976378ddad8 --- /dev/null +++ b/src/test/run-pass/issue-17904.rs @@ -0,0 +1,22 @@ +// 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. + +// Tests that type assignability is used to search for instances when +// making method calls, but only if there aren't any matches without +// it. + +struct Foo where T: Copy; +struct Bar(T) where T: Copy; +struct Bleh(T, U) where T: Copy, U: Sized; +struct Baz where T: Copy { + field: T +} + +fn main() {} From bf6c007760169e9c382d3700fd1cdd20037e4343 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 5 Dec 2014 15:56:25 -0800 Subject: [PATCH 031/106] Change `&` pat to only work with &T, and `&mut` with &mut T. This implements RFC 179 by making the pattern `&` require matching against a variable of type `&T`, and introducing the pattern `&mut ` which only works with variables of type `&mut T`. The pattern `&mut x` currently parses as `&(mut x)` i.e. a pattern match through a `&T` or a `&mut T` that binds the variable `x` to have type `T` and to be mutable. This should be rewritten as follows, for example, for &mut x in slice.iter() { becomes for &x in slice.iter() { let mut x = x; Due to this, this is a [breaking-change] Closes #20496. --- src/doc/reference.md | 5 ++-- src/libcore/str/mod.rs | 2 +- src/librustc/middle/cfg/construct.rs | 2 +- src/librustc/middle/check_match.rs | 6 ++--- src/librustc/middle/mem_categorization.rs | 6 +++-- src/librustc_trans/trans/_match.rs | 4 +-- src/librustc_trans/trans/debuginfo.rs | 2 +- src/librustc_typeck/check/_match.rs | 10 ++++--- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/parser.rs | 9 +++++-- src/libsyntax/print/pprust.rs | 5 +++- src/libsyntax/visit.rs | 2 +- src/libtest/stats.rs | 3 ++- .../mut-pattern-internal-mutability.rs | 24 +++++++++++++++++ .../compile-fail/mut-pattern-mismatched.rs | 26 +++++++++++++++++++ 19 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 src/test/compile-fail/mut-pattern-internal-mutability.rs create mode 100644 src/test/compile-fail/mut-pattern-mismatched.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index d793028526052..0d3f9430bd677 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3484,8 +3484,9 @@ fn main() { ``` -Patterns can also dereference pointers by using the `&`, `box` symbols, -as appropriate. For example, these two matches on `x: &int` are equivalent: +Patterns can also dereference pointers by using the `&`, `&mut` and `box` +symbols, as appropriate. For example, these two matches on `x: &int` are +equivalent: ``` # let x = &3i; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..b497e9733bc9e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -230,7 +230,7 @@ impl CharEq for F where F: FnMut(char) -> bool { impl<'a> CharEq for &'a [char] { #[inline] fn matches(&mut self, c: char) -> bool { - self.iter().any(|&mut m| m.matches(c)) + self.iter().any(|&m| { let mut m = m; m.matches(c) }) } #[inline] diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index de81f307c4d7c..3c672d0fdb6fa 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::PatBox(ref subpat) | - ast::PatRegion(ref subpat) | + ast::PatRegion(ref subpat, _) | ast::PatIdent(_, _, Some(ref subpat)) => { let subpat_exit = self.pat(&**subpat, pred); self.add_node(pat.id, &[subpat_exit]) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 2d9284846acf3..f2b9ecb5ec432 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -473,7 +473,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor, } } - ty::ty_rptr(_, ty::mt { ty, .. }) => { + ty::ty_rptr(_, ty::mt { ty, mutbl }) => { match ty.sty { ty::ty_vec(_, Some(n)) => match ctor { &Single => { @@ -493,7 +493,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor, _ => { assert_eq!(pats_len, 1); - ast::PatRegion(pats.nth(0).unwrap()) + ast::PatRegion(pats.nth(0).unwrap(), mutbl) } } } @@ -860,7 +860,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], ast::PatTup(ref args) => Some(args.iter().map(|p| &**p).collect()), - ast::PatBox(ref inner) | ast::PatRegion(ref inner) => + ast::PatBox(ref inner) | ast::PatRegion(ref inner, _) => Some(vec![&**inner]), ast::PatLit(ref expr) => { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 31c3ca4199feb..f600086fc5e62 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1262,8 +1262,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } - ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => { - // @p1, ~p1, ref p1 + ast::PatBox(ref subpat) | ast::PatRegion(ref subpat, _) => { + // box p1, &p1, &mut p1. we can ignore the mutability of + // PatRegion since that information is already contained + // in the type. let subcmt = try!(self.cat_deref(pat, cmt, 0, false)); try!(self.cat_pattern_(subcmt, &**subpat, op)); } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 50cbe664b9079..fed0931cab71d 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -683,7 +683,7 @@ fn any_uniq_pat(m: &[Match], col: uint) -> bool { } fn any_region_pat(m: &[Match], col: uint) -> bool { - any_pat!(m, col, ast::PatRegion(_)) + any_pat!(m, col, ast::PatRegion(..)) } fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool { @@ -1725,7 +1725,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llbox = Load(bcx, val); bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope); } - ast::PatRegion(ref inner) => { + ast::PatRegion(ref inner, _) => { let loaded_val = Load(bcx, val); bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope); } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 916fcbfe13ef7..0789be956429c 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3472,7 +3472,7 @@ fn create_scope_map(cx: &CrateContext, } } - ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat) => { + ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => { scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata); walk_pattern(cx, &**sub_pat, scope_stack, scope_map); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d8b410abf8449..1efff9d41f1ba 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -146,12 +146,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, check_pat(pcx, &**inner, tcx.types.err); } } - ast::PatRegion(ref inner) => { + ast::PatRegion(ref inner, mutbl) => { let inner_ty = fcx.infcx().next_ty_var(); - let mutbl = + // SNAP c894171 remove this `if`-`else` entirely after next snapshot + let mutbl = if mutbl == ast::MutImmutable { ty::deref(fcx.infcx().shallow_resolve(expected), true) - .map_or(ast::MutImmutable, |mt| mt.mutbl); + .map_or(ast::MutImmutable, |mt| mt.mutbl) + } else { + mutbl + }; let mt = ty::mt { ty: inner_ty, mutbl: mutbl }; let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f4d0bb79d88d6..6a4337a664b78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2235,7 +2235,7 @@ fn name_from_pat(p: &ast::Pat) -> String { PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::>().connect(", ")), PatBox(ref p) => name_from_pat(&**p), - PatRegion(ref p) => name_from_pat(&**p), + PatRegion(ref p, _) => name_from_pat(&**p), PatLit(..) => { warn!("tried to get argument name from PatLit, \ which is silly in function arguments"); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a33ee44be8968..d61b7a17a930d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -556,7 +556,7 @@ pub enum Pat_ { PatStruct(Path, Vec>, bool), PatTup(Vec>), PatBox(P), - PatRegion(P), // reference pattern + PatRegion(P, Mutability), // reference pattern PatLit(P), PatRange(P, P), /// [a, b, ..i, y, z] is represented as: diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 4026da6cf8e47..5e03afec16cf8 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -633,7 +633,7 @@ pub fn walk_pat(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool { PatEnum(_, Some(ref s)) | PatTup(ref s) => { s.iter().all(|p| walk_pat_(&**p, it)) } - PatBox(ref s) | PatRegion(ref s) => { + PatBox(ref s) | PatRegion(ref s, _) => { walk_pat_(&**s, it) } PatVec(ref before, ref slice, ref after) => { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 8863de8757bf7..d522c346fa0ee 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -940,7 +940,7 @@ impl<'a> MethodDef<'a> { &**variant, self_arg_name, ast::MutImmutable); - (cx.pat(sp, ast::PatRegion(p)), idents) + (cx.pat(sp, ast::PatRegion(p, ast::MutImmutable)), idents) }; // A single arm has form (&VariantK, &VariantK, ...) => BodyK diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 3d3068f6868c6..03a4f9046b549 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1267,7 +1267,7 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { } PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))), PatBox(inner) => PatBox(folder.fold_pat(inner)), - PatRegion(inner) => PatRegion(folder.fold_pat(inner)), + PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl), PatRange(e1, e2) => { PatRange(folder.fold_expr(e1), folder.fold_expr(e2)) }, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 37ac86a33242e..d9183ef0c49f5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3357,11 +3357,16 @@ impl<'a> Parser<'a> { }) } token::BinOp(token::And) | token::AndAnd => { - // parse &pat + // parse &pat and &mut pat let lo = self.span.lo; self.expect_and(); + let mutability = if self.eat_keyword(keywords::Mut) { + ast::MutMutable + } else { + ast::MutImmutable + }; let sub = self.parse_pat(); - pat = PatRegion(sub); + pat = PatRegion(sub, mutability); hi = self.last_span.hi; return P(ast::Pat { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9702c79719c64..9b2ee9de3584e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2092,8 +2092,11 @@ impl<'a> State<'a> { try!(word(&mut self.s, "box ")); try!(self.print_pat(&**inner)); } - ast::PatRegion(ref inner) => { + ast::PatRegion(ref inner, mutbl) => { try!(word(&mut self.s, "&")); + if mutbl == ast::MutMutable { + try!(word(&mut self.s, "mut ")); + } try!(self.print_pat(&**inner)); } ast::PatLit(ref e) => try!(self.print_expr(&**e)), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ec6b2cfa5c396..99701ec971003 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -519,7 +519,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { } } PatBox(ref subpattern) | - PatRegion(ref subpattern) => { + PatRegion(ref subpattern, _) => { visitor.visit_pat(&**subpattern) } PatIdent(_, ref pth1, ref optional_subpattern) => { diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 35af0e763d7dd..c42cf4d055166 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -169,7 +169,8 @@ impl Stats for [T] { fn sum(&self) -> T { let mut partials = vec![]; - for &mut x in self.iter() { + for &x in self.iter() { + let mut x = x; let mut j = 0; // This inner loop applies `hi`/`lo` summation to each // partial so that the list of partial sums remains exact. diff --git a/src/test/compile-fail/mut-pattern-internal-mutability.rs b/src/test/compile-fail/mut-pattern-internal-mutability.rs new file mode 100644 index 0000000000000..05c6c4a96557c --- /dev/null +++ b/src/test/compile-fail/mut-pattern-internal-mutability.rs @@ -0,0 +1,24 @@ +// Copyright 2015 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. + +fn main() { + let foo = &mut 1i; + + let &mut x = foo; + x += 1; //~ ERROR re-assignment of immutable variable + + // explicitly mut-ify internals + let &mut mut x = foo; + x += 1; + + // check borrowing is detected successfully + let &mut ref x = foo; + *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed +} diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs new file mode 100644 index 0000000000000..74e6141a2b3ff --- /dev/null +++ b/src/test/compile-fail/mut-pattern-mismatched.rs @@ -0,0 +1,26 @@ +// 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. + +fn main() { + let foo = &mut 1i; + + // (separate lines to ensure the spans are accurate) + + // SNAP c894171 uncomment this after the next snapshot + // NOTE(stage0) just in case tidy doesn't check SNAP's in tests + // let &_ // ~ ERROR expected `&mut int`, found `&_` + // = foo; + let &mut _ = foo; + + let bar = &1i; + let &_ = bar; + let &mut _ //~ ERROR expected `&int`, found `&mut _` + = bar; +} From 09c4e8fe96c4c150d4f0d20a74a0da090e1d2d64 Mon Sep 17 00:00:00 2001 From: York Xiang Date: Mon, 5 Jan 2015 15:11:54 +0800 Subject: [PATCH 032/106] kate syntax highlight: update keyword list --- src/etc/kate/rust.xml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index 9d0450285091c..1fb01767a130b 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -15,28 +15,41 @@ type + + abstract + alignof + be + do + final + offsetof + override + priv + pure + sizeof + typeof + unsized + yield + as - break box + break const continue crate - do - drop else enum extern for if impl + in let loop match mod move mut - priv pub ref return @@ -192,6 +205,7 @@ + From 267b73d95e4fcc906e1b1207ab610fa45f6e6613 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 4 Jan 2015 23:32:20 -0800 Subject: [PATCH 033/106] std: Fixup some missing stabilization on str * The `str` module itself is stable. * The `StrExt` trait is stable (and impls). * The `Utf8Error` type is unstable. * The `from_utf8` function is stable * Some iterators are now stable: * `Chars` * `CharIndices` * The `MatchIndices` iterator is now unstable * The public `traits` module is no longer public. --- src/libcollections/str.rs | 3 +++ src/libcore/str/mod.rs | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ed6a957d2acfa..fee06422fdd1f 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -50,6 +50,7 @@ //! is the same as `&[u8]`. #![doc(primitive = "str")] +#![stable] use self::RecompositionState::*; use self::DecompositionType::*; @@ -401,6 +402,7 @@ Section: Trait implementations */ /// Any string that can be represented as a slice. +#[stable] pub trait StrExt for Sized?: ops::Slice { /// Escapes each char in `s` with `char::escape_default`. #[unstable = "return type may change to be an iterator"] @@ -1340,6 +1342,7 @@ pub trait StrExt for Sized?: ops::Slice { } } +#[stable] impl StrExt for str {} #[cfg(test)] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..964e0089e44ee 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -142,6 +142,7 @@ Section: Creating a string /// Errors which can occur when attempting to interpret a byte slice as a `str`. #[derive(Copy, Eq, PartialEq, Clone)] +#[unstable = "error enumeration recently added and definitions may be refined"] pub enum Utf8Error { /// An invalid byte was detected at the byte offset given. /// @@ -165,6 +166,7 @@ pub enum Utf8Error { /// /// Returns `Err` if the slice is not utf-8 with a description as to why the /// provided slice is not utf-8. +#[stable] pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { try!(run_utf8_validation_iterator(&mut v.iter())); Ok(unsafe { from_utf8_unchecked(v) }) @@ -247,6 +249,7 @@ Section: Iterators /// /// Created with the method `.chars()`. #[derive(Clone, Copy)] +#[stable] pub struct Chars<'a> { iter: slice::Iter<'a, u8> } @@ -356,6 +359,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { /// External iterator for a string's characters and their byte offsets. /// Use with the `std::iter` module. #[derive(Clone)] +#[stable] pub struct CharIndices<'a> { front_offset: uint, iter: Chars<'a>, @@ -848,6 +852,7 @@ impl Searcher { /// An iterator over the start and end indices of the matches of a /// substring within a larger string #[derive(Clone)] +#[unstable = "type may be removed"] pub struct MatchIndices<'a> { // constants haystack: &'a str, @@ -858,7 +863,7 @@ pub struct MatchIndices<'a> { /// An iterator over the substrings of a string separated by a given /// search string #[derive(Clone)] -#[unstable = "Type might get removed"] +#[unstable = "type may be removed"] pub struct SplitStr<'a> { it: MatchIndices<'a>, last_end: uint, @@ -1056,8 +1061,7 @@ const TAG_CONT_U8: u8 = 0b1000_0000u8; Section: Trait implementations */ -#[allow(missing_docs)] -pub mod traits { +mod traits { use cmp::{Ordering, Ord, PartialEq, PartialOrd, Eq}; use cmp::Ordering::{Less, Equal, Greater}; use iter::IteratorExt; From 177f8bc55c544d5a5f35ffb19f47125d001e48c4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 4 Jan 2015 23:34:42 -0800 Subject: [PATCH 034/106] std: Fix missing stability in sync * The `sync` module is stable * The `sync::mpsc` module is stable * The `Sender::send` method is stable. * The `Once::doit` method is now removed. * Deprecated atomic initializers are removed. * Renamed atomic initializers are now stable. --- src/libcore/atomic.rs | 16 +++------------- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/mpsc/mod.rs | 3 +++ src/libstd/sync/once.rs | 4 ---- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 0ac0dc396cc1a..fbb8f9d8cf754 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -146,28 +146,18 @@ pub enum Ordering { } /// An `AtomicBool` initialized to `false`. -#[unstable = "may be renamed, pending conventions for static initalizers"] +#[stable] pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool { v: UnsafeCell { value: 0 } }; /// An `AtomicInt` initialized to `0`. -#[unstable = "may be renamed, pending conventions for static initalizers"] +#[stable] pub const ATOMIC_INT_INIT: AtomicInt = AtomicInt { v: UnsafeCell { value: 0 } }; /// An `AtomicUint` initialized to `0`. -#[unstable = "may be renamed, pending conventions for static initalizers"] +#[stable] pub const ATOMIC_UINT_INIT: AtomicUint = AtomicUint { v: UnsafeCell { value: 0, } }; -/// Deprecated -#[deprecated = "renamed to ATOMIC_BOOL_INIT"] -pub const INIT_ATOMIC_BOOL: AtomicBool = ATOMIC_BOOL_INIT; -/// Deprecated -#[deprecated = "renamed to ATOMIC_INT_INIT"] -pub const INIT_ATOMIC_INT: AtomicInt = ATOMIC_INT_INIT; -/// Deprecated -#[deprecated = "renamed to ATOMIC_UINT_INIT"] -pub const INIT_ATOMIC_UINT: AtomicUint = ATOMIC_UINT_INIT; - // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly const UINT_TRUE: uint = -1; diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 6ce278726e9de..44671b52ba084 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -15,7 +15,7 @@ //! and/or blocking at all, but rather provide the necessary tools to build //! other types of concurrent primitives. -#![experimental] +#![stable] pub use alloc::arc::{Arc, Weak}; pub use core::atomic; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6bc3f561bb3c7..84284ae6d66e2 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -163,6 +163,8 @@ //! } //! ``` +#![stable] + // A description of how Rust's channel implementation works // // Channels are supposed to be the basic building block for all other @@ -565,6 +567,7 @@ impl Sender { /// drop(rx); /// assert_eq!(tx.send(1i).err().unwrap().0, 1); /// ``` + #[stable] pub fn send(&self, t: T) -> Result<(), SendError> { let (new_inner, ret) = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 08e323c9cb4c3..aa2d957a3eb5e 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -121,10 +121,6 @@ impl Once { unsafe { self.mutex.destroy() } } } - - /// Deprecated - #[deprecated = "renamed to `call_once`"] - pub fn doit(&'static self, f: F) where F: FnOnce() { self.call_once(f) } } #[cfg(test)] From dc246ae0188500c2e3c62704aa9f8b2f02fd586c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 4 Jan 2015 23:40:07 -0800 Subject: [PATCH 035/106] std: Fix missing stability on prelude The module itself is stable (the name) --- src/libstd/prelude/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 1fbd17ede08f2..0496944dbaf88 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -35,5 +35,7 @@ //! pervasive that it would be obnoxious to import for every use, particularly //! those that define methods on primitive types. +#![stable] + #[stable] pub mod v1; From 73019ac10ecbe4929f9e955bf067f6ec2a389e27 Mon Sep 17 00:00:00 2001 From: Zbigniew Siciarz Date: Mon, 5 Jan 2015 08:44:18 +0100 Subject: [PATCH 036/106] Fix misleading name in AsciiExt docs --- src/libstd/ascii.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index bcd87f6786d35..e9b7e33bcf599 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -53,7 +53,7 @@ pub trait AsciiExt for Sized? { fn to_ascii_lowercase(&self) -> T; /// Check that two strings are an ASCII case-insensitive match. - /// Same as `to_ascii_lowercase(a) == to_ascii_lower(b)`, + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporary strings. fn eq_ignore_ascii_case(&self, other: &Self) -> bool; } From c02fac471a9126e971617449a55930b0d69058c0 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sun, 4 Jan 2015 02:35:14 -0800 Subject: [PATCH 037/106] Refactor struct parsing and add tests --- src/libsyntax/parse/parser.rs | 121 +++++++++++++++++---------- src/libsyntax/print/pprust.rs | 3 +- src/test/compile-fail/issue-17904.rs | 17 ++++ src/test/compile-fail/unsized.rs | 2 +- src/test/run-pass/issue-17904.rs | 4 - 5 files changed, 96 insertions(+), 51 deletions(-) create mode 100644 src/test/compile-fail/issue-17904.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 570ef67bbccfd..79e5fe7cc9a07 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4875,9 +4875,6 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "`virtual` structs have been removed from the language"); } - let mut fields: Vec; - let is_tuple_like; - // There is a special case worth noting here, as reported in issue #17904. // If we are parsing a tuple struct it is the case that the where clause // should follow the field list. Like so: @@ -4892,68 +4889,102 @@ impl<'a> Parser<'a> { // Otherwise if we look ahead and see a paren we parse a tuple-style // struct. - // Will parse the where-clause if it precedes the brace. - self.parse_where_clause(&mut generics); + let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { + self.parse_where_clause(&mut generics); + if self.eat(&token::Semi) { + // If we see a: `struct Foo where T: Copy;` style decl. + (Vec::new(), Some(ast::DUMMY_NODE_ID)) + } else { + // If we see: `struct Foo where T: Copy { ... }` + (self.parse_record_struct_body(&class_name), None) + } + // No `where` so: `struct Foo;` + } else if self.eat(&token::Semi) { + (Vec::new(), Some(ast::DUMMY_NODE_ID)) + // Record-style struct definition + } else if self.token == token::OpenDelim(token::Brace) { + let fields = self.parse_record_struct_body(&class_name); + (fields, None) + // Tuple-style struct definition with optional where-clause. + } else { + let fields = self.parse_tuple_struct_body(&class_name, &mut generics); + (fields, Some(ast::DUMMY_NODE_ID)) + }; + (class_name, + ItemStruct(P(ast::StructDef { + fields: fields, + ctor_id: ctor_id, + }), generics), + None) + } + + pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec { + let mut fields = Vec::new(); if self.eat(&token::OpenDelim(token::Brace)) { - // It's a record-like struct. - is_tuple_like = false; - fields = Vec::new(); while self.token != token::CloseDelim(token::Brace) { fields.push(self.parse_struct_decl_field(true)); } + if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ - written as `struct {};`", - token::get_ident(class_name))[]); + written as `struct {};`", + token::get_ident(class_name.clone()))[]); } + self.bump(); - } else if self.check(&token::OpenDelim(token::Paren)) { - // It's a tuple-like struct. - is_tuple_like = true; - fields = self.parse_unspanned_seq( + } else { + let token_str = self.this_token_to_string(); + self.fatal(format!("expected `where`, or `{}` after struct \ + name, found `{}`", "{", + token_str)[]); + } + + fields + } + + pub fn parse_tuple_struct_body(&mut self, + class_name: &ast::Ident, + generics: &mut ast::Generics) + -> Vec { + // This is the case where we find `struct Foo(T) where T: Copy;` + if self.check(&token::OpenDelim(token::Paren)) { + let fields = self.parse_unspanned_seq( &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), |p| { - let attrs = p.parse_outer_attributes(); - let lo = p.span.lo; - let struct_field_ = ast::StructField_ { - kind: UnnamedField(p.parse_visibility()), - id: ast::DUMMY_NODE_ID, - ty: p.parse_ty_sum(), - attrs: attrs, - }; - spanned(lo, p.span.hi, struct_field_) - }); + let attrs = p.parse_outer_attributes(); + let lo = p.span.lo; + let struct_field_ = ast::StructField_ { + kind: UnnamedField(p.parse_visibility()), + id: ast::DUMMY_NODE_ID, + ty: p.parse_ty_sum(), + attrs: attrs, + }; + spanned(lo, p.span.hi, struct_field_) + }); + if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ - written as `struct {};`", - token::get_ident(class_name))[]); + written as `struct {};`", + token::get_ident(class_name.clone()))[]); } - self.parse_where_clause(&mut generics); + + self.parse_where_clause(generics); self.expect(&token::Semi); - } else if self.token.is_keyword(keywords::Where) || self.eat(&token::Semi) { - // We can find a where clause here. - self.parse_where_clause(&mut generics); - // It's a unit-like struct. - is_tuple_like = true; - fields = Vec::new(); + fields + // This is the case where we just see struct Foo where T: Copy; + } else if self.token.is_keyword(keywords::Where) { + self.parse_where_clause(generics); + self.expect(&token::Semi); + Vec::new() + // This case is where we see: `struct Foo;` } else { let token_str = self.this_token_to_string(); - self.fatal(format!("expected `{}`, `(`, or `;` after struct \ - name, found `{}`", "{", - token_str)[]) + self.fatal(format!("expected `where`, `{}`, `(`, or `;` after struct \ + name, found `{}`", "{", token_str)[]); } - - let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. - let new_id = ast::DUMMY_NODE_ID; - (class_name, - ItemStruct(P(ast::StructDef { - fields: fields, - ctor_id: if is_tuple_like { Some(new_id) } else { None }, - }), generics), - None) } /// Parse a structure field declaration diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9702c79719c64..2176cd13b287b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1067,7 +1067,6 @@ impl<'a> State<'a> { span: codemap::Span) -> IoResult<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); - try!(self.print_where_clause(generics)); if ast_util::struct_def_is_tuple_like(struct_def) { if !struct_def.fields.is_empty() { try!(self.popen()); @@ -1086,10 +1085,12 @@ impl<'a> State<'a> { )); try!(self.pclose()); } + try!(self.print_where_clause(generics)); try!(word(&mut self.s, ";")); try!(self.end()); self.end() // close the outer-box } else { + try!(self.print_where_clause(generics)); try!(self.nbsp()); try!(self.bopen()); try!(self.hardbreak_if_not_bol()); diff --git a/src/test/compile-fail/issue-17904.rs b/src/test/compile-fail/issue-17904.rs new file mode 100644 index 0000000000000..96ba712bbae8b --- /dev/null +++ b/src/test/compile-fail/issue-17904.rs @@ -0,0 +1,17 @@ +// 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. + +struct Baz where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. +struct Baz where U: Eq(U) -> R; // Notice this parses as well. +struct Baz(U) where U: Eq; // This rightfully signals no error as well. +struct Foo where T: Copy, (T); //~ ERROR unexpected token in `where` clause +struct Bar { x: T } where T: Copy //~ ERROR expected item, found `where` + +fn main() {} diff --git a/src/test/compile-fail/unsized.rs b/src/test/compile-fail/unsized.rs index 43db4dfd395b0..92dbea0424b6f 100644 --- a/src/test/compile-fail/unsized.rs +++ b/src/test/compile-fail/unsized.rs @@ -10,7 +10,7 @@ // Test syntax checks for `type` keyword. -struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name, found `for` +struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for` pub fn main() { } diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs index c2976378ddad8..3ce347d67e3d9 100644 --- a/src/test/run-pass/issue-17904.rs +++ b/src/test/run-pass/issue-17904.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Tests that type assignability is used to search for instances when -// making method calls, but only if there aren't any matches without -// it. - struct Foo where T: Copy; struct Bar(T) where T: Copy; struct Bleh(T, U) where T: Copy, U: Sized; From 82a96a11abcb9cc4d342402746af270eb4f28325 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:04:32 +1100 Subject: [PATCH 038/106] Ungate associated types. They work pretty well now, and the stdlib is using them everywhere so they're impossible to avoid anyway. --- src/libsyntax/feature_gate.rs | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f8ac34cfe2920..caf3bcd77c49f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -67,7 +67,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("import_shadowing", Active), ("advanced_slice_patterns", Active), ("tuple_indexing", Accepted), - ("associated_types", Active), + ("associated_types", Accepted), ("visible_private_types", Active), ("slicing_syntax", Active), @@ -313,18 +313,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { many unsafe patterns and may be \ removed in the future"); } - - for item in items.iter() { - match *item { - ast::MethodImplItem(_) => {} - ast::TypeImplItem(ref typedef) => { - self.gate_feature("associated_types", - typedef.span, - "associated types are \ - experimental") - } - } - } } _ => {} @@ -333,17 +321,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_item(self, i); } - fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { - match *trait_item { - ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} - ast::TypeTraitItem(ref ti) => { - self.gate_feature("associated_types", - ti.ty_param.span, - "associated types are experimental") - } - } - } - fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { if attr::contains_name(i.attrs[], "linkage") { self.gate_feature("linkage", i.span, From 679514816974f23eff367b37e9082599a25900f0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:04:55 +1100 Subject: [PATCH 039/106] Ungate globs. These are in scope for 1.0, so this is good to e.g. make it easier find bugs. --- src/libsyntax/feature_gate.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index caf3bcd77c49f..19e44c2c21b55 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -36,7 +36,7 @@ use std::ascii::AsciiExt; // if you change this list without updating src/doc/reference.md, @cmr will be sad static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ - ("globs", Active), + ("globs", Accepted), ("macro_rules", Active), ("struct_variant", Accepted), ("asm", Active), @@ -232,13 +232,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_view_item(&mut self, i: &ast::ViewItem) { match i.node { - ast::ViewItemUse(ref path) => { - if let ast::ViewPathGlob(..) = path.node { - self.gate_feature("globs", path.span, - "glob import statements are \ - experimental and possibly buggy"); - } - } + ast::ViewItemUse(..) => {} ast::ViewItemExternCrate(..) => { for attr in i.attrs.iter() { if attr.name().get() == "phase"{ From 6e3d78f06fc78e6ad58379824be2d7fed525655a Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:07:16 +1100 Subject: [PATCH 040/106] Ungate default type parameters. These are in scope for 1.0, and this is good to e.g. find as many bugs as possible. --- src/librustc_driver/driver.rs | 1 - src/librustc_llvm/lib.rs | 1 + src/librustc_resolve/lib.rs | 1 + src/librustc_typeck/astconv.rs | 8 -------- src/libsyntax/ext/deriving/hash.rs | 20 +++++++------------- src/libsyntax/ext/expand.rs | 2 -- src/libsyntax/feature_gate.rs | 19 +------------------ 7 files changed, 10 insertions(+), 42 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1455aa3c99bb3..1a4856333bf17 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -272,7 +272,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, } let cfg = syntax::ext::expand::ExpansionConfig { crate_name: crate_name.to_string(), - deriving_hash_type_parameter: sess.features.borrow().default_type_params, enable_quotes: sess.features.borrow().quote, recursion_limit: sess.recursion_limit.get(), }; diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 2ec5f37634afb..0445404f8e622 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -24,6 +24,7 @@ #![feature(globs)] #![feature(link_args)] #![feature(unboxed_closures)] +#![feature(old_orphan_check)] extern crate libc; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2c2678c8dc68e..5573b67521427 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -19,6 +19,7 @@ #![feature(globs, phase, slicing_syntax)] #![feature(rustc_diagnostic_macros)] #![feature(associated_types)] +#![feature(old_orphan_check)] #[phase(plugin, link)] extern crate log; #[phase(plugin, link)] extern crate syntax; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1d62733875e00..bf01d5e38e71e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -360,14 +360,6 @@ fn create_substs_for_ast_path<'tcx,AC,RS>( supplied_ty_param_count)[]); } - if supplied_ty_param_count > required_ty_param_count - && !this.tcx().sess.features.borrow().default_type_params { - span_err!(this.tcx().sess, span, E0108, - "default type parameters are experimental and possibly buggy"); - span_help!(this.tcx().sess, span, - "add #![feature(default_type_params)] to the crate attributes to enable"); - } - let mut substs = Substs::new_type(types, regions); match self_ty { diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 9ff42d85cfbb8..553b8af172fec 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -25,20 +25,14 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, F: FnOnce(P), { - let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter { - (Path::new_(vec!("std", "hash", "Hash"), None, - vec!(box Literal(Path::new_local("__S"))), true), - LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec!(("__S", - vec!(Path::new(vec!("std", "hash", "Writer"))))), - }, - Path::new_local("__S")) - } else { - (Path::new(vec!("std", "hash", "Hash")), - LifetimeBounds::empty(), - Path::new(vec!("std", "hash", "sip", "SipState"))) + let path = Path::new_(vec!("std", "hash", "Hash"), None, + vec!(box Literal(Path::new_local("__S"))), true); + let generics = LifetimeBounds { + lifetimes: Vec::new(), + bounds: vec!(("__S", + vec!(Path::new(vec!("std", "hash", "Writer"))))), }; + let args = Path::new_local("__S"); let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let hash_trait_def = TraitDef { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b3f30dd4581c9..b3e839b4fb648 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1161,7 +1161,6 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span { pub struct ExpansionConfig { pub crate_name: String, - pub deriving_hash_type_parameter: bool, pub enable_quotes: bool, pub recursion_limit: uint, } @@ -1170,7 +1169,6 @@ impl ExpansionConfig { pub fn default(crate_name: String) -> ExpansionConfig { ExpansionConfig { crate_name: crate_name, - deriving_hash_type_parameter: false, enable_quotes: false, recursion_limit: 64, } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 19e44c2c21b55..584558638b783 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -54,7 +54,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("lang_items", Active), ("simd", Active), - ("default_type_params", Active), + ("default_type_params", Accepted), ("quote", Active), ("link_llvm_intrinsics", Active), ("linkage", Active), @@ -112,7 +112,6 @@ enum Status { /// A set of features to be used by later passes. #[derive(Copy)] pub struct Features { - pub default_type_params: bool, pub unboxed_closures: bool, pub rustc_diagnostic_macros: bool, pub import_shadowing: bool, @@ -125,7 +124,6 @@ pub struct Features { impl Features { pub fn new() -> Features { Features { - default_type_params: false, unboxed_closures: false, rustc_diagnostic_macros: false, import_shadowing: false, @@ -356,20 +354,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_expr(self, e); } - fn visit_generics(&mut self, generics: &ast::Generics) { - for type_parameter in generics.ty_params.iter() { - match type_parameter.default { - Some(ref ty) => { - self.gate_feature("default_type_params", ty.span, - "default type parameters are \ - experimental and possibly buggy"); - } - None => {} - } - } - visit::walk_generics(self, generics); - } - fn visit_attribute(&mut self, attr: &ast::Attribute) { if attr::contains_name(slice::ref_slice(attr), "lang") { self.gate_feature("lang_items", @@ -475,7 +459,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C check(&mut cx, krate); (Features { - default_type_params: cx.has_feature("default_type_params"), unboxed_closures: cx.has_feature("unboxed_closures"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), import_shadowing: cx.has_feature("import_shadowing"), From 4016c729f18ce5aa8976fc16617b9368437c28db Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:28:53 +1100 Subject: [PATCH 041/106] Remove use of associated_types feature gate from tests. --- src/test/auxiliary/associated-types-cc-lib.rs | 1 - src/test/auxiliary/issue-16643.rs | 1 - src/test/auxiliary/issue_20389.rs | 2 -- src/test/auxiliary/overloaded_autoderef_xc.rs | 2 -- src/test/auxiliary/trait_inheritance_overloading_xc.rs | 2 -- src/test/bench/shootout-fasta.rs | 2 +- src/test/bench/shootout-k-nucleotide.rs | 2 +- src/test/bench/shootout-meteor.rs | 2 -- src/test/bench/shootout-reverse-complement.rs | 2 +- .../associated-types-ICE-when-projecting-out-of-err.rs | 2 +- src/test/compile-fail/associated-types-bound-failure.rs | 2 -- src/test/compile-fail/associated-types-eq-1.rs | 2 -- src/test/compile-fail/associated-types-eq-2.rs | 2 -- src/test/compile-fail/associated-types-eq-3.rs | 2 -- src/test/compile-fail/associated-types-eq-expr-path.rs | 2 -- src/test/compile-fail/associated-types-eq-hr.rs | 2 -- src/test/compile-fail/associated-types-for-unimpl-trait.rs | 3 --- .../compile-fail/associated-types-in-ambiguous-context.rs | 3 --- src/test/compile-fail/associated-types-incomplete-object.rs | 2 -- src/test/compile-fail/associated-types-issue-20346.rs | 1 - src/test/compile-fail/associated-types-no-suitable-bound.rs | 3 --- .../compile-fail/associated-types-no-suitable-supertrait.rs | 2 -- src/test/compile-fail/associated-types-path-1.rs | 3 --- src/test/compile-fail/associated-types-path-2.rs | 2 -- .../associated-types-project-from-hrtb-explicit.rs | 2 -- .../associated-types-project-from-hrtb-in-fn-body.rs | 2 -- .../compile-fail/associated-types-project-from-hrtb-in-fn.rs | 2 -- .../associated-types-project-from-hrtb-in-struct.rs | 2 -- .../associated-types-project-from-hrtb-in-trait-method.rs | 2 -- src/test/compile-fail/associated-types-unconstrained.rs | 2 -- src/test/compile-fail/associated-types-unsized.rs | 3 --- src/test/compile-fail/binop-consume-args.rs | 2 +- src/test/compile-fail/binop-move-semantics.rs | 2 +- .../compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs | 2 -- .../compile-fail/borrowck-borrow-overloaded-auto-deref.rs | 2 -- src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs | 2 -- src/test/compile-fail/borrowck-borrow-overloaded-deref.rs | 2 -- src/test/compile-fail/borrowck-loan-in-overloaded-op.rs | 2 -- src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs | 2 +- src/test/compile-fail/borrowck-overloaded-index-2.rs | 2 -- src/test/compile-fail/borrowck-overloaded-index-autoderef.rs | 4 ---- src/test/compile-fail/borrowck-overloaded-index.rs | 4 ---- src/test/compile-fail/dst-index.rs | 2 -- src/test/compile-fail/infinite-autoderef.rs | 2 -- src/test/compile-fail/issue-18389.rs | 1 - src/test/compile-fail/issue-18566.rs | 2 -- src/test/compile-fail/issue-18611.rs | 2 -- src/test/compile-fail/issue-18819.rs | 2 -- src/test/compile-fail/issue-19883.rs | 2 -- src/test/compile-fail/issue-20005.rs | 2 -- src/test/compile-fail/static-reference-to-fn-2.rs | 3 --- src/test/compile-fail/wrong-mul-method-signature.rs | 2 +- src/test/run-pass/associated-types-basic.rs | 3 --- src/test/run-pass/associated-types-binding-in-where-clause.rs | 2 -- src/test/run-pass/associated-types-bound.rs | 2 -- src/test/run-pass/associated-types-cc.rs | 2 -- src/test/run-pass/associated-types-conditional-dispatch.rs | 2 +- src/test/run-pass/associated-types-constant-type.rs | 3 --- src/test/run-pass/associated-types-eq-obj.rs | 2 -- src/test/run-pass/associated-types-impl-redirect.rs | 2 +- src/test/run-pass/associated-types-in-default-method.rs | 4 ---- src/test/run-pass/associated-types-in-fn.rs | 3 --- src/test/run-pass/associated-types-in-impl-generics.rs | 3 --- src/test/run-pass/associated-types-in-inherent-method.rs | 3 --- src/test/run-pass/associated-types-issue-20371.rs | 1 - .../run-pass/associated-types-normalize-in-bounds-ufcs.rs | 2 -- src/test/run-pass/associated-types-normalize-in-bounds.rs | 2 -- .../associated-types-projection-bound-in-supertraits.rs | 2 -- ...ed-types-qualified-path-with-trait-with-type-parameters.rs | 2 -- src/test/run-pass/associated-types-resolve-lifetime.rs | 2 -- src/test/run-pass/associated-types-return.rs | 2 -- src/test/run-pass/associated-types-simple.rs | 3 --- src/test/run-pass/associated-types-sugar-path.rs | 2 -- .../run-pass/associated-types-where-clause-impl-ambiguity.rs | 2 +- src/test/run-pass/dst-deref-mut.rs | 2 -- src/test/run-pass/dst-deref.rs | 2 -- src/test/run-pass/dst-index.rs | 2 -- src/test/run-pass/fixup-deref-mut.rs | 3 --- src/test/run-pass/issue-13167.rs | 2 -- src/test/run-pass/issue-13264.rs | 2 -- src/test/run-pass/issue-14919.rs | 2 -- src/test/run-pass/issue-15734.rs | 2 +- src/test/run-pass/issue-16596.rs | 2 -- src/test/run-pass/issue-16774.rs | 2 +- src/test/run-pass/issue-17732.rs | 1 - src/test/run-pass/issue-19081.rs | 2 -- src/test/run-pass/issue-19121.rs | 2 -- src/test/run-pass/issue-19129-1.rs | 2 -- src/test/run-pass/issue-19129-2.rs | 2 -- src/test/run-pass/issue-19479.rs | 1 - src/test/run-pass/issue-19631.rs | 2 -- src/test/run-pass/issue-19632.rs | 2 -- src/test/run-pass/issue-19850.rs | 2 -- src/test/run-pass/issue-20009.rs | 2 -- src/test/run-pass/issue-20389.rs | 1 - src/test/run-pass/issue-3743.rs | 2 +- src/test/run-pass/operator-multidispatch.rs | 2 +- src/test/run-pass/operator-overloading.rs | 2 -- src/test/run-pass/overloaded-autoderef-count.rs | 2 -- src/test/run-pass/overloaded-autoderef-indexing.rs | 2 -- src/test/run-pass/overloaded-autoderef-order.rs | 2 -- src/test/run-pass/overloaded-autoderef-vtable.rs | 2 -- src/test/run-pass/overloaded-deref-count.rs | 2 -- src/test/run-pass/overloaded-index-assoc-list.rs | 2 -- src/test/run-pass/overloaded-index-autoderef.rs | 3 --- src/test/run-pass/overloaded-index-in-field.rs | 3 --- src/test/run-pass/overloaded-index.rs | 3 --- src/test/run-pass/parse-assoc-type-lt.rs | 2 -- src/test/run-pass/regions-no-bound-in-argument-cleanup.rs | 2 +- src/test/run-pass/simd-generics.rs | 2 +- src/test/run-pass/trait-inheritance-overloading.rs | 2 -- 111 files changed, 17 insertions(+), 219 deletions(-) diff --git a/src/test/auxiliary/associated-types-cc-lib.rs b/src/test/auxiliary/associated-types-cc-lib.rs index 17b2a0751fe29..44fbcf2150a4b 100644 --- a/src/test/auxiliary/associated-types-cc-lib.rs +++ b/src/test/auxiliary/associated-types-cc-lib.rs @@ -12,7 +12,6 @@ // cross-crate scenario. #![crate_type="lib"] -#![feature(associated_types)] pub trait Bar { type T; diff --git a/src/test/auxiliary/issue-16643.rs b/src/test/auxiliary/issue-16643.rs index 41572998b58a4..c3f7f2d1aa166 100644 --- a/src/test/auxiliary/issue-16643.rs +++ b/src/test/auxiliary/issue-16643.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "lib"] -#![feature(associated_types)] pub struct TreeBuilder; diff --git a/src/test/auxiliary/issue_20389.rs b/src/test/auxiliary/issue_20389.rs index 60e3cb13e2e46..7a378b06df9e1 100644 --- a/src/test/auxiliary/issue_20389.rs +++ b/src/test/auxiliary/issue_20389.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - pub trait T { type C; } diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs index 05960a5b8e1dd..caa9bbe5736e4 100644 --- a/src/test/auxiliary/overloaded_autoderef_xc.rs +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Deref; struct DerefWithHelper { diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 7394373e9229b..cbd2ac69c7894 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::cmp::PartialEq; use std::ops::{Add, Sub, Mul}; diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 8777fa9689f94..9128930651f25 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -38,7 +38,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(associated_types, slicing_syntax)] +#![feature(slicing_syntax)] use std::cmp::min; use std::io::{BufferedWriter, File}; diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 359f06d0cf5f9..28d7488c9bf8f 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -40,7 +40,7 @@ // ignore-android see #10393 #13206 -#![feature(associated_types, slicing_syntax)] +#![feature(slicing_syntax)] use std::ascii::OwnedAsciiExt; use std::iter::repeat; diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index 438775d8ba0a4..0a0af127765da 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -40,8 +40,6 @@ // no-pretty-expanded FIXME #15189 -#![feature(associated_types)] - use std::iter::repeat; use std::sync::Arc; use std::sync::mpsc::channel; diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index bbbd7aebd5475..77bae87c7dd21 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -40,7 +40,7 @@ // ignore-android see #10393 #13206 -#![feature(associated_types, slicing_syntax, unboxed_closures)] +#![feature(slicing_syntax, unboxed_closures)] extern crate libc; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 5743216b6ca69..0abec3e1d12a5 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -12,7 +12,7 @@ // just propagate the error. #![crate_type = "lib"] -#![feature(associated_types, default_type_params, lang_items)] +#![feature(default_type_params, lang_items)] #![no_std] #[lang="sized"] diff --git a/src/test/compile-fail/associated-types-bound-failure.rs b/src/test/compile-fail/associated-types-bound-failure.rs index 7981fe3182712..918826bb390cb 100644 --- a/src/test/compile-fail/associated-types-bound-failure.rs +++ b/src/test/compile-fail/associated-types-bound-failure.rs @@ -10,8 +10,6 @@ // Test equality constraints on associated types in a where clause. -#![feature(associated_types)] - pub trait ToInt { fn to_int(&self) -> int; } diff --git a/src/test/compile-fail/associated-types-eq-1.rs b/src/test/compile-fail/associated-types-eq-1.rs index e93d9db28cf4b..58dbb9863254a 100644 --- a/src/test/compile-fail/associated-types-eq-1.rs +++ b/src/test/compile-fail/associated-types-eq-1.rs @@ -11,8 +11,6 @@ // Test equality constraints on associated types. Check that unsupported syntax // does not ICE. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/compile-fail/associated-types-eq-2.rs b/src/test/compile-fail/associated-types-eq-2.rs index b89cdd8c0eed7..e298d05d11dad 100644 --- a/src/test/compile-fail/associated-types-eq-2.rs +++ b/src/test/compile-fail/associated-types-eq-2.rs @@ -11,8 +11,6 @@ // Test equality constraints on associated types. Check we get an error when an // equality constraint is used in a qualified path. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/compile-fail/associated-types-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs index e5974925d7370..0f18a84cd1ae3 100644 --- a/src/test/compile-fail/associated-types-eq-3.rs +++ b/src/test/compile-fail/associated-types-eq-3.rs @@ -11,8 +11,6 @@ // Test equality constraints on associated types. Check we get type errors // where we should. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index 1a96b0ca6812e..ef56fdeb05183 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -10,8 +10,6 @@ // Check that an associated type cannot be bound in an expression path. -#![feature(associated_types)] - trait Foo { type A; fn bar() -> int; diff --git a/src/test/compile-fail/associated-types-eq-hr.rs b/src/test/compile-fail/associated-types-eq-hr.rs index aad55745c25df..2532977b1ca24 100644 --- a/src/test/compile-fail/associated-types-eq-hr.rs +++ b/src/test/compile-fail/associated-types-eq-hr.rs @@ -10,8 +10,6 @@ // Check testing of equality constraints in a higher-ranked context. -#![feature(associated_types)] - pub trait TheTrait { type A; diff --git a/src/test/compile-fail/associated-types-for-unimpl-trait.rs b/src/test/compile-fail/associated-types-for-unimpl-trait.rs index 2c6ee502fca3e..9c173515793f4 100644 --- a/src/test/compile-fail/associated-types-for-unimpl-trait.rs +++ b/src/test/compile-fail/associated-types-for-unimpl-trait.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> ::Value; @@ -22,4 +20,3 @@ trait Other { fn main() { } - diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs index fcd3e4d163646..3999e9cbe753d 100644 --- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs +++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> ::Value; @@ -26,4 +24,3 @@ trait Grab { fn main() { } - diff --git a/src/test/compile-fail/associated-types-incomplete-object.rs b/src/test/compile-fail/associated-types-incomplete-object.rs index 7e4e1315110af..371f97e867a29 100644 --- a/src/test/compile-fail/associated-types-incomplete-object.rs +++ b/src/test/compile-fail/associated-types-incomplete-object.rs @@ -11,8 +11,6 @@ // Check that the user gets an errror if they omit a binding from an // object type. -#![feature(associated_types)] - pub trait Foo { type A; type B; diff --git a/src/test/compile-fail/associated-types-issue-20346.rs b/src/test/compile-fail/associated-types-issue-20346.rs index e4364b12580d3..a00aa8364bde2 100644 --- a/src/test/compile-fail/associated-types-issue-20346.rs +++ b/src/test/compile-fail/associated-types-issue-20346.rs @@ -11,7 +11,6 @@ // Test that we reliably check the value of the associated type. #![crate_type = "lib"] -#![feature(associated_types)] #![no_implicit_prelude] use std::option::Option::{self, None, Some}; diff --git a/src/test/compile-fail/associated-types-no-suitable-bound.rs b/src/test/compile-fail/associated-types-no-suitable-bound.rs index 6b85620409151..98f2355f9be1a 100644 --- a/src/test/compile-fail/associated-types-no-suitable-bound.rs +++ b/src/test/compile-fail/associated-types-no-suitable-bound.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> ::Value; @@ -26,4 +24,3 @@ impl Struct { fn main() { } - diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index 5a4ebeac41eef..a3f2850b29464 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - // Check that we get an error when you use `::Value` in // the trait definition but `Self` does not, in fact, implement `Get`. diff --git a/src/test/compile-fail/associated-types-path-1.rs b/src/test/compile-fail/associated-types-path-1.rs index 41f5bc17b561b..ab061ca4d8da6 100644 --- a/src/test/compile-fail/associated-types-path-1.rs +++ b/src/test/compile-fail/associated-types-path-1.rs @@ -10,8 +10,6 @@ // Test that we have one and only one associated type per ref. -#![feature(associated_types)] - pub trait Foo { type A; } @@ -23,4 +21,3 @@ pub fn f1(a: T, x: T::A) {} //~ERROR associated type `A` not found pub fn f2(a: T, x: T::A) {} //~ERROR ambiguous associated type `A` pub fn main() {} - diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index 989214d81da9e..ef85fc22fe7d4 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -10,8 +10,6 @@ // Test type checking of uses of associated types via sugary paths. -#![feature(associated_types)] - pub trait Foo { type A; } diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs index 1f0f044a4c0c3..c5245840c4285 100644 --- a/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs +++ b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs @@ -11,8 +11,6 @@ // Test you can't use a higher-ranked trait bound inside of a qualified // path (just won't parse). -#![feature(associated_types)] - pub trait Foo { type A; diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs index 0e13efdebc955..1f1ab4ca4b6d8 100644 --- a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs @@ -11,8 +11,6 @@ // Check projection of an associated type out of a higher-ranked // trait-bound in the context of a function body. -#![feature(associated_types)] - pub trait Foo { type A; diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs index 0d5c69591423b..0920bfab32b97 100644 --- a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs @@ -11,8 +11,6 @@ // Check projection of an associated type out of a higher-ranked trait-bound // in the context of a function signature. -#![feature(associated_types)] - pub trait Foo { type A; diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs index 5016c6448a50e..0acb0f4853bc2 100644 --- a/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs @@ -11,8 +11,6 @@ // Check projection of an associated type out of a higher-ranked trait-bound // in the context of a struct definition. -#![feature(associated_types)] - pub trait Foo { type A; diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs index a92d4ec04cb20..21e92c53058d6 100644 --- a/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs +++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs @@ -11,8 +11,6 @@ // Check projection of an associated type out of a higher-ranked trait-bound // in the context of a method definition in a trait. -#![feature(associated_types)] - pub trait Foo { type A; diff --git a/src/test/compile-fail/associated-types-unconstrained.rs b/src/test/compile-fail/associated-types-unconstrained.rs index 02e1121880678..968634669446a 100644 --- a/src/test/compile-fail/associated-types-unconstrained.rs +++ b/src/test/compile-fail/associated-types-unconstrained.rs @@ -10,8 +10,6 @@ // Check that an associated type cannot be bound in an expression path. -#![feature(associated_types)] - trait Foo { type A; fn bar() -> int; diff --git a/src/test/compile-fail/associated-types-unsized.rs b/src/test/compile-fail/associated-types-unsized.rs index 47ab09d279f62..5ae2f65fb2e47 100644 --- a/src/test/compile-fail/associated-types-unsized.rs +++ b/src/test/compile-fail/associated-types-unsized.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Sized? Value; fn get(&self) -> ::Value; @@ -21,4 +19,3 @@ fn foo(t: T) { fn main() { } - diff --git a/src/test/compile-fail/binop-consume-args.rs b/src/test/compile-fail/binop-consume-args.rs index 930000e5f0c37..2f26059330e48 100644 --- a/src/test/compile-fail/binop-consume-args.rs +++ b/src/test/compile-fail/binop-consume-args.rs @@ -10,7 +10,7 @@ // Test that binary operators consume their arguments -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr}; diff --git a/src/test/compile-fail/binop-move-semantics.rs b/src/test/compile-fail/binop-move-semantics.rs index e51ca6a70f28b..65e3564d913eb 100644 --- a/src/test/compile-fail/binop-move-semantics.rs +++ b/src/test/compile-fail/binop-move-semantics.rs @@ -10,7 +10,7 @@ // Test that move restrictions are enforced on overloaded binary operations -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops::Add; diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs index 7cd170f7773e9..66bcfc2380835 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -11,8 +11,6 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. -#![feature(associated_types)] - use std::ops::{Deref, DerefMut}; struct Own { diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs index 759467aeda36e..abab9e57ffe34 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs @@ -11,8 +11,6 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. -#![feature(associated_types)] - use std::ops::Deref; struct Rc { diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs index 74dceab18ea48..dda7e4d10474b 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs @@ -11,8 +11,6 @@ // Test how overloaded deref interacts with borrows when DerefMut // is implemented. -#![feature(associated_types)] - use std::ops::{Deref, DerefMut}; struct Own { diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs index 635e440c6fe12..001a5232b127f 100644 --- a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs +++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs @@ -11,8 +11,6 @@ // Test how overloaded deref interacts with borrows when only // Deref and not DerefMut is implemented. -#![feature(associated_types)] - use std::ops::Deref; struct Rc { diff --git a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs index 141dd8905bece..924d70e9f46c6 100644 --- a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Add; #[derive(Clone)] diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index e0a961e5cc5fc..96782e226c4e2 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops::Add; diff --git a/src/test/compile-fail/borrowck-overloaded-index-2.rs b/src/test/compile-fail/borrowck-overloaded-index-2.rs index 87e647d16ddf8..53fb935755cf0 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-2.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Index; struct MyVec { diff --git a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs index e7bd7cdf0b79d..416e67dac0ced 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs @@ -11,8 +11,6 @@ // Test that we still see borrowck errors of various kinds when using // indexing and autoderef in combination. -#![feature(associated_types)] - use std::ops::{Index, IndexMut}; struct Foo { @@ -95,5 +93,3 @@ fn test9(mut f: Box, g: Bar, s: String) { fn main() { } - - diff --git a/src/test/compile-fail/borrowck-overloaded-index.rs b/src/test/compile-fail/borrowck-overloaded-index.rs index 532f32ce770a6..80b68dbf519ee 100644 --- a/src/test/compile-fail/borrowck-overloaded-index.rs +++ b/src/test/compile-fail/borrowck-overloaded-index.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::{Index, IndexMut}; struct Foo { @@ -70,5 +68,3 @@ fn main() { s[2] = 20; //~^ ERROR cannot assign to immutable dereference (dereference is implicit, due to indexing) } - - diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs index 06d20c3361bc9..e297ecaac233e 100644 --- a/src/test/compile-fail/dst-index.rs +++ b/src/test/compile-fail/dst-index.rs @@ -11,8 +11,6 @@ // Test that overloaded index expressions with DST result types // can't be used as rvalues -#![feature(associated_types)] - use std::ops::Index; use std::fmt::Show; diff --git a/src/test/compile-fail/infinite-autoderef.rs b/src/test/compile-fail/infinite-autoderef.rs index ab770c099e125..f0b9e796ae62d 100644 --- a/src/test/compile-fail/infinite-autoderef.rs +++ b/src/test/compile-fail/infinite-autoderef.rs @@ -10,8 +10,6 @@ // error-pattern: reached the recursion limit while auto-dereferencing -#![feature(associated_types)] - use std::ops::Deref; struct Foo; diff --git a/src/test/compile-fail/issue-18389.rs b/src/test/compile-fail/issue-18389.rs index 38ebbc062f048..37bb1cb1911e5 100644 --- a/src/test/compile-fail/issue-18389.rs +++ b/src/test/compile-fail/issue-18389.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(unboxed_closures)] -#![feature(associated_types)] use std::any::Any; use std::intrinsics::TypeId; diff --git a/src/test/compile-fail/issue-18566.rs b/src/test/compile-fail/issue-18566.rs index 491707a9e3104..0d1a1f16c2c93 100644 --- a/src/test/compile-fail/issue-18566.rs +++ b/src/test/compile-fail/issue-18566.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Deref; struct MyPtr<'a>(&'a mut uint); diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs index 49eeccb2b0cf1..95782630efc82 100644 --- a/src/test/compile-fail/issue-18611.rs +++ b/src/test/compile-fail/issue-18611.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - fn add_state(op: ::State) { //~^ ERROR the trait `HasState` is not implemented for the type `int` } diff --git a/src/test/compile-fail/issue-18819.rs b/src/test/compile-fail/issue-18819.rs index 32a51ee065b17..3a9de74104364 100644 --- a/src/test/compile-fail/issue-18819.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Foo { type Item; } diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs index 196a04db18a38..70fe6b9b6a868 100644 --- a/src/test/compile-fail/issue-19883.rs +++ b/src/test/compile-fail/issue-19883.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait From { type Output; diff --git a/src/test/compile-fail/issue-20005.rs b/src/test/compile-fail/issue-20005.rs index d9520583ca53b..b52f2b1b13857 100644 --- a/src/test/compile-fail/issue-20005.rs +++ b/src/test/compile-fail/issue-20005.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait From { type Result; diff --git a/src/test/compile-fail/static-reference-to-fn-2.rs b/src/test/compile-fail/static-reference-to-fn-2.rs index 2bdbdb4fde295..d58e89e7767e8 100644 --- a/src/test/compile-fail/static-reference-to-fn-2.rs +++ b/src/test/compile-fail/static-reference-to-fn-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - struct StateMachineIter<'a> { statefn: &'a StateMachineFunc<'a> } @@ -61,4 +59,3 @@ fn main() { println!("{}",it.next()); println!("{}",it.next()); } - diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index 7aa6ead89d7e0..30609ddc9446a 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -13,7 +13,7 @@ // (In this case the mul method should take &f64 and not f64) // See: #11450 -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops::Mul; diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs index fcfcce3ff1b78..3314b61320159 100644 --- a/src/test/run-pass/associated-types-basic.rs +++ b/src/test/run-pass/associated-types-basic.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Foo { type T; } @@ -23,4 +21,3 @@ fn main() { let y: int = 44; assert_eq!(x * 2, y); } - diff --git a/src/test/run-pass/associated-types-binding-in-where-clause.rs b/src/test/run-pass/associated-types-binding-in-where-clause.rs index e3bd587742c31..caf7d31a5fd45 100644 --- a/src/test/run-pass/associated-types-binding-in-where-clause.rs +++ b/src/test/run-pass/associated-types-binding-in-where-clause.rs @@ -10,8 +10,6 @@ // Test equality constraints on associated types in a where clause. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/run-pass/associated-types-bound.rs b/src/test/run-pass/associated-types-bound.rs index db5119132cc3f..c34a19e1d8242 100644 --- a/src/test/run-pass/associated-types-bound.rs +++ b/src/test/run-pass/associated-types-bound.rs @@ -10,8 +10,6 @@ // Test equality constraints on associated types in a where clause. -#![feature(associated_types)] - pub trait ToInt { fn to_int(&self) -> int; } diff --git a/src/test/run-pass/associated-types-cc.rs b/src/test/run-pass/associated-types-cc.rs index c0cf917aa4117..58aa351ba9c41 100644 --- a/src/test/run-pass/associated-types-cc.rs +++ b/src/test/run-pass/associated-types-cc.rs @@ -13,8 +13,6 @@ // Test that we are able to reference cross-crate traits that employ // associated types. -#![feature(associated_types)] - extern crate "associated-types-cc-lib" as bar; use bar::Bar; diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index 3b53203d218e0..d05275e6ffea7 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,7 +14,7 @@ // `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops::Deref; diff --git a/src/test/run-pass/associated-types-constant-type.rs b/src/test/run-pass/associated-types-constant-type.rs index ea2cf84b757c3..68b49af0d3b69 100644 --- a/src/test/run-pass/associated-types-constant-type.rs +++ b/src/test/run-pass/associated-types-constant-type.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait SignedUnsigned { type Opposite; fn convert(self) -> Self::Opposite; @@ -39,4 +37,3 @@ fn main() { let x = get(22); assert_eq!(22u, x); } - diff --git a/src/test/run-pass/associated-types-eq-obj.rs b/src/test/run-pass/associated-types-eq-obj.rs index f0343a743cb50..0ec8a3661906f 100644 --- a/src/test/run-pass/associated-types-eq-obj.rs +++ b/src/test/run-pass/associated-types-eq-obj.rs @@ -10,8 +10,6 @@ // Test equality constraints on associated types inside of an object type -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs index eb6a3111cc15b..388a2d7344731 100644 --- a/src/test/run-pass/associated-types-impl-redirect.rs +++ b/src/test/run-pass/associated-types-impl-redirect.rs @@ -16,7 +16,7 @@ // ignore-pretty -- FIXME(#17362) -#![feature(associated_types, lang_items, unboxed_closures)] +#![feature(lang_items, unboxed_closures)] #![no_implicit_prelude] use std::kinds::Sized; diff --git a/src/test/run-pass/associated-types-in-default-method.rs b/src/test/run-pass/associated-types-in-default-method.rs index e01b18a64db22..0ae6103715472 100644 --- a/src/test/run-pass/associated-types-in-default-method.rs +++ b/src/test/run-pass/associated-types-in-default-method.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> &::Value; @@ -35,5 +33,3 @@ fn main() { }; assert_eq!(*s.grab(), 100); } - - diff --git a/src/test/run-pass/associated-types-in-fn.rs b/src/test/run-pass/associated-types-in-fn.rs index 4ed213e85d878..4104f520a0c5d 100644 --- a/src/test/run-pass/associated-types-in-fn.rs +++ b/src/test/run-pass/associated-types-in-fn.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> &::Value; @@ -36,4 +34,3 @@ fn main() { }; assert_eq!(*grab(&s), 100); } - diff --git a/src/test/run-pass/associated-types-in-impl-generics.rs b/src/test/run-pass/associated-types-in-impl-generics.rs index f6aaaf3b3fa15..59f05e1184285 100644 --- a/src/test/run-pass/associated-types-in-impl-generics.rs +++ b/src/test/run-pass/associated-types-in-impl-generics.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> &::Value; @@ -44,4 +42,3 @@ fn main() { }; assert_eq!(*s.grab(), 100); } - diff --git a/src/test/run-pass/associated-types-in-inherent-method.rs b/src/test/run-pass/associated-types-in-inherent-method.rs index 341682692460f..951497709fd69 100644 --- a/src/test/run-pass/associated-types-in-inherent-method.rs +++ b/src/test/run-pass/associated-types-in-inherent-method.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> &::Value; @@ -38,4 +36,3 @@ fn main() { }; assert_eq!(*Struct::grab(&s), 100); } - diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs index a6fb2b9e2ea53..d35b7331d4dbf 100644 --- a/src/test/run-pass/associated-types-issue-20371.rs +++ b/src/test/run-pass/associated-types-issue-20371.rs @@ -11,7 +11,6 @@ // Test that we are able to have an impl that defines an associated type // before the actual trait. -#![feature(associated_types)] impl X for f64 { type Y = int; } trait X {type Y; } fn main() {} diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs index 0fd477204215e..00237e2fb0f0f 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs @@ -11,8 +11,6 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. -#![feature(associated_types)] - struct Splits<'a, T, P>; struct SplitsN; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs index f09c27029d7fa..dcfdba5e746c3 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -11,8 +11,6 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. -#![feature(associated_types)] - struct Splits<'a, T, P>; struct SplitsN; diff --git a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs index 92daee5225d01..24dae20b3e77e 100644 --- a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs +++ b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs @@ -13,8 +13,6 @@ // this case, the `Result=Self` binding in the supertrait listing of // `Int` was being ignored. -#![feature(associated_types)] - trait Not { type Result; diff --git a/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs index 1b4eb2604a82b..abbde16faefca 100644 --- a/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs +++ b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Foo { type Bar; fn get_bar() -> >::Bar; diff --git a/src/test/run-pass/associated-types-resolve-lifetime.rs b/src/test/run-pass/associated-types-resolve-lifetime.rs index 1be09e1e0680d..e7a8061a3467a 100644 --- a/src/test/run-pass/associated-types-resolve-lifetime.rs +++ b/src/test/run-pass/associated-types-resolve-lifetime.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { fn get(&self) -> T; } diff --git a/src/test/run-pass/associated-types-return.rs b/src/test/run-pass/associated-types-return.rs index 1c2ff46689546..b9b6d14f8a071 100644 --- a/src/test/run-pass/associated-types-return.rs +++ b/src/test/run-pass/associated-types-return.rs @@ -10,8 +10,6 @@ // Test equality constraints on associated types in a where clause. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> ::A; diff --git a/src/test/run-pass/associated-types-simple.rs b/src/test/run-pass/associated-types-simple.rs index 82ae0d89b4605..9e388dc3d347e 100644 --- a/src/test/run-pass/associated-types-simple.rs +++ b/src/test/run-pass/associated-types-simple.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { type Value; fn get(&self) -> &::Value; @@ -32,4 +30,3 @@ fn main() { }; assert_eq!(*s.get(), 100); } - diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 28c06f51cebc2..880554b61b2ff 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -10,8 +10,6 @@ // Test paths to associated types using the type-parameter-only sugar. -#![feature(associated_types)] - pub trait Foo { type A; fn boo(&self) -> Self::A; diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs index 8a1a090e919cc..abbe250b6279a 100644 --- a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs +++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs @@ -16,7 +16,7 @@ // ignore-pretty -- FIXME(#17362) pretty prints with `<<` which lexes wrong -#![feature(associated_types, lang_items, unboxed_closures)] +#![feature(lang_items, unboxed_closures)] #![no_implicit_prelude] use std::kinds::Sized; diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs index 0e0ed1f436c9a..0a12df53de232 100644 --- a/src/test/run-pass/dst-deref-mut.rs +++ b/src/test/run-pass/dst-deref-mut.rs @@ -10,8 +10,6 @@ // Test that a custom deref with a fat pointer return type does not ICE -#![feature(associated_types)] - use std::ops::{Deref, DerefMut}; pub struct Arr { diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs index a39670a27b967..8ef8f1a868d51 100644 --- a/src/test/run-pass/dst-deref.rs +++ b/src/test/run-pass/dst-deref.rs @@ -10,8 +10,6 @@ // Test that a custom deref with a fat pointer return type does not ICE -#![feature(associated_types)] - use std::ops::Deref; pub struct Arr { diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs index 6a69bfc248f16..d1823359af135 100644 --- a/src/test/run-pass/dst-index.rs +++ b/src/test/run-pass/dst-index.rs @@ -11,8 +11,6 @@ // Test that overloaded index expressions with DST result types // work and don't ICE. -#![feature(associated_types)] - use std::ops::Index; use std::fmt::Show; diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs index 8fb3893e5decf..a673a67089a3a 100644 --- a/src/test/run-pass/fixup-deref-mut.rs +++ b/src/test/run-pass/fixup-deref-mut.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::{Deref, DerefMut}; // Generic unique/owned smaht pointer. @@ -55,4 +53,3 @@ fn test2(mut x: Own>>) { } fn main() {} - diff --git a/src/test/run-pass/issue-13167.rs b/src/test/run-pass/issue-13167.rs index ee556ce2c8459..21b54ba0e793b 100644 --- a/src/test/run-pass/issue-13167.rs +++ b/src/test/run-pass/issue-13167.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::slice; pub struct PhfMapEntries<'a, T: 'a> { diff --git a/src/test/run-pass/issue-13264.rs b/src/test/run-pass/issue-13264.rs index 00b508ab92c30..3c76a827fb295 100644 --- a/src/test/run-pass/issue-13264.rs +++ b/src/test/run-pass/issue-13264.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Deref; struct Root { diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index d66bbe9187a28..2e8bfc52832a7 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Matcher { fn next_match(&mut self) -> Option<(uint, uint)>; } diff --git a/src/test/run-pass/issue-15734.rs b/src/test/run-pass/issue-15734.rs index f261098f53811..e404f5fa11874 100644 --- a/src/test/run-pass/issue-15734.rs +++ b/src/test/run-pass/issue-15734.rs @@ -11,7 +11,7 @@ // If `Index` used an associated type for its output, this test would // work more smoothly. -#![feature(associated_types, old_orphan_check)] +#![feature(old_orphan_check)] use std::ops::Index; diff --git a/src/test/run-pass/issue-16596.rs b/src/test/run-pass/issue-16596.rs index 7bc6d989fa75c..e01de3a3262ed 100644 --- a/src/test/run-pass/issue-16596.rs +++ b/src/test/run-pass/issue-16596.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait MatrixRow {} struct Mat; diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs index 45cfabcd872ec..6ef4f868d2150 100644 --- a/src/test/run-pass/issue-16774.rs +++ b/src/test/run-pass/issue-16774.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types, unboxed_closures)] +#![feature(unboxed_closures)] use std::ops::{Deref, DerefMut}; diff --git a/src/test/run-pass/issue-17732.rs b/src/test/run-pass/issue-17732.rs index 45d3b53132dbf..b4bd55da59757 100644 --- a/src/test/run-pass/issue-17732.rs +++ b/src/test/run-pass/issue-17732.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] trait Person { type string; } diff --git a/src/test/run-pass/issue-19081.rs b/src/test/run-pass/issue-19081.rs index 57724ba91b02f..83ba322ba3013 100644 --- a/src/test/run-pass/issue-19081.rs +++ b/src/test/run-pass/issue-19081.rs @@ -10,8 +10,6 @@ // ignore-pretty -- FIXME(#17362) pretty prints as `Hash< { type Output; diff --git a/src/test/run-pass/issue-19129-2.rs b/src/test/run-pass/issue-19129-2.rs index aeaf5e3764459..d6b3a1908b82d 100644 --- a/src/test/run-pass/issue-19129-2.rs +++ b/src/test/run-pass/issue-19129-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Trait { type Output; diff --git a/src/test/run-pass/issue-19479.rs b/src/test/run-pass/issue-19479.rs index b3354530a0c38..91bc645b2d486 100644 --- a/src/test/run-pass/issue-19479.rs +++ b/src/test/run-pass/issue-19479.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] trait Base {} trait AssocA { type X: Base; diff --git a/src/test/run-pass/issue-19631.rs b/src/test/run-pass/issue-19631.rs index d036bab99f880..43116f63641de 100644 --- a/src/test/run-pass/issue-19631.rs +++ b/src/test/run-pass/issue-19631.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait PoolManager { type C; } diff --git a/src/test/run-pass/issue-19632.rs b/src/test/run-pass/issue-19632.rs index 9bc74e5017305..01a073a6889ae 100644 --- a/src/test/run-pass/issue-19632.rs +++ b/src/test/run-pass/issue-19632.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait PoolManager { type C; } diff --git a/src/test/run-pass/issue-19850.rs b/src/test/run-pass/issue-19850.rs index cd56fe1868924..a9ce6c7a9eb48 100644 --- a/src/test/run-pass/issue-19850.rs +++ b/src/test/run-pass/issue-19850.rs @@ -11,8 +11,6 @@ // Test that `::Output` and `Self::Output` are accepted as type annotations in let // bindings -#![feature(associated_types)] - trait Int { fn one() -> Self; fn leading_zeros(self) -> uint; diff --git a/src/test/run-pass/issue-20009.rs b/src/test/run-pass/issue-20009.rs index 535538793d1cf..374460487d8f2 100644 --- a/src/test/run-pass/issue-20009.rs +++ b/src/test/run-pass/issue-20009.rs @@ -10,8 +10,6 @@ // Check that associated types are `Sized` -#![feature(associated_types)] - trait Trait { type Output; diff --git a/src/test/run-pass/issue-20389.rs b/src/test/run-pass/issue-20389.rs index 0ef14149c9430..877cec48b5dc7 100644 --- a/src/test/run-pass/issue-20389.rs +++ b/src/test/run-pass/issue-20389.rs @@ -10,7 +10,6 @@ // aux-build:issue_20389.rs -#![feature(associated_types)] extern crate issue_20389; struct Foo; diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 741f168482da2..8868b6905ad07 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -10,7 +10,7 @@ // If `Mul` used an associated type for its output, this test would // work more smoothly. -#![feature(associated_types, default_type_params, old_orphan_check)] +#![feature(default_type_params, old_orphan_check)] use std::ops::Mul; diff --git a/src/test/run-pass/operator-multidispatch.rs b/src/test/run-pass/operator-multidispatch.rs index 5999840091967..7e1a8d8d7017f 100644 --- a/src/test/run-pass/operator-multidispatch.rs +++ b/src/test/run-pass/operator-multidispatch.rs @@ -11,7 +11,7 @@ // Test that we can overload the `+` operator for points so that two // points can be added, and a point can be added to an integer. -#![feature(associated_types, default_type_params)] +#![feature(default_type_params)] use std::ops; diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index 41e7586f1e3db..c20b7336deb32 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::cmp; use std::ops; diff --git a/src/test/run-pass/overloaded-autoderef-count.rs b/src/test/run-pass/overloaded-autoderef-count.rs index e9eb924d4493d..f0646853b6be8 100644 --- a/src/test/run-pass/overloaded-autoderef-count.rs +++ b/src/test/run-pass/overloaded-autoderef-count.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::cell::Cell; use std::ops::{Deref, DerefMut}; diff --git a/src/test/run-pass/overloaded-autoderef-indexing.rs b/src/test/run-pass/overloaded-autoderef-indexing.rs index 6d8d09b321ee5..de37173810f04 100644 --- a/src/test/run-pass/overloaded-autoderef-indexing.rs +++ b/src/test/run-pass/overloaded-autoderef-indexing.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Deref; struct DerefArray<'a, T:'a> { diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index cafb665fc370d..c34aed42c970f 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::rc::Rc; use std::ops::Deref; diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index 23efba157495c..be2b309b8217f 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::Deref; struct DerefWithHelper { diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs index b6fb38d5cc2cf..5cd76879798cb 100644 --- a/src/test/run-pass/overloaded-deref-count.rs +++ b/src/test/run-pass/overloaded-deref-count.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::cell::Cell; use std::ops::{Deref, DerefMut}; use std::vec::Vec; diff --git a/src/test/run-pass/overloaded-index-assoc-list.rs b/src/test/run-pass/overloaded-index-assoc-list.rs index 77bb981cfd9b9..aac0b5e06d004 100644 --- a/src/test/run-pass/overloaded-index-assoc-list.rs +++ b/src/test/run-pass/overloaded-index-assoc-list.rs @@ -11,8 +11,6 @@ // Test overloading of the `[]` operator. In particular test that it // takes its argument *by reference*. -#![feature(associated_types)] - use std::ops::Index; struct AssociationList { diff --git a/src/test/run-pass/overloaded-index-autoderef.rs b/src/test/run-pass/overloaded-index-autoderef.rs index d141234287d13..bc67c0afc7b52 100644 --- a/src/test/run-pass/overloaded-index-autoderef.rs +++ b/src/test/run-pass/overloaded-index-autoderef.rs @@ -10,8 +10,6 @@ // Test overloaded indexing combined with autoderef. -#![feature(associated_types)] - use std::ops::{Index, IndexMut}; struct Foo { @@ -84,4 +82,3 @@ fn main() { assert_eq!(f[1].get(), 5); assert_eq!(f[1].get_from_ref(), 5); } - diff --git a/src/test/run-pass/overloaded-index-in-field.rs b/src/test/run-pass/overloaded-index-in-field.rs index 9c6afc0912d06..487fb93c9fee8 100644 --- a/src/test/run-pass/overloaded-index-in-field.rs +++ b/src/test/run-pass/overloaded-index-in-field.rs @@ -11,8 +11,6 @@ // Test using overloaded indexing when the "map" is stored in a // field. This caused problems at some point. -#![feature(associated_types)] - use std::ops::Index; struct Foo { @@ -55,4 +53,3 @@ fn main() { } }; assert_eq!(f.foo[1].get(), 2); } - diff --git a/src/test/run-pass/overloaded-index.rs b/src/test/run-pass/overloaded-index.rs index fe09b47cf0a78..0afdb24a81cc0 100644 --- a/src/test/run-pass/overloaded-index.rs +++ b/src/test/run-pass/overloaded-index.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::ops::{Index, IndexMut}; struct Foo { @@ -75,4 +73,3 @@ fn main() { assert_eq!(f[1].get(), 5); assert_eq!(f[1].get_from_ref(), 5); } - diff --git a/src/test/run-pass/parse-assoc-type-lt.rs b/src/test/run-pass/parse-assoc-type-lt.rs index 8a68711a769fc..5649c4c784daf 100644 --- a/src/test/run-pass/parse-assoc-type-lt.rs +++ b/src/test/run-pass/parse-assoc-type-lt.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Foo { type T; fn foo() -> Box<::T>; diff --git a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs index d52c1c0b12c53..d3464f01203ac 100644 --- a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs +++ b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types, unsafe_destructor)] +#![feature(unsafe_destructor)] pub struct Foo; diff --git a/src/test/run-pass/simd-generics.rs b/src/test/run-pass/simd-generics.rs index ceb6b79042681..e89d5c9922dfa 100644 --- a/src/test/run-pass/simd-generics.rs +++ b/src/test/run-pass/simd-generics.rs @@ -9,7 +9,7 @@ // except according to those terms. -#![feature(associated_types, simd)] +#![feature(simd)] use std::ops; diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index 3e8db61b94044..43494458518cd 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - use std::cmp::PartialEq; use std::ops::{Add, Sub, Mul}; From b98a589e23a5471caa6698d953c6eec66304863d Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:32:59 +1100 Subject: [PATCH 042/106] Remove use of globs feature gate from tests. --- src/test/auxiliary/issue_2316_b.rs | 1 - src/test/auxiliary/macro_crate_test.rs | 2 +- src/test/auxiliary/namespaced_enum_emulate_flat.rs | 3 --- src/test/auxiliary/syntax-extension-with-dll-deps-2.rs | 2 +- src/test/compile-fail/glob-resolve1.rs | 2 -- src/test/compile-fail/import-glob-0.rs | 2 -- src/test/compile-fail/import-glob-circular.rs | 2 -- src/test/compile-fail/import-shadow-1.rs | 1 - src/test/compile-fail/import-shadow-2.rs | 1 - src/test/compile-fail/import-shadow-3.rs | 1 - src/test/compile-fail/import-shadow-4.rs | 1 - src/test/compile-fail/import-shadow-5.rs | 1 - src/test/compile-fail/import-shadow-6.rs | 1 - src/test/compile-fail/import-shadow-7.rs | 1 - src/test/compile-fail/issue-1697.rs | 2 -- src/test/compile-fail/issue-4366-2.rs | 3 --- src/test/compile-fail/issue-4366.rs | 2 -- src/test/compile-fail/issue-8208.rs | 3 --- src/test/compile-fail/lint-missing-doc.rs | 1 - src/test/compile-fail/lint-stability.rs | 2 +- src/test/compile-fail/lint-unused-extern-crate.rs | 1 - src/test/compile-fail/lint-unused-imports.rs | 1 - src/test/compile-fail/name-clash-nullary.rs | 2 -- .../namespaced-enum-glob-import-no-impls-xcrate.rs | 3 --- src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs | 1 - src/test/compile-fail/privacy-ns1.rs | 2 -- src/test/compile-fail/privacy-ns2.rs | 2 -- src/test/compile-fail/privacy1.rs | 2 +- src/test/compile-fail/privacy2.rs | 2 -- src/test/compile-fail/privacy3.rs | 1 - src/test/compile-fail/privacy4.rs | 2 +- src/test/compile-fail/std-uncopyable-atomics.rs | 1 - src/test/run-fail/glob-use-std.rs | 1 - src/test/run-pass/export-glob-imports-target.rs | 3 --- src/test/run-pass/import-glob-0.rs | 3 --- src/test/run-pass/import-glob-crate.rs | 2 -- src/test/run-pass/import-in-block.rs | 2 -- src/test/run-pass/intrinsics-integer.rs | 2 +- src/test/run-pass/intrinsics-math.rs | 2 +- src/test/run-pass/issue-16597.rs | 2 -- src/test/run-pass/issue-2526-a.rs | 1 - src/test/run-pass/issue-7663.rs | 1 - src/test/run-pass/namespaced-enum-emulate-flat.rs | 1 - src/test/run-pass/namespaced-enum-glob-import-xcrate.rs | 1 - src/test/run-pass/namespaced-enum-glob-import.rs | 1 - src/test/run-pass/privacy-ns.rs | 2 -- src/test/run-pass/reexport-star.rs | 2 -- src/test/run-pass/tag-exports.rs | 2 -- src/test/run-pass/tcp-connect-timeouts.rs | 2 +- 49 files changed, 8 insertions(+), 76 deletions(-) diff --git a/src/test/auxiliary/issue_2316_b.rs b/src/test/auxiliary/issue_2316_b.rs index 8a9fa4dbc4adf..8a212f6e5a9c5 100644 --- a/src/test/auxiliary/issue_2316_b.rs +++ b/src/test/auxiliary/issue_2316_b.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(unused_imports)] -#![feature(globs)] extern crate issue_2316_a; diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index b82cfcbc8fcb2..39c4e83c4b9da 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -10,7 +10,7 @@ // force-host -#![feature(globs, plugin_registrar, macro_rules, quote)] +#![feature(plugin_registrar, macro_rules, quote)] extern crate syntax; extern crate rustc; diff --git a/src/test/auxiliary/namespaced_enum_emulate_flat.rs b/src/test/auxiliary/namespaced_enum_emulate_flat.rs index c7387dd284ebf..7412c17fd45b2 100644 --- a/src/test/auxiliary/namespaced_enum_emulate_flat.rs +++ b/src/test/auxiliary/namespaced_enum_emulate_flat.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] pub use Foo::*; @@ -34,5 +33,3 @@ pub mod nest { pub fn foo() {} } } - - diff --git a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs b/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs index 88548bb5410e6..5ad1d244c926d 100644 --- a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs +++ b/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs @@ -11,7 +11,7 @@ // force-host #![crate_type = "dylib"] -#![feature(plugin_registrar, quote, globs)] +#![feature(plugin_registrar, quote)] extern crate "syntax-extension-with-dll-deps-1" as other; extern crate syntax; diff --git a/src/test/compile-fail/glob-resolve1.rs b/src/test/compile-fail/glob-resolve1.rs index 459a5d8c9e3cb..d8258a72ce35b 100644 --- a/src/test/compile-fail/glob-resolve1.rs +++ b/src/test/compile-fail/glob-resolve1.rs @@ -10,8 +10,6 @@ // Make sure that globs only bring in public things. -#![feature(globs)] - use bar::*; mod bar { diff --git a/src/test/compile-fail/import-glob-0.rs b/src/test/compile-fail/import-glob-0.rs index 210a47d2d039c..21aa811ea7188 100644 --- a/src/test/compile-fail/import-glob-0.rs +++ b/src/test/compile-fail/import-glob-0.rs @@ -10,8 +10,6 @@ // error-pattern: unresolved name -#![feature(globs)] - use module_of_many_things::*; mod module_of_many_things { diff --git a/src/test/compile-fail/import-glob-circular.rs b/src/test/compile-fail/import-glob-circular.rs index 39b18e1c445a2..fda7b190d72b4 100644 --- a/src/test/compile-fail/import-glob-circular.rs +++ b/src/test/compile-fail/import-glob-circular.rs @@ -10,8 +10,6 @@ // error-pattern: unresolved -#![feature(globs)] - mod circ1 { pub use circ2::f2; pub fn f1() { println!("f1"); } diff --git a/src/test/compile-fail/import-shadow-1.rs b/src/test/compile-fail/import-shadow-1.rs index 007b28b6924e4..eac5a98140f89 100644 --- a/src/test/compile-fail/import-shadow-1.rs +++ b/src/test/compile-fail/import-shadow-1.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::*; use bar::*; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-2.rs b/src/test/compile-fail/import-shadow-2.rs index e597b55738386..8b0809fd55a8a 100644 --- a/src/test/compile-fail/import-shadow-2.rs +++ b/src/test/compile-fail/import-shadow-2.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::*; use foo::*; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-3.rs b/src/test/compile-fail/import-shadow-3.rs index 68222fa3fd727..cef481af6ba5f 100644 --- a/src/test/compile-fail/import-shadow-3.rs +++ b/src/test/compile-fail/import-shadow-3.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::Baz; use bar::*; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-4.rs b/src/test/compile-fail/import-shadow-4.rs index c698004bda0e4..919eea0e04601 100644 --- a/src/test/compile-fail/import-shadow-4.rs +++ b/src/test/compile-fail/import-shadow-4.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::*; use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-5.rs b/src/test/compile-fail/import-shadow-5.rs index 6ad7e5ec3e260..df17b7f0a2057 100644 --- a/src/test/compile-fail/import-shadow-5.rs +++ b/src/test/compile-fail/import-shadow-5.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::Baz; use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/import-shadow-6.rs index 1864251e71b42..94269043b0205 100644 --- a/src/test/compile-fail/import-shadow-6.rs +++ b/src/test/compile-fail/import-shadow-6.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use qux::*; use foo::*; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/import-shadow-7.rs b/src/test/compile-fail/import-shadow-7.rs index a2df266fb74f3..b3bac380710cd 100644 --- a/src/test/compile-fail/import-shadow-7.rs +++ b/src/test/compile-fail/import-shadow-7.rs @@ -11,7 +11,6 @@ // Test that import shadowing using globs causes errors #![no_implicit_prelude] -#![feature(globs)] use foo::*; use qux::*; //~ERROR a type named `Baz` has already been imported in this module diff --git a/src/test/compile-fail/issue-1697.rs b/src/test/compile-fail/issue-1697.rs index 46d9a558d9ea9..f2d858391cea2 100644 --- a/src/test/compile-fail/issue-1697.rs +++ b/src/test/compile-fail/issue-1697.rs @@ -10,8 +10,6 @@ // Testing that we don't fail abnormally after hitting the errors -#![feature(globs)] - use unresolved::*; //~ ERROR unresolved import `unresolved::*`. Maybe a missing `extern crate unres fn main() {} diff --git a/src/test/compile-fail/issue-4366-2.rs b/src/test/compile-fail/issue-4366-2.rs index 373e7339b6939..289e9855525ac 100644 --- a/src/test/compile-fail/issue-4366-2.rs +++ b/src/test/compile-fail/issue-4366-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - // ensures that 'use foo:*' doesn't import non-public item use m1::*; @@ -36,4 +34,3 @@ mod m1 { fn main() { foo(); //~ ERROR: unresolved name } - diff --git a/src/test/compile-fail/issue-4366.rs b/src/test/compile-fail/issue-4366.rs index 7959078359cf0..289aa21e1cba5 100644 --- a/src/test/compile-fail/issue-4366.rs +++ b/src/test/compile-fail/issue-4366.rs @@ -13,8 +13,6 @@ // ensures that 'use foo:*' doesn't import non-public 'use' statements in the // module 'foo' -#![feature(globs)] - use m1::*; mod foo { diff --git a/src/test/compile-fail/issue-8208.rs b/src/test/compile-fail/issue-8208.rs index 8d8e87da76e07..7e3f1171e252f 100644 --- a/src/test/compile-fail/issue-8208.rs +++ b/src/test/compile-fail/issue-8208.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - use self::*; //~ ERROR: unresolved import fn main() { } - diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index b73c3fa261050..e50f636050c53 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -10,7 +10,6 @@ // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. -#![feature(globs)] #![deny(missing_docs)] #![allow(dead_code)] #![allow(missing_copy_implementations)] diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 8e1723ddab24c..6d59f2c650184 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -13,7 +13,7 @@ // aux-build:stability_cfg1.rs // aux-build:stability_cfg2.rs -#![feature(globs, phase)] +#![feature(phase)] #![deny(unstable)] #![deny(deprecated)] #![deny(experimental)] diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index 93190a0ffe5cd..a77de551f5d2c 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -10,7 +10,6 @@ // aux-build:lint-unused-extern-crate.rs -#![feature(globs)] #![deny(unused_extern_crates)] #![allow(unused_variables)] diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs index b1a6c82a734fe..b5c0dce6e531e 100644 --- a/src/test/compile-fail/lint-unused-imports.rs +++ b/src/test/compile-fail/lint-unused-imports.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] #![deny(unused_imports)] #![allow(dead_code)] diff --git a/src/test/compile-fail/name-clash-nullary.rs b/src/test/compile-fail/name-clash-nullary.rs index b5c0157cb5e29..2f0588b261e54 100644 --- a/src/test/compile-fail/name-clash-nullary.rs +++ b/src/test/compile-fail/name-clash-nullary.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - // error-pattern:declaration of `None` shadows use std::option::*; diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs index 120f092d732f9..4fcb31d36865a 100644 --- a/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs +++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs @@ -9,8 +9,6 @@ // except according to those terms. // aux-build:namespaced_enums.rs -#![feature(globs)] - extern crate namespaced_enums; mod m { @@ -25,4 +23,3 @@ pub fn main() { bar(); //~ ERROR unresolved name `bar` m::bar(); //~ ERROR unresolved name `m::bar` } - diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs index a8f4e6ba0903b..602ec9ba76280 100644 --- a/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs +++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] mod m2 { pub enum Foo { diff --git a/src/test/compile-fail/privacy-ns1.rs b/src/test/compile-fail/privacy-ns1.rs index 2862268b55257..5952f05b7bc4c 100644 --- a/src/test/compile-fail/privacy-ns1.rs +++ b/src/test/compile-fail/privacy-ns1.rs @@ -11,7 +11,6 @@ // Check we do the correct privacy checks when we import a name and there is an // item with that name in both the value and type namespaces. -#![feature(globs)] #![allow(dead_code)] #![allow(unused_imports)] @@ -64,4 +63,3 @@ fn test_glob3() { fn main() { } - diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs index 769bdae80f118..7fe0574ab7d9a 100644 --- a/src/test/compile-fail/privacy-ns2.rs +++ b/src/test/compile-fail/privacy-ns2.rs @@ -11,7 +11,6 @@ // Check we do the correct privacy checks when we import a name and there is an // item with that name in both the value and type namespaces. -#![feature(globs)] #![allow(dead_code)] #![allow(unused_imports)] @@ -88,4 +87,3 @@ fn test_list3() { fn main() { } - diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 41621a934d17a..ffee00642acf6 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, lang_items)] +#![feature(lang_items)] #![no_std] // makes debugging this test *a lot* easier (during resolve) #[lang="sized"] diff --git a/src/test/compile-fail/privacy2.rs b/src/test/compile-fail/privacy2.rs index 1a94751b46bfe..b38d7aedf841c 100644 --- a/src/test/compile-fail/privacy2.rs +++ b/src/test/compile-fail/privacy2.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] #![no_std] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that globs don't leak in regular `use` statements. @@ -34,4 +33,3 @@ fn test2() { } #[start] fn main(_: int, _: *const *const u8) -> int { 3 } - diff --git a/src/test/compile-fail/privacy3.rs b/src/test/compile-fail/privacy3.rs index 4c67a9910cfe9..5ec10d5a4caa9 100644 --- a/src/test/compile-fail/privacy3.rs +++ b/src/test/compile-fail/privacy3.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] #![no_std] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that private items imported through globs remain private diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index 70e7e2df98a69..7bfeb88864530 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, lang_items)] +#![feature(lang_items)] #![no_std] // makes debugging this test *a lot* easier (during resolve) #[lang = "sized"] pub trait Sized for Sized? {} diff --git a/src/test/compile-fail/std-uncopyable-atomics.rs b/src/test/compile-fail/std-uncopyable-atomics.rs index a97a3e6167819..5ebabc2e3548c 100644 --- a/src/test/compile-fail/std-uncopyable-atomics.rs +++ b/src/test/compile-fail/std-uncopyable-atomics.rs @@ -10,7 +10,6 @@ // Issue #8380 -#![feature(globs)] use std::sync::atomic::*; use std::ptr; diff --git a/src/test/run-fail/glob-use-std.rs b/src/test/run-fail/glob-use-std.rs index 939845a7b349a..6712b3b065908 100644 --- a/src/test/run-fail/glob-use-std.rs +++ b/src/test/run-fail/glob-use-std.rs @@ -15,7 +15,6 @@ // Expanded pretty printing causes resolve conflicts. // error-pattern:panic works -#![feature(globs)] use std::*; diff --git a/src/test/run-pass/export-glob-imports-target.rs b/src/test/run-pass/export-glob-imports-target.rs index b960a31bc0c71..da0a3e9e107e6 100644 --- a/src/test/run-pass/export-glob-imports-target.rs +++ b/src/test/run-pass/export-glob-imports-target.rs @@ -1,4 +1,3 @@ - // 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. @@ -14,8 +13,6 @@ // Modified to not use export since it's going away. --pcw -#![feature(globs)] - mod foo { use foo::bar::*; pub mod bar { diff --git a/src/test/run-pass/import-glob-0.rs b/src/test/run-pass/import-glob-0.rs index 44d9885205411..a57b8de629eb5 100644 --- a/src/test/run-pass/import-glob-0.rs +++ b/src/test/run-pass/import-glob-0.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - use module_of_many_things::*; use dug::too::greedily::and::too::deep::*; diff --git a/src/test/run-pass/import-glob-crate.rs b/src/test/run-pass/import-glob-crate.rs index 5ffcbb7e0fdd9..24d90741bbca4 100644 --- a/src/test/run-pass/import-glob-crate.rs +++ b/src/test/run-pass/import-glob-crate.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] #![allow(dead_assignment)] use std::mem::*; diff --git a/src/test/run-pass/import-in-block.rs b/src/test/run-pass/import-in-block.rs index 19300569d2050..3c28354dedcad 100644 --- a/src/test/run-pass/import-in-block.rs +++ b/src/test/run-pass/import-in-block.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] - pub fn main() { use std::mem::replace; let mut x = 5i; diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 5121e2185cb7b..2b0f7cc7d7d32 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, intrinsics)] +#![feature(intrinsics)] mod rusti { extern "rust-intrinsic" { diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 9f2fe155cdf95..523e7ab02d4a3 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -9,7 +9,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, macro_rules, intrinsics)] +#![feature(macro_rules, intrinsics)] macro_rules! assert_approx_eq( ($a:expr, $b:expr) => ({ diff --git a/src/test/run-pass/issue-16597.rs b/src/test/run-pass/issue-16597.rs index da1cf0a38ca1c..72e948e613b2e 100644 --- a/src/test/run-pass/issue-16597.rs +++ b/src/test/run-pass/issue-16597.rs @@ -11,8 +11,6 @@ // compile-flags:--test // ignore-pretty turns out the pretty-printer doesn't handle gensym'd things... -#![feature(globs)] - mod test { use super::*; diff --git a/src/test/run-pass/issue-2526-a.rs b/src/test/run-pass/issue-2526-a.rs index a8cbb0911b8ab..18c59dc9adc8e 100644 --- a/src/test/run-pass/issue-2526-a.rs +++ b/src/test/run-pass/issue-2526-a.rs @@ -10,7 +10,6 @@ // aux-build:issue-2526.rs -#![feature(globs)] #![allow(unused_imports)] extern crate issue_2526; diff --git a/src/test/run-pass/issue-7663.rs b/src/test/run-pass/issue-7663.rs index 39b0711721b54..0ff265e483efe 100644 --- a/src/test/run-pass/issue-7663.rs +++ b/src/test/run-pass/issue-7663.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] #![allow(unused_imports, dead_code)] mod test1 { diff --git a/src/test/run-pass/namespaced-enum-emulate-flat.rs b/src/test/run-pass/namespaced-enum-emulate-flat.rs index 676fe6500818e..e4a8ec19eb8e8 100644 --- a/src/test/run-pass/namespaced-enum-emulate-flat.rs +++ b/src/test/run-pass/namespaced-enum-emulate-flat.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] pub use Foo::*; use nest::{Bar, D, E, F}; diff --git a/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs index cc4985927f190..e5317c2f57302 100644 --- a/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs +++ b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:namespaced_enums.rs -#![feature(globs)] extern crate namespaced_enums; diff --git a/src/test/run-pass/namespaced-enum-glob-import.rs b/src/test/run-pass/namespaced-enum-glob-import.rs index 137dd543566bd..c48be3af248f0 100644 --- a/src/test/run-pass/namespaced-enum-glob-import.rs +++ b/src/test/run-pass/namespaced-enum-glob-import.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] mod m2 { pub enum Foo { diff --git a/src/test/run-pass/privacy-ns.rs b/src/test/run-pass/privacy-ns.rs index 336791e65fdee..f3380352f5fa9 100644 --- a/src/test/run-pass/privacy-ns.rs +++ b/src/test/run-pass/privacy-ns.rs @@ -12,7 +12,6 @@ // Check we do the correct privacy checks when we import a name and there is an // item with that name in both the value and type namespaces. -#![feature(globs)] #![allow(dead_code)] #![allow(unused_imports)] @@ -115,4 +114,3 @@ fn test_glob3() { fn main() { } - diff --git a/src/test/run-pass/reexport-star.rs b/src/test/run-pass/reexport-star.rs index 8de88aacae7fc..22ca737d42198 100644 --- a/src/test/run-pass/reexport-star.rs +++ b/src/test/run-pass/reexport-star.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] mod a { pub fn f() {} diff --git a/src/test/run-pass/tag-exports.rs b/src/test/run-pass/tag-exports.rs index 2177ab01db9c3..2eff97d31b25d 100644 --- a/src/test/run-pass/tag-exports.rs +++ b/src/test/run-pass/tag-exports.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs)] use alder::*; diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index 6812255d82ca0..2598679f92107 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -16,7 +16,7 @@ // one test task to ensure that errors are timeouts, not file descriptor // exhaustion. -#![feature(macro_rules, globs)] +#![feature(macro_rules)] #![allow(experimental)] #![reexport_test_harness_main = "test_main"] From 3e9d5938cc4030de2e8c8e140633cc4d7d58733c Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 5 Jan 2015 17:36:00 +1100 Subject: [PATCH 043/106] Remove uses of default_type_params feature gate from tests. --- src/test/auxiliary/default_type_params_xc.rs | 2 -- .../associated-types-ICE-when-projecting-out-of-err.rs | 2 +- src/test/compile-fail/binop-consume-args.rs | 2 -- src/test/compile-fail/binop-move-semantics.rs | 2 -- src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs | 2 -- .../compile-fail/generic-impl-less-params-with-defaults.rs | 2 -- .../compile-fail/generic-impl-more-params-with-defaults.rs | 2 -- src/test/compile-fail/generic-non-trailing-defaults.rs | 2 -- .../compile-fail/generic-type-less-params-with-defaults.rs | 2 -- .../compile-fail/generic-type-more-params-with-defaults.rs | 2 -- src/test/compile-fail/generic-type-params-forward-mention.rs | 2 -- src/test/compile-fail/generic-type-params-name-repr.rs | 2 -- src/test/compile-fail/unboxed-closure-sugar-default.rs | 2 +- src/test/compile-fail/unboxed-closure-sugar-region.rs | 2 +- src/test/compile-fail/wrong-mul-method-signature.rs | 2 -- src/test/run-pass/associated-types-conditional-dispatch.rs | 2 -- src/test/run-pass/eq-multidispatch.rs | 2 -- src/test/run-pass/generic-default-type-params-cross-crate.rs | 2 -- src/test/run-pass/generic-default-type-params.rs | 2 -- src/test/run-pass/issue-11709.rs | 2 -- src/test/run-pass/issue-14933.rs | 2 -- src/test/run-pass/issue-17897.rs | 2 +- src/test/run-pass/issue-18188.rs | 2 +- src/test/run-pass/issue-3609.rs | 2 -- src/test/run-pass/issue-3743.rs | 2 +- src/test/run-pass/operator-multidispatch.rs | 2 -- src/test/run-pass/overloaded-calls-param-vtables.rs | 3 +-- 27 files changed, 7 insertions(+), 48 deletions(-) diff --git a/src/test/auxiliary/default_type_params_xc.rs b/src/test/auxiliary/default_type_params_xc.rs index 0e0a206500821..d12f716decf99 100644 --- a/src/test/auxiliary/default_type_params_xc.rs +++ b/src/test/auxiliary/default_type_params_xc.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - pub struct Heap; pub struct FakeHeap; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 0abec3e1d12a5..f67f65ec2ef93 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -12,7 +12,7 @@ // just propagate the error. #![crate_type = "lib"] -#![feature(default_type_params, lang_items)] +#![feature(lang_items)] #![no_std] #[lang="sized"] diff --git a/src/test/compile-fail/binop-consume-args.rs b/src/test/compile-fail/binop-consume-args.rs index 2f26059330e48..c525a67c7e9f8 100644 --- a/src/test/compile-fail/binop-consume-args.rs +++ b/src/test/compile-fail/binop-consume-args.rs @@ -10,8 +10,6 @@ // Test that binary operators consume their arguments -#![feature(default_type_params)] - use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr}; fn add, B>(lhs: A, rhs: B) { diff --git a/src/test/compile-fail/binop-move-semantics.rs b/src/test/compile-fail/binop-move-semantics.rs index 65e3564d913eb..ffc38cc0a6005 100644 --- a/src/test/compile-fail/binop-move-semantics.rs +++ b/src/test/compile-fail/binop-move-semantics.rs @@ -10,8 +10,6 @@ // Test that move restrictions are enforced on overloaded binary operations -#![feature(default_type_params)] - use std::ops::Add; fn double_move>(x: T) { diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index 96782e226c4e2..5aa2deb44f192 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - use std::ops::Add; #[derive(Copy)] diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 7e7eee3cfaca8..a8b1911426c42 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Foo; impl Foo { diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index ceaed9438be53..696235333a123 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Heap; struct Vec; diff --git a/src/test/compile-fail/generic-non-trailing-defaults.rs b/src/test/compile-fail/generic-non-trailing-defaults.rs index 0b6480fc17dcc..0cfb05b9332a4 100644 --- a/src/test/compile-fail/generic-non-trailing-defaults.rs +++ b/src/test/compile-fail/generic-non-trailing-defaults.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Heap; struct Vec; //~ ERROR type parameters with a default must be trailing diff --git a/src/test/compile-fail/generic-type-less-params-with-defaults.rs b/src/test/compile-fail/generic-type-less-params-with-defaults.rs index ec226061e2abe..f25d8f99b8d54 100644 --- a/src/test/compile-fail/generic-type-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-less-params-with-defaults.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Heap; struct Vec; diff --git a/src/test/compile-fail/generic-type-more-params-with-defaults.rs b/src/test/compile-fail/generic-type-more-params-with-defaults.rs index b16abd1757548..ee3e1818779f3 100644 --- a/src/test/compile-fail/generic-type-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-more-params-with-defaults.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Heap; struct Vec; diff --git a/src/test/compile-fail/generic-type-params-forward-mention.rs b/src/test/compile-fail/generic-type-params-forward-mention.rs index ace53fb51a405..eda1b014fa7a4 100644 --- a/src/test/compile-fail/generic-type-params-forward-mention.rs +++ b/src/test/compile-fail/generic-type-params-forward-mention.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - // Ensure that we get an error and not an ICE for this problematic case. struct Foo, U = bool>; //~^ ERROR type parameters with a default cannot use forward declared identifiers diff --git a/src/test/compile-fail/generic-type-params-name-repr.rs b/src/test/compile-fail/generic-type-params-name-repr.rs index 1c14644ec186d..5bdee543d738d 100644 --- a/src/test/compile-fail/generic-type-params-name-repr.rs +++ b/src/test/compile-fail/generic-type-params-name-repr.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct A; struct B; struct C; diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 06a934063927a..a7861c4b90d67 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -11,7 +11,7 @@ // Test interaction between unboxed closure sugar and default type // parameters (should be exactly as if angle brackets were used). -#![feature(default_type_params, unboxed_closures)] +#![feature(unboxed_closures)] #![allow(dead_code)] trait Foo { diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index a938f126c1607..df53ecdac7c26 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -12,7 +12,7 @@ // parameters (should be exactly as if angle brackets were used // and regions omitted). -#![feature(default_type_params, unboxed_closures)] +#![feature(unboxed_closures)] #![allow(dead_code)] use std::kinds::marker; diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index 30609ddc9446a..e6fbcf2d38f2b 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -13,8 +13,6 @@ // (In this case the mul method should take &f64 and not f64) // See: #11450 -#![feature(default_type_params)] - use std::ops::Mul; struct Vec1 { diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index d05275e6ffea7..46cf9110476d0 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,8 +14,6 @@ // `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. -#![feature(default_type_params)] - use std::ops::Deref; pub trait MyEq for Sized? { diff --git a/src/test/run-pass/eq-multidispatch.rs b/src/test/run-pass/eq-multidispatch.rs index 31ed212db999c..2dcf6bf6d0907 100644 --- a/src/test/run-pass/eq-multidispatch.rs +++ b/src/test/run-pass/eq-multidispatch.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - #[derive(PartialEq)] struct Bar; struct Baz; diff --git a/src/test/run-pass/generic-default-type-params-cross-crate.rs b/src/test/run-pass/generic-default-type-params-cross-crate.rs index bb956b9ed8901..ed8c6e73255bb 100644 --- a/src/test/run-pass/generic-default-type-params-cross-crate.rs +++ b/src/test/run-pass/generic-default-type-params-cross-crate.rs @@ -10,8 +10,6 @@ // aux-build:default_type_params_xc.rs -#![feature(default_type_params)] - extern crate default_type_params_xc; struct Vec; diff --git a/src/test/run-pass/generic-default-type-params.rs b/src/test/run-pass/generic-default-type-params.rs index e88801f14ed48..5ec478d39e34f 100644 --- a/src/test/run-pass/generic-default-type-params.rs +++ b/src/test/run-pass/generic-default-type-params.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - struct Foo { a: A } diff --git a/src/test/run-pass/issue-11709.rs b/src/test/run-pass/issue-11709.rs index f9d7956793297..4a07b5fc432c2 100644 --- a/src/test/run-pass/issue-11709.rs +++ b/src/test/run-pass/issue-11709.rs @@ -15,8 +15,6 @@ // when this bug was opened. The cases where the compiler // panics before the fix have a comment. -#![feature(default_type_params)] - use std::thunk::Thunk; struct S {x:()} diff --git a/src/test/run-pass/issue-14933.rs b/src/test/run-pass/issue-14933.rs index 9796322b264c9..549ed08aaf37a 100644 --- a/src/test/run-pass/issue-14933.rs +++ b/src/test/run-pass/issue-14933.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - pub type BigRat = T; fn main() {} diff --git a/src/test/run-pass/issue-17897.rs b/src/test/run-pass/issue-17897.rs index 49b03a974d868..da6c83142eab6 100644 --- a/src/test/run-pass/issue-17897.rs +++ b/src/test/run-pass/issue-17897.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params, unboxed_closures)] +#![feature(unboxed_closures)] use std::thunk::Thunk; diff --git a/src/test/run-pass/issue-18188.rs b/src/test/run-pass/issue-18188.rs index aa95856a8b5ba..a2152db6884ac 100644 --- a/src/test/run-pass/issue-18188.rs +++ b/src/test/run-pass/issue-18188.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params, unboxed_closures)] +#![feature(unboxed_closures)] use std::thunk::Thunk; diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index b89ee81a7274f..c3cfaf22dee05 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(default_type_params)] - use std::thread::Thread; use std::sync::mpsc::Sender; use std::thunk::Invoke; diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 8868b6905ad07..43852fb332400 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -10,7 +10,7 @@ // If `Mul` used an associated type for its output, this test would // work more smoothly. -#![feature(default_type_params, old_orphan_check)] +#![feature(old_orphan_check)] use std::ops::Mul; diff --git a/src/test/run-pass/operator-multidispatch.rs b/src/test/run-pass/operator-multidispatch.rs index 7e1a8d8d7017f..8e5750005e2e9 100644 --- a/src/test/run-pass/operator-multidispatch.rs +++ b/src/test/run-pass/operator-multidispatch.rs @@ -11,8 +11,6 @@ // Test that we can overload the `+` operator for points so that two // points can be added, and a point can be added to an integer. -#![feature(default_type_params)] - use std::ops; #[derive(Show,PartialEq,Eq)] diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index b3c9ec3dc934e..56887636d5dfb 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -10,7 +10,7 @@ // Tests that nested vtables work with overloaded calls. -#![feature(default_type_params, unboxed_closures)] +#![feature(unboxed_closures)] use std::ops::Fn; use std::ops::Add; @@ -27,4 +27,3 @@ fn main() { // ICE trigger G(1i); } - From 2c441958959e46fd03c7f2736806d75bebeebd30 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Sat, 3 Jan 2015 21:49:01 +0000 Subject: [PATCH 044/106] Make temporary directory names non-deterministic. The previous scheme made it possible for another user/attacker to cause the temporary directory creation scheme to panic. All you needed to know was the pid of the process you wanted to target ('other_pid') and the suffix it was using (let's pretend it's 'sfx') and then code such as this would, in essence, DOS it: for i in range(0u, 1001) { let tp = &Path::new(format!("/tmp/rs-{}-{}-sfx", other_pid, i)); match fs::mkdir(tp, io::USER_RWX) { _ => () } } Since the scheme retried only 1000 times to create a temporary directory before dying, the next time the attacked process called TempDir::new("sfx") after that would typically cause a panic. Of course, you don't necessarily need an attacker to cause such a DOS: creating 1000 temporary directories without closing any of the previous would be enough to DOS yourself. This patch broadly follows the OpenBSD implementation of mkstemp. It uses the operating system's random number generator to produce random directory names that are impractical to guess (and, just in case someone manages to do that, it retries creating the directory for a long time before giving up; OpenBSD retries INT_MAX times, although 1<<31 seems enough to thwart even the most patient attacker). As a small additional change, this patch also makes the argument that TempDir::new takes a prefix rather than a suffix. This is because 1) it more closely matches what mkstemp and friends do 2) if you're going to have a deterministic part of a filename, you really want it at the beginning so that shell completion is useful. --- src/libstd/io/tempfile.rs | 74 +++++++++++++++++++++-------------- src/test/run-pass/tempfile.rs | 2 +- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs index 45e0dd4e8e5df..394686be814f2 100644 --- a/src/libstd/io/tempfile.rs +++ b/src/libstd/io/tempfile.rs @@ -10,16 +10,18 @@ //! Temporary files and directories -use io::{fs, IoResult}; +use io::{fs, IoError, IoErrorKind, IoResult}; use io; -use libc; +use iter::{IteratorExt, range}; use ops::Drop; use option::Option; use option::Option::{None, Some}; use os; use path::{Path, GenericPath}; +use rand::{Rng, thread_rng}; use result::Result::{Ok, Err}; -use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; +use str::StrExt; +use string::String; /// A wrapper for a path to temporary directory implementing automatic /// scope-based deletion. @@ -31,7 +33,7 @@ use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; /// /// { /// // create a temporary directory -/// let tmpdir = match TempDir::new("mysuffix") { +/// let tmpdir = match TempDir::new("myprefix") { /// Ok(dir) => dir, /// Err(e) => panic!("couldn't create temporary directory: {}", e) /// }; @@ -46,7 +48,7 @@ use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; /// } /// { /// // create a temporary directory, this time using a custom path -/// let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "mysuffix") { +/// let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "myprefix") { /// Ok(dir) => dir, /// Err(e) => panic!("couldn't create temporary directory: {}", e) /// }; @@ -61,7 +63,7 @@ use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; /// } /// { /// // create a temporary directory -/// let tmpdir = match TempDir::new("mysuffix") { +/// let tmpdir = match TempDir::new("myprefix") { /// Ok(dir) => dir, /// Err(e) => panic!("couldn't create temporary directory: {}", e) /// }; @@ -78,47 +80,59 @@ pub struct TempDir { disarmed: bool } +// How many times should we (re)try finding an unused random name? It should be +// enough that an attacker will run out of luck before we run out of patience. +const NUM_RETRIES: u32 = 1 << 31; +// How many characters should we include in a random file name? It needs to +// be enough to dissuade an attacker from trying to preemptively create names +// of that length, but not so huge that we unnecessarily drain the random number +// generator of entropy. +const NUM_RAND_CHARS: uint = 12; + impl TempDir { /// Attempts to make a temporary directory inside of `tmpdir` whose name - /// will have the suffix `suffix`. The directory will be automatically + /// will have the prefix `prefix`. The directory will be automatically /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. - pub fn new_in(tmpdir: &Path, suffix: &str) -> IoResult { + pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { let abs_tmpdir = try!(os::make_absolute(tmpdir)); - return TempDir::new_in(&abs_tmpdir, suffix); + return TempDir::new_in(&abs_tmpdir, prefix); } - static CNT: AtomicUint = ATOMIC_UINT_INIT; - - let mut attempts = 0u; - loop { - let filename = - format!("rs-{}-{}-{}", - unsafe { libc::getpid() }, - CNT.fetch_add(1, Ordering::SeqCst), - suffix); - let p = tmpdir.join(filename); - match fs::mkdir(&p, io::USER_RWX) { - Err(error) => { - if attempts >= 1000 { - return Err(error) - } - attempts += 1; - } - Ok(()) => return Ok(TempDir { path: Some(p), disarmed: false }) + let mut rng = thread_rng(); + for _ in range(0, NUM_RETRIES) { + let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect(); + let leaf = if prefix.len() > 0 { + format!("{}.{}", prefix, suffix) + } else { + // If we're given an empty string for a prefix, then creating a + // directory starting with "." would lead to it being + // semi-invisible on some systems. + suffix + }; + let path = tmpdir.join(leaf); + match fs::mkdir(&path, io::USER_RWX) { + Ok(_) => return Ok(TempDir { path: Some(path), disarmed: false }), + Err(IoError{kind:IoErrorKind::PathAlreadyExists,..}) => (), + Err(e) => return Err(e) } } + + return Err(IoError{ + kind: IoErrorKind::PathAlreadyExists, + desc:"Exhausted", + detail: None}); } /// Attempts to make a temporary directory inside of `os::tmpdir()` whose - /// name will have the suffix `suffix`. The directory will be automatically + /// name will have the prefix `prefix`. The directory will be automatically /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. - pub fn new(suffix: &str) -> IoResult { - TempDir::new_in(&os::tmpdir(), suffix) + pub fn new(prefix: &str) -> IoResult { + TempDir::new_in(&os::tmpdir(), prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 8fda8a951693f..9ca5fc94ffcb2 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -29,7 +29,7 @@ fn test_tempdir() { let path = { let p = TempDir::new_in(&Path::new("."), "foobar").unwrap(); let p = p.path(); - assert!(p.as_vec().ends_with(b"foobar")); + assert!(p.as_str().unwrap().contains("foobar")); p.clone() }; assert!(!path.exists()); From f677deeab397c8672c74fa134978df9aa10e0ff3 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 23 Dec 2014 13:55:12 +0200 Subject: [PATCH 045/106] Implement Clone for PRNGs --- src/librand/chacha.rs | 4 +--- src/librand/isaac.rs | 15 +++++++++++++++ src/librand/lib.rs | 13 ++----------- src/libstd/rand/mod.rs | 3 ++- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 71ce882e98ca9..79d836baece95 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -12,7 +12,6 @@ use core::prelude::*; use core::num::Int; - use {Rng, SeedableRng, Rand}; const KEY_WORDS : uint = 8; // 8 words for the 256-bit key @@ -28,8 +27,7 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of /// /// [1]: D. J. Bernstein, [*ChaCha, a variant of /// Salsa20*](http://cr.yp.to/chacha.html) - -#[derive(Copy)] +#[deriving(Copy, Clone)] pub struct ChaChaRng { buffer: [u32; STATE_WORDS], // Internal buffer of output state: [u32; STATE_WORDS], // Initial state diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 53ae242c5e245..c8a8da0818db8 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -179,6 +179,13 @@ impl IsaacRng { } } +// Cannot be derived because [u32; 256] does not implement Clone +impl Clone for IsaacRng { + fn clone(&self) -> IsaacRng { + *self + } +} + impl Rng for IsaacRng { #[inline] fn next_u32(&mut self) -> u32 { @@ -415,6 +422,13 @@ impl Isaac64Rng { } } +// Cannot be derived because [u32; 256] does not implement Clone +impl Clone for Isaac64Rng { + fn clone(&self) -> Isaac64Rng { + *self + } +} + impl Rng for Isaac64Rng { // FIXME #7771: having next_u32 like this should be unnecessary #[inline] @@ -485,6 +499,7 @@ impl Rand for Isaac64Rng { } } + #[cfg(test)] mod test { use std::prelude::v1::*; diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0f8dbc78cde32..d459bb83e98b5 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -385,6 +385,7 @@ pub trait SeedableRng: Rng { /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of /// Statistical Software*. Vol. 8 (Issue 14). #[allow(missing_copy_implementations)] +#[deriving(Clone)] pub struct XorShiftRng { x: u32, y: u32, @@ -392,17 +393,6 @@ pub struct XorShiftRng { w: u32, } -impl Clone for XorShiftRng { - fn clone(&self) -> XorShiftRng { - XorShiftRng { - x: self.x, - y: self.y, - z: self.z, - w: self.w, - } - } -} - impl XorShiftRng { /// Creates a new XorShiftRng instance which is not seeded. /// @@ -507,6 +497,7 @@ pub struct Closed01(pub F); #[cfg(not(test))] mod std { pub use core::{option, fmt}; // panic!() + pub use core::clone; // derive Clone pub use core::kinds; } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index aa28c8266d193..cadaae5de5c20 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -245,7 +245,7 @@ pub mod reader; /// The standard RNG. This is designed to be efficient on the current /// platform. -#[derive(Copy)] +#[deriving(Copy, Clone)] pub struct StdRng { rng: IsaacWordRng, } @@ -322,6 +322,7 @@ static THREAD_RNG_RESEED_THRESHOLD: uint = 32_768; type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. +#[deriving(Clone)] pub struct ThreadRng { rng: Rc>, } From 6ca1f0c6ea61760138c7e3cb4c14fa3be71c7414 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 3 Jan 2015 21:58:20 +0200 Subject: [PATCH 046/106] Add tests for ChaCha and Isaac Clone impls --- src/librand/chacha.rs | 10 ++++++++++ src/librand/isaac.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 79d836baece95..ce055a84d3f2a 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -281,5 +281,15 @@ mod test { 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4)); } + + #[test] + fn test_rng_clone() { + let seed : &[_] = &[0u32, ..8]; + let mut rng: ChaChaRng = SeedableRng::from_seed(seed); + let mut clone = rng.clone(); + for _ in range(0u, 16) { + assert_eq!(rng.next_u64(), clone.next_u64()); + } + } } diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index c8a8da0818db8..03b56963ba944 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -609,4 +609,14 @@ mod test { 596345674630742204, 9947027391921273664, 11788097613744130851, 10391409374914919106)); } + + #[test] + fn test_rng_clone() { + let seed: &[_] = &[1, 23, 456, 7890, 12345]; + let mut rng: Isaac64Rng = SeedableRng::from_seed(seed); + let mut clone = rng.clone(); + for _ in range(0u, 16) { + assert_eq!(rng.next_u64(), clone.next_u64()); + } + } } From 156a1c31346634c16beaf827d4d6efdfef6e2b36 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Mon, 5 Jan 2015 15:48:58 +0100 Subject: [PATCH 047/106] Implement a few methods for RingBuf * shrink_to_fit * swap_back_remove * swap_front_remove * truncate * resize --- src/libcollections/ring_buf.rs | 329 ++++++++++++++++++++++++++++++--- 1 file changed, 307 insertions(+), 22 deletions(-) diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index e86c40bed212f..f1a55f2674544 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -17,7 +17,7 @@ use core::prelude::*; use core::cmp::Ordering; use core::default::Default; use core::fmt; -use core::iter::{self, FromIterator, RandomAccessIterator}; +use core::iter::{self, repeat, FromIterator, RandomAccessIterator}; use core::kinds::marker; use core::mem; use core::num::{Int, UnsignedInt}; @@ -30,11 +30,8 @@ use std::cmp; use alloc::heap; -static INITIAL_CAPACITY: uint = 8u; // 2^3 -static MINIMUM_CAPACITY: uint = 2u; - -// FIXME(conventions): implement shrink_to_fit. Awkward with the current design, but it should -// be scrapped anyway. Defer to rewrite? +static INITIAL_CAPACITY: uint = 7u; // 2^3 - 1 +static MINIMUM_CAPACITY: uint = 1u; // 2 - 1 /// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently. #[stable] @@ -127,7 +124,20 @@ impl RingBuf { self.cap); ptr::copy_memory( self.ptr.offset(dst as int), - self.ptr.offset(src as int) as *const T, + self.ptr.offset(src as int), + len); + } + + /// Copies a contiguous block of memory len long from src to dst + #[inline] + unsafe fn copy_nonoverlapping(&self, dst: uint, src: uint, len: uint) { + debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len, + self.cap); + debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len, + self.cap); + ptr::copy_nonoverlapping_memory( + self.ptr.offset(dst as int), + self.ptr.offset(src as int), len); } } @@ -143,7 +153,8 @@ impl RingBuf { #[stable] pub fn with_capacity(n: uint) -> RingBuf { // +1 since the ringbuffer always leaves one space empty - let cap = cmp::max(n + 1, MINIMUM_CAPACITY).next_power_of_two(); + let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + assert!(cap > n, "capacity overflow"); let size = cap.checked_mul(mem::size_of::()) .expect("capacity overflow"); @@ -346,31 +357,134 @@ impl RingBuf { // Nop } else if self.head < oldcap - self.tail { // B unsafe { - ptr::copy_nonoverlapping_memory( - self.ptr.offset(oldcap as int), - self.ptr as *const T, - self.head - ); + self.copy_nonoverlapping(oldcap, 0, self.head); } self.head += oldcap; debug_assert!(self.head > self.tail); } else { // C + let new_tail = count - (oldcap - self.tail); unsafe { - ptr::copy_nonoverlapping_memory( - self.ptr.offset((count - (oldcap - self.tail)) as int), - self.ptr.offset(self.tail as int) as *const T, - oldcap - self.tail - ); + self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail); } - self.tail = count - (oldcap - self.tail); + self.tail = new_tail; + debug_assert!(self.head < self.tail); + } + debug_assert!(self.head < self.cap); + debug_assert!(self.tail < self.cap); + debug_assert!(self.cap.count_ones() == 1); + } + } + + /// Shrinks the capacity of the ringbuf as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator may still inform the + /// ringbuf that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::with_capacity(15); + /// buf.extend(range(0u, 4)); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to_fit(); + /// assert!(buf.capacity() >= 4); + /// ``` + pub fn shrink_to_fit(&mut self) { + // +1 since the ringbuffer always leaves one space empty + // len + 1 can't overflow for an existing, well-formed ringbuf. + let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + if target_cap < self.cap { + // There are three cases of interest: + // All elements are out of desired bounds + // Elements are contiguous, and head is out of desired bounds + // Elements are discontiguous, and tail is out of desired bounds + // + // At all other times, element positions are unaffected. + // + // Indicates that elements at the head should be moved. + let head_outside = self.head == 0 || self.head >= target_cap; + // Move elements from out of desired bounds (positions after target_cap) + if self.tail >= target_cap && head_outside { + // T H + // [. . . . . . . . o o o o o o o . ] + // T H + // [o o o o o o o . ] + unsafe { + self.copy_nonoverlapping(0, self.tail, self.len()); + } + self.head = self.len(); + self.tail = 0; + } else if self.tail != 0 && self.tail < target_cap && head_outside { + // T H + // [. . . o o o o o o o . . . . . . ] + // H T + // [o o . o o o o o ] + let len = self.wrap_index(self.head - target_cap); + unsafe { + self.copy_nonoverlapping(0, target_cap, len); + } + self.head = len; + debug_assert!(self.head < self.tail); + } else if self.tail >= target_cap { + // H T + // [o o o o o . . . . . . . . . o o ] + // H T + // [o o o o o . o o ] + debug_assert!(self.wrap_index(self.head - 1) < target_cap); + let len = self.cap - self.tail; + let new_tail = target_cap - len; + unsafe { + self.copy_nonoverlapping(new_tail, self.tail, len); + } + self.tail = new_tail; debug_assert!(self.head < self.tail); } + + if mem::size_of::() != 0 { + let old = self.cap * mem::size_of::(); + let new_size = target_cap * mem::size_of::(); + unsafe { + self.ptr = heap::reallocate(self.ptr as *mut u8, + old, + new_size, + mem::min_align_of::()) as *mut T; + if self.ptr.is_null() { ::alloc::oom() } + } + } + self.cap = target_cap; debug_assert!(self.head < self.cap); debug_assert!(self.tail < self.cap); debug_assert!(self.cap.count_ones() == 1); } } + /// Shorten a ringbuf, dropping excess elements from the back. + /// + /// If `len` is greater than the ringbuf's current length, this has no + /// effect. + /// + /// # Examples + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push_back(5i); + /// buf.push_back(10i); + /// buf.push_back(15); + /// buf.truncate(1); + /// assert_eq!(buf.len(), 1); + /// assert_eq!(Some(&5), buf.get(0)); + /// ``` + #[unstable = "matches collection reform specification; waiting on panic semantics"] + pub fn truncate(&mut self, len: uint) { + for _ in range(len, self.len()) { + self.pop_back(); + } + } + /// Returns a front-to-back iterator. /// /// # Examples @@ -735,6 +849,70 @@ impl RingBuf { self.tail <= self.head } + /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last + /// element. + /// + /// This does not preserve ordering, but is O(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// assert_eq!(buf.swap_back_remove(0), None); + /// buf.push_back(5i); + /// buf.push_back(99); + /// buf.push_back(15); + /// buf.push_back(20); + /// buf.push_back(10); + /// assert_eq!(buf.swap_back_remove(1), Some(99)); + /// ``` + #[unstable = "the naming of this function may be altered"] + pub fn swap_back_remove(&mut self, index: uint) -> Option { + let length = self.len(); + if length > 0 && index < length - 1 { + self.swap(index, length - 1); + } else if index >= length { + return None; + } + self.pop_back() + } + + /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first + /// element. + /// + /// This does not preserve ordering, but is O(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// assert_eq!(buf.swap_front_remove(0), None); + /// buf.push_back(15i); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(99); + /// buf.push_back(20i); + /// assert_eq!(buf.swap_front_remove(3), Some(99)); + /// ``` + #[unstable = "the naming of this function may be altered"] + pub fn swap_front_remove(&mut self, index: uint) -> Option { + let length = self.len(); + if length > 0 && index < length && index != 0 { + self.swap(index, 0); + } else if index >= length { + return None; + } + self.pop_front() + } + /// Inserts an element at position `i` within the ringbuf. Whichever /// end is closer to the insertion point will be moved to make room, /// and all the affected elements will be moved to new positions. @@ -743,7 +921,7 @@ impl RingBuf { /// /// Panics if `i` is greater than ringbuf's length /// - /// # Example + /// # Examples /// ```rust /// use std::collections::RingBuf; /// @@ -945,7 +1123,7 @@ impl RingBuf { /// room, and all the affected elements will be moved to new positions. /// Returns `None` if `i` is out of bounds. /// - /// # Example + /// # Examples /// ```rust /// use std::collections::RingBuf; /// @@ -990,7 +1168,7 @@ impl RingBuf { let distance_to_tail = i; let distance_to_head = self.len() - i; - let contiguous = self.tail <= self.head; + let contiguous = self.is_contiguous(); match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) { (true, true, _) => unsafe { @@ -1105,6 +1283,37 @@ impl RingBuf { } } +impl RingBuf { + /// Modifies the ringbuf in-place so that `len()` is equal to new_len, + /// either by removing excess elements or by appending copies of a value to the back. + /// + /// # Examples + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push_back(5i); + /// buf.push_back(10i); + /// buf.push_back(15); + /// buf.resize(2, 0); + /// buf.resize(6, 20); + /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) { + /// assert_eq!(a, b); + /// } + /// ``` + #[unstable = "matches collection reform specification; waiting on panic semantics"] + pub fn resize(&mut self, new_len: uint, value: T) { + let len = self.len(); + + if new_len > len { + self.extend(repeat(value).take(new_len - len)) + } else { + self.truncate(new_len); + } + } +} + /// Returns the index in the underlying buffer for a given logical element index. #[inline] fn wrap_index(index: uint, size: uint) -> uint { @@ -2292,6 +2501,50 @@ mod tests { assert_eq!(ring.get_mut(2), None); } + #[test] + fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = RingBuf::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in range(0, final_len) { + let expected = if back { + range(0, len).collect() + } else { + range(0, len).rev().collect() + }; + for tail_pos in range(0, usable_cap) { + tester.tail = tail_pos; + tester.head = tail_pos; + if back { + for i in range(0, len * 2) { + tester.push_front(i); + } + for i in range(0, len) { + assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); + } + } else { + for i in range(0, len * 2) { + tester.push_back(i); + } + for i in range(0, len) { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); + } + #[test] fn test_insert() { // This test checks that every single combination of tail position, length, and @@ -2363,6 +2616,38 @@ mod tests { } } + #[test] + fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = RingBuf::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in range(0, cap + 1) { + // 0, 1, 2, .., len - 1 + let expected = iter::count(0, 1).take(len).collect(); + for tail_pos in range(0, max_cap + 1) { + tester.tail = tail_pos; + tester.head = tail_pos; + tester.reserve(63); + for i in range(0, len) { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.tail < tester.cap); + assert!(tester.head < tester.cap); + assert_eq!(tester, expected); + } + } + } + #[test] fn test_front() { let mut ring = RingBuf::new(); From c8868942e845254abfd3623a709847d65e015a2f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 3 Jan 2015 04:40:33 -0500 Subject: [PATCH 048/106] Treat associated types the same as type parameters when it comes to region bounding. Fixes #20303. Strictly speaking, this is a [breaking-change] (if you are using associated types). You are no longer free to wantonly violate the type system rules by closing associated types into objects without any form of region bound. Instead you should add region bounds like `T::X : 'a`, just as you would with a normal type parameter. --- src/librustc/middle/infer/error_reporting.rs | 59 ++++++------- src/librustc/middle/infer/mod.rs | 28 ++++--- .../middle/infer/region_inference/mod.rs | 82 +++++++++++++----- src/librustc_typeck/check/regionck.rs | 63 +++++++------- src/librustc_typeck/check/regionmanip.rs | 25 ++++-- ...gions-close-associated-type-into-object.rs | 83 +++++++++++++++++++ .../regions-close-param-into-object.rs | 39 +++++++++ 7 files changed, 275 insertions(+), 104 deletions(-) create mode 100644 src/test/compile-fail/regions-close-associated-type-into-object.rs create mode 100644 src/test/compile-fail/regions-close-param-into-object.rs diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index c015c2307f65e..e58ff53b00cb9 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -66,7 +66,8 @@ use super::region_inference::RegionResolutionError; use super::region_inference::ConcreteFailure; use super::region_inference::SubSupConflict; use super::region_inference::SupSupConflict; -use super::region_inference::ParamBoundFailure; +use super::region_inference::GenericBoundFailure; +use super::region_inference::GenericKind; use super::region_inference::ProcessedErrors; use super::region_inference::SameRegions; @@ -120,11 +121,11 @@ pub trait ErrorReporting<'tcx> { sub: Region, sup: Region); - fn report_param_bound_failure(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - sups: Vec); + fn report_generic_bound_failure(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + sub: Region, + sups: Vec); fn report_sub_sup_conflict(&self, var_origin: RegionVariableOrigin, @@ -175,8 +176,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { self.report_concrete_failure(origin, sub, sup); } - ParamBoundFailure(origin, param_ty, sub, sups) => { - self.report_param_bound_failure(origin, param_ty, sub, sups); + GenericBoundFailure(kind, param_ty, sub, sups) => { + self.report_generic_bound_failure(kind, param_ty, sub, sups); } SubSupConflict(var_origin, @@ -421,30 +422,35 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { found.user_string(self.tcx))) } - fn report_param_bound_failure(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - _sups: Vec) { - + fn report_generic_bound_failure(&self, + origin: SubregionOrigin<'tcx>, + bound_kind: GenericKind<'tcx>, + sub: Region, + _sups: Vec) + { // FIXME: it would be better to report the first error message // with the span of the parameter itself, rather than the span // where the error was detected. But that span is not readily // accessible. + let labeled_user_string = match bound_kind { + GenericKind::Param(ref p) => + format!("the parameter type `{}`", p.user_string(self.tcx)), + GenericKind::Projection(ref p) => + format!("the associated type `{}`", p.user_string(self.tcx)), + }; + match sub { ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => { // Does the required lifetime have a nice name we can print? self.tcx.sess.span_err( origin.span(), - format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + format!("{} may not live long enough", labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: {}`...", - param_ty.user_string(self.tcx), + bound_kind.user_string(self.tcx), sub.user_string(self.tcx))[]); } @@ -452,14 +458,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { // Does the required lifetime have a nice name we can print? self.tcx.sess.span_err( origin.span(), - format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + format!("{} may not live long enough", labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( "consider adding an explicit lifetime bound `{}: 'static`...", - param_ty.user_string(self.tcx))[]); + bound_kind.user_string(self.tcx))[]); } _ => { @@ -467,17 +471,16 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.sess.span_err( origin.span(), format!( - "the parameter type `{}` may not live long enough", - param_ty.user_string(self.tcx))[]); + "{} may not live long enough", + labeled_user_string)[]); self.tcx.sess.span_help( origin.span(), format!( - "consider adding an explicit lifetime bound to `{}`", - param_ty.user_string(self.tcx))[]); + "consider adding an explicit lifetime bound for `{}`", + bound_kind.user_string(self.tcx))[]); note_and_explain_region( self.tcx, - format!("the parameter type `{}` must be valid for ", - param_ty.user_string(self.tcx))[], + format!("{} must be valid for ", labeled_user_string)[], sub, "..."); } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index e1401898f7a79..c2db81d311483 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -20,6 +20,7 @@ pub use self::ValuePairs::*; pub use self::fixup_err::*; pub use middle::ty::IntVarValue; pub use self::freshen::TypeFreshener; +pub use self::region_inference::GenericKind; use middle::subst; use middle::subst::Substs; @@ -382,19 +383,6 @@ pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, cx.region_vars.commit(snapshot); } -pub fn verify_param_bound<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - a: ty::Region, - bs: Vec) { - debug!("verify_param_bound({}, {} <: {})", - param_ty.repr(cx.tcx), - a.repr(cx.tcx), - bs.repr(cx.tcx)); - - cx.region_vars.verify_param_bound(origin, param_ty, a, bs); -} - pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a_is_expected: bool, origin: TypeOrigin, @@ -1070,6 +1058,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { value, |br, _| self.next_region_var(LateBoundRegion(span, br, lbrct))) } + + /// See `verify_generic_bound` method in `region_inference` + pub fn verify_generic_bound(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + a: ty::Region, + bs: Vec) { + debug!("verify_generic_bound({}, {} <: {})", + kind.repr(self.tcx), + a.repr(self.tcx), + bs.repr(self.tcx)); + + self.region_vars.verify_generic_bound(origin, kind, a, bs); + } } impl<'tcx> TypeTrace<'tcx> { diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index f0ee63c08e8b6..23e96dafa611b 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -22,7 +22,7 @@ use super::cres; use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable}; use middle::region; -use middle::ty; +use middle::ty::{mod, Ty}; use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid}; use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound}; use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; @@ -30,7 +30,7 @@ use middle::graph; use middle::graph::{Direction, NodeIndex}; use util::common::indenter; use util::nodemap::{FnvHashMap, FnvHashSet}; -use util::ppaux::Repr; +use util::ppaux::{Repr, UserString}; use std::cell::{Cell, RefCell}; use std::cmp::Ordering::{self, Less, Greater, Equal}; @@ -61,12 +61,18 @@ pub enum Verify<'tcx> { // `b` are inference variables. VerifyRegSubReg(SubregionOrigin<'tcx>, Region, Region), - // VerifyParamBound(T, _, R, RS): The parameter type `T` must - // outlive the region `R`. `T` is known to outlive `RS`. Therefore - // verify that `R <= RS[i]` for some `i`. Inference variables may - // be involved (but this verification step doesn't influence - // inference). - VerifyParamBound(ty::ParamTy, SubregionOrigin<'tcx>, Region, Vec), + // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or + // associated type) must outlive the region `R`. `T` is known to + // outlive `RS`. Therefore verify that `R <= RS[i]` for some + // `i`. Inference variables may be involved (but this verification + // step doesn't influence inference). + VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec), +} + +#[deriving(Clone, Show, PartialEq, Eq)] +pub enum GenericKind<'tcx> { + Param(ty::ParamTy), + Projection(ty::ProjectionTy<'tcx>), } #[derive(Copy, PartialEq, Eq, Hash)] @@ -98,12 +104,12 @@ pub enum RegionResolutionError<'tcx> { /// `o` requires that `a <= b`, but this does not hold ConcreteFailure(SubregionOrigin<'tcx>, Region, Region), - /// `ParamBoundFailure(p, s, a, bs) + /// `GenericBoundFailure(p, s, a, bs) /// - /// The parameter type `p` must be known to outlive the lifetime + /// The parameter/assocated-type `p` must be known to outlive the lifetime /// `a`, but it is only known to outlive `bs` (and none of the /// regions in `bs` outlive `a`). - ParamBoundFailure(SubregionOrigin<'tcx>, ty::ParamTy, Region, Vec), + GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec), /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`: /// @@ -489,12 +495,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } - pub fn verify_param_bound(&self, - origin: SubregionOrigin<'tcx>, - param_ty: ty::ParamTy, - sub: Region, - sups: Vec) { - self.add_verify(VerifyParamBound(param_ty, origin, sub, sups)); + /// See `Verify::VerifyGenericBound` + pub fn verify_generic_bound(&self, + origin: SubregionOrigin<'tcx>, + kind: GenericKind<'tcx>, + sub: Region, + sups: Vec) { + self.add_verify(VerifyGenericBound(kind, origin, sub, sups)); } pub fn lub_regions(&self, @@ -660,7 +667,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { &mut result_set, r, a, b); } - VerifyParamBound(_, _, a, ref bs) => { + VerifyGenericBound(_, _, a, ref bs) => { for &b in bs.iter() { consider_adding_bidirectional_edges( &mut result_set, r, @@ -1211,7 +1218,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { errors.push(ConcreteFailure((*origin).clone(), sub, sup)); } - VerifyParamBound(ref param_ty, ref origin, sub, ref sups) => { + VerifyGenericBound(ref kind, ref origin, sub, ref sups) => { let sub = normalize(values, sub); if sups.iter() .map(|&sup| normalize(values, sup)) @@ -1223,8 +1230,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { let sups = sups.iter().map(|&sup| normalize(values, sup)) .collect(); errors.push( - ParamBoundFailure( - (*origin).clone(), *param_ty, sub, sups)); + GenericBoundFailure( + (*origin).clone(), kind.clone(), sub, sups)); } } } @@ -1584,8 +1591,8 @@ impl<'tcx> Repr<'tcx> for Verify<'tcx> { VerifyRegSubReg(_, ref a, ref b) => { format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx)) } - VerifyParamBound(_, ref p, ref a, ref bs) => { - format!("VerifyParamBound({}, {}, {})", + VerifyGenericBound(_, ref p, ref a, ref bs) => { + format!("VerifyGenericBound({}, {}, {})", p.repr(tcx), a.repr(tcx), bs.repr(tcx)) } } @@ -1624,3 +1631,32 @@ impl<'tcx> Repr<'tcx> for RegionAndOrigin<'tcx> { self.origin.repr(tcx)) } } + +impl<'tcx> Repr<'tcx> for GenericKind<'tcx> { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + GenericKind::Param(ref p) => p.repr(tcx), + GenericKind::Projection(ref p) => p.repr(tcx), + } + } +} + +impl<'tcx> UserString<'tcx> for GenericKind<'tcx> { + fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String { + match *self { + GenericKind::Param(ref p) => p.user_string(tcx), + GenericKind::Projection(ref p) => p.user_string(tcx), + } + } +} + +impl<'tcx> GenericKind<'tcx> { + pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { + match *self { + GenericKind::Param(ref p) => + p.to_ty(tcx), + GenericKind::Projection(ref p) => + ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name), + } + } +} diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b5ddb528c2f2f..99216930dfef5 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -92,7 +92,7 @@ use middle::region::CodeExtent; use middle::traits; use middle::ty::{ReScope}; use middle::ty::{self, Ty, MethodCall}; -use middle::infer; +use middle::infer::{mod, GenericKind}; use middle::pat_util; use util::ppaux::{ty_to_string, Repr}; @@ -164,7 +164,7 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub struct Rcx<'a, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'tcx>, - region_param_pairs: Vec<(ty::Region, ty::ParamTy)>, + region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>, // id of innermost fn or loop repeating_scope: ast::NodeId, @@ -205,7 +205,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Rcx { fcx: fcx, repeating_scope: initial_repeating_scope, subject: subject, - region_param_pairs: Vec::new() } + region_bound_pairs: Vec::new() } } pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { @@ -286,12 +286,12 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { } }; - let len = self.region_param_pairs.len(); + let len = self.region_bound_pairs.len(); self.relate_free_regions(fn_sig[], body.id); link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs[]); self.visit_block(body); self.visit_region_obligations(body.id); - self.region_param_pairs.truncate(len); + self.region_bound_pairs.truncate(len); } fn visit_region_obligations(&mut self, node_id: ast::NodeId) @@ -357,11 +357,11 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // relationship that arises here, but // presently we do not.) } - regionmanip::RegionSubParamConstraint(_, r_a, p_b) => { - debug!("RegionSubParamConstraint: {} <= {}", - r_a.repr(tcx), p_b.repr(tcx)); + regionmanip::RegionSubGenericConstraint(_, r_a, ref generic_b) => { + debug!("RegionSubGenericConstraint: {} <= {}", + r_a.repr(tcx), generic_b.repr(tcx)); - self.region_param_pairs.push((r_a, p_b)); + self.region_bound_pairs.push((r_a, generic_b.clone())); } } } @@ -1477,31 +1477,31 @@ fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); rcx.fcx.mk_subr(o1, r_a, r_b); } - regionmanip::RegionSubParamConstraint(None, r_a, param_b) => { - param_must_outlive(rcx, origin.clone(), r_a, param_b); + regionmanip::RegionSubGenericConstraint(None, r_a, ref generic_b) => { + generic_must_outlive(rcx, origin.clone(), r_a, generic_b); } - regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => { + regionmanip::RegionSubGenericConstraint(Some(ty), r_a, ref generic_b) => { let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); - param_must_outlive(rcx, o1, r_a, param_b); + generic_must_outlive(rcx, o1, r_a, generic_b); } } } } -fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, - origin: infer::SubregionOrigin<'tcx>, - region: ty::Region, - param_ty: ty::ParamTy) { +fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region, + generic: &GenericKind<'tcx>) { let param_env = &rcx.fcx.inh.param_env; - debug!("param_must_outlive(region={}, param_ty={})", + debug!("param_must_outlive(region={}, generic={})", region.repr(rcx.tcx()), - param_ty.repr(rcx.tcx())); + generic.repr(rcx.tcx())); // To start, collect bounds from user: let mut param_bounds = ty::required_region_bounds(rcx.tcx(), - param_ty.to_ty(rcx.tcx()), + generic.to_ty(rcx.tcx()), param_env.caller_bounds.predicates.as_slice().to_vec()); // Add in the default bound of fn body that applies to all in @@ -1517,22 +1517,21 @@ fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, // fn foo<'a, A>(x: &'a A) { x.bar() } // // The problem is that the type of `x` is `&'a A`. To be - // well-formed, then, A must be lower-bounded by `'a`, but we + // well-formed, then, A must be lower-generic by `'a`, but we // don't know that this holds from first principles. - for &(ref r, ref p) in rcx.region_param_pairs.iter() { - debug!("param_ty={} p={}", - param_ty.repr(rcx.tcx()), + for &(ref r, ref p) in rcx.region_bound_pairs.iter() { + debug!("generic={} p={}", + generic.repr(rcx.tcx()), p.repr(rcx.tcx())); - if param_ty == *p { + if generic == p { param_bounds.push(*r); } } - // Inform region inference that this parameter type must be - // properly bounded. - infer::verify_param_bound(rcx.fcx.infcx(), - origin, - param_ty, - region, - param_bounds); + // Inform region inference that this generic must be properly + // bounded. + rcx.fcx.infcx().verify_generic_bound(origin, + generic.clone(), + region, + param_bounds); } diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs index 66cf077d4c21f..eb03e7bec07b7 100644 --- a/src/librustc_typeck/check/regionmanip.rs +++ b/src/librustc_typeck/check/regionmanip.rs @@ -12,6 +12,7 @@ pub use self::WfConstraint::*; +use middle::infer::GenericKind; use middle::subst::{ParamSpace, Subst, Substs}; use middle::ty::{self, Ty}; use middle::ty_fold::{TypeFolder}; @@ -24,7 +25,7 @@ use util::ppaux::Repr; pub enum WfConstraint<'tcx> { RegionSubRegionConstraint(Option>, ty::Region, ty::Region), - RegionSubParamConstraint(Option>, ty::Region, ty::ParamTy), + RegionSubGenericConstraint(Option>, ty::Region, GenericKind<'tcx>), } struct Wf<'a, 'tcx: 'a> { @@ -125,8 +126,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { ty::ty_projection(ref data) => { // `>::Name` - // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region, - // like a type parameter + self.push_projection_constraint_from_top(data); // this seems like a minimal requirement: let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id); @@ -215,12 +215,21 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { self.push_param_constraint(region, opt_ty, param_ty); } + /// Pushes a constraint that `projection_ty` must outlive the top region on the stack. + fn push_projection_constraint_from_top(&mut self, + projection_ty: &ty::ProjectionTy<'tcx>) { + let &(region, opt_ty) = self.stack.last().unwrap(); + self.out.push(RegionSubGenericConstraint( + opt_ty, region, GenericKind::Projection(projection_ty.clone()))); + } + /// Pushes a constraint that `region <= param_ty`, due to `opt_ty` fn push_param_constraint(&mut self, region: ty::Region, opt_ty: Option>, param_ty: ty::ParamTy) { - self.out.push(RegionSubParamConstraint(opt_ty, region, param_ty)); + self.out.push(RegionSubGenericConstraint( + opt_ty, region, GenericKind::Param(param_ty))); } fn accumulate_from_adt(&mut self, @@ -393,16 +402,16 @@ impl<'a, 'tcx> Wf<'a, 'tcx> { } impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> { - fn repr(&self, tcx: &ty::ctxt) -> String { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { - RegionSubRegionConstraint(_, r_a, r_b) => { + RegionSubRegionConstraint(_, ref r_a, ref r_b) => { format!("RegionSubRegionConstraint({}, {})", r_a.repr(tcx), r_b.repr(tcx)) } - RegionSubParamConstraint(_, r, p) => { - format!("RegionSubParamConstraint({}, {})", + RegionSubGenericConstraint(_, ref r, ref p) => { + format!("RegionSubGenericConstraint({}, {})", r.repr(tcx), p.repr(tcx)) } diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs new file mode 100644 index 0000000000000..84664078d5629 --- /dev/null +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -0,0 +1,83 @@ +// 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. + +#![feature(associated_types)] + +trait X {} + +trait Iter { + type Item: X; + + fn into_item(self) -> Self::Item; + fn as_item(&self) -> &Self::Item; +} + +fn bad1(v: T) -> Box +{ + let item = v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad2(v: T) -> Box + where Box : X +{ + let item = box v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad3<'a, T: Iter>(v: T) -> Box +{ + let item = v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn bad4<'a, T: Iter>(v: T) -> Box + where Box : X +{ + let item = box v.into_item(); + box item //~ ERROR associated type `::Item` may not live long enough +} + +fn ok1<'a, T: Iter>(v: T) -> Box + where T::Item : 'a +{ + let item = v.into_item(); + box item // OK, T::Item : 'a is declared +} + +fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box + where T::Item : Clone +{ + let item = Clone::clone(w); + box item // OK, T::Item : 'a is implied +} + +fn ok3<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone + 'a +{ + let item = Clone::clone(v.as_item()); + box item // OK, T::Item : 'a was declared +} + +fn meh1<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone +{ + // This case is kind of interesting. It's the same as `ok3` but + // without the explicit declaration. In principle, it seems like + // we ought to be able to infer that `T::Item : 'a` because we + // invoked `v.as_self()` which yielded a value of type `&'a + // T::Item`. But we're not that smart at present. + + let item = Clone::clone(v.as_item()); + box item //~ ERROR associated type `::Item` may not live +} + +fn main() {} + diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs new file mode 100644 index 0000000000000..3e91d090c3140 --- /dev/null +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -0,0 +1,39 @@ +// 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. + + +trait X {} + +fn p1(v: T) -> Box + where T : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p2(v: Box) -> Box + where Box : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p3<'a,T>(v: T) -> Box + where T : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn p4<'a,T>(v: Box) -> Box + where Box : X +{ + box v //~ ERROR parameter type `T` may not live long enough +} + +fn main() {} + From 05c5b5f03392edb9df8515f645883edd0bd8b816 Mon Sep 17 00:00:00 2001 From: FakeKane Date: Mon, 5 Jan 2015 08:57:43 -0500 Subject: [PATCH 049/106] reverting other changes --- src/libstd/tuple.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index f40b62182d42c..a12844f039ec6 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -10,18 +10,12 @@ //! Operations on tuples //! -//! To access a single element of a tuple one can use the following -//! methods: +//! To access the _N_-th element of a tuple one can use `N` itself +//! as a field of the tuple. //! -//! * `valN` - returns a value of _N_-th element -//! * `refN` - returns a reference to _N_-th element -//! * `mutN` - returns a mutable reference to _N_-th element -//! -//! Indexing starts from zero, so `val0` returns first value, `val1` +//! Indexing starts from zero, so `0` returns first value, `1` //! returns second value, and so on. In general, a tuple with _S_ -//! elements provides aforementioned methods suffixed with numbers -//! from `0` to `S-1`. Traits which contain these methods are -//! implemented for tuples with up to 12 elements. +//! elements provides aforementioned fields from `0` to `S-1` //! //! If every type inside a tuple implements one of the following //! traits, then a tuple itself also implements it. From ec7a50d20dff416d9fec837a6492dfe244f5f3ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 25 Nov 2014 13:28:35 -0800 Subject: [PATCH 050/106] std: Redesign c_str and c_vec This commit is an implementation of [RFC 494][rfc] which removes the entire `std::c_vec` module and redesigns the `std::c_str` module as `std::ffi`. [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0494-c_str-and-c_vec-stability.md The interface of the new `CString` is outlined in the linked RFC, the primary changes being: * The `ToCStr` trait is gone, meaning the `with_c_str` and `to_c_str` methods are now gone. These two methods are replaced with a `CString::from_slice` method. * The `CString` type is now just a wrapper around `Vec` with a static guarantee that there is a trailing nul byte with no internal nul bytes. This means that `CString` now implements `Deref`, which is where it gains most of its methods from. A few helper methods are added to acquire a slice of `u8` instead of `c_char`, as well as including a slice with the trailing nul byte if necessary. * All usage of non-owned `CString` values is now done via two functions inside of `std::ffi`, called `c_str_to_bytes` and `c_str_to_bytes_with_nul`. These functions are now the one method used to convert a `*const c_char` to a Rust slice of `u8`. Many more details, including newly deprecated methods, can be found linked in the RFC. This is a: [breaking-change] Closes #20444 --- src/doc/guide-ffi.md | 50 +- src/libcollections/string.rs | 42 - src/libcore/str/mod.rs | 2 +- src/libflate/lib.rs | 43 +- src/librustc/metadata/cstore.rs | 4 +- src/librustc/metadata/loader.rs | 12 +- src/librustc_llvm/archive_ro.rs | 13 +- src/librustc_llvm/lib.rs | 7 +- src/librustc_trans/back/lto.rs | 13 +- src/librustc_trans/back/write.rs | 112 ++- src/librustc_trans/trans/asm.rs | 19 +- src/librustc_trans/trans/base.rs | 89 +- src/librustc_trans/trans/builder.rs | 26 +- src/librustc_trans/trans/common.rs | 31 +- src/librustc_trans/trans/consts.rs | 6 +- src/librustc_trans/trans/context.rs | 27 +- src/librustc_trans/trans/debuginfo.rs | 526 ++++++------ src/librustc_trans/trans/foreign.rs | 28 +- src/librustc_trans/trans/glue.rs | 12 +- src/librustc_trans/trans/meth.rs | 8 +- src/librustc_trans/trans/type_.rs | 5 +- src/librustdoc/flock.rs | 10 +- src/librustdoc/html/markdown.rs | 16 +- src/libstd/c_str.rs | 857 ------------------- src/libstd/c_vec.rs | 232 ----- src/libstd/dynamic_lib.rs | 41 +- src/libstd/ffi/c_str.rs | 218 +++++ src/libstd/ffi/mod.rs | 20 + src/libstd/io/net/pipe.rs | 21 +- src/libstd/io/process.rs | 81 +- src/libstd/lib.rs | 6 +- src/libstd/os.rs | 41 +- src/libstd/path/mod.rs | 22 +- src/libstd/path/posix.rs | 31 +- src/libstd/path/windows.rs | 26 +- src/libstd/rt/args.rs | 11 +- src/libstd/rt/backtrace.rs | 2 +- src/libstd/rt/unwind.rs | 2 +- src/libstd/rt/util.rs | 2 +- src/libstd/sys/common/mod.rs | 2 +- src/libstd/sys/common/net.rs | 12 +- src/libstd/sys/unix/backtrace.rs | 23 +- src/libstd/sys/unix/fs.rs | 48 +- src/libstd/sys/unix/mod.rs | 13 +- src/libstd/sys/unix/os.rs | 31 +- src/libstd/sys/unix/pipe.rs | 4 +- src/libstd/sys/unix/process.rs | 6 +- src/libstd/sys/unix/timer.rs | 2 +- src/libstd/sys/windows/backtrace.rs | 18 +- src/libstd/sys/windows/c.rs | 17 +- src/libstd/sys/windows/fs.rs | 1 - src/libstd/sys/windows/pipe.rs | 21 +- src/libstd/sys/windows/process.rs | 31 +- src/test/auxiliary/linkage-visibility.rs | 2 +- src/test/run-pass/c-stack-returning-int64.rs | 8 +- src/test/run-pass/const-str-ptr.rs | 4 - src/test/run-pass/foreign-fn-linkname.rs | 11 +- src/test/run-pass/rename-directory.rs | 23 +- src/test/run-pass/variadic-ffi.rs | 35 +- 59 files changed, 1023 insertions(+), 2003 deletions(-) delete mode 100644 src/libstd/c_str.rs delete mode 100644 src/libstd/c_vec.rs create mode 100644 src/libstd/ffi/c_str.rs create mode 100644 src/libstd/ffi/mod.rs diff --git a/src/doc/guide-ffi.md b/src/doc/guide-ffi.md index b8808eaf57d93..7ee1c1a7032a5 100644 --- a/src/doc/guide-ffi.md +++ b/src/doc/guide-ffi.md @@ -451,7 +451,7 @@ them. ~~~no_run extern crate libc; -use std::c_str::ToCStr; +use std::ffi::CString; use std::ptr; #[link(name = "readline")] @@ -460,11 +460,10 @@ extern { } fn main() { - "[my-awesome-shell] $".with_c_str(|buf| { - unsafe { rl_prompt = buf; } - // get a line, process it - unsafe { rl_prompt = ptr::null(); } - }); + let prompt = CString::from_slice(b"[my-awesome-shell] $"); + unsafe { rl_prompt = prompt.as_ptr(); } + // get a line, process it + unsafe { rl_prompt = ptr::null(); } } ~~~ @@ -509,23 +508,28 @@ to define a block for all windows systems, not just x86 ones. # Interoperability with foreign code -Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C -only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out -struct members without padding. `#[repr(C)]` can also be applied to an enum. - -Rust's owned boxes (`Box`) use non-nullable pointers as handles which point to the contained -object. However, they should not be manually created because they are managed by internal -allocators. References can safely be assumed to be non-nullable pointers directly to the type. -However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer -using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about -them. - -Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and -`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a -NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function. - -The standard library includes type aliases and function definitions for the C standard library in -the `libc` module, and Rust links against `libc` and `libm` by default. +Rust guarantees that the layout of a `struct` is compatible with the platform's +representation in C only if the `#[repr(C)]` attribute is applied to it. +`#[repr(C, packed)]` can be used to lay out struct members without padding. +`#[repr(C)]` can also be applied to an enum. + +Rust's owned boxes (`Box`) use non-nullable pointers as handles which point +to the contained object. However, they should not be manually created because +they are managed by internal allocators. References can safely be assumed to be +non-nullable pointers directly to the type. However, breaking the borrow +checking or mutability rules is not guaranteed to be safe, so prefer using raw +pointers (`*`) if that's needed because the compiler can't make as many +assumptions about them. + +Vectors and strings share the same basic memory layout, and utilities are +available in the `vec` and `str` modules for working with C APIs. However, +strings are not terminated with `\0`. If you need a NUL-terminated string for +interoperability with C, you should use the `CString` type in the `std::ffi` +module. + +The standard library includes type aliases and function definitions for the C +standard library in the `libc` module, and Rust links against `libc` and `libm` +by default. # The "nullable pointer optimization" diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e7451331908ae..11e6c48cfdbad 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -320,30 +320,6 @@ impl String { } } - /// Creates a `String` from a null-terminated `*const u8` buffer. - /// - /// This function is unsafe because we dereference memory until we find the - /// NUL character, which is not guaranteed to be present. Additionally, the - /// slice is not checked to see whether it contains valid UTF-8 - #[unstable = "just renamed from `mod raw`"] - pub unsafe fn from_raw_buf(buf: *const u8) -> String { - String::from_str(str::from_c_str(buf as *const i8)) - } - - /// Creates a `String` from a `*const u8` buffer of the given length. - /// - /// This function is unsafe because it blindly assumes the validity of the - /// pointer `buf` for `len` bytes of memory. This function will copy the - /// memory from `buf` into a new allocation (owned by the returned - /// `String`). - /// - /// This function is also unsafe because it does not validate that the - /// buffer is valid UTF-8 encoded data. - #[unstable = "just renamed from `mod raw`"] - pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String { - String::from_utf8_unchecked(Vec::from_raw_buf(buf, len)) - } - /// Converts a vector of bytes to a new `String` without checking if /// it contains valid UTF-8. This is unsafe because it assumes that /// the UTF-8-ness of the vector has already been validated. @@ -1126,24 +1102,6 @@ mod tests { String::from_str("\u{FFFD}𐒋\u{FFFD}")); } - #[test] - fn test_from_buf_len() { - unsafe { - let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0]; - assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA")); - } - } - - #[test] - fn test_from_buf() { - unsafe { - let a = vec![65, 65, 65, 65, 65, 65, 65, 0]; - let b = a.as_ptr(); - let c = String::from_raw_buf(b); - assert_eq!(c, String::from_str("AAAAAAA")); - } - } - #[test] fn test_push_bytes() { let mut s = String::from_str("ABC"); diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..8fdd66f83cee4 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -190,7 +190,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { /// # Panics /// /// This function will panic if the string pointed to by `s` is not valid UTF-8. -#[unstable = "may change location based on the outcome of the c_str module"] +#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"] pub unsafe fn from_c_str(s: *const i8) -> &'static str { let s = s as *const u8; let mut len = 0u; diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index aa1550ae5b874..a0c9da3ae6d49 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -21,15 +21,34 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(phase, unboxed_closures)] +#![feature(phase, unboxed_closures, associated_types)] #[cfg(test)] #[phase(plugin, link)] extern crate log; extern crate libc; use libc::{c_void, size_t, c_int}; -use std::c_vec::CVec; +use std::ops::Deref; use std::ptr::Unique; +use std::slice; + +pub struct Bytes { + ptr: Unique, + len: uint, +} + +impl Deref for Bytes { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) } + } +} + +impl Drop for Bytes { + fn drop(&mut self) { + unsafe { libc::free(self.ptr.0 as *mut _); } + } +} #[link(name = "miniz", kind = "static")] extern { @@ -52,7 +71,7 @@ static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal" static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum -fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { +fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { unsafe { let mut outsz : size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, @@ -60,8 +79,8 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { &mut outsz, flags); if !res.is_null() { - let res = Unique(res); - Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0))) + let res = Unique(res as *mut u8); + Some(Bytes { ptr: res, len: outsz as uint }) } else { None } @@ -69,16 +88,16 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { } /// Compress a buffer, without writing any sort of header on the output. -pub fn deflate_bytes(bytes: &[u8]) -> Option> { +pub fn deflate_bytes(bytes: &[u8]) -> Option { deflate_bytes_internal(bytes, LZ_NORM) } /// Compress a buffer, using a header that zlib can understand. -pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option> { +pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option { deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) } -fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { +fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { unsafe { let mut outsz : size_t = 0; let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, @@ -86,8 +105,8 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { &mut outsz, flags); if !res.is_null() { - let res = Unique(res); - Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0))) + let res = Unique(res as *mut u8); + Some(Bytes { ptr: res, len: outsz as uint }) } else { None } @@ -95,12 +114,12 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { } /// Decompress a buffer, without parsing any sort of header on the input. -pub fn inflate_bytes(bytes: &[u8]) -> Option> { +pub fn inflate_bytes(bytes: &[u8]) -> Option { inflate_bytes_internal(bytes, 0) } /// Decompress a buffer that starts with a zlib header. -pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option> { +pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option { inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) } diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 2f4acaca4de4d..ec0b80c3a5342 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -23,8 +23,8 @@ use metadata::loader; use util::nodemap::{FnvHashMap, NodeMap}; use std::cell::RefCell; -use std::c_vec::CVec; use std::rc::Rc; +use flate::Bytes; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token::IdentInterner; @@ -36,7 +36,7 @@ use syntax::parse::token::IdentInterner; pub type cnum_map = FnvHashMap; pub enum MetadataBlob { - MetadataVec(CVec), + MetadataVec(Bytes), MetadataArchive(loader::ArchiveMetadata), } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index c18bd421b3b07..7c0645b4ca204 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -226,7 +226,7 @@ use syntax::codemap::Span; use syntax::diagnostic::SpanHandler; use util::fs; -use std::c_str::ToCStr; +use std::ffi::CString; use std::cmp; use std::collections::{HashMap, HashSet}; use std::io::fs::PathExtensions; @@ -720,9 +720,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result Result Option { unsafe { - let ar = dst.with_c_str(|dst| { - ::LLVMRustOpenArchive(dst) - }); + let s = CString::from_slice(dst.as_vec()); + let ar = ::LLVMRustOpenArchive(s.as_ptr()); if ar.is_null() { None } else { @@ -45,9 +44,9 @@ impl ArchiveRO { pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> { unsafe { let mut size = 0 as libc::size_t; - let ptr = file.with_c_str(|file| { - ::LLVMRustArchiveReadSection(self.ptr, file, &mut size) - }); + let file = CString::from_slice(file.as_bytes()); + let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(), + &mut size); if ptr.is_null() { None } else { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 2ec5f37634afb..854ac5ff5c01c 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -47,7 +47,7 @@ pub use self::Visibility::*; pub use self::DiagnosticSeverity::*; pub use self::Linkage::*; -use std::c_str::ToCStr; +use std::ffi::CString; use std::cell::RefCell; use std::{raw, mem}; use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char}; @@ -2114,10 +2114,9 @@ impl Drop for TargetData { } pub fn mk_target_data(string_rep: &str) -> TargetData { + let string_rep = CString::from_slice(string_rep.as_bytes()); TargetData { - lltd: string_rep.with_c_str(|buf| { - unsafe { LLVMCreateTargetData(buf) } - }) + lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index c6488ec6638a3..f3e90c43a8414 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -20,7 +20,7 @@ use rustc::util::common::time; use libc; use flate; -use std::c_str::ToCStr; +use std::ffi::CString; use std::iter; use std::mem; use std::num::Int; @@ -139,9 +139,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, } // Internalize everything but the reachable symbols of the current module - let cstrs: Vec<::std::c_str::CString> = - reachable.iter().map(|s| s.to_c_str()).collect(); - let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect(); + let cstrs: Vec = reachable.iter().map(|s| { + CString::from_slice(s.as_bytes()) + }).collect(); + let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect(); let ptr = arr.as_ptr(); unsafe { llvm::LLVMRustRunRestrictionPass(llmod, @@ -164,7 +165,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, unsafe { let pm = llvm::LLVMCreatePassManager(); llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod); - "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s)); + llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); let builder = llvm::LLVMPassManagerBuilderCreate(); llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm, @@ -172,7 +173,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, /* RunInliner = */ True); llvm::LLVMPassManagerBuilderDispose(builder); - "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s)); + llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); time(sess.time_passes(), "LTO passes", (), |()| llvm::LLVMRunPassManager(pm, llmod)); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 33011d9e35c10..089d7f737d3cf 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,7 +22,7 @@ use syntax::codemap; use syntax::diagnostic; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; -use std::c_str::{ToCStr, CString}; +use std::ffi::{mod, CString}; use std::io::Command; use std::io::fs; use std::iter::Unfold; @@ -32,7 +32,7 @@ use std::mem; use std::sync::{Arc, Mutex}; use std::sync::mpsc::channel; use std::thread; -use libc::{c_uint, c_int, c_void}; +use libc::{mod, c_uint, c_int, c_void}; #[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)] pub enum OutputType { @@ -49,8 +49,9 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { if cstr == ptr::null() { handler.fatal(msg[]); } else { - let err = CString::new(cstr, true); - let err = String::from_utf8_lossy(err.as_bytes()); + let err = ffi::c_str_to_bytes(&cstr); + let err = String::from_utf8_lossy(err.as_slice()).to_string(); + libc::free(cstr as *mut _); handler.fatal(format!("{}: {}", msg[], err[])[]); @@ -66,13 +67,12 @@ pub fn write_output_file( output: &Path, file_type: llvm::FileType) { unsafe { - output.with_c_str(|output| { - let result = llvm::LLVMRustWriteOutputFile( - target, pm, m, output, file_type); - if !result { - llvm_err(handler, "could not write output".to_string()); - } - }) + let output = CString::from_slice(output.as_vec()); + let result = llvm::LLVMRustWriteOutputFile( + target, pm, m, output.as_ptr(), file_type); + if !result { + llvm_err(handler, "could not write output".to_string()); + } } } @@ -221,28 +221,25 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { let triple = sess.target.target.llvm_target[]; let tm = unsafe { - triple.with_c_str(|t| { - let cpu = match sess.opts.cg.target_cpu { - Some(ref s) => s[], - None => sess.target.target.options.cpu[] - }; - cpu.with_c_str(|cpu| { - target_feature(sess).with_c_str(|features| { - llvm::LLVMRustCreateTargetMachine( - t, cpu, features, - code_model, - reloc_model, - opt_level, - true /* EnableSegstk */, - use_softfp, - no_fp_elim, - !any_library && reloc_model == llvm::RelocPIC, - ffunction_sections, - fdata_sections, - ) - }) - }) - }) + let triple = CString::from_slice(triple.as_bytes()); + let cpu = match sess.opts.cg.target_cpu { + Some(ref s) => s.as_slice(), + None => sess.target.target.options.cpu.as_slice() + }; + let cpu = CString::from_slice(cpu.as_bytes()); + let features = CString::from_slice(target_feature(sess).as_bytes()); + llvm::LLVMRustCreateTargetMachine( + triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), + code_model, + reloc_model, + opt_level, + true /* EnableSegstk */, + use_softfp, + no_fp_elim, + !any_library && reloc_model == llvm::RelocPIC, + ffunction_sections, + fdata_sections, + ) }; if tm.is_null() { @@ -371,8 +368,9 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo match llvm::diagnostic::Diagnostic::unpack(info) { llvm::diagnostic::Optimization(opt) => { - let pass_name = CString::new(opt.pass_name, false); - let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM"); + let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name)) + .ok() + .expect("got a non-UTF8 pass name from LLVM"); let enabled = match cgcx.remark { AllPasses => true, SomePasses(ref v) => v.iter().any(|s| *s == pass_name), @@ -416,9 +414,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_no_opt_bc { let ext = format!("{}.no-opt.bc", name_extra); - output_names.with_extension(ext[]).with_c_str(|buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - }) + let out = output_names.with_extension(ext.as_slice()); + let out = CString::from_slice(out.as_vec()); + llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } match config.opt_level { @@ -433,7 +431,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // If we're verifying or linting, add them to the function pass // manager. let addpass = |&: pass: &str| { - pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s)) + let pass = CString::from_slice(pass.as_bytes()); + llvm::LLVMRustAddPass(fpm, pass.as_ptr()) }; if !config.no_verify { assert!(addpass("verify")); } @@ -445,12 +444,11 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } for pass in config.passes.iter() { - pass.with_c_str(|s| { - if !llvm::LLVMRustAddPass(mpm, s) { - cgcx.handler.warn(format!("unknown pass {}, ignoring", - *pass)[]); - } - }) + let pass = CString::from_slice(pass.as_bytes()); + if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) { + cgcx.handler.warn(format!("unknown pass {}, ignoring", + pass).as_slice()); + } } // Finally, run the actual optimization passes @@ -470,9 +468,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_lto_bc { let name = format!("{}.lto.bc", name_extra); - output_names.with_extension(name[]).with_c_str(|buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - }) + let out = output_names.with_extension(name.as_slice()); + let out = CString::from_slice(out.as_vec()); + llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } }, _ => {}, @@ -504,18 +502,18 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_bc { let ext = format!("{}.bc", name_extra); - output_names.with_extension(ext[]).with_c_str(|buf| { - llvm::LLVMWriteBitcodeToFile(llmod, buf); - }) + let out = output_names.with_extension(ext.as_slice()); + let out = CString::from_slice(out.as_vec()); + llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } time(config.time_passes, "codegen passes", (), |()| { if config.emit_ir { let ext = format!("{}.ll", name_extra); - output_names.with_extension(ext[]).with_c_str(|output| { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, output); - }) + let out = output_names.with_extension(ext.as_slice()); + let out = CString::from_slice(out.as_vec()); + with_codegen(tm, llmod, config.no_builtins, |cpm| { + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); }) } @@ -995,7 +993,7 @@ unsafe fn configure_llvm(sess: &Session) { let mut llvm_args = Vec::new(); { let mut add = |&mut : arg: &str| { - let s = arg.to_c_str(); + let s = CString::from_slice(arg.as_bytes()); llvm_args.push(s.as_ptr()); llvm_c_strs.push(s); }; @@ -1083,7 +1081,7 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef, match opt { llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => { - "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s)); + llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _); } _ => {} }; diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index 5597e112f76d1..f18d483f70328 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -20,9 +20,8 @@ use trans::expr; use trans::type_of; use trans::type_::Type; -use std::c_str::ToCStr; -use std::string::String; use syntax::ast; +use std::ffi::CString; use libc::{c_uint, c_char}; // Take an inline assembly expression and splat it out via LLVM @@ -121,18 +120,16 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) ast::AsmIntel => llvm::AD_Intel }; - let r = ia.asm.get().with_c_str(|a| { - constraints.with_c_str(|c| { - InlineAsmCall(bcx, - a, - c, - inputs[], + let asm = CString::from_slice(ia.asm.get().as_bytes()); + let constraints = CString::from_slice(constraints.as_bytes()); + let r = InlineAsmCall(bcx, + asm.as_ptr(), + constraints.as_ptr(), + inputs.as_slice(), output_type, ia.volatile, ia.alignstack, - dialect) - }) - }); + dialect); // Again, based on how many outputs we have if num_outputs == 1 { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 518042cf70889..d9c397d0c159e 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -88,11 +88,12 @@ use util::nodemap::NodeMap; use arena::TypedArena; use libc::{c_uint, uint64_t}; -use std::c_str::ToCStr; +use std::ffi::{mod, CString}; use std::cell::{Cell, RefCell}; use std::collections::HashSet; use std::mem; use std::rc::Rc; +use std::str; use std::{i8, i16, i32, i64}; use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi}; use syntax::ast_util::local_def; @@ -187,11 +188,10 @@ impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> { pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv, ty: Type, output: ty::FnOutput) -> ValueRef { - let llfn: ValueRef = name.with_c_str(|buf| { - unsafe { - llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf, ty.to_ref()) - } - }); + let buf = CString::from_slice(name.as_bytes()); + let llfn: ValueRef = unsafe { + llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref()) + }; // diverging functions may unwind, but can never return normally if output == ty::FnDiverging { @@ -334,9 +334,8 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, None => () } unsafe { - let c = name.with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf) - }); + let buf = CString::from_slice(name.as_bytes()); + let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr()); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the // thread-local attribute locally if it was present remotely. If we @@ -475,15 +474,17 @@ pub fn set_always_inline(f: ValueRef) { } pub fn set_split_stack(f: ValueRef) { - "split-stack".with_c_str(|buf| { - unsafe { llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); } - }) + unsafe { + llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, + "split-stack\0".as_ptr() as *const _); + } } pub fn unset_split_stack(f: ValueRef) { - "split-stack".with_c_str(|buf| { - unsafe { llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); } - }) + unsafe { + llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, + "split-stack\0".as_ptr() as *const _); + } } // Double-check that we never ask LLVM to declare the same symbol twice. It @@ -537,11 +538,8 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Structural comparison: a rather involved form of glue. pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) { if cx.sess().opts.cg.save_temps { - s.with_c_str(|buf| { - unsafe { - llvm::LLVMSetValueName(v, buf) - } - }) + let buf = CString::from_slice(s.as_bytes()); + unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) } } } @@ -2645,11 +2643,10 @@ pub fn create_entry_wrapper(ccx: &CrateContext, unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) } } - let llbb = "top".with_c_str(|buf| { - unsafe { - llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, buf) - } - }); + let llbb = unsafe { + llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, + "top\0".as_ptr() as *const _) + }; let bld = ccx.raw_builder(); unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); @@ -2670,9 +2667,9 @@ pub fn create_entry_wrapper(ccx: &CrateContext, }; let args = { - let opaque_rust_main = "rust_main".with_c_str(|buf| { - llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf) - }); + let opaque_rust_main = llvm::LLVMBuildPointerCast(bld, + rust_main, Type::i8p(ccx).to_ref(), + "rust_main\0".as_ptr() as *const _); vec!( opaque_rust_main, @@ -2779,9 +2776,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { format!("Illegal null byte in export_name \ value: `{}`", sym)[]); } - let g = sym.with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), llty, buf) - }); + let buf = CString::from_slice(sym.as_bytes()); + let g = llvm::LLVMAddGlobal(ccx.llmod(), llty, + buf.as_ptr()); if attr::contains_name(i.attrs[], "thread_local") { @@ -2823,9 +2820,8 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { sect.get())[]); } unsafe { - sect.get().with_c_str(|buf| { - llvm::LLVMSetSection(v, buf); - }) + let buf = CString::from_slice(sect.get().as_bytes()); + llvm::LLVMSetSection(v, buf.as_ptr()); } }, None => () @@ -2992,17 +2988,16 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { let name = format!("rust_metadata_{}_{}", cx.link_meta().crate_name, cx.link_meta().crate_hash); - let llglobal = name.with_c_str(|buf| { - unsafe { - llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf) - } - }); + let buf = CString::from_vec(name.into_bytes()); + let llglobal = unsafe { + llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), + buf.as_ptr()) + }; unsafe { llvm::LLVMSetInitializer(llglobal, llconst); let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx); - name.with_c_str(|buf| { - llvm::LLVMSetSection(llglobal, buf) - }); + let name = CString::from_slice(name.as_bytes()); + llvm::LLVMSetSection(llglobal, name.as_ptr()) } return metadata; } @@ -3010,8 +3005,6 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { /// Find any symbols that are defined in one compilation unit, but not declared /// in any other compilation unit. Give these symbols internal linkage. fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { - use std::c_str::CString; - unsafe { let mut declared = HashSet::new(); @@ -3041,7 +3034,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { continue } - let name = CString::new(llvm::LLVMGetValueName(val), false); + let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val)) + .to_vec(); declared.insert(name); } } @@ -3057,9 +3051,10 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { continue } - let name = CString::new(llvm::LLVMGetValueName(val), false); + let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val)) + .to_vec(); if !declared.contains(&name) && - !reachable.contains(name.as_str().unwrap()) { + !reachable.contains(str::from_utf8(name.as_slice()).unwrap()) { llvm::SetLinkage(val, llvm::InternalLinkage); } } diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index 97f0b92a290f8..e09d36ddae923 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -20,7 +20,8 @@ use trans::machine::llalign_of_pref; use trans::type_::Type; use util::nodemap::FnvHashMap; use libc::{c_uint, c_char}; -use std::c_str::ToCStr; + +use std::ffi::CString; use syntax::codemap::Span; pub struct Builder<'a, 'tcx: 'a> { @@ -429,9 +430,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if name.is_empty() { llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname()) } else { - name.with_c_str(|c| { - llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c) - }) + let name = CString::from_slice(name.as_bytes()); + llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), + name.as_ptr()) } } } @@ -774,12 +775,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let comment_text = format!("{} {}", "#", sanitized.replace("\n", "\n\t# ")); self.count_insn("inlineasm"); - let asm = comment_text.with_c_str(|c| { - unsafe { - llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(), - c, noname(), False, False) - } - }); + let comment_text = CString::from_vec(comment_text.into_bytes()); + let asm = unsafe { + llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(), + comment_text.as_ptr(), noname(), False, + False) + }; self.call(asm, &[], None); } } @@ -926,9 +927,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder); let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb); let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_); - let t: ValueRef = "llvm.trap".with_c_str(|buf| { - llvm::LLVMGetNamedFunction(m, buf) - }); + let p = "llvm.trap\0".as_ptr(); + let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _); assert!((t as int != 0)); let args: &[ValueRef] = &[]; self.count_insn("trap"); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index e8dee19ed54c1..094f98e988aad 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -44,7 +44,7 @@ use util::nodemap::{FnvHashMap, NodeMap}; use arena::TypedArena; use libc::{c_uint, c_char}; -use std::c_str::ToCStr; +use std::ffi::CString; use std::cell::{Cell, RefCell}; use std::vec::Vec; use syntax::ast::Ident; @@ -401,9 +401,8 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { if self.llreturn.get().is_none() { self.llreturn.set(Some(unsafe { - "return".with_c_str(|buf| { - llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf) - }) + llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, + "return\0".as_ptr() as *const _) })) } @@ -429,11 +428,10 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { opt_node_id: Option) -> Block<'a, 'tcx> { unsafe { - let llbb = name.with_c_str(|buf| { - llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), - self.llfn, - buf) - }); + let name = CString::from_slice(name.as_bytes()); + let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), + self.llfn, + name.as_ptr()); BlockS::new(llbb, is_lpad, opt_node_id, self) } } @@ -708,7 +706,8 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef { pub fn C_floating(s: &str, t: Type) -> ValueRef { unsafe { - s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf)) + let s = CString::from_slice(s.as_bytes()); + llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr()) } } @@ -789,9 +788,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va !null_terminated as Bool); let gsym = token::gensym("str"); - let g = format!("str{}", gsym.uint()).with_c_str(|buf| { - llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf) - }); + let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes()); + let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr()); llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); llvm::SetLinkage(g, llvm::InternalLinkage); @@ -815,9 +813,10 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef { let lldata = C_bytes(cx, data); let gsym = token::gensym("binary"); - let g = format!("binary{}", gsym.uint()).with_c_str(|buf| { - llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf) - }); + let name = format!("binary{}", gsym.uint()); + let name = CString::from_vec(name.into_bytes()); + let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), + name.as_ptr()); llvm::LLVMSetInitializer(g, lldata); llvm::LLVMSetGlobalConstant(g, True); llvm::SetLinkage(g, llvm::InternalLinkage); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index b17e852d7cbc4..9432fa8bd3d59 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -24,7 +24,6 @@ use middle::subst::Substs; use middle::ty::{self, Ty}; use util::ppaux::{Repr, ty_to_string}; -use std::c_str::ToCStr; use std::iter::repeat; use libc::c_uint; use syntax::{ast, ast_util}; @@ -103,9 +102,8 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr, pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef { unsafe { - let gv = "const".with_c_str(|name| { - llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), name) - }); + let gv = llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), + "const\0".as_ptr() as *const _); llvm::LLVMSetInitializer(gv, cv); llvm::LLVMSetGlobalConstant(gv, if mutbl == ast::MutImmutable {True} else {False}); diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index e5a0e2e9234d5..f974a6faf4c19 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -29,8 +29,8 @@ use util::ppaux::Repr; use util::sha2::Sha256; use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet}; +use std::ffi::CString; use std::cell::{Cell, RefCell}; -use std::c_str::ToCStr; use std::ptr; use std::rc::Rc; use syntax::ast; @@ -221,21 +221,16 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> { unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { let llcx = llvm::LLVMContextCreate(); - let llmod = mod_name.with_c_str(|buf| { - llvm::LLVMModuleCreateWithNameInContext(buf, llcx) - }); - sess.target - .target - .data_layout - .with_c_str(|buf| { - llvm::LLVMSetDataLayout(llmod, buf); - }); - sess.target - .target - .llvm_target - .with_c_str(|buf| { - llvm::LLVMRustSetNormalizedTarget(llmod, buf); - }); + let mod_name = CString::from_slice(mod_name.as_bytes()); + let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); + + let data_layout = sess.target.target.data_layout.as_slice(); + let data_layout = CString::from_slice(data_layout.as_bytes()); + llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); + + let llvm_target = sess.target.target.llvm_target.as_slice(); + let llvm_target = CString::from_slice(llvm_target.as_bytes()); + llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); (llcx, llmod) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 916fcbfe13ef7..a55953a882f03 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -207,7 +207,7 @@ use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; use util::ppaux; use libc::c_uint; -use std::c_str::{CString, ToCStr}; +use std::ffi::CString; use std::cell::{Cell, RefCell}; use std::ptr; use std::rc::{Rc, Weak}; @@ -760,14 +760,15 @@ pub fn finalize(cx: &CrateContext) { // for OS X to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. if cx.sess().target.target.options.is_like_osx { - "Dwarf Version".with_c_str( - |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2)); + llvm::LLVMRustAddModuleFlag(cx.llmod(), + "Dwarf Version\0".as_ptr() as *const _, + 2) } // Prevent bitcode readers from deleting the debug info. - "Debug Info Version".with_c_str( - |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, - llvm::LLVMRustDebugMetadataVersion)); + let ptr = "Debug Info Version\0".as_ptr(); + llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _, + llvm::LLVMRustDebugMetadataVersion); }; } @@ -829,22 +830,20 @@ pub fn create_global_var_metadata(cx: &CrateContext, namespace_node.mangled_name_of_contained_item(var_name[]); let var_scope = namespace_node.scope; - var_name.with_c_str(|var_name| { - linkage_name.with_c_str(|linkage_name| { - unsafe { - llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx), - var_scope, - var_name, - linkage_name, - file_metadata, - line_number, - type_metadata, - is_local_to_unit, - global, - ptr::null_mut()); - } - }) - }); + let var_name = CString::from_slice(var_name.as_bytes()); + let linkage_name = CString::from_slice(linkage_name.as_bytes()); + unsafe { + llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx), + var_scope, + var_name.as_ptr(), + linkage_name.as_ptr(), + file_metadata, + line_number, + type_metadata, + is_local_to_unit, + global, + ptr::null_mut()); + } } /// Creates debug information for the given local variable. @@ -1388,28 +1387,26 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id); - let fn_metadata = function_name.with_c_str(|function_name| { - linkage_name.with_c_str(|linkage_name| { - unsafe { - llvm::LLVMDIBuilderCreateFunction( - DIB(cx), - containing_scope, - function_name, - linkage_name, - file_metadata, - loc.line as c_uint, - function_type_metadata, - is_local_to_unit, - true, - scope_line as c_uint, - FlagPrototyped as c_uint, - cx.sess().opts.optimize != config::No, - llfn, - template_parameters, - ptr::null_mut()) - } - }) - }); + let function_name = CString::from_slice(function_name.as_bytes()); + let linkage_name = CString::from_slice(linkage_name.as_bytes()); + let fn_metadata = unsafe { + llvm::LLVMDIBuilderCreateFunction( + DIB(cx), + containing_scope, + function_name.as_ptr(), + linkage_name.as_ptr(), + file_metadata, + loc.line as c_uint, + function_type_metadata, + is_local_to_unit, + true, + scope_line as c_uint, + FlagPrototyped as c_uint, + cx.sess().opts.optimize != config::No, + llfn, + template_parameters, + ptr::null_mut()) + }; let scope_map = create_scope_map(cx, fn_decl.inputs.as_slice(), @@ -1514,19 +1511,18 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let ident = special_idents::type_self; - let param_metadata = token::get_ident(ident).get() - .with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateTemplateTypeParameter( - DIB(cx), - file_metadata, - name, - actual_self_type_metadata, - ptr::null_mut(), - 0, - 0) - } - }); + let ident = token::get_ident(ident); + let name = CString::from_slice(ident.get().as_bytes()); + let param_metadata = unsafe { + llvm::LLVMDIBuilderCreateTemplateTypeParameter( + DIB(cx), + file_metadata, + name.as_ptr(), + actual_self_type_metadata, + ptr::null_mut(), + 0, + 0) + }; template_params.push(param_metadata); } @@ -1549,19 +1545,18 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == FullDebugInfo { let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP); - let param_metadata = token::get_ident(ident).get() - .with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateTemplateTypeParameter( - DIB(cx), - file_metadata, - name, - actual_type_metadata, - ptr::null_mut(), - 0, - 0) - } - }); + let ident = token::get_ident(ident); + let name = CString::from_slice(ident.get().as_bytes()); + let param_metadata = unsafe { + llvm::LLVMDIBuilderCreateTemplateTypeParameter( + DIB(cx), + file_metadata, + name.as_ptr(), + actual_type_metadata, + ptr::null_mut(), + 0, + 0) + }; template_params.push(param_metadata); } } @@ -1606,19 +1601,19 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { } else { match abs_path.path_relative_from(work_dir) { Some(ref p) if p.is_relative() => { - // prepend "./" if necessary - let dotdot = b".."; - let prefix = [dotdot[0], ::std::path::SEP_BYTE]; - let mut path_bytes = p.as_vec().to_vec(); - - if path_bytes.slice_to(2) != prefix && - path_bytes.slice_to(2) != dotdot { - path_bytes.insert(0, prefix[0]); - path_bytes.insert(1, prefix[1]); - } - - path_bytes.to_c_str() + // prepend "./" if necessary + let dotdot = b".."; + let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE]; + let mut path_bytes = p.as_vec().to_vec(); + + if path_bytes.slice_to(2) != prefix && + path_bytes.slice_to(2) != dotdot { + path_bytes.insert(0, prefix[0]); + path_bytes.insert(1, prefix[1]); } + + CString::from_vec(path_bytes) + } _ => fallback_path(cx) } } @@ -1630,29 +1625,25 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { (option_env!("CFG_VERSION")).expect("CFG_VERSION")); let compile_unit_name = compile_unit_name.as_ptr(); - return work_dir.as_vec().with_c_str(|work_dir| { - producer.with_c_str(|producer| { - "".with_c_str(|flags| { - "".with_c_str(|split_name| { - unsafe { - llvm::LLVMDIBuilderCreateCompileUnit( - debug_context(cx).builder, - DW_LANG_RUST, - compile_unit_name, - work_dir, - producer, - cx.sess().opts.optimize != config::No, - flags, - 0, - split_name) - } - }) - }) - }) - }); + let work_dir = CString::from_slice(work_dir.as_vec()); + let producer = CString::from_slice(producer.as_bytes()); + let flags = "\0"; + let split_name = "\0"; + return unsafe { + llvm::LLVMDIBuilderCreateCompileUnit( + debug_context(cx).builder, + DW_LANG_RUST, + compile_unit_name, + work_dir.as_ptr(), + producer.as_ptr(), + cx.sess().opts.optimize != config::No, + flags.as_ptr() as *const _, + 0, + split_name.as_ptr() as *const _) + }; fn fallback_path(cx: &CrateContext) -> CString { - cx.link_meta().crate_name.to_c_str() + CString::from_slice(cx.link_meta().crate_name.as_bytes()) } } @@ -1678,42 +1669,41 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, CapturedVariable => (0, DW_TAG_auto_variable) }; - let (var_alloca, var_metadata) = name.get().with_c_str(|name| { - match variable_access { - DirectVariable { alloca } => ( - alloca, - unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( - DIB(cx), - dwarf_tag, - scope_metadata, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - cx.sess().opts.optimize != config::No, - 0, - argument_index) - } - ), - IndirectVariable { alloca, address_operations } => ( - alloca, - unsafe { - llvm::LLVMDIBuilderCreateComplexVariable( - DIB(cx), - dwarf_tag, - scope_metadata, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - address_operations.as_ptr(), - address_operations.len() as c_uint, - argument_index) - } - ) - } - }); + let name = CString::from_slice(name.get().as_bytes()); + let (var_alloca, var_metadata) = match variable_access { + DirectVariable { alloca } => ( + alloca, + unsafe { + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), + dwarf_tag, + scope_metadata, + name.as_ptr(), + file_metadata, + loc.line as c_uint, + type_metadata, + cx.sess().opts.optimize != config::No, + 0, + argument_index) + } + ), + IndirectVariable { alloca, address_operations } => ( + alloca, + unsafe { + llvm::LLVMDIBuilderCreateComplexVariable( + DIB(cx), + dwarf_tag, + scope_metadata, + name.as_ptr(), + file_metadata, + loc.line as c_uint, + type_metadata, + address_operations.as_ptr(), + address_operations.len() as c_uint, + argument_index) + } + ) + }; set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, @@ -1758,14 +1748,12 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { full_path }; - let file_metadata = - file_name.with_c_str(|file_name| { - work_dir.with_c_str(|work_dir| { - unsafe { - llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir) - } - }) - }); + let file_name = CString::from_slice(file_name.as_bytes()); + let work_dir = CString::from_slice(work_dir.as_bytes()); + let file_metadata = unsafe { + llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), + work_dir.as_ptr()) + }; let mut created_files = debug_context(cx).created_files.borrow_mut(); created_files.insert(full_path.to_string(), file_metadata); @@ -1793,16 +1781,14 @@ fn scope_metadata(fcx: &FunctionContext, } fn diverging_type_metadata(cx: &CrateContext) -> DIType { - "!".with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateBasicType( - DIB(cx), - name, - bytes_to_bits(0), - bytes_to_bits(0), - DW_ATE_unsigned) - } - }) + unsafe { + llvm::LLVMDIBuilderCreateBasicType( + DIB(cx), + "!\0".as_ptr() as *const _, + bytes_to_bits(0), + bytes_to_bits(0), + DW_ATE_unsigned) + } } fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, @@ -1838,16 +1824,15 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let llvm_type = type_of::type_of(cx, t); let (size, align) = size_and_align_of(cx, llvm_type); - let ty_metadata = name.with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateBasicType( - DIB(cx), - name, - bytes_to_bits(size), - bytes_to_bits(align), - encoding) - } - }); + let name = CString::from_slice(name.as_bytes()); + let ty_metadata = unsafe { + llvm::LLVMDIBuilderCreateBasicType( + DIB(cx), + name.as_ptr(), + bytes_to_bits(size), + bytes_to_bits(align), + encoding) + }; return ty_metadata; } @@ -1859,16 +1844,15 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let pointer_llvm_type = type_of::type_of(cx, pointer_type); let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); let name = compute_debuginfo_type_name(cx, pointer_type, false); - let ptr_metadata = name.with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreatePointerType( - DIB(cx), - pointee_type_metadata, - bytes_to_bits(pointer_size), - bytes_to_bits(pointer_align), - name) - } - }); + let name = CString::from_slice(name.as_bytes()); + let ptr_metadata = unsafe { + llvm::LLVMDIBuilderCreatePointerType( + DIB(cx), + pointee_type_metadata, + bytes_to_bits(pointer_size), + bytes_to_bits(pointer_align), + name.as_ptr()) + }; return ptr_metadata; } @@ -2478,14 +2462,14 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let enumerators_metadata: Vec = variants .iter() .map(|v| { - token::get_name(v.name).get().with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateEnumerator( - DIB(cx), - name, - v.disr_val as u64) - } - }) + let token = token::get_name(v.name); + let name = CString::from_slice(token.get().as_bytes()); + unsafe { + llvm::LLVMDIBuilderCreateEnumerator( + DIB(cx), + name.as_ptr(), + v.disr_val as u64) + } }) .collect(); @@ -2509,20 +2493,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, codemap::DUMMY_SP); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); - let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| { - unsafe { - llvm::LLVMDIBuilderCreateEnumerationType( - DIB(cx), - containing_scope, - name, - UNKNOWN_FILE_METADATA, - UNKNOWN_LINE_NUMBER, - bytes_to_bits(discriminant_size), - bytes_to_bits(discriminant_align), - create_DIArray(DIB(cx), enumerators_metadata[]), - discriminant_base_type_metadata) - } - }); + let name = CString::from_slice(discriminant_name.get().as_bytes()); + let discriminant_type_metadata = unsafe { + llvm::LLVMDIBuilderCreateEnumerationType( + DIB(cx), + containing_scope, + name.as_ptr(), + UNKNOWN_FILE_METADATA, + UNKNOWN_LINE_NUMBER, + bytes_to_bits(discriminant_size), + bytes_to_bits(discriminant_align), + create_DIArray(DIB(cx), enumerators_metadata.as_slice()), + discriminant_base_type_metadata) + }; debug_context(cx).created_enum_disr_types .borrow_mut() @@ -2553,24 +2536,22 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .borrow() .get_unique_type_id_as_string(unique_type_id); - let enum_metadata = enum_name.with_c_str(|enum_name| { - unique_type_id_str.with_c_str(|unique_type_id_str| { - unsafe { - llvm::LLVMDIBuilderCreateUnionType( - DIB(cx), - containing_scope, - enum_name, - UNKNOWN_FILE_METADATA, - UNKNOWN_LINE_NUMBER, - bytes_to_bits(enum_type_size), - bytes_to_bits(enum_type_align), - 0, // Flags - ptr::null_mut(), - 0, // RuntimeLang - unique_type_id_str) - } - }) - }); + let enum_name = CString::from_slice(enum_name.as_bytes()); + let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes()); + let enum_metadata = unsafe { + llvm::LLVMDIBuilderCreateUnionType( + DIB(cx), + containing_scope, + enum_name.as_ptr(), + UNKNOWN_FILE_METADATA, + UNKNOWN_LINE_NUMBER, + bytes_to_bits(enum_type_size), + bytes_to_bits(enum_type_align), + 0, // Flags + ptr::null_mut(), + 0, // RuntimeLang + unique_type_id_str.as_ptr()) + }; return create_and_register_recursive_type_forward_declaration( cx, @@ -2681,21 +2662,20 @@ fn set_members_of_composite_type(cx: &CrateContext, ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i) }; - member_description.name.with_c_str(|member_name| { - unsafe { - llvm::LLVMDIBuilderCreateMemberType( - DIB(cx), - composite_type_metadata, - member_name, - UNKNOWN_FILE_METADATA, - UNKNOWN_LINE_NUMBER, - bytes_to_bits(member_size), - bytes_to_bits(member_align), - bytes_to_bits(member_offset), - member_description.flags, - member_description.type_metadata) - } - }) + let member_name = CString::from_slice(member_description.name.as_bytes()); + unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + composite_type_metadata, + member_name.as_ptr(), + UNKNOWN_FILE_METADATA, + UNKNOWN_LINE_NUMBER, + bytes_to_bits(member_size), + bytes_to_bits(member_align), + bytes_to_bits(member_offset), + member_description.flags, + member_description.type_metadata) + } }) .collect(); @@ -2719,30 +2699,28 @@ fn create_struct_stub(cx: &CrateContext, let unique_type_id_str = debug_context(cx).type_map .borrow() .get_unique_type_id_as_string(unique_type_id); + let name = CString::from_slice(struct_type_name.as_bytes()); + let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes()); let metadata_stub = unsafe { - struct_type_name.with_c_str(|name| { - unique_type_id_str.with_c_str(|unique_type_id| { - // LLVMDIBuilderCreateStructType() wants an empty array. A null - // pointer will lead to hard to trace and debug LLVM assertions - // later on in llvm/lib/IR/Value.cpp. - let empty_array = create_DIArray(DIB(cx), &[]); - - llvm::LLVMDIBuilderCreateStructType( - DIB(cx), - containing_scope, - name, - UNKNOWN_FILE_METADATA, - UNKNOWN_LINE_NUMBER, - bytes_to_bits(struct_size), - bytes_to_bits(struct_align), - 0, - ptr::null_mut(), - empty_array, - 0, - ptr::null_mut(), - unique_type_id) - }) - }) + // LLVMDIBuilderCreateStructType() wants an empty array. A null + // pointer will lead to hard to trace and debug LLVM assertions + // later on in llvm/lib/IR/Value.cpp. + let empty_array = create_DIArray(DIB(cx), &[]); + + llvm::LLVMDIBuilderCreateStructType( + DIB(cx), + containing_scope, + name.as_ptr(), + UNKNOWN_FILE_METADATA, + UNKNOWN_LINE_NUMBER, + bytes_to_bits(struct_size), + bytes_to_bits(struct_align), + 0, + ptr::null_mut(), + empty_array, + 0, + ptr::null_mut(), + unique_type_id.as_ptr()) }; return metadata_stub; @@ -4079,18 +4057,18 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc ptr::null_mut() }; let namespace_name = token::get_name(name); - let scope = namespace_name.get().with_c_str(|namespace_name| { - unsafe { - llvm::LLVMDIBuilderCreateNameSpace( - DIB(cx), - parent_scope, - namespace_name, - // cannot reconstruct file ... - ptr::null_mut(), - // ... or line information, but that's not so important. - 0) - } - }); + let namespace_name = CString::from_slice(namespace_name + .get().as_bytes()); + let scope = unsafe { + llvm::LLVMDIBuilderCreateNameSpace( + DIB(cx), + parent_scope, + namespace_name.as_ptr(), + // cannot reconstruct file ... + ptr::null_mut(), + // ... or line information, but that's not so important. + 0) + }; let node = Rc::new(NamespaceTreeNode { name: name, @@ -4128,7 +4106,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc llvm::ValueRef { - let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str(); + let section_var_name = b"__rustc_debug_gdb_scripts_section__\0"; let section_var = unsafe { - llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr()) + llvm::LLVMGetNamedGlobal(ccx.llmod(), + section_var_name.as_ptr() as *const _) }; if section_var == ptr::null_mut() { - let section_name = b".debug_gdb_scripts".to_c_str(); + let section_name = b".debug_gdb_scripts\0"; let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; unsafe { @@ -4160,8 +4139,9 @@ fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext) section_contents.len() as u64); let section_var = llvm::LLVMAddGlobal(ccx.llmod(), llvm_type.to_ref(), - section_var_name.as_ptr()); - llvm::LLVMSetSection(section_var, section_name.as_ptr()); + section_var_name.as_ptr() + as *const _); + llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _); llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddr(section_var, llvm::True); diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index a4cfec791d817..1c9be6ae4a8ba 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -24,9 +24,10 @@ use trans::type_::Type; use trans::type_of::*; use trans::type_of; use middle::ty::{self, Ty}; -use middle::subst::{Substs}; +use middle::subst::Substs; + +use std::ffi::CString; use std::cmp; -use std::c_str::ToCStr; use libc::c_uint; use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System}; @@ -132,9 +133,9 @@ pub fn register_static(ccx: &CrateContext, }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = ident.get().with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf) - }); + let buf = CString::from_slice(ident.get().as_bytes()); + let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), + buf.as_ptr()); llvm::SetLinkage(g1, linkage); // Declare an internal global `extern_with_linkage_foo` which @@ -145,9 +146,9 @@ pub fn register_static(ccx: &CrateContext, // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(ident.get()); - let g2 = real_name.with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf) - }); + let real_name = CString::from_vec(real_name.into_bytes()); + let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), + real_name.as_ptr()); llvm::SetLinkage(g2, llvm::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); g2 @@ -155,9 +156,8 @@ pub fn register_static(ccx: &CrateContext, } None => unsafe { // Generate an external declaration. - ident.get().with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf) - }) + let buf = CString::from_slice(ident.get().as_bytes()); + llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr()) } } } @@ -606,9 +606,9 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // return r; // } - let the_block = - "the block".with_c_str( - |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s)); + let ptr = "the block\0".as_ptr(); + let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, + ptr as *const _); let builder = ccx.builder(); builder.position_at_end(the_block); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index c049704181354..2525220c57021 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -40,8 +40,8 @@ use util::ppaux::{ty_to_short_str, Repr}; use util::ppaux; use arena::TypedArena; -use std::c_str::ToCStr; use libc::c_uint; +use std::ffi::CString; use syntax::ast; use syntax::parse::token; @@ -498,11 +498,11 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) let llalign = llalign_of(ccx, llty); let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc"); debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name); - let gvar = name.with_c_str(|buf| { - unsafe { - llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), buf) - } - }); + let buf = CString::from_slice(name.as_bytes()); + let gvar = unsafe { + llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), + buf.as_ptr()) + }; note_unique_llvm_symbol(ccx, name); let ty_name = token::intern_and_get_ident( diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index c13516134c20c..dec4524e67665 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -34,7 +34,7 @@ use middle::ty::{self, Ty}; use middle::ty::MethodCall; use util::ppaux::Repr; -use std::c_str::ToCStr; +use std::ffi::CString; use std::rc::Rc; use syntax::abi::{Rust, RustCall}; use syntax::parse::token; @@ -742,9 +742,9 @@ pub fn make_vtable>(ccx: &CrateContext, unsafe { let tbl = C_struct(ccx, components[], false); let sym = token::gensym("vtable"); - let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| { - llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf) - }); + let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes()); + let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), + buf.as_ptr()); llvm::LLVMSetInitializer(vt_gvar, tbl); llvm::LLVMSetGlobalConstant(vt_gvar, llvm::True); llvm::SetLinkage(vt_gvar, llvm::InternalLinkage); diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 5b76f5bb8270e..3785c2fb9bc54 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -19,7 +19,7 @@ use util::nodemap::FnvHashMap; use syntax::ast; -use std::c_str::ToCStr; +use std::ffi::CString; use std::mem; use std::cell::RefCell; use std::iter::repeat; @@ -157,7 +157,8 @@ impl Type { } pub fn named_struct(ccx: &CrateContext, name: &str) -> Type { - ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s))) + let name = CString::from_slice(name.as_bytes()); + ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr())) } pub fn empty_struct(ccx: &CrateContext) -> Type { diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 0f0dbf6a24dff..dcc90117d2660 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -20,8 +20,8 @@ pub use self::imp::Lock; #[cfg(unix)] mod imp { + use std::ffi::CString; use libc; - use std::c_str::ToCStr; #[cfg(target_os = "linux")] mod os { @@ -111,9 +111,11 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let fd = p.with_c_str(|s| unsafe { - libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU) - }); + let buf = CString::from_slice(p.as_vec()); + let fd = unsafe { + libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, + libc::S_IRWXU) + }; assert!(fd > 0); let flock = os::flock { l_start: 0, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9d003eca27f3d..3b9265cf56976 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -29,7 +29,7 @@ use libc; use std::ascii::AsciiExt; -use std::c_str::ToCStr; +use std::ffi::CString; use std::cell::{RefCell, Cell}; use std::collections::HashMap; use std::fmt; @@ -215,7 +215,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { let id = id.as_ref().map(|a| a.as_slice()); s.push_str(highlight::highlight(text.as_slice(), None, id) .as_slice()); - let output = s.to_c_str(); + let output = CString::from_vec(s.into_bytes()); hoedown_buffer_puts(ob, output.as_ptr()); }) } @@ -224,15 +224,16 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer, level: libc::c_int, opaque: *mut libc::c_void) { // hoedown does this, we may as well too - "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) }); + unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); } // Extract the text provided let s = if text.is_null() { "".to_string() } else { - unsafe { - String::from_raw_buf_len((*text).data, (*text).size as uint) - } + let s = unsafe { + slice::from_raw_buf(&(*text).data, (*text).size as uint) + }; + str::from_utf8(s).unwrap().to_string() }; // Transform the contents of the header into a hyphenated string @@ -273,7 +274,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { format!("{} ", sec) }); - text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) }); + let text = CString::from_vec(text.into_bytes()); + unsafe { hoedown_buffer_puts(ob, text.as_ptr()) } } reset_headers(); diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs deleted file mode 100644 index 9c96a9cac7831..0000000000000 --- a/src/libstd/c_str.rs +++ /dev/null @@ -1,857 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! C-string manipulation and management -//! -//! This modules provides the basic methods for creating and manipulating -//! null-terminated strings for use with FFI calls (back to C). Most C APIs require -//! that the string being passed to them is null-terminated, and by default rust's -//! string types are *not* null terminated. -//! -//! The other problem with translating Rust strings to C strings is that Rust -//! strings can validly contain a null-byte in the middle of the string (0 is a -//! valid Unicode codepoint). This means that not all Rust strings can actually be -//! translated to C strings. -//! -//! # Creation of a C string -//! -//! A C string is managed through the `CString` type defined in this module. It -//! "owns" the internal buffer of characters and will automatically deallocate the -//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str` -//! and `&[u8]`, but the conversions can fail due to some of the limitations -//! explained above. -//! -//! This also means that currently whenever a C string is created, an allocation -//! must be performed to place the data elsewhere (the lifetime of the C string is -//! not tied to the lifetime of the original string/data buffer). If C strings are -//! heavily used in applications, then caching may be advisable to prevent -//! unnecessary amounts of allocations. -//! -//! Be carefull to remember that the memory is managed by C allocator API and not -//! by Rust allocator API. -//! That means that the CString pointers should be freed with C allocator API -//! if you intend to do that on your own, as the behaviour if you free them with -//! Rust's allocator API is not well defined -//! -//! An example of creating and using a C string would be: -//! -//! ```rust -//! extern crate libc; -//! -//! use std::c_str::ToCStr; -//! -//! extern { -//! fn puts(s: *const libc::c_char); -//! } -//! -//! fn main() { -//! let my_string = "Hello, world!"; -//! -//! // Allocate the C string with an explicit local that owns the string. The -//! // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope. -//! let my_c_string = my_string.to_c_str(); -//! unsafe { -//! puts(my_c_string.as_ptr()); -//! } -//! -//! // Don't save/return the pointer to the C string, the `c_buffer` will be -//! // deallocated when this block returns! -//! my_string.with_c_str(|c_buffer| { -//! unsafe { puts(c_buffer); } -//! }); -//! } -//! ``` - -use core::prelude::*; -use libc; - -use cmp::Ordering; -use fmt; -use hash; -use mem; -use ptr; -use slice::{self, IntSliceExt}; -use str; -use string::String; -use core::kinds::marker; - -/// The representation of a C String. -/// -/// This structure wraps a `*libc::c_char`, and will automatically free the -/// memory it is pointing to when it goes out of scope. -#[allow(missing_copy_implementations)] -pub struct CString { - buf: *const libc::c_char, - owns_buffer_: bool, -} - -unsafe impl Send for CString { } -unsafe impl Sync for CString { } - -impl Clone for CString { - /// Clone this CString into a new, uniquely owned CString. For safety - /// reasons, this is always a deep clone with the memory allocated - /// with C's allocator API, rather than the usual shallow clone. - fn clone(&self) -> CString { - let len = self.len() + 1; - let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char; - if buf.is_null() { ::alloc::oom() } - unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); } - CString { buf: buf as *const libc::c_char, owns_buffer_: true } - } -} - -impl PartialEq for CString { - fn eq(&self, other: &CString) -> bool { - // Check if the two strings share the same buffer - if self.buf as uint == other.buf as uint { - true - } else { - unsafe { - libc::strcmp(self.buf, other.buf) == 0 - } - } - } -} - -impl PartialOrd for CString { - #[inline] - fn partial_cmp(&self, other: &CString) -> Option { - self.as_bytes().partial_cmp(other.as_bytes()) - } -} - -impl Eq for CString {} - -impl hash::Hash for CString { - #[inline] - fn hash(&self, state: &mut S) { - self.as_bytes().hash(state) - } -} - -impl CString { - /// Create a C String from a pointer, with memory managed by C's allocator - /// API, so avoid calling it with a pointer to memory managed by Rust's - /// allocator API, as the behaviour would not be well defined. - /// - ///# Panics - /// - /// Panics if `buf` is null - pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString { - assert!(!buf.is_null()); - CString { buf: buf, owns_buffer_: owns_buffer } - } - - /// Return a pointer to the NUL-terminated string data. - /// - /// `.as_ptr` returns an internal pointer into the `CString`, and - /// may be invalidated when the `CString` falls out of scope (the - /// destructor will run, freeing the allocation if there is - /// one). - /// - /// ```rust - /// use std::c_str::ToCStr; - /// - /// let foo = "some string"; - /// - /// // right - /// let x = foo.to_c_str(); - /// let p = x.as_ptr(); - /// - /// // wrong (the CString will be freed, invalidating `p`) - /// let p = foo.to_c_str().as_ptr(); - /// ``` - /// - /// # Example - /// - /// ```rust - /// extern crate libc; - /// - /// use std::c_str::ToCStr; - /// - /// fn main() { - /// let c_str = "foo bar".to_c_str(); - /// unsafe { - /// libc::puts(c_str.as_ptr()); - /// } - /// } - /// ``` - pub fn as_ptr(&self) -> *const libc::c_char { - self.buf - } - - /// Return a mutable pointer to the NUL-terminated string data. - /// - /// `.as_mut_ptr` returns an internal pointer into the `CString`, and - /// may be invalidated when the `CString` falls out of scope (the - /// destructor will run, freeing the allocation if there is - /// one). - /// - /// ```rust - /// use std::c_str::ToCStr; - /// - /// let foo = "some string"; - /// - /// // right - /// let mut x = foo.to_c_str(); - /// let p = x.as_mut_ptr(); - /// - /// // wrong (the CString will be freed, invalidating `p`) - /// let p = foo.to_c_str().as_mut_ptr(); - /// ``` - pub fn as_mut_ptr(&mut self) -> *mut libc::c_char { - self.buf as *mut _ - } - - /// Returns whether or not the `CString` owns the buffer. - pub fn owns_buffer(&self) -> bool { - self.owns_buffer_ - } - - /// Converts the CString into a `&[u8]` without copying. - /// Includes the terminating NUL byte. - #[inline] - pub fn as_bytes<'a>(&'a self) -> &'a [u8] { - unsafe { - slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned() - } - } - - /// Converts the CString into a `&[u8]` without copying. - /// Does not include the terminating NUL byte. - #[inline] - pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] { - unsafe { - slice::from_raw_buf(&self.buf, self.len()).as_unsigned() - } - } - - /// Converts the CString into a `&str` without copying. - /// Returns None if the CString is not UTF-8. - #[inline] - pub fn as_str<'a>(&'a self) -> Option<&'a str> { - let buf = self.as_bytes_no_nul(); - str::from_utf8(buf).ok() - } - - /// Return a CString iterator. - pub fn iter<'a>(&'a self) -> CChars<'a> { - CChars { - ptr: self.buf, - marker: marker::ContravariantLifetime, - } - } - - /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper. - /// - /// Any ownership of the buffer by the `CString` wrapper is - /// forgotten, meaning that the backing allocation of this - /// `CString` is not automatically freed if it owns the - /// allocation. In this case, a user of `.unwrap()` should ensure - /// the allocation is freed, to avoid leaking memory. You should - /// use libc's memory allocator in this case. - /// - /// Prefer `.as_ptr()` when just retrieving a pointer to the - /// string data, as that does not relinquish ownership. - pub unsafe fn into_inner(mut self) -> *const libc::c_char { - self.owns_buffer_ = false; - self.buf - } - - /// Return the number of bytes in the CString (not including the NUL - /// terminator). - #[inline] - pub fn len(&self) -> uint { - unsafe { libc::strlen(self.buf) as uint } - } - - /// Returns if there are no bytes in this string - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } -} - -impl Drop for CString { - fn drop(&mut self) { - if self.owns_buffer_ { - unsafe { - libc::free(self.buf as *mut libc::c_void) - } - } - } -} - -impl fmt::Show for CString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f) - } -} - -/// A generic trait for converting a value to a CString. -pub trait ToCStr for Sized? { - /// Copy the receiver into a CString. - /// - /// # Panics - /// - /// Panics the task if the receiver has an interior null. - fn to_c_str(&self) -> CString; - - /// Unsafe variant of `to_c_str()` that doesn't check for nulls. - unsafe fn to_c_str_unchecked(&self) -> CString; - - /// Work with a temporary CString constructed from the receiver. - /// The provided `*libc::c_char` will be freed immediately upon return. - /// - /// # Example - /// - /// ```rust - /// extern crate libc; - /// - /// use std::c_str::ToCStr; - /// - /// fn main() { - /// let s = "PATH".with_c_str(|path| unsafe { - /// libc::getenv(path) - /// }); - /// } - /// ``` - /// - /// # Panics - /// - /// Panics the task if the receiver has an interior null. - #[inline] - fn with_c_str(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - let c_str = self.to_c_str(); - f(c_str.as_ptr()) - } - - /// Unsafe variant of `with_c_str()` that doesn't check for nulls. - #[inline] - unsafe fn with_c_str_unchecked(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - let c_str = self.to_c_str_unchecked(); - f(c_str.as_ptr()) - } -} - -impl ToCStr for str { - #[inline] - fn to_c_str(&self) -> CString { - self.as_bytes().to_c_str() - } - - #[inline] - unsafe fn to_c_str_unchecked(&self) -> CString { - self.as_bytes().to_c_str_unchecked() - } - - #[inline] - fn with_c_str(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - self.as_bytes().with_c_str(f) - } - - #[inline] - unsafe fn with_c_str_unchecked(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - self.as_bytes().with_c_str_unchecked(f) - } -} - -impl ToCStr for String { - #[inline] - fn to_c_str(&self) -> CString { - self.as_bytes().to_c_str() - } - - #[inline] - unsafe fn to_c_str_unchecked(&self) -> CString { - self.as_bytes().to_c_str_unchecked() - } - - #[inline] - fn with_c_str(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - self.as_bytes().with_c_str(f) - } - - #[inline] - unsafe fn with_c_str_unchecked(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - self.as_bytes().with_c_str_unchecked(f) - } -} - -// The length of the stack allocated buffer for `vec.with_c_str()` -const BUF_LEN: uint = 128; - -impl ToCStr for [u8] { - fn to_c_str(&self) -> CString { - let mut cs = unsafe { self.to_c_str_unchecked() }; - check_for_null(self, cs.as_mut_ptr()); - cs - } - - unsafe fn to_c_str_unchecked(&self) -> CString { - let self_len = self.len(); - let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8; - if buf.is_null() { ::alloc::oom() } - - ptr::copy_memory(buf, self.as_ptr(), self_len); - *buf.offset(self_len as int) = 0; - - CString::new(buf as *const libc::c_char, true) - } - - fn with_c_str(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - unsafe { with_c_str(self, true, f) } - } - - unsafe fn with_c_str_unchecked(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - with_c_str(self, false, f) - } -} - -impl<'a, Sized? T: ToCStr> ToCStr for &'a T { - #[inline] - fn to_c_str(&self) -> CString { - (**self).to_c_str() - } - - #[inline] - unsafe fn to_c_str_unchecked(&self) -> CString { - (**self).to_c_str_unchecked() - } - - #[inline] - fn with_c_str(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - (**self).with_c_str(f) - } - - #[inline] - unsafe fn with_c_str_unchecked(&self, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, - { - (**self).with_c_str_unchecked(f) - } -} - -// Unsafe function that handles possibly copying the &[u8] into a stack array. -unsafe fn with_c_str(v: &[u8], checked: bool, f: F) -> T where - F: FnOnce(*const libc::c_char) -> T, -{ - let c_str = if v.len() < BUF_LEN { - let mut buf: [u8; BUF_LEN] = mem::uninitialized(); - slice::bytes::copy_memory(&mut buf, v); - buf[v.len()] = 0; - - let buf = buf.as_mut_ptr(); - if checked { - check_for_null(v, buf as *mut libc::c_char); - } - - return f(buf as *const libc::c_char) - } else if checked { - v.to_c_str() - } else { - v.to_c_str_unchecked() - }; - - f(c_str.as_ptr()) -} - -#[inline] -fn check_for_null(v: &[u8], buf: *mut libc::c_char) { - for i in range(0, v.len()) { - unsafe { - let p = buf.offset(i as int); - assert!(*p != 0); - } - } -} - -/// External iterator for a CString's bytes. -/// -/// Use with the `std::iter` module. -#[allow(raw_pointer_deriving)] -#[derive(Clone)] -pub struct CChars<'a> { - ptr: *const libc::c_char, - marker: marker::ContravariantLifetime<'a>, -} - -impl<'a> Iterator for CChars<'a> { - type Item = libc::c_char; - - fn next(&mut self) -> Option { - let ch = unsafe { *self.ptr }; - if ch == 0 { - None - } else { - self.ptr = unsafe { self.ptr.offset(1) }; - Some(ch) - } - } -} - -/// Parses a C "multistring", eg windows env values or -/// the req->ptr result in a uv_fs_readdir() call. -/// -/// Optionally, a `count` can be passed in, limiting the -/// parsing to only being done `count`-times. -/// -/// The specified closure is invoked with each string that -/// is found, and the number of strings found is returned. -pub unsafe fn from_c_multistring(buf: *const libc::c_char, - count: Option, - mut f: F) - -> uint where - F: FnMut(&CString), -{ - - let mut curr_ptr: uint = buf as uint; - let mut ctr = 0; - let (limited_count, limit) = match count { - Some(limit) => (true, limit), - None => (false, 0) - }; - while ((limited_count && ctr < limit) || !limited_count) - && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char { - let cstr = CString::new(curr_ptr as *const libc::c_char, false); - f(&cstr); - curr_ptr += cstr.len() + 1; - ctr += 1; - } - return ctr; -} - -#[cfg(test)] -mod tests { - use prelude::v1::*; - use super::*; - use ptr; - use thread::Thread; - use libc; - - #[test] - fn test_str_multistring_parsing() { - unsafe { - let input = b"zero\0one\0\0"; - let ptr = input.as_ptr(); - let expected = ["zero", "one"]; - let mut it = expected.iter(); - let result = from_c_multistring(ptr as *const libc::c_char, None, |c| { - let cbytes = c.as_bytes_no_nul(); - assert_eq!(cbytes, it.next().unwrap().as_bytes()); - }); - assert_eq!(result, 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_str_to_c_str() { - let c_str = "".to_c_str(); - unsafe { - assert_eq!(*c_str.as_ptr().offset(0), 0); - } - - let c_str = "hello".to_c_str(); - let buf = c_str.as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), 'h' as libc::c_char); - assert_eq!(*buf.offset(1), 'e' as libc::c_char); - assert_eq!(*buf.offset(2), 'l' as libc::c_char); - assert_eq!(*buf.offset(3), 'l' as libc::c_char); - assert_eq!(*buf.offset(4), 'o' as libc::c_char); - assert_eq!(*buf.offset(5), 0); - } - } - - #[test] - fn test_vec_to_c_str() { - let b: &[u8] = &[]; - let c_str = b.to_c_str(); - unsafe { - assert_eq!(*c_str.as_ptr().offset(0), 0); - } - - let c_str = b"hello".to_c_str(); - let buf = c_str.as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), 'h' as libc::c_char); - assert_eq!(*buf.offset(1), 'e' as libc::c_char); - assert_eq!(*buf.offset(2), 'l' as libc::c_char); - assert_eq!(*buf.offset(3), 'l' as libc::c_char); - assert_eq!(*buf.offset(4), 'o' as libc::c_char); - assert_eq!(*buf.offset(5), 0); - } - - let c_str = b"foo\xFF".to_c_str(); - let buf = c_str.as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), 'f' as libc::c_char); - assert_eq!(*buf.offset(1), 'o' as libc::c_char); - assert_eq!(*buf.offset(2), 'o' as libc::c_char); - assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char); - assert_eq!(*buf.offset(4), 0); - } - } - - #[test] - fn test_unwrap() { - let c_str = "hello".to_c_str(); - unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) } - } - - #[test] - fn test_as_ptr() { - let c_str = "hello".to_c_str(); - let len = unsafe { libc::strlen(c_str.as_ptr()) }; - assert_eq!(len, 5); - } - - #[test] - fn test_iterator() { - let c_str = "".to_c_str(); - let mut iter = c_str.iter(); - assert_eq!(iter.next(), None); - - let c_str = "hello".to_c_str(); - let mut iter = c_str.iter(); - assert_eq!(iter.next(), Some('h' as libc::c_char)); - assert_eq!(iter.next(), Some('e' as libc::c_char)); - assert_eq!(iter.next(), Some('l' as libc::c_char)); - assert_eq!(iter.next(), Some('l' as libc::c_char)); - assert_eq!(iter.next(), Some('o' as libc::c_char)); - assert_eq!(iter.next(), None); - } - - #[test] - fn test_to_c_str_fail() { - assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err()); - } - - #[test] - fn test_to_c_str_unchecked() { - unsafe { - let c_string = "he\x00llo".to_c_str_unchecked(); - let buf = c_string.as_ptr(); - assert_eq!(*buf.offset(0), 'h' as libc::c_char); - assert_eq!(*buf.offset(1), 'e' as libc::c_char); - assert_eq!(*buf.offset(2), 0); - assert_eq!(*buf.offset(3), 'l' as libc::c_char); - assert_eq!(*buf.offset(4), 'l' as libc::c_char); - assert_eq!(*buf.offset(5), 'o' as libc::c_char); - assert_eq!(*buf.offset(6), 0); - } - } - - #[test] - fn test_as_bytes() { - let c_str = "hello".to_c_str(); - assert_eq!(c_str.as_bytes(), b"hello\0"); - let c_str = "".to_c_str(); - assert_eq!(c_str.as_bytes(), b"\0"); - let c_str = b"foo\xFF".to_c_str(); - assert_eq!(c_str.as_bytes(), b"foo\xFF\0"); - } - - #[test] - fn test_as_bytes_no_nul() { - let c_str = "hello".to_c_str(); - assert_eq!(c_str.as_bytes_no_nul(), b"hello"); - let c_str = "".to_c_str(); - let exp: &[u8] = &[]; - assert_eq!(c_str.as_bytes_no_nul(), exp); - let c_str = b"foo\xFF".to_c_str(); - assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF"); - } - - #[test] - fn test_as_str() { - let c_str = "hello".to_c_str(); - assert_eq!(c_str.as_str(), Some("hello")); - let c_str = "".to_c_str(); - assert_eq!(c_str.as_str(), Some("")); - let c_str = b"foo\xFF".to_c_str(); - assert_eq!(c_str.as_str(), None); - } - - #[test] - #[should_fail] - fn test_new_fail() { - let _c_str = unsafe { CString::new(ptr::null(), false) }; - } - - #[test] - fn test_clone() { - let a = "hello".to_c_str(); - let b = a.clone(); - assert!(a == b); - } - - #[test] - fn test_clone_noleak() { - fn foo(f: F) where F: FnOnce(&CString) { - let s = "test".to_string(); - let c = s.to_c_str(); - // give the closure a non-owned CString - let mut c_ = unsafe { CString::new(c.as_ptr(), false) }; - f(&c_); - // muck with the buffer for later printing - unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char } - } - - let mut c_: Option = None; - foo(|c| { - c_ = Some(c.clone()); - c.clone(); - // force a copy, reading the memory - c.as_bytes().to_vec(); - }); - let c_ = c_.unwrap(); - // force a copy, reading the memory - c_.as_bytes().to_vec(); - } -} - -#[cfg(test)] -mod bench { - extern crate test; - - use prelude::v1::*; - use self::test::Bencher; - use libc; - use c_str::ToCStr; - - #[inline] - fn check(s: &str, c_str: *const libc::c_char) { - let s_buf = s.as_ptr(); - for i in range(0, s.len()) { - unsafe { - assert_eq!( - *s_buf.offset(i as int) as libc::c_char, - *c_str.offset(i as int)); - } - } - } - - static S_SHORT: &'static str = "Mary"; - static S_MEDIUM: &'static str = "Mary had a little lamb"; - static S_LONG: &'static str = "\ - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb"; - - fn bench_to_string(b: &mut Bencher, s: &str) { - b.iter(|| { - let c_str = s.to_c_str(); - check(s, c_str.as_ptr()); - }) - } - - #[bench] - fn bench_to_c_str_short(b: &mut Bencher) { - bench_to_string(b, S_SHORT) - } - - #[bench] - fn bench_to_c_str_medium(b: &mut Bencher) { - bench_to_string(b, S_MEDIUM) - } - - #[bench] - fn bench_to_c_str_long(b: &mut Bencher) { - bench_to_string(b, S_LONG) - } - - fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) { - b.iter(|| { - let c_str = unsafe { s.to_c_str_unchecked() }; - check(s, c_str.as_ptr()) - }) - } - - #[bench] - fn bench_to_c_str_unchecked_short(b: &mut Bencher) { - bench_to_c_str_unchecked(b, S_SHORT) - } - - #[bench] - fn bench_to_c_str_unchecked_medium(b: &mut Bencher) { - bench_to_c_str_unchecked(b, S_MEDIUM) - } - - #[bench] - fn bench_to_c_str_unchecked_long(b: &mut Bencher) { - bench_to_c_str_unchecked(b, S_LONG) - } - - fn bench_with_c_str(b: &mut Bencher, s: &str) { - b.iter(|| { - s.with_c_str(|c_str_buf| check(s, c_str_buf)) - }) - } - - #[bench] - fn bench_with_c_str_short(b: &mut Bencher) { - bench_with_c_str(b, S_SHORT) - } - - #[bench] - fn bench_with_c_str_medium(b: &mut Bencher) { - bench_with_c_str(b, S_MEDIUM) - } - - #[bench] - fn bench_with_c_str_long(b: &mut Bencher) { - bench_with_c_str(b, S_LONG) - } - - fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) { - b.iter(|| { - unsafe { - s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf)) - } - }) - } - - #[bench] - fn bench_with_c_str_unchecked_short(b: &mut Bencher) { - bench_with_c_str_unchecked(b, S_SHORT) - } - - #[bench] - fn bench_with_c_str_unchecked_medium(b: &mut Bencher) { - bench_with_c_str_unchecked(b, S_MEDIUM) - } - - #[bench] - fn bench_with_c_str_unchecked_long(b: &mut Bencher) { - bench_with_c_str_unchecked(b, S_LONG) - } -} diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs deleted file mode 100644 index 4a20208f31a6a..0000000000000 --- a/src/libstd/c_vec.rs +++ /dev/null @@ -1,232 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Library to interface with chunks of memory allocated in C. -//! -//! It is often desirable to safely interface with memory allocated from C, -//! encapsulating the unsafety into allocation and destruction time. Indeed, -//! allocating memory externally is currently the only way to give Rust shared -//! mut state with C programs that keep their own references; vectors are -//! unsuitable because they could be reallocated or moved at any time, and -//! importing C memory into a vector takes a one-time snapshot of the memory. -//! -//! This module simplifies the usage of such external blocks of memory. Memory -//! is encapsulated into an opaque object after creation; the lifecycle of the -//! memory can be optionally managed by Rust, if an appropriate destructor -//! closure is provided. Safety is ensured by bounds-checking accesses, which -//! are marshalled through get and set functions. -//! -//! There are three unsafe functions: the two constructors, and the -//! unwrap method. The constructors are unsafe for the -//! obvious reason (they act on a pointer that cannot be checked inside the -//! method), but `unwrap()` is somewhat more subtle in its unsafety. -//! It returns the contained pointer, but at the same time destroys the CVec -//! without running its destructor. This can be used to pass memory back to -//! C, but care must be taken that the ownership of underlying resources are -//! handled correctly, i.e. that allocated memory is eventually freed -//! if necessary. - -#![experimental] - -use kinds::Send; -use mem; -use ops::{Drop, FnOnce}; -use option::Option; -use option::Option::{Some, None}; -use ptr::PtrExt; -use ptr; -use raw; -use slice::AsSlice; -use thunk::{Thunk}; - -/// The type representing a foreign chunk of memory -pub struct CVec { - base: *mut T, - len: uint, - dtor: Option, -} - -#[unsafe_destructor] -impl Drop for CVec { - fn drop(&mut self) { - match self.dtor.take() { - None => (), - Some(f) => f.invoke(()) - } - } -} - -impl CVec { - /// Create a `CVec` from a raw pointer to a buffer with a given length. - /// - /// Panics if the given pointer is null. The returned vector will not attempt - /// to deallocate the vector when dropped. - /// - /// # Arguments - /// - /// * base - A raw pointer to a buffer - /// * len - The number of elements in the buffer - pub unsafe fn new(base: *mut T, len: uint) -> CVec { - assert!(base != ptr::null_mut()); - CVec { - base: base, - len: len, - dtor: None, - } - } - - /// Create a `CVec` from a foreign buffer, with a given length, - /// and a function to run upon destruction. - /// - /// Panics if the given pointer is null. - /// - /// # Arguments - /// - /// * base - A foreign pointer to a buffer - /// * len - The number of elements in the buffer - /// * dtor - A fn to run when the value is destructed, useful - /// for freeing the buffer, etc. - pub unsafe fn new_with_dtor(base: *mut T, - len: uint, - dtor: F) - -> CVec - where F : FnOnce(), F : Send - { - assert!(base != ptr::null_mut()); - let dtor: Thunk = Thunk::new(dtor); - CVec { - base: base, - len: len, - dtor: Some(dtor) - } - } - - /// View the stored data as a mutable slice. - pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] { - unsafe { - mem::transmute(raw::Slice { data: self.base as *const T, len: self.len }) - } - } - - /// Retrieves an element at a given index, returning `None` if the requested - /// index is greater than the length of the vector. - pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> { - if ofs < self.len { - Some(unsafe { &*self.base.offset(ofs as int) }) - } else { - None - } - } - - /// Retrieves a mutable element at a given index, returning `None` if the - /// requested index is greater than the length of the vector. - pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> { - if ofs < self.len { - Some(unsafe { &mut *self.base.offset(ofs as int) }) - } else { - None - } - } - - /// Unwrap the pointer without running the destructor - /// - /// This method retrieves the underlying pointer, and in the process - /// destroys the CVec but without running the destructor. A use case - /// would be transferring ownership of the buffer to a C function, as - /// in this case you would not want to run the destructor. - /// - /// Note that if you want to access the underlying pointer without - /// cancelling the destructor, you can simply call `transmute` on the return - /// value of `get(0)`. - pub unsafe fn into_inner(mut self) -> *mut T { - self.dtor = None; - self.base - } - - /// Returns the number of items in this vector. - pub fn len(&self) -> uint { self.len } - - /// Returns whether this vector is empty. - pub fn is_empty(&self) -> bool { self.len() == 0 } -} - -impl AsSlice for CVec { - /// View the stored data as a slice. - fn as_slice<'a>(&'a self) -> &'a [T] { - unsafe { - mem::transmute(raw::Slice { data: self.base as *const T, len: self.len }) - } - } -} - -#[cfg(test)] -mod tests { - use prelude::v1::*; - - use super::CVec; - use libc; - use ptr; - - fn malloc(n: uint) -> CVec { - unsafe { - let mem = ptr::Unique(libc::malloc(n as libc::size_t)); - if mem.0.is_null() { ::alloc::oom() } - - CVec::new_with_dtor(mem.0 as *mut u8, - n, - move|| { libc::free(mem.0 as *mut libc::c_void); }) - } - } - - #[test] - fn test_basic() { - let mut cv = malloc(16); - - *cv.get_mut(3).unwrap() = 8; - *cv.get_mut(4).unwrap() = 9; - assert_eq!(*cv.get(3).unwrap(), 8); - assert_eq!(*cv.get(4).unwrap(), 9); - assert_eq!(cv.len(), 16); - } - - #[test] - #[should_fail] - fn test_panic_at_null() { - unsafe { - CVec::new(ptr::null_mut::(), 9); - } - } - - #[test] - fn test_overrun_get() { - let cv = malloc(16); - - assert!(cv.get(17).is_none()); - } - - #[test] - fn test_overrun_set() { - let mut cv = malloc(16); - - assert!(cv.get_mut(17).is_none()); - } - - #[test] - fn test_unwrap() { - unsafe { - let cv = CVec::new_with_dtor(1 as *mut int, - 0, - move|:| panic!("Don't run this destructor!")); - let p = cv.into_inner(); - assert_eq!(p, 1 as *mut int); - } - } - -} diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index de3d75ffb3242..66cb1f2c948d9 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -17,7 +17,7 @@ use prelude::v1::*; -use c_str::ToCStr; +use ffi::CString; use mem; use os; use str; @@ -51,13 +51,11 @@ impl DynamicLibrary { /// Lazily open a dynamic library. When passed None it gives a /// handle to the calling process - pub fn open(filename: Option) - -> Result { + pub fn open(filename: Option<&Path>) -> Result { unsafe { - let mut filename = filename; let maybe_library = dl::check_for_errors_in(|| { - match filename.take() { - Some(name) => dl::open_external(name), + match filename { + Some(name) => dl::open_external(name.as_vec()), None => dl::open_internal() } }); @@ -131,9 +129,8 @@ impl DynamicLibrary { // T but that feature is still unimplemented let maybe_symbol_value = dl::check_for_errors_in(|| { - symbol.with_c_str(|raw_string| { - dl::symbol(self.handle, raw_string) - }) + let raw_string = CString::from_slice(symbol.as_bytes()); + dl::symbol(self.handle, raw_string.as_ptr()) }); // The value must not be constructed if there is an error so @@ -157,7 +154,7 @@ mod test { fn test_loading_cosine() { // The math library does not need to be loaded since it is already // statically linked in - let none: Option = None; // appease the typechecker + let none: Option<&Path> = None; // appease the typechecker let libm = match DynamicLibrary::open(none) { Err(error) => panic!("Could not load self as module: {}", error), Ok(libm) => libm @@ -202,17 +199,17 @@ mod test { target_os = "freebsd", target_os = "dragonfly"))] pub mod dl { - use self::Rtld::*; - + pub use self::Rtld::*; use prelude::v1::*; - use c_str::{CString, ToCStr}; + + use ffi::{self, CString}; + use str; use libc; use ptr; - pub unsafe fn open_external(filename: T) -> *mut u8 { - filename.with_c_str(|raw_name| { - dlopen(raw_name, Lazy as libc::c_int) as *mut u8 - }) + pub unsafe fn open_external(filename: &[u8]) -> *mut u8 { + let s = CString::from_slice(filename); + dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8 } pub unsafe fn open_internal() -> *mut u8 { @@ -236,8 +233,8 @@ pub mod dl { let ret = if ptr::null() == last_error { Ok(result) } else { - Err(String::from_str(CString::new(last_error, false).as_str() - .unwrap())) + let s = ffi::c_str_to_bytes(&last_error); + Err(str::from_utf8(s).unwrap().to_string()) }; ret @@ -273,7 +270,6 @@ pub mod dl { #[cfg(target_os = "windows")] pub mod dl { - use c_str::ToCStr; use iter::IteratorExt; use libc; use ops::FnOnce; @@ -287,10 +283,9 @@ pub mod dl { use string::String; use vec::Vec; - pub unsafe fn open_external(filename: T) -> *mut u8 { + pub unsafe fn open_external(filename: &[u8]) -> *mut u8 { // Windows expects Unicode data - let filename_cstr = filename.to_c_str(); - let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap(); + let filename_str = str::from_utf8(filename).unwrap(); let mut filename_str: Vec = filename_str.utf16_units().collect(); filename_str.push(0); LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8 diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs new file mode 100644 index 0000000000000..bef2344d9e8bc --- /dev/null +++ b/src/libstd/ffi/c_str.rs @@ -0,0 +1,218 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use fmt; +use iter::IteratorExt; +use libc; +use mem; +use ops::Deref; +use slice::{self, SliceExt, AsSlice}; +use string::String; +use vec::Vec; + +/// A type representing a C-compatible string +/// +/// This type serves the primary purpose of being able to generate a +/// C-compatible string from a Rust byte slice or vector. An instance of this +/// type is a static guarantee that the underlying bytes contain no interior 0 +/// bytes and the final byte is 0. +/// +/// A `CString` is created from either a byte slice or a byte vector. After +/// being created, a `CString` predominately inherits all of its methods from +/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying +/// array is represented as an array of `libc::c_char` as opposed to `u8`. A +/// `u8` slice can be obtained with the `as_bytes` method. Slices produced from +/// a `CString` do *not* contain the trailing nul terminator unless otherwise +/// specified. +/// +/// # Example +/// +/// ```no_run +/// # extern crate libc; +/// # fn main() { +/// use std::ffi::CString; +/// use libc; +/// +/// extern { +/// fn my_printer(s: *const libc::c_char); +/// } +/// +/// let to_print = "Hello, world!"; +/// let c_to_print = CString::from_slice(to_print.as_bytes()); +/// unsafe { +/// my_printer(c_to_print.as_ptr()); +/// } +/// # } +/// ``` +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct CString { + inner: Vec, +} + +impl CString { + /// Create a new C-compatible string from a byte slice. + /// + /// This method will copy the data of the slice provided into a new + /// allocation, ensuring that there is a trailing 0 byte. + /// + /// # Panics + /// + /// This function will panic if there are any 0 bytes already in the slice + /// provided. + pub fn from_slice(v: &[u8]) -> CString { + CString::from_vec(v.to_vec()) + } + + /// Create a C-compatible string from a byte vector. + /// + /// This method will consume ownership of the provided vector, appending a 0 + /// byte to the end after verifying that there are no interior 0 bytes. + /// + /// # Panics + /// + /// This function will panic if there are any 0 bytes already in the vector + /// provided. + pub fn from_vec(v: Vec) -> CString { + assert!(!v.iter().any(|&x| x == 0)); + unsafe { CString::from_vec_unchecked(v) } + } + + /// Create a C-compatibel string from a byte vector without checking for + /// interior 0 bytes. + /// + /// This method is equivalent to `from_vec` except that no runtime assertion + /// is made that `v` contains no 0 bytes. + pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { + v.push(0); + CString { inner: mem::transmute(v) } + } + + /// Create a view into this C string which includes the trailing nul + /// terminator at the end of the string. + pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() } + + /// Similar to the `as_slice` method, but returns a `u8` slice instead of a + /// `libc::c_char` slice. + pub fn as_bytes(&self) -> &[u8] { + unsafe { mem::transmute(self.as_slice()) } + } + + /// Equivalend to `as_slice_with_nul` except that the type returned is a + /// `u8` slice instead of a `libc::c_char` slice. + pub fn as_bytes_with_nul(&self) -> &[u8] { + unsafe { mem::transmute(self.as_slice_with_nul()) } + } +} + +impl Deref for CString { + type Target = [libc::c_char]; + + fn deref(&self) -> &[libc::c_char] { + self.inner.slice_to(self.inner.len() - 1) + } +} + +impl fmt::Show for CString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + String::from_utf8_lossy(self.as_bytes()).fmt(f) + } +} + +/// Interpret a C string as a byte slice. +/// +/// This function will calculate the length of the C string provided, and it +/// will then return a corresponding slice for the contents of the C string not +/// including the nul terminator. +/// +/// This function will tie the lifetime of the returned slice to the lifetime of +/// the pointer provided. This is done to help prevent the slice from escaping +/// the lifetime of the pointer itself. If a longer lifetime is needed, then +/// `mem::copy_lifetime` should be used. +/// +/// This function is unsafe because there is no guarantee of the validity of the +/// pointer `raw` or a guarantee that a nul terminator will be found. +/// +/// # Example +/// +/// ```no_run +/// # extern crate libc; +/// # fn main() { +/// use std::ffi; +/// use std::str; +/// use libc; +/// +/// extern { +/// fn my_string() -> *const libc::c_char; +/// } +/// +/// unsafe { +/// let to_print = my_string(); +/// let slice = ffi::c_str_to_bytes(&to_print); +/// println!("string returned: {}", str::from_utf8(slice).unwrap()); +/// } +/// # } +/// ``` +pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { + let len = libc::strlen(*raw); + slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint) +} + +/// Interpret a C string as a byte slice with the nul terminator. +/// +/// This function is identical to `from_raw_buf` except that the returned slice +/// will include the nul terminator of the string. +pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { + let len = libc::strlen(*raw) + 1; + slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint) +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + use super::*; + use libc; + use mem; + + #[test] + fn c_to_rust() { + let data = b"123\0"; + let ptr = data.as_ptr() as *const libc::c_char; + unsafe { + assert_eq!(c_str_to_bytes(&ptr), b"123"); + assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0"); + } + } + + #[test] + fn simple() { + let s = CString::from_slice(b"1234"); + assert_eq!(s.as_bytes(), b"1234"); + assert_eq!(s.as_bytes_with_nul(), b"1234\0"); + unsafe { + assert_eq!(s.as_slice(), + mem::transmute::<_, &[libc::c_char]>(b"1234")); + assert_eq!(s.as_slice_with_nul(), + mem::transmute::<_, &[libc::c_char]>(b"1234\0")); + } + } + + #[should_fail] #[test] + fn build_with_zero1() { CString::from_slice(b"\0"); } + #[should_fail] #[test] + fn build_with_zero2() { CString::from_vec(vec![0]); } + + #[test] + fn build_with_zero3() { + unsafe { + let s = CString::from_vec_unchecked(vec![0]); + assert_eq!(s.as_bytes(), b"\0"); + } + } +} diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs new file mode 100644 index 0000000000000..cc86f804e3eb1 --- /dev/null +++ b/src/libstd/ffi/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +//! Utilities related to FFI bindings. + +#![unstable = "module just underwent fairly large reorganization and the dust \ + still needs to settle"] + +pub use self::c_str::CString; +pub use self::c_str::c_str_to_bytes; +pub use self::c_str::c_str_to_bytes_with_nul; + +mod c_str; diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index daefdd28b306a..738c70412f78a 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -22,7 +22,8 @@ use prelude::v1::*; -use c_str::ToCStr; +use ffi::CString; +use path::BytesContainer; use io::{Listener, Acceptor, IoResult, TimedOut, standard_error}; use sys::pipe::UnixAcceptor as UnixAcceptorImp; use sys::pipe::UnixListener as UnixListenerImp; @@ -53,8 +54,9 @@ impl UnixStream { /// let mut stream = UnixStream::connect(&server); /// stream.write(&[1, 2, 3]); /// ``` - pub fn connect(path: &P) -> IoResult { - UnixStreamImp::connect(&path.to_c_str(), None) + pub fn connect(path: P) -> IoResult { + let path = CString::from_slice(path.container_as_bytes()); + UnixStreamImp::connect(&path, None) .map(|inner| UnixStream { inner: inner }) } @@ -67,13 +69,15 @@ impl UnixStream { /// If a `timeout` with zero or negative duration is specified then /// the function returns `Err`, with the error kind set to `TimedOut`. #[experimental = "the timeout argument is likely to change types"] - pub fn connect_timeout(path: &P, - timeout: Duration) -> IoResult { + pub fn connect_timeout

(path: P, timeout: Duration) + -> IoResult + where P: BytesContainer { if timeout <= Duration::milliseconds(0) { return Err(standard_error(TimedOut)); } - UnixStreamImp::connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64)) + let path = CString::from_slice(path.container_as_bytes()); + UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64)) .map(|inner| UnixStream { inner: inner }) } @@ -177,8 +181,9 @@ impl UnixListener { /// } /// # } /// ``` - pub fn bind(path: &P) -> IoResult { - UnixListenerImp::bind(&path.to_c_str()) + pub fn bind(path: P) -> IoResult { + let path = CString::from_slice(path.container_as_bytes()); + UnixListenerImp::bind(&path) .map(|inner| UnixListener { inner: inner }) } } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 5886c9cc3e287..ea232ad0c3f1b 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -18,8 +18,8 @@ pub use self::ProcessExit::*; use prelude::v1::*; -use c_str::{CString, ToCStr}; use collections::HashMap; +use ffi::CString; use fmt; use hash::Hash; use io::pipe::{PipeStream, PipePair}; @@ -35,6 +35,7 @@ use sys; use thread::Thread; #[cfg(windows)] use std::hash::sip::SipState; +#[cfg(windows)] use str; /// Signal a process to exit, without forcibly killing it. Corresponds to /// SIGTERM on unix platforms. @@ -109,11 +110,11 @@ struct EnvKey(CString); impl Hash for EnvKey { fn hash(&self, state: &mut SipState) { let &EnvKey(ref x) = self; - match x.as_str() { - Some(s) => for ch in s.chars() { + match str::from_utf8(x.as_bytes()) { + Ok(s) => for ch in s.chars() { (ch as u8 as char).to_lowercase().hash(state); }, - None => x.hash(state) + Err(..) => x.hash(state) } } } @@ -123,8 +124,8 @@ impl PartialEq for EnvKey { fn eq(&self, other: &EnvKey) -> bool { let &EnvKey(ref x) = self; let &EnvKey(ref y) = other; - match (x.as_str(), y.as_str()) { - (Some(xs), Some(ys)) => { + match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) { + (Ok(xs), Ok(ys)) => { if xs.len() != ys.len() { return false } else { @@ -185,10 +186,10 @@ pub struct Command { } // FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so -// we cannot usefully take ToCStr arguments by reference (without forcing an +// we cannot usefully take BytesContainer arguments by reference (without forcing an // additional & around &str). So we are instead temporarily adding an instance -// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path -// instance should be removed, and arguments bound by ToCStr should be passed by +// for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path +// instance should be removed, and arguments bound by BytesContainer should be passed by // reference. (Here: {new, arg, args, env}.) impl Command { @@ -203,9 +204,9 @@ impl Command { /// /// Builder methods are provided to change these defaults and /// otherwise configure the process. - pub fn new(program: T) -> Command { + pub fn new(program: T) -> Command { Command { - program: program.to_c_str(), + program: CString::from_slice(program.container_as_bytes()), args: Vec::new(), env: None, cwd: None, @@ -219,27 +220,29 @@ impl Command { } /// Add an argument to pass to the program. - pub fn arg<'a, T: ToCStr>(&'a mut self, arg: T) -> &'a mut Command { - self.args.push(arg.to_c_str()); + pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command { + self.args.push(CString::from_slice(arg.container_as_bytes())); self } /// Add multiple arguments to pass to the program. - pub fn args<'a, T: ToCStr>(&'a mut self, args: &[T]) -> &'a mut Command { - self.args.extend(args.iter().map(|arg| arg.to_c_str()));; + pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command { + self.args.extend(args.iter().map(|arg| { + CString::from_slice(arg.container_as_bytes()) + })); self } // Get a mutable borrow of the environment variable map for this `Command`. - fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap { + fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap { match self.env { Some(ref mut map) => map, None => { // if the env is currently just inheriting from the parent's, // materialize the parent's env into a hashtable. - self.env = Some(os::env_as_bytes().into_iter() - .map(|(k, v)| (EnvKey(k.to_c_str()), - v.to_c_str())) - .collect()); + self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| { + (EnvKey(CString::from_slice(k.as_slice())), + CString::from_slice(v.as_slice())) + }).collect()); self.env.as_mut().unwrap() } } @@ -249,15 +252,20 @@ impl Command { /// /// Note that environment variable names are case-insensitive (but case-preserving) on Windows, /// and case-sensitive on all other platforms. - pub fn env<'a, T: ToCStr, U: ToCStr>(&'a mut self, key: T, val: U) - -> &'a mut Command { - self.get_env_map().insert(EnvKey(key.to_c_str()), val.to_c_str()); + pub fn env<'a, T, U>(&'a mut self, key: T, val: U) + -> &'a mut Command + where T: BytesContainer, U: BytesContainer { + let key = EnvKey(CString::from_slice(key.container_as_bytes())); + let val = CString::from_slice(val.container_as_bytes()); + self.get_env_map().insert(key, val); self } /// Removes an environment variable mapping. - pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command { - self.get_env_map().remove(&EnvKey(key.to_c_str())); + pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command + where T: BytesContainer { + let key = EnvKey(CString::from_slice(key.container_as_bytes())); + self.get_env_map().remove(&key); self } @@ -265,16 +273,19 @@ impl Command { /// /// If the given slice contains multiple instances of an environment /// variable, the *rightmost* instance will determine the value. - pub fn env_set_all<'a, T: ToCStr, U: ToCStr>(&'a mut self, env: &[(T,U)]) - -> &'a mut Command { - self.env = Some(env.iter().map(|&(ref k, ref v)| (EnvKey(k.to_c_str()), v.to_c_str())) - .collect()); + pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)]) + -> &'a mut Command + where T: BytesContainer, U: BytesContainer { + self.env = Some(env.iter().map(|&(ref k, ref v)| { + (EnvKey(CString::from_slice(k.container_as_bytes())), + CString::from_slice(v.container_as_bytes())) + }).collect()); self } /// Set the working directory for the child process. pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command { - self.cwd = Some(dir.to_c_str()); + self.cwd = Some(CString::from_slice(dir.as_vec())); self } @@ -389,9 +400,9 @@ impl fmt::Show for Command { /// non-utf8 data is lossily converted using the utf8 replacement /// character. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes_no_nul()))); + try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes()))); for arg in self.args.iter() { - try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes_no_nul()))); + try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes()))); } Ok(()) } @@ -1208,13 +1219,13 @@ mod tests { #[test] #[cfg(windows)] fn env_map_keys_ci() { - use c_str::ToCStr; + use ffi::CString; use super::EnvKey; let mut cmd = Command::new(""); cmd.env("path", "foo"); cmd.env("Path", "bar"); let env = &cmd.env.unwrap(); - let val = env.get(&EnvKey("PATH".to_c_str())); - assert!(val.unwrap() == &"bar".to_c_str()); + let val = env.get(&EnvKey(CString::from_slice(b"PATH"))); + assert!(val.unwrap() == &CString::from_slice(b"bar")); } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 608ad9882b977..2d3a4639379cf 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -208,10 +208,10 @@ pub mod num; /* Runtime and platform support */ -pub mod thread_local; -pub mod c_str; -pub mod c_vec; +pub mod thread_local; // first for macros + pub mod dynamic_lib; +pub mod ffi; pub mod fmt; pub mod io; pub mod os; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index be8f82349c222..300ceec4b45bf 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -57,12 +57,10 @@ use string::{String, ToString}; use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering}; use vec::Vec; -#[cfg(unix)] use c_str::ToCStr; +#[cfg(unix)] use ffi::{self, CString}; -#[cfg(unix)] -pub use sys::ext as unix; -#[cfg(windows)] -pub use sys::ext as windows; +#[cfg(unix)] pub use sys::ext as unix; +#[cfg(windows)] pub use sys::ext as windows; /// Get the number of cores available pub fn num_cpus() -> uint { @@ -196,15 +194,14 @@ pub fn getenv(n: &str) -> Option { /// /// Panics if `n` has any interior NULs. pub fn getenv_as_bytes(n: &str) -> Option> { - use c_str::CString; - unsafe { with_env_lock(|| { - let s = n.with_c_str(|buf| libc::getenv(buf)); + let s = CString::from_slice(n.as_bytes()); + let s = libc::getenv(s.as_ptr()) as *const _; if s.is_null() { None } else { - Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec()) + Some(ffi::c_str_to_bytes(&s).to_vec()) } }) } @@ -253,13 +250,12 @@ pub fn setenv(n: &str, v: T) { fn _setenv(n: &str, v: &[u8]) { unsafe { with_env_lock(|| { - n.with_c_str(|nbuf| { - v.with_c_str(|vbuf| { - if libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1) != 0 { - panic!(IoError::last_error()); - } - }) - }) + let k = CString::from_slice(n.as_bytes()); + let v = CString::from_slice(v); + if libc::funcs::posix01::unistd::setenv(k.as_ptr(), + v.as_ptr(), 1) != 0 { + panic!(IoError::last_error()); + } }) } } @@ -289,11 +285,10 @@ pub fn unsetenv(n: &str) { fn _unsetenv(n: &str) { unsafe { with_env_lock(|| { - n.with_c_str(|nbuf| { - if libc::funcs::posix01::unistd::unsetenv(nbuf) != 0 { - panic!(IoError::last_error()); - } - }) + let nbuf = CString::from_slice(n.as_bytes()); + if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { + panic!(IoError::last_error()); + } }) } } @@ -618,11 +613,10 @@ pub fn get_exit_status() -> int { #[cfg(target_os = "macos")] unsafe fn load_argc_and_argv(argc: int, argv: *const *const c_char) -> Vec> { - use c_str::CString; use iter::range; range(0, argc as uint).map(|i| { - CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec() + ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec() }).collect() } @@ -652,7 +646,6 @@ fn real_args_as_bytes() -> Vec> { // res #[cfg(target_os = "ios")] fn real_args_as_bytes() -> Vec> { - use c_str::CString; use iter::range; use mem; diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index bf9ffbffe7d50..2f014872402cf 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -62,7 +62,7 @@ #![experimental] use core::kinds::Sized; -use c_str::CString; +use ffi::CString; use clone::Clone; use fmt; use iter::IteratorExt; @@ -892,7 +892,7 @@ impl BytesContainer for Vec { impl BytesContainer for CString { #[inline] fn container_as_bytes<'a>(&'a self) -> &'a [u8] { - self.as_bytes_no_nul() + self.as_bytes() } } @@ -913,21 +913,3 @@ impl<'a, Sized? T: BytesContainer> BytesContainer for &'a T { fn contains_nul(v: &T) -> bool { v.container_as_bytes().iter().any(|&x| x == 0) } - -#[cfg(test)] -mod tests { - use prelude::v1::*; - use c_str::ToCStr; - use path::{WindowsPath, PosixPath}; - - #[test] - fn test_cstring() { - let input = "/foo/bar/baz"; - let path: PosixPath = PosixPath::new(input.to_c_str()); - assert_eq!(path.as_vec(), input.as_bytes()); - - let input = r"\foo\bar\baz"; - let path: WindowsPath = WindowsPath::new(input.to_c_str()); - assert_eq!(path.as_str().unwrap(), input); - } -} diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index ae82e201cb855..013212b27058c 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -10,19 +10,16 @@ //! POSIX file path handling -use c_str::{CString, ToCStr}; use clone::Clone; -use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; +use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; use hash; use io::Writer; use iter::{AdditiveIterator, Extend}; use iter::{Iterator, IteratorExt, Map}; -use option::Option; -use option::Option::{None, Some}; use kinds::Sized; -use str::{FromStr, Str}; -use str; -use slice::{Split, AsSlice, SliceConcatExt, SliceExt}; +use option::Option::{self, Some, None}; +use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; +use str::{self, FromStr, StrExt}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -86,26 +83,6 @@ impl FromStr for Path { } } -// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so -// we cannot usefully take ToCStr arguments by reference (without forcing an -// additional & around &str). So we are instead temporarily adding an instance -// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path -// instance should be removed, and arguments bound by ToCStr should be passed by -// reference. - -impl ToCStr for Path { - #[inline] - fn to_c_str(&self) -> CString { - // The Path impl guarantees no internal NUL - unsafe { self.to_c_str_unchecked() } - } - - #[inline] - unsafe fn to_c_str_unchecked(&self) -> CString { - self.as_vec().to_c_str_unchecked() - } -} - impl hash::Hash for Path { #[inline] fn hash(&self, state: &mut S) { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index cf8bc0e6242b3..05129a7ab9da3 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -15,17 +15,15 @@ use self::PathPrefix::*; use ascii::AsciiExt; -use c_str::{CString, ToCStr}; use char::CharExt; use clone::Clone; -use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; +use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; use hash; use io::Writer; use iter::{AdditiveIterator, Extend}; use iter::{Iterator, IteratorExt, Map, repeat}; use mem; -use option::Option; -use option::Option::{Some, None}; +use option::Option::{self, Some, None}; use slice::{SliceExt, SliceConcatExt}; use str::{SplitTerminator, FromStr, StrExt}; use string::{String, ToString}; @@ -112,26 +110,6 @@ impl FromStr for Path { } } -// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so -// we cannot usefully take ToCStr arguments by reference (without forcing an -// additional & around &str). So we are instead temporarily adding an instance -// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path -// instance should be removed, and arguments bound by ToCStr should be passed by -// reference. - -impl ToCStr for Path { - #[inline] - fn to_c_str(&self) -> CString { - // The Path impl guarantees no internal NUL - unsafe { self.to_c_str_unchecked() } - } - - #[inline] - unsafe fn to_c_str_unchecked(&self) -> CString { - self.as_vec().to_c_str_unchecked() - } -} - impl hash::Hash for Path { #[cfg(not(test))] #[inline] diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 4734a39c83542..86abacb936501 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -46,8 +46,9 @@ pub fn clone() -> Option>> { imp::clone() } mod imp { use prelude::v1::*; + use libc; use mem; - use slice; + use ffi; use sync::{StaticMutex, MUTEX_INIT}; @@ -95,13 +96,9 @@ mod imp { } unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec> { + let argv = argv as *const *const libc::c_char; range(0, argc as uint).map(|i| { - let arg = *argv.offset(i as int); - let mut len = 0u; - while *arg.offset(len as int) != 0 { - len += 1u; - } - slice::from_raw_buf(&arg, len).to_vec() + ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec() }).collect() } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 578239c9cc42e..bb0b6fe804bea 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -15,7 +15,7 @@ use prelude::v1::*; use os; -use sync::atomic::{mod, Ordering}; +use sync::atomic::{self, Ordering}; pub use sys::backtrace::write; diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index a48a8edd82f60..71169386c186a 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -67,7 +67,7 @@ use fmt; use intrinsics; use libc::c_void; use mem; -use sync::atomic::{mod, Ordering}; +use sync::atomic::{self, Ordering}; use sync::{Once, ONCE_INIT}; use rt::libunwind as uw; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 883a01fa31801..bc01ce926f8bc 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -19,7 +19,7 @@ use libc::{self, uintptr_t}; use os; use slice; use str; -use sync::atomic::{mod, Ordering}; +use sync::atomic::{self, Ordering}; /// Dynamically inquire about whether we're running under V. /// You should usually not use this unless your test definitely diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index a441e55a732b0..a31dcc9884f46 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -14,7 +14,7 @@ use io::{self, IoError, IoResult}; use prelude::v1::*; use sys::{last_error, retry}; -use c_str::CString; +use ffi::CString; use num::Int; use path::BytesContainer; use collections; diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 3f67b284f6887..4cf891ac4985e 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -12,15 +12,16 @@ use prelude::v1::*; use self::SocketStatus::*; use self::InAddr::*; -use c_str::ToCStr; +use ffi::CString; +use ffi; use io::net::addrinfo; use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; use io::{IoResult, IoError}; use libc::{self, c_char, c_int}; -use c_str::CString; use mem; use num::Int; use ptr::{self, null, null_mut}; +use str; use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock, wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval, decode_error_detailed}; @@ -234,9 +235,9 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, assert!(host.is_some() || servname.is_some()); - let c_host = host.map(|x| x.to_c_str()); + let c_host = host.map(|x| CString::from_slice(x.as_bytes())); let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); - let c_serv = servname.map(|x| x.to_c_str()); + let c_serv = servname.map(|x| CString::from_slice(x.as_bytes())); let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); let hint = hint.map(|hint| { @@ -324,7 +325,8 @@ pub fn get_address_name(addr: IpAddr) -> Result { } unsafe { - Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string()) + Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr())) + .unwrap().to_string()) } } diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 5b261ea6b9e58..ca268a8f27ff3 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -83,12 +83,13 @@ /// to symbols. This is a bit of a hokey implementation as-is, but it works for /// all unix platforms we support right now, so it at least gets the job done. -use c_str::CString; -use io::{IoResult, Writer}; +use prelude::v1::*; + +use ffi; +use io::IoResult; use libc; use mem; -use option::Option::{self, Some, None}; -use result::Result::{Ok, Err}; +use str; use sync::{StaticMutex, MUTEX_INIT}; use sys_common::backtrace::*; @@ -105,9 +106,7 @@ use sys_common::backtrace::*; #[cfg(all(target_os = "ios", target_arch = "arm"))] #[inline(never)] pub fn write(w: &mut Writer) -> IoResult<()> { - use iter::{IteratorExt, range}; use result; - use slice::SliceExt; extern { fn backtrace(buf: *mut *mut libc::c_void, @@ -234,19 +233,15 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { output(w, idx,addr, None) } else { output(w, idx, addr, Some(unsafe { - CString::new(info.dli_sname, false) + ffi::c_str_to_bytes(&info.dli_sname) })) } } #[cfg(not(any(target_os = "macos", target_os = "ios")))] fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { - use iter::{Iterator, IteratorExt}; use os; - use path::GenericPath; - use ptr::PtrExt; use ptr; - use slice::SliceExt; //////////////////////////////////////////////////////////////////////// // libbacktrace.h API @@ -368,15 +363,15 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { if ret == 0 || data.is_null() { output(w, idx, addr, None) } else { - output(w, idx, addr, Some(unsafe { CString::new(data, false) })) + output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) })) } } // Finally, after all that work above, we can emit a symbol. fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void, - s: Option) -> IoResult<()> { + s: Option<&[u8]>) -> IoResult<()> { try!(write!(w, " {:2}: {:2$} - ", idx, addr, HEX_WIDTH)); - match s.as_ref().and_then(|c| c.as_str()) { + match s.and_then(|s| str::from_utf8(s).ok()) { Some(string) => try!(demangle(w, string)), None => try!(write!(w, "")), } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index b49ace8e2f8d8..1ad775517bba7 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -12,7 +12,7 @@ use prelude::v1::*; -use c_str::{CString, ToCStr}; +use ffi::{self, CString}; use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use io::{IoResult, FileStat, SeekStyle}; use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; @@ -150,6 +150,10 @@ impl Drop for FileDesc { } } +fn cstr(path: &Path) -> CString { + CString::from_slice(path.as_vec()) +} + pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { let flags = match fm { Open => 0, @@ -165,7 +169,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { libc::S_IRUSR | libc::S_IWUSR), }; - let path = path.to_c_str(); + let path = cstr(path); match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) { -1 => Err(super::last_error()), fd => Ok(FileDesc::new(fd, true)), @@ -173,7 +177,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { } pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) }) } @@ -182,7 +186,6 @@ pub fn readdir(p: &Path) -> IoResult> { use libc::{opendir, readdir_r, closedir}; fn prune(root: &CString, dirs: Vec) -> Vec { - let root = unsafe { CString::new(root.as_ptr(), false) }; let root = Path::new(root); dirs.into_iter().filter(|path| { @@ -199,7 +202,7 @@ pub fn readdir(p: &Path) -> IoResult> { let mut buf = Vec::::with_capacity(size as uint); let ptr = buf.as_mut_ptr() as *mut dirent_t; - let p = p.to_c_str(); + let p = CString::from_slice(p.as_vec()); let dir_ptr = unsafe {opendir(p.as_ptr())}; if dir_ptr as uint != 0 { @@ -207,10 +210,9 @@ pub fn readdir(p: &Path) -> IoResult> { let mut entry_ptr = 0 as *mut dirent_t; while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } { if entry_ptr.is_null() { break } - let cstr = unsafe { - CString::new(rust_list_dir_val(entry_ptr), false) - }; - paths.push(Path::new(cstr)); + paths.push(unsafe { + Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr))) + }); } assert_eq!(unsafe { closedir(dir_ptr) }, 0); Ok(prune(&p, paths)) @@ -220,39 +222,39 @@ pub fn readdir(p: &Path) -> IoResult> { } pub fn unlink(p: &Path) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); mkerr_libc(unsafe { libc::unlink(p.as_ptr()) }) } pub fn rename(old: &Path, new: &Path) -> IoResult<()> { - let old = old.to_c_str(); - let new = new.to_c_str(); + let old = cstr(old); + let new = cstr(new); mkerr_libc(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }) } pub fn chmod(p: &Path, mode: uint) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); mkerr_libc(retry(|| unsafe { libc::chmod(p.as_ptr(), mode as libc::mode_t) })) } pub fn rmdir(p: &Path) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) }) } pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); mkerr_libc(retry(|| unsafe { libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })) } pub fn readlink(p: &Path) -> IoResult { - let c_path = p.to_c_str(); + let c_path = cstr(p); let p = c_path.as_ptr(); let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) }; if len == -1 { @@ -273,14 +275,14 @@ pub fn readlink(p: &Path) -> IoResult { } pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { - let src = src.to_c_str(); - let dst = dst.to_c_str(); + let src = cstr(src); + let dst = cstr(dst); mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }) } pub fn link(src: &Path, dst: &Path) -> IoResult<()> { - let src = src.to_c_str(); - let dst = dst.to_c_str(); + let src = cstr(src); + let dst = cstr(dst); mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }) } @@ -328,7 +330,7 @@ fn mkstat(stat: &libc::stat) -> FileStat { } pub fn stat(p: &Path) -> IoResult { - let p = p.to_c_str(); + let p = cstr(p); let mut stat: libc::stat = unsafe { mem::zeroed() }; match unsafe { libc::stat(p.as_ptr(), &mut stat) } { 0 => Ok(mkstat(&stat)), @@ -337,7 +339,7 @@ pub fn stat(p: &Path) -> IoResult { } pub fn lstat(p: &Path) -> IoResult { - let p = p.to_c_str(); + let p = cstr(p); let mut stat: libc::stat = unsafe { mem::zeroed() }; match unsafe { libc::lstat(p.as_ptr(), &mut stat) } { 0 => Ok(mkstat(&stat)), @@ -346,7 +348,7 @@ pub fn lstat(p: &Path) -> IoResult { } pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> { - let p = p.to_c_str(); + let p = cstr(p); let buf = libc::utimbuf { actime: (atime / 1000) as libc::time_t, modtime: (mtime / 1000) as libc::time_t, diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index ea0d230e8b210..6a408aa60f0bf 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -15,12 +15,14 @@ #![allow(unused_unsafe)] #![allow(unused_mut)] -extern crate libc; - -use num; -use num::{Int, SignedInt}; use prelude::v1::*; + +use ffi; use io::{self, IoResult, IoError}; +use libc; +use num::{Int, SignedInt}; +use num; +use str; use sys_common::mkerr_libc; macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( @@ -78,11 +80,10 @@ extern "system" { } pub fn last_gai_error(s: libc::c_int) -> IoError { - use c_str::CString; let mut err = decode_error(s); err.detail = Some(unsafe { - CString::new(gai_strerror(s), false).as_str().unwrap().to_string() + str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string() }); err } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 181b8fdd0f8a1..175c4e2e353f9 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -12,18 +12,18 @@ use prelude::v1::*; -use c_str::ToCStr; use error::{FromError, Error}; +use ffi::{self, CString}; use fmt; use io::{IoError, IoResult}; use libc::{self, c_int, c_char, c_void}; +use os::TMPBUF_SZ; use os; use path::{BytesContainer}; use ptr; +use str; use sys::fs::FileDesc; -use os::TMPBUF_SZ; - const BUF_BYTES : uint = 2048u; /// Returns the platform-specific value of errno @@ -108,7 +108,8 @@ pub fn error_string(errno: i32) -> String { panic!("strerror_r failure"); } - String::from_raw_buf(p as *const u8) + let p = p as *const _; + str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string() } } @@ -122,21 +123,17 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { } pub fn getcwd() -> IoResult { - use c_str::CString; - let mut buf = [0 as c_char; BUF_BYTES]; unsafe { if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { Err(IoError::last_error()) } else { - Ok(Path::new(CString::new(buf.as_ptr(), false))) + Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr()))) } } } pub unsafe fn get_env_pairs() -> Vec> { - use c_str::CString; - extern { fn rust_env_pairs() -> *const *const c_char; } @@ -147,8 +144,7 @@ pub unsafe fn get_env_pairs() -> Vec> { } let mut result = Vec::new(); while *environ != 0 as *const _ { - let env_pair = - CString::new(*environ, false).as_bytes_no_nul().to_vec(); + let env_pair = ffi::c_str_to_bytes(&*environ).to_vec(); result.push(env_pair); environ = environ.offset(1); } @@ -234,14 +230,13 @@ pub fn load_self() -> Option> { } pub fn chdir(p: &Path) -> IoResult<()> { - p.with_c_str(|buf| { - unsafe { - match libc::chdir(buf) == (0 as c_int) { - true => Ok(()), - false => Err(IoError::last_error()), - } + let p = CString::from_slice(p.as_vec()); + unsafe { + match libc::chdir(p.as_ptr()) == (0 as c_int) { + true => Ok(()), + false => Err(IoError::last_error()), } - }) + } } pub fn page_size() -> uint { diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 9063fbc2ba955..158a1ce220411 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -10,8 +10,8 @@ use prelude::v1::*; +use ffi::CString; use libc; -use c_str::CString; use mem; use sync::{Arc, Mutex}; use sync::atomic::{AtomicBool, Ordering}; @@ -48,7 +48,7 @@ fn addr_to_sockaddr_un(addr: &CString, } s.sun_family = libc::AF_UNIX as libc::sa_family_t; for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) { - *slot = value; + *slot = *value; } // count the null terminator diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index b73919fe2a2cc..5bc6b0c703b1c 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -11,8 +11,8 @@ use prelude::v1::*; use self::Req::*; -use c_str::{CString, ToCStr}; use collections; +use ffi::CString; use hash::Hash; use io::process::{ProcessExit, ExitStatus, ExitSignal}; use io::{self, IoResult, IoError, EndOfFile}; @@ -101,7 +101,7 @@ impl Process { // We may use this in the child, so perform allocations before the // fork - let devnull = "/dev/null".to_c_str(); + let devnull = b"/dev/null\0"; set_cloexec(output.fd()); @@ -204,7 +204,7 @@ impl Process { } else { libc::O_RDWR }; - libc::open(devnull.as_ptr(), flags, 0) + libc::open(devnull.as_ptr() as *const _, flags, 0) } Some(obj) => { let fd = obj.as_inner().fd(); diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index 11f29232a925d..62f3242a20625 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -54,7 +54,7 @@ use libc; use mem; use os; use ptr; -use sync::atomic::{mod, Ordering}; +use sync::atomic::{self, Ordering}; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; use sys::c; use sys::fs::FileDesc; diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 319a458087b9b..4ccecfd1f5f2e 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -21,7 +21,8 @@ /// copy of that function in my mingw install (maybe it was broken?). Instead, /// this takes the route of using StackWalk64 in order to walk the stack. -use c_str::CString; +use dynamic_lib::DynamicLibrary; +use ffi; use intrinsics; use io::{IoResult, Writer}; use libc; @@ -30,10 +31,9 @@ use ops::Drop; use option::Option::{Some, None}; use path::Path; use result::Result::{Ok, Err}; -use sync::{StaticMutex, MUTEX_INIT}; use slice::SliceExt; -use str::StrExt; -use dynamic_lib::DynamicLibrary; +use str::{self, StrExt}; +use sync::{StaticMutex, MUTEX_INIT}; use sys_common::backtrace::*; @@ -357,11 +357,11 @@ pub fn write(w: &mut Writer) -> IoResult<()> { if ret == libc::TRUE { try!(write!(w, " - ")); - let cstr = unsafe { CString::new(info.Name.as_ptr(), false) }; - let bytes = cstr.as_bytes(); - match cstr.as_str() { - Some(s) => try!(demangle(w, s)), - None => try!(w.write(bytes[..bytes.len()-1])), + let ptr = info.Name.as_ptr() as *const libc::c_char; + let bytes = unsafe { ffi::c_str_to_bytes(&ptr) }; + match str::from_utf8(bytes) { + Ok(s) => try!(demangle(w, s)), + Err(..) => try!(w.write(bytes[..bytes.len()-1])), } } try!(w.write(&['\n' as u8])); diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1ee57434fb91a..945c2e8e7d156 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -133,7 +133,7 @@ pub mod compat { use intrinsics::{atomic_store_relaxed, transmute}; use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; use prelude::v1::*; - use c_str::ToCStr; + use ffi::CString; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; @@ -147,14 +147,13 @@ pub mod compat { unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) { let mut module: Vec = module.utf16_units().collect(); module.push(0); - symbol.with_c_str(|symbol| { - let handle = GetModuleHandleW(module.as_ptr()); - let func: uint = transmute(GetProcAddress(handle, symbol)); - atomic_store_relaxed(ptr, if func == 0 { - fallback - } else { - func - }) + let symbol = CString::from_slice(symbol.as_bytes()); + let handle = GetModuleHandleW(module.as_ptr()); + let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr())); + atomic_store_relaxed(ptr, if func == 0 { + fallback + } else { + func }) } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 9a94230065680..f8c75335b35dc 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -13,7 +13,6 @@ use alloc::arc::Arc; use libc::{self, c_int}; -use c_str::CString; use mem; use sys::os::fill_utf16_buf_and_decode; use path; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 9057515cad294..9996909f2f5bb 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -87,16 +87,21 @@ use prelude::v1::*; use libc; -use c_str::CString; +use ffi::CString; +use io::{self, IoError, IoResult}; use mem; use ptr; -use sync::{Arc, Mutex}; +use str; use sync::atomic::{AtomicBool, Ordering}; -use io::{self, IoError, IoResult}; +use sync::{Arc, Mutex}; use sys_common::{self, eof}; -use super::{c, os, timer, to_utf16, decode_error_detailed}; +use super::{c, os, timer, decode_error_detailed}; + +fn to_utf16(c: &CString) -> IoResult> { + super::to_utf16(str::from_utf8(c.as_bytes()).ok()) +} struct Event(libc::HANDLE); @@ -270,7 +275,7 @@ impl UnixStream { } pub fn connect(addr: &CString, timeout: Option) -> IoResult { - let addr = try!(to_utf16(addr.as_str())); + let addr = try!(to_utf16(addr)); let start = timer::now(); loop { match UnixStream::try_connect(addr.as_ptr()) { @@ -571,7 +576,7 @@ impl UnixListener { // Although we technically don't need the pipe until much later, we // create the initial handle up front to test the validity of the name // and such. - let addr_v = try!(to_utf16(addr.as_str())); + let addr_v = try!(to_utf16(addr)); let ret = unsafe { pipe(addr_v.as_ptr(), true) }; if ret == libc::INVALID_HANDLE_VALUE { Err(super::last_error()) @@ -661,7 +666,7 @@ impl UnixAcceptor { // proceed in accepting new clients in the future if self.inner.closed.load(Ordering::SeqCst) { return Err(eof()) } - let name = try!(to_utf16(self.listener.name.as_str())); + let name = try!(to_utf16(&self.listener.name)); // Once we've got a "server handle", we need to wait for a client to // connect. The ConnectNamedPipe function will block this thread until @@ -753,7 +758,7 @@ impl UnixAcceptor { impl Clone for UnixAcceptor { fn clone(&self) -> UnixAcceptor { - let name = to_utf16(self.listener.name.as_str()).ok().unwrap(); + let name = to_utf16(&self.listener.name).ok().unwrap(); UnixAcceptor { inner: self.inner.clone(), event: Event::new(true, false).ok().unwrap(), diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 81e8f974a1223..9b3f2ca03736e 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,27 +10,26 @@ use prelude::v1::*; +use collections; +use ffi::CString; +use hash::Hash; +use io::fs::PathExtensions; +use io::process::{ProcessExit, ExitStatus, ExitSignal}; +use io::{IoResult, IoError}; +use io; use libc::{pid_t, c_void, c_int}; use libc; -use c_str::{CString, ToCStr}; -use io; use mem; use os; -use ptr; -use io::process::{ProcessExit, ExitStatus, ExitSignal}; -use collections; use path::BytesContainer; -use hash::Hash; -use io::{IoResult, IoError}; - +use ptr; +use str; +use sys::fs::FileDesc; use sys::fs; use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer}; -use sys::fs::FileDesc; use sys_common::helper_thread::Helper; use sys_common::{AsInner, mkerr_libc, timeout}; -use io::fs::PathExtensions; - pub use sys_common::ProcessConfig; /// A value representing a child process. @@ -142,10 +141,10 @@ impl Process { // Split the value and test each path to see if the // program exists. for path in os::split_paths(v.container_as_bytes()).into_iter() { - let path = path.join(cfg.program().as_bytes_no_nul()) + let path = path.join(cfg.program().as_bytes()) .with_extension(os::consts::EXE_EXTENSION); if path.exists() { - return Some(path.to_c_str()) + return Some(CString::from_slice(path.as_vec())) } } break @@ -363,11 +362,11 @@ fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMA fn make_command_line(prog: &CString, args: &[CString]) -> String { let mut cmd = String::new(); - append_arg(&mut cmd, prog.as_str() + append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok() .expect("expected program name to be utf-8 encoded")); for arg in args.iter() { cmd.push(' '); - append_arg(&mut cmd, arg.as_str() + append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok() .expect("expected argument to be utf-8 encoded")); } return cmd; @@ -449,7 +448,7 @@ fn with_dirp(d: Option<&CString>, cb: F) -> T where { match d { Some(dir) => { - let dir_str = dir.as_str() + let dir_str = str::from_utf8(dir.as_bytes()).ok() .expect("expected workingdirectory to be utf-8 encoded"); let mut dir_str: Vec = dir_str.utf16_units().collect(); dir_str.push(0); diff --git a/src/test/auxiliary/linkage-visibility.rs b/src/test/auxiliary/linkage-visibility.rs index 0b4bea49fa249..6cd94ee5602aa 100644 --- a/src/test/auxiliary/linkage-visibility.rs +++ b/src/test/auxiliary/linkage-visibility.rs @@ -27,7 +27,7 @@ fn bar() { } fn baz() { } pub fn test() { - let none: Option = None; // appease the typechecker + let none: Option<&Path> = None; // appease the typechecker let lib = DynamicLibrary::open(none).unwrap(); unsafe { assert!(lib.symbol::("foo").is_ok()); diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index c95cf0bfdee45..22c322b86c979 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -12,7 +12,7 @@ extern crate libc; -use std::c_str::ToCStr; +use std::ffi::CString; mod mlibc { use libc::{c_char, c_long, c_longlong}; @@ -24,11 +24,13 @@ mod mlibc { } fn atol(s: String) -> int { - s.as_slice().with_c_str(|x| unsafe { mlibc::atol(x) as int }) + let c = CString::from_slice(s.as_bytes()); + unsafe { mlibc::atol(c.as_ptr()) as int } } fn atoll(s: String) -> i64 { - s.as_slice().with_c_str(|x| unsafe { mlibc::atoll(x) as i64 }) + let c = CString::from_slice(s.as_bytes()); + unsafe { mlibc::atoll(c.as_ptr()) as i64 } } pub fn main() { diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index 5e028d3774fc5..1a84236793b4f 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::{str, string}; -use std::c_str::ToCStr; const A: [u8; 2] = ['h' as u8, 'i' as u8]; const B: &'static [u8; 2] = &A; @@ -23,8 +22,5 @@ pub fn main() { assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string()); assert!(*C == A[0]); assert!(*(&B[0] as *const u8) == A[0]); - - let bar = str::from_utf8_unchecked(&A).to_c_str(); - assert_eq!(bar.as_str(), "hi".to_c_str().as_str()); } } diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 8a75fdd685dd1..dff1a1eaa0473 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -11,7 +11,7 @@ // ignore-fast doesn't like extern crate extern crate libc; -use std::c_str::ToCStr; +use std::ffi::CString; mod mlibc { use libc::{c_char, size_t}; @@ -24,11 +24,10 @@ mod mlibc { fn strlen(str: String) -> uint { // C string is terminated with a zero - str.as_slice().with_c_str(|buf| { - unsafe { - mlibc::my_strlen(buf) as uint - } - }) + let s = CString::from_slice(str.as_bytes()); + unsafe { + mlibc::my_strlen(s.as_ptr()) as uint + } } pub fn main() { diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs index c7aa405b513e4..d610bf09edb95 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass/rename-directory.rs @@ -13,8 +13,8 @@ extern crate libc; +use std::ffi::CString; use std::io::TempDir; -use std::c_str::ToCStr; use std::io::fs::PathExtensions; use std::io::fs; use std::io; @@ -31,20 +31,17 @@ fn rename_directory() { let test_file = &old_path.join("temp.txt"); /* Write the temp input file */ - let ostream = test_file.with_c_str(|fromp| { - "w+b".with_c_str(|modebuf| { - libc::fopen(fromp, modebuf) - }) - }); + let fromp = CString::from_slice(test_file.as_vec()); + let modebuf = CString::from_slice(b"w+b"); + let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr()); assert!((ostream as uint != 0u)); let s = "hello".to_string(); - "hello".with_c_str(|buf| { - let write_len = libc::fwrite(buf as *const libc::c_void, - 1u as libc::size_t, - (s.len() + 1u) as libc::size_t, - ostream); - assert_eq!(write_len, (s.len() + 1) as libc::size_t) - }); + let buf = CString::from_slice(b"hello"); + let write_len = libc::fwrite(buf.as_ptr() as *mut _, + 1u as libc::size_t, + (s.len() + 1u) as libc::size_t, + ostream); + assert_eq!(write_len, (s.len() + 1) as libc::size_t); assert_eq!(libc::fclose(ostream), (0u as libc::c_int)); let new_path = tmpdir.join_many(&["quux", "blat"]); diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index ec320c1f8a309..de9d7880411a1 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -10,7 +10,7 @@ extern crate libc; -use std::c_str::{CString, ToCStr}; +use std::ffi::{self, CString}; use libc::{c_char, c_int}; // ignore-fast doesn't like extern crate @@ -22,40 +22,35 @@ extern { unsafe fn check(expected: &str, f: |*mut c_char| -> T) { let mut x = [0 as c_char; 50]; f(&mut x[0] as *mut c_char); - let res = CString::new(&x[0], false); - assert_eq!(expected, res.as_str().unwrap()); + assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr())); } pub fn main() { unsafe { // Call with just the named parameter - "Hello World\n".with_c_str(|c| { - check("Hello World\n", |s| sprintf(s, c)); - }); + let c = CString::from_slice(b"Hello World\n"); + check("Hello World\n", |s| sprintf(s, c.as_ptr())); // Call with variable number of arguments - "%d %f %c %s\n".with_c_str(|c| { - check("42 42.500000 a %d %f %c %s\n\n", |s| { - sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c); - }) + let c = CString::from_slice(b"%d %f %c %s\n"); + check("42 42.500000 a %d %f %c %s\n\n", |s| { + sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr()); }); // Make a function pointer - let x: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int = sprintf; + let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf; // A function that takes a function pointer - unsafe fn call(p: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int) { - // Call with just the named parameter via fn pointer - "Hello World\n".with_c_str(|c| { - check("Hello World\n", |s| p(s, c)); - }); + unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) { + // Call with just the named parameter + let c = CString::from_slice(b"Hello World\n"); + check("Hello World\n", |s| sprintf(s, c.as_ptr())); // Call with variable number of arguments - "%d %f %c %s\n".with_c_str(|c| { - check("42 42.500000 a %d %f %c %s\n\n", |s| { - p(s, c, 42i, 42.5f64, 'a' as c_int, c); - }) + let c = CString::from_slice(b"%d %f %c %s\n"); + check("42 42.500000 a %d %f %c %s\n\n", |s| { + sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr()); }); } From 540a7777b8ba53950d340ee9537ede1b3fb0b24d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 3 Jan 2015 06:01:56 -0500 Subject: [PATCH 051/106] Don't ICE just because an impl is missing an associated type. Trust in the other compiler passes. Fixes #17359. --- src/librustc/middle/traits/project.rs | 11 +++++---- .../associated-types-issue-17359.rs | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/associated-types-issue-17359.rs diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index d5b41d2380628..65f7ad296db51 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -643,11 +643,12 @@ fn confirm_candidate<'cx,'tcx>( match impl_ty { Some(ty) => (ty, impl_vtable.nested.to_vec()), None => { - selcx.tcx().sess.span_bug( - obligation.cause.span, - format!("impl `{}` did not contain projection for `{}`", - impl_vtable.repr(selcx.tcx()), - obligation.repr(selcx.tcx())).as_slice()); + // This means that the impl is missing a + // definition for the associated type. This error + // ought to be reported by the type checker method + // `check_impl_items_against_trait`, so here we + // just return ty_err. + (selcx.tcx().types.err, vec!()) } } } diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs new file mode 100644 index 0000000000000..764b79c4cc649 --- /dev/null +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -0,0 +1,23 @@ +// 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. + +// Test that we do not ICE when an impl is missing an associated type (and that we report +// a useful error, of course). + +#![feature(associated_types)] + +trait Trait { + type Type; +} + +impl Trait for int {} //~ ERROR missing: `Type` + +fn main() {} + From 5caf847b3f16ca08ad1203614455b20aa07f4f0c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 3 Jan 2015 06:07:07 -0500 Subject: [PATCH 052/106] Add a test for issue #18865. Fixes #18865. --- ...ted-types-invalid-trait-ref-issue-18865.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs diff --git a/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs new file mode 100644 index 0000000000000..8afd86195ff53 --- /dev/null +++ b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs @@ -0,0 +1,26 @@ +// 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. + +// Test that we report an error if the trait ref in an qualified type +// uses invalid type arguments. + +#![feature(associated_types)] + +trait Foo { + type Bar; + fn get_bar(&self) -> Self::Bar; +} + +fn f>(t: &T) { + let u: >::Bar = t.get_bar(); + //~^ ERROR the trait `Foo` is not implemented for the type `T` +} + +fn main() { } From 61bb6ac9debca80e3390d781fe057eb7e0515dbf Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Mon, 5 Jan 2015 11:37:44 -0500 Subject: [PATCH 053/106] remove unnecessary `Default` bound from `Hash{Map,Set}`'s `Extend` impl --- src/libstd/collections/hash/map.rs | 2 +- src/libstd/collections/hash/set.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a6532707f3e36..b8f13e3095780 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1508,7 +1508,7 @@ impl, V, S, H: Hasher + Default> FromIterator<(K, V)> for Has } #[stable] -impl, V, S, H: Hasher + Default> Extend<(K, V)> for HashMap { +impl, V, S, H: Hasher> Extend<(K, V)> for HashMap { fn extend>(&mut self, mut iter: T) { for (k, v) in iter { self.insert(k, v); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b1824db93aad1..1b029458a6f73 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -605,7 +605,7 @@ impl, S, H: Hasher + Default> FromIterator for HashSet, S, H: Hasher + Default> Extend for HashSet { +impl, S, H: Hasher> Extend for HashSet { fn extend>(&mut self, mut iter: I) { for k in iter { self.insert(k); From a56e7aee81733485d6edd415ab383347232e3c36 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Thu, 11 Dec 2014 11:37:20 -0500 Subject: [PATCH 054/106] Add lifetime elision information to the ownership guide. Fixes #19662. --- src/doc/guide-ownership.md | 79 +++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/src/doc/guide-ownership.md b/src/doc/guide-ownership.md index bf750ecaa8f67..414a874082eef 100644 --- a/src/doc/guide-ownership.md +++ b/src/doc/guide-ownership.md @@ -230,8 +230,9 @@ fn add_one(num: &int) -> int { ``` Rust has a feature called 'lifetime elision,' which allows you to not write -lifetime annotations in certain circumstances. This is one of them. Without -eliding the lifetimes, `add_one` looks like this: +lifetime annotations in certain circumstances. This is one of them. We will +cover the others later. Without eliding the lifetimes, `add_one` looks like +this: ```rust fn add_one<'a>(num: &'a int) -> int { @@ -449,6 +450,80 @@ This is the simplest kind of multiple ownership possible. For example, there's also `Arc`, which uses more expensive atomic instructions to be the thread-safe counterpart of `Rc`. +## Lifetime Elision + +Earlier, we mentioned 'lifetime elision,' a feature of Rust which allows you to +not write lifetime annotations in certain circumstances. All references have a +lifetime, and so if you elide a lifetime (like `&T` instead of `&'a T`), Rust +will do three things to determine what those lifetimes should be. + +When talking about lifetime elision, we use the term 'input lifetime' and +'output lifetime'. An 'input liftime' is a lifetime associated with a parameter +of a function, and an 'output lifetime' is a lifetime associated with the return +value of a function. For example, this function has an input lifetime: + +```{rust,ignore} +fn foo<'a>(bar: &'a str) +``` + +This one has an output lifetime: + +```{rust,ignore} +fn foo<'a>() -> &'a str +``` + +This one has a lifetime in both positions: + +```{rust,ignore} +fn foo<'a>(bar: &'a str) -> &'a str +``` + +Here are the three rules: + +* Each elided lifetime in a function's arguments becomes a distinct lifetime + parameter. + +* If there is exactly one input lifetime, elided or not, that lifetime is + assigned to all elided lifetimes in the return values of that function.. + +* If there are multiple input lifetimes, but one of them is `&self` or `&mut + self`, the lifetime of `self` is assigned to all elided output lifetimes. + +Otherwise, it is an error to elide an output lifetime. + +### Examples + +Here are some examples of functions with elided lifetimes, and the version of +what the elided lifetimes are expand to: + +```{rust,ignore} +fn print(s: &str); // elided +fn print<'a>(s: &'a str); // expanded + +fn debug(lvl: uint, s: &str); // elided +fn debug<'a>(lvl: uint, s: &'a str); // expanded + +// In the preceeding example, `lvl` doesn't need a lifetime because it's not a +// reference (`&`). Only things relating to references (such as a `struct` +// which contains a reference) need lifetimes. + +fn substr(s: &str, until: uint) -> &str; // elided +fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded + +fn get_str() -> &str; // ILLEGAL, no inputs + +fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs + +fn get_mut(&mut self) -> &mut T; // elided +fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded + +fn args(&mut self, args: &[T]) -> &mut Command // elided +fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded + +fn new(buf: &mut [u8]) -> BufWriter; // elided +fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded +``` + # Related Resources Coming Soon. From 5488ddb307159e06bb471cefe9512a0efd28ad60 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Sat, 3 Jan 2015 12:42:34 +0100 Subject: [PATCH 055/106] Segmented stack support for DragonFly --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index ec1fdb3b9d3b1..b820135911e17 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit ec1fdb3b9d3b1fb9e1dae97a65dd3a13db9bfb23 +Subproject commit b820135911e17c7a46b901db56baa48e5155bf46 From 66da36f6eed73bbaa4578a3bd312ee124d55d96c Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Mon, 5 Jan 2015 10:54:40 +0100 Subject: [PATCH 056/106] Ensure that LLVM is rebuilt with recent changes --- src/rustllvm/llvm-auto-clean-trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index c1ad6754ca1c3..2ac855681f28b 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2015-01-03 +2015-01-05 From faf07b1365cdf6d6c479ad8fc0e5337c9c2bf315 Mon Sep 17 00:00:00 2001 From: Chase Southwood Date: Mon, 5 Jan 2015 12:13:43 -0600 Subject: [PATCH 057/106] Update reexports in vim syntax file --- src/etc/vim/syntax/rust.vim | 60 ++++++++++++------------------------- 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 5588152a244c4..aa20fe3c395d9 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -3,7 +3,7 @@ " Maintainer: Patrick Walton " Maintainer: Ben Blum " Maintainer: Chris Morgan -" Last Change: July 18, 2014 +" Last Change: January 5, 2015 if version < 600 syntax clear @@ -68,59 +68,37 @@ syn keyword rustType f64 i8 i16 i32 i64 str Self " Reexported core operators {{{3 syn keyword rustTrait Copy Send Sized Sync -syn keyword rustTrait Add Sub Mul Div Rem Neg Not -syn keyword rustTrait BitAnd BitOr BitXor -syn keyword rustTrait Drop Deref DerefMut -syn keyword rustTrait Shl Shr -syn keyword rustTrait Index IndexMut -syn keyword rustTrait Slice SliceMut -syn keyword rustTrait Fn FnMut FnOnce +syn keyword rustTrait Drop Fn FnMut FnOnce " Reexported functions {{{3 -"syn keyword rustFunction range repeat -"syn keyword rustFunction drop -"syn keyword rustFunction from_str +syn keyword rustFunction drop " Reexported types and traits {{{3 -syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr -syn keyword rustTrait IntoBytes -syn keyword rustTrait ToCStr -syn keyword rustTrait Char UnicodeChar +syn keyword rustTrait Box +syn keyword rustTrait CharExt syn keyword rustTrait Clone syn keyword rustTrait PartialEq PartialOrd Eq Ord -syn keyword rustEnum Ordering Equiv -syn keyword rustEnumVariant Less Equal Greater -syn keyword rustTrait FromIterator Extend ExactSizeIterator -syn keyword rustTrait Iterator DoubleEndedIterator -syn keyword rustTrait RandomAccessIterator CloneableIterator -syn keyword rustTrait OrdIterator MutableDoubleEndedIterator -syn keyword rustTrait ToPrimitive FromPrimitive -syn keyword rustTrait Box +syn keyword rustTrait DoubleEndedIterator +syn keyword rustTrait ExactSizeIterator +syn keyword rustTrait Iterator IteratorExt Extend syn keyword rustEnum Option syn keyword rustEnumVariant Some None -syn keyword rustTrait GenericPath Path PosixPath WindowsPath -syn keyword rustTrait RawPtr RawMutPtr +syn keyword rustTrait PtrExt MutPtrExt syn keyword rustEnum Result syn keyword rustEnumVariant Ok Err -syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude -syn keyword rustTrait Str StrVector StrPrelude -syn keyword rustTrait IntoMaybeOwned StrAllocating UnicodeStrPrelude -syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4 -syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8 -syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12 -syn keyword rustTrait SlicePrelude AsSlice CloneSlicePrelude -syn keyword rustTrait VectorVector PartialEqSlicePrelude OrdSlicePrelude -syn keyword rustTrait CloneSliceAllocPrelude OrdSliceAllocPrelude SliceAllocPrelude -syn keyword rustTrait IntoString String ToString +syn keyword rustTrait AsSlice +syn keyword rustTrait SliceExt SliceConcatExt +syn keyword rustTrait Str StrExt +syn keyword rustTrait String ToString syn keyword rustTrait Vec - -" Reexported runtime types {{{3 -"syn keyword rustFunction sync_channel channel -syn keyword rustTrait SyncSender Sender Receiver -"syn keyword rustFunction spawn +" FIXME: remove when path reform lands +syn keyword rustTrait Path GenericPath +" FIXME: remove when I/O reform lands +syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude +" FIXME: remove when range syntax lands +syn keyword rustFunction range " Other syntax {{{2 - syn keyword rustSelf self syn keyword rustBoolean true false From 40bd1c245f527fd8bb896be92e1e78fdd4155b5f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 5 Jan 2015 10:25:49 -0800 Subject: [PATCH 058/106] Put version number in beta channel artifacts --- mk/main.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index 0d9419cccfa83..278c2e01060ad 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -29,14 +29,14 @@ endif ifeq ($(CFG_RELEASE_CHANNEL),beta) # The beta channel is temporarily called 'alpha' CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE) -# When building beta/nightly distributables just reuse the same "beta" -# name so when we upload we'll always override the previous -# nighly. This doesn't actually impact the version reported by rustc - -# it's just for file naming. -CFG_PACKAGE_VERS=alpha +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE) endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly +# When building nightlydistributables just reuse the same "beta" name +# so when we upload we'll always override the previous nighly. This +# doesn't actually impact the version reported by rustc - it's just +# for file naming. CFG_PACKAGE_VERS=nightly endif ifeq ($(CFG_RELEASE_CHANNEL),dev) From edbb7c3ed10c1f2482ff4b2860f3b14e6f73cb7b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 5 Jan 2015 10:26:10 -0800 Subject: [PATCH 059/106] 0.13.0 -> 1.0.0 --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index 278c2e01060ad..113737c1525c5 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,7 +13,7 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=0.13.0 +CFG_RELEASE_NUM=1.0.0 # An optional number to put after the label, e.g. '2' -> '-beta2' CFG_BETA_CYCLE= From c548b879ef361736c53a615edd93e51a8c845a55 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 5 Jan 2015 10:28:18 -0800 Subject: [PATCH 060/106] Typo --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index 113737c1525c5..a97e68af59b38 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -33,7 +33,7 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE) endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly -# When building nightlydistributables just reuse the same "beta" name +# When building nightly distributables just reuse the same "nightly" name # so when we upload we'll always override the previous nighly. This # doesn't actually impact the version reported by rustc - it's just # for file naming. From d1cf1b1e6bf0b33fe3bb9fa01d9d94f797c9f9fc Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 31 Dec 2014 17:30:45 -0800 Subject: [PATCH 061/106] Don't test codegen-units errors on stage1 (c.f. #20184) --- src/test/compile-fail/asm-src-loc-codegen-units.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/compile-fail/asm-src-loc-codegen-units.rs b/src/test/compile-fail/asm-src-loc-codegen-units.rs index 1b8fb32a808dc..5ebcdb20b1952 100644 --- a/src/test/compile-fail/asm-src-loc-codegen-units.rs +++ b/src/test/compile-fail/asm-src-loc-codegen-units.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // +// ignore-stage1 (#20184) // compile-flags: -C codegen-units=2 // error-pattern: build without -C codegen-units for more exact errors From 5e5924b79915326d81db2aebfe73d2a20b8506f1 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 15 Sep 2014 16:09:09 -0700 Subject: [PATCH 062/106] Replace LetSyntaxTT with MacroRulesTT The implementation of LetSyntaxTT was specialized to macro_rules! in various ways. This gets rid of the false generality and simplifies the code. --- src/librustc/plugin/registry.rs | 21 +++++--- src/librustc_driver/driver.rs | 2 +- src/libsyntax/ext/base.rs | 12 ++--- src/libsyntax/ext/expand.rs | 54 ++++++++----------- src/libsyntax/ext/tt/macro_rules.rs | 21 ++------ .../auxiliary/macro_crate_MacroRulesTT.rs | 25 +++++++++ .../plugin-MacroRulesTT.rs | 21 ++++++++ 7 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 src/test/auxiliary/macro_crate_MacroRulesTT.rs create mode 100644 src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index 99e870a901e08..c5550902f1989 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -11,9 +11,10 @@ //! Used by plugin crates to tell `rustc` about the plugins they provide. use lint::{LintPassObject, LintId, Lint}; +use session::Session; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; -use syntax::ext::base::{IdentTT, LetSyntaxTT, Decorator, Modifier}; +use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT}; use syntax::ext::base::{MacroExpanderFn}; use syntax::codemap::Span; use syntax::parse::token; @@ -29,7 +30,11 @@ use std::collections::HashMap; /// This struct has public fields and other methods for use by `rustc` /// itself. They are not documented here, and plugin authors should /// not use them. -pub struct Registry { +pub struct Registry<'a> { + /// Compiler session. Useful if you want to emit diagnostic messages + /// from the plugin registrar. + pub sess: &'a Session, + #[doc(hidden)] pub krate_span: Span, @@ -43,10 +48,11 @@ pub struct Registry { pub lint_groups: HashMap<&'static str, Vec>, } -impl Registry { +impl<'a> Registry<'a> { #[doc(hidden)] - pub fn new(krate: &ast::Crate) -> Registry { + pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> { Registry { + sess: sess, krate_span: krate.span, syntax_exts: vec!(), lint_passes: vec!(), @@ -63,8 +69,11 @@ impl Registry { IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)), Decorator(ext) => Decorator(ext), Modifier(ext) => Modifier(ext), - // there's probably a nicer way to signal this: - LetSyntaxTT(_, _) => panic!("can't register a new LetSyntax!"), + + MacroRulesTT => { + self.sess.err("plugin tried to register a new MacroRulesTT"); + return; + } })); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1455aa3c99bb3..0d9736a82736f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -216,7 +216,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, = time(time_passes, "plugin loading", (), |_| plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap())); - let mut registry = Registry::new(&krate); + let mut registry = Registry::new(sess, &krate); time(time_passes, "plugin registration", (), |_| { if sess.features.borrow().rustc_diagnostic_macros { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 91cc8a2462205..4b38e6c0cb231 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -328,13 +328,8 @@ pub enum SyntaxExtension { /// IdentTT(Box, Option), - /// An ident macro that has two properties: - /// - it adds a macro definition to the environment, and - /// - the definition it adds doesn't introduce any new - /// identifiers. - /// - /// `macro_rules!` is a LetSyntaxTT - LetSyntaxTT(Box, Option), + /// Represents `macro_rules!` itself. + MacroRulesTT, } pub type NamedSyntaxExtension = (Name, SyntaxExtension); @@ -364,8 +359,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { } let mut syntax_expanders = SyntaxEnv::new(); - syntax_expanders.insert(intern("macro_rules"), - LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None)); + syntax_expanders.insert(intern("macro_rules"), MacroRulesTT); syntax_expanders.insert(intern("fmt"), builtin_normal_expander( ext::fmt::expand_syntax_ext)); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b3f30dd4581c9..a1a13f2306477 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use self::Either::*; use ast::{Block, Crate, DeclLocal, ExprMac, PatMac}; use ast::{Local, Ident, MacInvocTT}; @@ -18,6 +17,7 @@ use ast; use ast_util::path_to_ident; use ext::mtwt; use ext::build::AstBuilder; +use ext::tt::macro_rules; use attr; use attr::AttrMetaMethods; use codemap; @@ -33,11 +33,6 @@ use util::small_vector::SmallVector; use visit; use visit::Visitor; -enum Either { - Left(L), - Right(R) -} - pub fn expand_type(t: P, fld: &mut MacroExpander, impl_ty: Option>) @@ -548,8 +543,8 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) let extnamestr = token::get_ident(extname); let fm = fresh_mark(); - let def_or_items = { - let mut expanded = match fld.cx.syntax_env.find(&extname.name) { + let items = { + let expanded = match fld.cx.syntax_env.find(&extname.name) { None => { fld.cx.span_err(path_span, format!("macro undefined: '{}!'", @@ -600,11 +595,10 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) let marked_tts = mark_tts(tts[], fm); expander.expand(fld.cx, it.span, it.ident, marked_tts) } - LetSyntaxTT(ref expander, span) => { + MacroRulesTT => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, - format!("macro {}! expects an ident argument", - extnamestr.get())[]); + format!("macro_rules! expects an ident argument")[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -612,11 +606,21 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) callee: NameAndSpan { name: extnamestr.get().to_string(), format: MacroBang, - span: span + span: None, } }); - // DON'T mark before expansion: - expander.expand(fld.cx, it.span, it.ident, tts) + // DON'T mark before expansion. + let MacroDef { name, ext } + = macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts); + + fld.cx.syntax_env.insert(intern(name.as_slice()), ext); + if attr::contains_name(it.attrs.as_slice(), "macro_export") { + fld.cx.exported_macros.push(it); + } + + // macro_rules! has a side effect but expands to nothing. + fld.cx.bt_pop(); + return SmallVector::zero(); } _ => { fld.cx.span_err(it.span, @@ -627,31 +631,17 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) } }; - match expanded.make_def() { - Some(def) => Left(def), - None => Right(expanded.make_items()) - } + expanded.make_items() }; - let items = match def_or_items { - Left(MacroDef { name, ext }) => { - // hidden invariant: this should only be possible as the - // result of expanding a LetSyntaxTT, and thus doesn't - // need to be marked. Not that it could be marked anyway. - // create issue to recommend refactoring here? - fld.cx.syntax_env.insert(intern(name[]), ext); - if attr::contains_name(it.attrs[], "macro_export") { - fld.cx.exported_macros.push(it); - } - SmallVector::zero() - } - Right(Some(items)) => { + let items = match items { + Some(items) => { items.into_iter() .map(|i| mark_item(i, fm)) .flat_map(|i| fld.fold_item(i).into_iter()) .collect() } - Right(None) => { + None => { fld.cx.span_err(path_span, format!("non-item macro in item position: {}", extnamestr.get())[]); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 08014dc13383f..15b75442ca2cb 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -129,15 +129,6 @@ impl TTMacroExpander for MacroRulesMacroExpander { } } -struct MacroRulesDefiner { - def: Option -} -impl MacResult for MacroRulesDefiner { - fn make_def(&mut self) -> Option { - Some(self.def.take().expect("empty MacroRulesDefiner")) - } -} - /// Given `lhses` and `rhses`, this is the new macro we create fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, @@ -219,7 +210,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, sp: Span, name: Ident, arg: Vec ) - -> Box { + -> MacroDef { let lhs_nm = gensym_ident("lhs"); let rhs_nm = gensym_ident("rhs"); @@ -279,10 +270,8 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, rhses: rhses, }; - box MacroRulesDefiner { - def: Some(MacroDef { - name: token::get_ident(name).to_string(), - ext: NormalTT(exp, Some(sp)) - }) - } as Box + MacroDef { + name: token::get_ident(name).to_string(), + ext: NormalTT(exp, Some(sp)) + } } diff --git a/src/test/auxiliary/macro_crate_MacroRulesTT.rs b/src/test/auxiliary/macro_crate_MacroRulesTT.rs new file mode 100644 index 0000000000000..d50c27a4e75bb --- /dev/null +++ b/src/test/auxiliary/macro_crate_MacroRulesTT.rs @@ -0,0 +1,25 @@ +// 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. + +// force-host + +#![feature(plugin_registrar)] + +extern crate syntax; +extern crate rustc; + +use syntax::parse::token; +use syntax::ext::base::MacroRulesTT; +use rustc::plugin::Registry; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_syntax_extension(token::intern("bogus"), MacroRulesTT); +} diff --git a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs new file mode 100644 index 0000000000000..302a64c5ed34b --- /dev/null +++ b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:macro_crate_MacroRulesTT.rs +// ignore-stage1 +// ignore-android +// error-pattern: plugin tried to register a new MacroRulesTT + +#![feature(phase)] + +#[phase(plugin)] +extern crate macro_crate_MacroRulesTT; + +fn main() { } From ad7c64777380a780b42028855ad0d09932a11623 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 15 Sep 2014 18:27:28 -0700 Subject: [PATCH 063/106] Add a special macro nonterminal $crate --- src/librustdoc/html/highlight.rs | 3 ++ src/libsyntax/ast.rs | 7 +++++ src/libsyntax/ext/expand.rs | 12 ++++---- src/libsyntax/ext/tt/macro_rules.rs | 8 +++++ src/libsyntax/ext/tt/transcribe.rs | 29 ++++++++++++++++++- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 7 +++-- src/libsyntax/parse/token.rs | 24 +++++++++++++++ src/libsyntax/print/pprust.rs | 2 ++ src/test/auxiliary/macro_crate_nonterminal.rs | 24 +++++++++++++++ .../macro-crate-nonterminal-renamed.rs | 22 ++++++++++++++ src/test/run-pass/macro-crate-nonterminal.rs | 22 ++++++++++++++ 12 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 src/test/auxiliary/macro_crate_nonterminal.rs create mode 100644 src/test/run-pass/macro-crate-nonterminal-renamed.rs create mode 100644 src/test/run-pass/macro-crate-nonterminal.rs diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index cfaae1a9f80fd..30b9d6c63c5bb 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -166,6 +166,9 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, } } + // Special macro vars are like keywords + token::SpecialVarNt(_) => "kw-2", + token::Lifetime(..) => "lifetime", token::DocComment(..) => "doccomment", token::Underscore | token::Eof | token::Interpolated(..) | diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c9d27e304ff15..55aa73b4faaee 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -884,6 +884,7 @@ impl TokenTree { match *self { TtToken(_, token::DocComment(_)) => 2, TtToken(_, token::SubstNt(..)) => 2, + TtToken(_, token::SpecialVarNt(..)) => 2, TtToken(_, token::MatchNt(..)) => 3, TtDelimited(_, ref delimed) => { delimed.tts.len() + 2 @@ -925,6 +926,12 @@ impl TokenTree { TtToken(sp, token::Ident(name, name_st))]; v[index] } + (&TtToken(sp, token::SpecialVarNt(var)), _) => { + let v = [TtToken(sp, token::Dollar), + TtToken(sp, token::Ident(token::str_to_ident(var.as_str()), + token::Plain))]; + v[index] + } (&TtToken(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => { let v = [TtToken(sp, token::SubstNt(name, name_st)), TtToken(sp, token::Colon), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a1a13f2306477..325d8aa594a32 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -432,7 +432,7 @@ pub fn expand_item(it: P, fld: &mut MacroExpander) } let mut new_items = match it.node { - ast::ItemMac(..) => expand_item_mac(it, fld), + ast::ItemMac(..) => expand_item_mac(it, None, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { let valid_ident = it.ident.name != parse::token::special_idents::invalid.name; @@ -529,8 +529,9 @@ fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. -pub fn expand_item_mac(it: P, fld: &mut MacroExpander) - -> SmallVector> { +pub fn expand_item_mac(it: P, + imported_from: Option, + fld: &mut MacroExpander) -> SmallVector> { let (extname, path_span, tts) = match it.node { ItemMac(codemap::Spanned { node: MacInvocTT(ref pth, ref tts, _), @@ -611,7 +612,8 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) }); // DON'T mark before expansion. let MacroDef { name, ext } - = macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts); + = macro_rules::add_new_extension(fld.cx, it.span, it.ident, + imported_from, tts); fld.cx.syntax_env.insert(intern(name.as_slice()), ext); if attr::contains_name(it.attrs.as_slice(), "macro_export") { @@ -1190,7 +1192,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, expander.cx.cfg(), expander.cx.parse_sess()) .expect("expected a serialized item"); - expand_item_mac(item, &mut expander); + expand_item_mac(item, Some(crate_name), &mut expander); } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 15b75442ca2cb..a278604b16756 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -110,6 +110,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: Ident, + imported_from: Option, lhses: Vec>, rhses: Vec>, } @@ -123,6 +124,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { generic_extension(cx, sp, self.name, + self.imported_from, arg, self.lhses[], self.rhses[]) @@ -133,6 +135,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, name: Ident, + imported_from: Option, arg: &[ast::TokenTree], lhses: &[Rc], rhses: &[Rc]) @@ -156,6 +159,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, }; // `None` is because we're not interpolating let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic, + None, None, arg.iter() .map(|x| (*x).clone()) @@ -177,6 +181,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic, Some(named_matches), + imported_from, rhs); let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr); // Let the context choose how to interpret the result. @@ -209,6 +214,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, sp: Span, name: Ident, + imported_from: Option, arg: Vec ) -> MacroDef { @@ -246,6 +252,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic, + None, None, arg.clone()); let argument_map = parse_or_else(cx.parse_sess(), @@ -266,6 +273,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, let exp = box MacroRulesMacroExpander { name: name, + imported_from: imported_from, lhses: lhses, rhses: rhses, }; diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 86e81ede8b0fe..e4e6f5ac6b0f0 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -15,7 +15,7 @@ use codemap::{Span, DUMMY_SP}; use diagnostic::SpanHandler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt}; -use parse::token::{Token, NtIdent}; +use parse::token::{Token, NtIdent, SpecialMacroVar}; use parse::token; use parse::lexer::TokenAndSpan; @@ -39,6 +39,10 @@ pub struct TtReader<'a> { stack: Vec, /* for MBE-style macro transcription */ interpolations: HashMap>, + imported_from: Option, + + // Some => return imported_from as the next token + crate_name_next: Option, repeat_idx: Vec, repeat_len: Vec, /* cached: */ @@ -53,6 +57,7 @@ pub struct TtReader<'a> { /// should) be none. pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, interp: Option>>, + imported_from: Option, src: Vec ) -> TtReader<'a> { let mut r = TtReader { @@ -71,6 +76,8 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, None => HashMap::new(), Some(x) => x, }, + imported_from: imported_from, + crate_name_next: None, repeat_idx: Vec::new(), repeat_len: Vec::new(), desugar_doc_comments: false, @@ -162,6 +169,14 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sp: r.cur_span.clone(), }; loop { + match r.crate_name_next.take() { + None => (), + Some(sp) => { + r.cur_span = sp; + r.cur_tok = token::Ident(r.imported_from.unwrap(), token::Plain); + return ret_val; + }, + } let should_pop = match r.stack.last() { None => { assert_eq!(ret_val.tok, token::Eof); @@ -307,6 +322,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sep: None }); } + TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { + r.stack.last_mut().unwrap().idx += 1; + + if r.imported_from.is_some() { + r.cur_span = sp; + r.cur_tok = token::ModSep; + r.crate_name_next = Some(sp); + return ret_val; + } + + // otherwise emit nothing and proceed to the next token + } TtToken(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8598571e5c37a..3e4f2c8d4e237 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -291,7 +291,7 @@ pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc) pub fn tts_to_parser<'a>(sess: &'a ParseSess, tts: Vec, cfg: ast::CrateConfig) -> Parser<'a> { - let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, tts); + let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts); Parser::new(sess, cfg, box trdr) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cc67079e53879..f513692c31d34 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -75,8 +75,8 @@ use parse::classify; use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed}; use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::*; -use parse::token::{self, MatchNt, SubstNt, InternedString}; -use parse::token::{keywords, special_idents}; +use parse::token::{self, MatchNt, SubstNt, SpecialVarNt, InternedString}; +use parse::token::{keywords, special_idents, SpecialMacroVar}; use parse::{new_sub_parser_from_file, ParseSess}; use print::pprust; use ptr::P; @@ -2747,6 +2747,9 @@ impl<'a> Parser<'a> { op: repeat, num_captures: name_num })) + } else if p.token.is_keyword_allow_following_colon(keywords::Crate) { + p.bump(); + TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar)) } else { // A nonterminal that matches or not let namep = match p.token { token::Ident(_, p) => p, _ => token::Plain }; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b7e89b32b709e..a653190cffdef 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -61,6 +61,21 @@ pub enum IdentStyle { Plain, } +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] +pub enum SpecialMacroVar { + /// `$crate` will be filled in with the name of the crate a macro was + /// imported from, if any. + CrateMacroVar, +} + +impl SpecialMacroVar { + pub fn as_str(self) -> &'static str { + match self { + SpecialMacroVar::CrateMacroVar => "crate", + } + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum Lit { Byte(ast::Name), @@ -143,6 +158,8 @@ pub enum Token { // In right-hand-sides of MBE macros: /// A syntactic variable that will be filled in by macro expansion. SubstNt(ast::Ident, IdentStyle), + /// A macro variable with special meaning. + SpecialVarNt(SpecialMacroVar), // Junk. These carry no data because we don't really care about the data // they *would* carry, and don't really want to allocate a new ident for @@ -265,6 +282,13 @@ impl Token { } } + pub fn is_keyword_allow_following_colon(&self, kw: keywords::Keyword) -> bool { + match *self { + Ident(sid, _) => { kw.to_name() == sid.name } + _ => { false } + } + } + /// Returns `true` if the token is either a special identifier, or a strict /// or reserved keyword. #[allow(non_upper_case_globals)] diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 61b7aa408a8d5..27db49b65ce19 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -272,6 +272,8 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()), + token::SpecialVarNt(var) => format!("${}", var.as_str()), + token::Interpolated(ref nt) => match *nt { token::NtExpr(ref e) => expr_to_string(&**e), token::NtMeta(ref e) => meta_item_to_string(&**e), diff --git a/src/test/auxiliary/macro_crate_nonterminal.rs b/src/test/auxiliary/macro_crate_nonterminal.rs new file mode 100644 index 0000000000000..20df664c3c6ad --- /dev/null +++ b/src/test/auxiliary/macro_crate_nonterminal.rs @@ -0,0 +1,24 @@ +// 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. + +#![feature(macro_rules)] + +pub fn increment(x: uint) -> uint { + x + 1 +} + +#[macro_export] +macro_rules! increment { + ($x:expr) => ($crate::increment($x)) +} + +pub fn check_local() { + assert_eq!(increment!(3), 4); +} diff --git a/src/test/run-pass/macro-crate-nonterminal-renamed.rs b/src/test/run-pass/macro-crate-nonterminal-renamed.rs new file mode 100644 index 0000000000000..cf9a53f27be5d --- /dev/null +++ b/src/test/run-pass/macro-crate-nonterminal-renamed.rs @@ -0,0 +1,22 @@ +// 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. + +// aux-build:macro_crate_nonterminal.rs +// ignore-stage1 + +#![feature(phase)] + +#[phase(plugin, link)] +extern crate "macro_crate_nonterminal" as new_name; + +pub fn main() { + new_name::check_local(); + assert_eq!(increment!(5), 6); +} diff --git a/src/test/run-pass/macro-crate-nonterminal.rs b/src/test/run-pass/macro-crate-nonterminal.rs new file mode 100644 index 0000000000000..8abf534ab1249 --- /dev/null +++ b/src/test/run-pass/macro-crate-nonterminal.rs @@ -0,0 +1,22 @@ +// 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. + +// aux-build:macro_crate_nonterminal.rs +// ignore-stage1 + +#![feature(phase)] + +#[phase(plugin, link)] +extern crate macro_crate_nonterminal; + +pub fn main() { + macro_crate_nonterminal::check_local(); + assert_eq!(increment!(5), 6); +} From e2a9c04e192926fde1a8e886b55e4c2b6e0e56cb Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Tue, 9 Dec 2014 22:53:12 -0800 Subject: [PATCH 064/106] Allow leading :: in use items --- src/libsyntax/parse/parser.rs | 4 ++++ src/test/run-pass/crate-leading-sep.rs | 14 +++++++++++++ src/test/run-pass/macro-crate-use.rs | 27 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/test/run-pass/crate-leading-sep.rs create mode 100644 src/test/run-pass/macro-crate-use.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f513692c31d34..62bda20473f76 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5973,6 +5973,10 @@ impl<'a> Parser<'a> { fn parse_view_path(&mut self) -> P { let lo = self.span.lo; + // Allow a leading :: because the paths are absolute either way. + // This occurs with "use $crate::..." in macros. + self.eat(&token::ModSep); + if self.check(&token::OpenDelim(token::Brace)) { // use {foo,bar} let idents = self.parse_unspanned_seq( diff --git a/src/test/run-pass/crate-leading-sep.rs b/src/test/run-pass/crate-leading-sep.rs new file mode 100644 index 0000000000000..b2956f4e229b6 --- /dev/null +++ b/src/test/run-pass/crate-leading-sep.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + use ::std::mem; + mem::drop(2u); +} diff --git a/src/test/run-pass/macro-crate-use.rs b/src/test/run-pass/macro-crate-use.rs new file mode 100644 index 0000000000000..1cea4fba2aa2e --- /dev/null +++ b/src/test/run-pass/macro-crate-use.rs @@ -0,0 +1,27 @@ +// 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. + +#![feature(macro_rules)] + +pub fn increment(x: uint) -> uint { + x + 1 +} + +#[macro_export] +macro_rules! increment { + ($x:expr) => ({ + use $crate::increment; + increment($x) + }) +} + +fn main() { + assert_eq!(increment!(3), 4); +} From 538288176a22b4d3755df085783f84d476386019 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 15 Sep 2014 19:02:14 -0700 Subject: [PATCH 065/106] Implement macro re-export Fixes #17103. --- src/librustc_driver/driver.rs | 2 + src/libsyntax/ext/expand.rs | 9 +++- src/libsyntax/ext/tt/reexport.rs | 41 +++++++++++++++++++ src/libsyntax/lib.rs | 1 + src/test/auxiliary/macro_reexport_1.rs | 17 ++++++++ src/test/auxiliary/macro_reexport_2.rs | 17 ++++++++ .../macro-reexport-malformed-1.rs | 13 ++++++ .../macro-reexport-malformed-2.rs | 13 ++++++ .../macro-reexport-malformed-3.rs | 13 ++++++ src/test/run-pass/macro-reexport.rs | 22 ++++++++++ 10 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/libsyntax/ext/tt/reexport.rs create mode 100644 src/test/auxiliary/macro_reexport_1.rs create mode 100644 src/test/auxiliary/macro_reexport_2.rs create mode 100644 src/test/compile-fail/macro-reexport-malformed-1.rs create mode 100644 src/test/compile-fail/macro-reexport-malformed-2.rs create mode 100644 src/test/compile-fail/macro-reexport-malformed-3.rs create mode 100644 src/test/run-pass/macro-reexport.rs diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 0d9736a82736f..5056ada6a8c11 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -275,6 +275,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, deriving_hash_type_parameter: sess.features.borrow().default_type_params, enable_quotes: sess.features.borrow().quote, recursion_limit: sess.recursion_limit.get(), + reexported_macros: syntax::ext::tt::reexport::gather(sess.diagnostic(), + &krate), }; let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, cfg, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 325d8aa594a32..d4be46d025ecf 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -616,7 +616,12 @@ pub fn expand_item_mac(it: P, imported_from, tts); fld.cx.syntax_env.insert(intern(name.as_slice()), ext); - if attr::contains_name(it.attrs.as_slice(), "macro_export") { + + if match imported_from { + None => attr::contains_name(it.attrs.as_slice(), "macro_export"), + Some(_) => fld.cx.ecfg.reexported_macros.iter() + .any(|e| e.as_slice() == name.as_slice()), + } { fld.cx.exported_macros.push(it); } @@ -1156,6 +1161,7 @@ pub struct ExpansionConfig { pub deriving_hash_type_parameter: bool, pub enable_quotes: bool, pub recursion_limit: uint, + pub reexported_macros: Vec, } impl ExpansionConfig { @@ -1165,6 +1171,7 @@ impl ExpansionConfig { deriving_hash_type_parameter: false, enable_quotes: false, recursion_limit: 64, + reexported_macros: vec![], } } } diff --git a/src/libsyntax/ext/tt/reexport.rs b/src/libsyntax/ext/tt/reexport.rs new file mode 100644 index 0000000000000..104f37872535c --- /dev/null +++ b/src/libsyntax/ext/tt/reexport.rs @@ -0,0 +1,41 @@ +// 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. + +//! Defines the crate attribute syntax for macro re-export. + +use ast; +use attr::AttrMetaMethods; +use diagnostic::SpanHandler; + +/// Return a vector of the names of all macros re-exported from the crate. +pub fn gather(diag: &SpanHandler, krate: &ast::Crate) -> Vec { + let usage = "malformed macro_reexport attribute, expected \ + #![macro_reexport(ident, ident, ...)]"; + + let mut reexported: Vec = vec!(); + for attr in krate.attrs.iter() { + if !attr.check_name("macro_reexport") { + continue; + } + + match attr.meta_item_list() { + None => diag.span_err(attr.span, usage), + Some(list) => for mi in list.iter() { + match mi.node { + ast::MetaWord(ref word) + => reexported.push(word.to_string()), + _ => diag.span_err(mi.span, usage), + } + } + } + } + + reexported +} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 18cdb3fc64789..0503d88cca201 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -104,5 +104,6 @@ pub mod ext { pub mod transcribe; pub mod macro_parser; pub mod macro_rules; + pub mod reexport; } } diff --git a/src/test/auxiliary/macro_reexport_1.rs b/src/test/auxiliary/macro_reexport_1.rs new file mode 100644 index 0000000000000..bd00b33f28012 --- /dev/null +++ b/src/test/auxiliary/macro_reexport_1.rs @@ -0,0 +1,17 @@ +// 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. + +#![crate_type = "dylib"] +#![feature(macro_rules)] + +#[macro_export] +macro_rules! reexported { + () => ( 3u ) +} diff --git a/src/test/auxiliary/macro_reexport_2.rs b/src/test/auxiliary/macro_reexport_2.rs new file mode 100644 index 0000000000000..3b68d47c55861 --- /dev/null +++ b/src/test/auxiliary/macro_reexport_2.rs @@ -0,0 +1,17 @@ +// 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. + +#![crate_type = "dylib"] +#![feature(phase)] + +#![macro_reexport(reexported)] + +#[phase(plugin)] +extern crate macro_reexport_1; diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs new file mode 100644 index 0000000000000..ea3074db124d6 --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-1.rs @@ -0,0 +1,13 @@ +// 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. + +#![macro_reexport] //~ ERROR malformed macro_reexport attribute + +fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs new file mode 100644 index 0000000000000..3daa089d2c677 --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-2.rs @@ -0,0 +1,13 @@ +// 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. + +#![macro_reexport="foo"] //~ ERROR malformed macro_reexport attribute + +fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs new file mode 100644 index 0000000000000..b3c0bf95ce981 --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-3.rs @@ -0,0 +1,13 @@ +// 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. + +#![macro_reexport(foo="bar")] //~ ERROR malformed macro_reexport attribute + +fn main() { } diff --git a/src/test/run-pass/macro-reexport.rs b/src/test/run-pass/macro-reexport.rs new file mode 100644 index 0000000000000..bc3632e76ba49 --- /dev/null +++ b/src/test/run-pass/macro-reexport.rs @@ -0,0 +1,22 @@ +// 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. + +// aux-build:macro_reexport_1.rs +// aux-build:macro_reexport_2.rs +// ignore-stage1 + +#![feature(phase)] + +#[phase(plugin)] +extern crate macro_reexport_2; + +fn main() { + assert_eq!(reexported!(), 3u); +} From 1c2fddc6bf6332212fe899c2cb86ae7e645f6eba Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Tue, 9 Dec 2014 18:34:22 -0800 Subject: [PATCH 066/106] Remove unused if_ok! macro --- src/librustc_borrowck/borrowck/mod.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 75545634b40cf..fd46a03553771 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,15 +39,6 @@ use syntax::visit; use syntax::visit::{Visitor, FnKind}; use syntax::ast::{FnDecl, Block, NodeId}; -macro_rules! if_ok { - ($inp: expr) => ( - match $inp { - Ok(v) => { v } - Err(e) => { return Err(e); } - } - ) -} - pub mod doc; pub mod check_loans; From 4236c52e34cd005af86ea9e5f199daeea9bb8fcb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Jan 2015 11:39:52 -0800 Subject: [PATCH 067/106] std: Move Atomic{Int,Uint} back to unstable The int/uint story is under heavy development, and these types are likely to be renamed. --- src/libcore/atomic.rs | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index fbb8f9d8cf754..15c20253c8bc7 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -86,7 +86,7 @@ pub struct AtomicBool { unsafe impl Sync for AtomicBool {} /// A signed integer type which can be safely shared between threads. -#[stable] +#[unstable = "awaiting int/uint conventions, may be renamed"] pub struct AtomicInt { v: UnsafeCell, } @@ -94,7 +94,7 @@ pub struct AtomicInt { unsafe impl Sync for AtomicInt {} /// An unsigned integer type which can be safely shared between threads. -#[stable] +#[unstable = "awaiting int/uint conventions, may be renamed"] pub struct AtomicUint { v: UnsafeCell, } @@ -150,11 +150,11 @@ pub enum Ordering { pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool { v: UnsafeCell { value: 0 } }; /// An `AtomicInt` initialized to `0`. -#[stable] +#[unstable = "awaiting int/uint conventions, may be renamed"] pub const ATOMIC_INT_INIT: AtomicInt = AtomicInt { v: UnsafeCell { value: 0 } }; /// An `AtomicUint` initialized to `0`. -#[stable] +#[unstable = "awaiting int/uint conventions, may be renamed"] pub const ATOMIC_UINT_INIT: AtomicUint = AtomicUint { v: UnsafeCell { value: 0, } }; @@ -403,6 +403,7 @@ impl AtomicBool { } } +#[unstable = "awaiting int/uint conventions, types may change"] impl AtomicInt { /// Creates a new `AtomicInt`. /// @@ -414,7 +415,6 @@ impl AtomicInt { /// let atomic_forty_two = AtomicInt::new(42); /// ``` #[inline] - #[stable] pub fn new(v: int) -> AtomicInt { AtomicInt {v: UnsafeCell::new(v)} } @@ -437,7 +437,6 @@ impl AtomicInt { /// let value = some_int.load(Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn load(&self, order: Ordering) -> int { unsafe { atomic_load(self.v.get() as *const int, order) } } @@ -460,7 +459,6 @@ impl AtomicInt { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] - #[stable] pub fn store(&self, val: int, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } @@ -479,7 +477,6 @@ impl AtomicInt { /// let value = some_int.swap(10, Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn swap(&self, val: int, order: Ordering) -> int { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -501,7 +498,6 @@ impl AtomicInt { /// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -518,7 +514,6 @@ impl AtomicInt { /// assert_eq!(10, foo.load(Ordering::SeqCst)); /// ``` #[inline] - #[stable] pub fn fetch_add(&self, val: int, order: Ordering) -> int { unsafe { atomic_add(self.v.get(), val, order) } } @@ -535,7 +530,6 @@ impl AtomicInt { /// assert_eq!(-10, foo.load(Ordering::SeqCst)); /// ``` #[inline] - #[stable] pub fn fetch_sub(&self, val: int, order: Ordering) -> int { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -551,7 +545,6 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst)); /// assert_eq!(0b100001, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_and(&self, val: int, order: Ordering) -> int { unsafe { atomic_and(self.v.get(), val, order) } } @@ -567,7 +560,6 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst)); /// assert_eq!(0b111111, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_or(&self, val: int, order: Ordering) -> int { unsafe { atomic_or(self.v.get(), val, order) } } @@ -583,12 +575,12 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst)); /// assert_eq!(0b011110, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_xor(&self, val: int, order: Ordering) -> int { unsafe { atomic_xor(self.v.get(), val, order) } } } +#[unstable = "awaiting int/uint conventions, types may change"] impl AtomicUint { /// Creates a new `AtomicUint`. /// @@ -600,7 +592,6 @@ impl AtomicUint { /// let atomic_forty_two = AtomicUint::new(42u); /// ``` #[inline] - #[stable] pub fn new(v: uint) -> AtomicUint { AtomicUint { v: UnsafeCell::new(v) } } @@ -623,7 +614,6 @@ impl AtomicUint { /// let value = some_uint.load(Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn load(&self, order: Ordering) -> uint { unsafe { atomic_load(self.v.get() as *const uint, order) } } @@ -646,7 +636,6 @@ impl AtomicUint { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] - #[stable] pub fn store(&self, val: uint, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } @@ -665,7 +654,6 @@ impl AtomicUint { /// let value = some_uint.swap(10, Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn swap(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -687,7 +675,6 @@ impl AtomicUint { /// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed); /// ``` #[inline] - #[stable] pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -704,7 +691,6 @@ impl AtomicUint { /// assert_eq!(10, foo.load(Ordering::SeqCst)); /// ``` #[inline] - #[stable] pub fn fetch_add(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_add(self.v.get(), val, order) } } @@ -721,7 +707,6 @@ impl AtomicUint { /// assert_eq!(0, foo.load(Ordering::SeqCst)); /// ``` #[inline] - #[stable] pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -737,7 +722,6 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst)); /// assert_eq!(0b100001, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_and(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_and(self.v.get(), val, order) } } @@ -753,7 +737,6 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst)); /// assert_eq!(0b111111, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_or(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_or(self.v.get(), val, order) } } @@ -769,7 +752,6 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst)); /// assert_eq!(0b011110, foo.load(Ordering::SeqCst)); #[inline] - #[stable] pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_xor(self.v.get(), val, order) } } From 774588fd9def900a467ba2b4ec3620f89832a799 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 4 Jan 2015 21:39:02 -0500 Subject: [PATCH 068/106] sed -i -s 's/ for Sized?//g' **/*.rs --- src/libcollections/slice.rs | 4 ++-- src/libcollections/str.rs | 2 +- src/libcore/borrow.rs | 6 +++--- src/libcore/cmp.rs | 8 ++++---- src/libcore/fmt/mod.rs | 16 +++++++-------- src/libcore/hash/mod.rs | 2 +- src/libcore/kinds.rs | 8 ++++---- src/libcore/ops.rs | 20 +++++++++---------- src/libcore/raw.rs | 2 +- src/libcore/slice.rs | 8 ++++---- src/libcore/str/mod.rs | 4 ++-- src/librustc/middle/traits/util.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- src/librustc_trans/trans/cabi_x86_64.rs | 2 +- src/librustc_trans/trans/llrepr.rs | 2 +- src/libserialize/base64.rs | 4 ++-- src/libserialize/hex.rs | 4 ++-- src/libserialize/json.rs | 2 +- src/libserialize/serialize.rs | 2 +- src/libstd/ascii.rs | 2 +- src/libstd/c_str.rs | 2 +- src/libstd/path/mod.rs | 2 +- src/libsyntax/ext/quote.rs | 4 ++-- src/libtest/stats.rs | 2 +- src/libunicode/u_str.rs | 2 +- src/test/auxiliary/lang-item-public.rs | 2 +- ...ed-types-ICE-when-projecting-out-of-err.rs | 2 +- .../dst-object-from-unsized-type.rs | 2 +- src/test/compile-fail/issue-18959.rs | 4 ++-- src/test/compile-fail/issue-19009.rs | 2 +- src/test/compile-fail/privacy4.rs | 2 +- src/test/compile-fail/required-lang-item.rs | 2 +- .../unboxed-closure-sugar-default.rs | 2 +- .../unboxed-closure-sugar-equiv.rs | 2 +- .../unboxed-closure-sugar-lifetime-elision.rs | 2 +- .../unboxed-closure-sugar-region.rs | 2 +- src/test/compile-fail/unsized3.rs | 2 +- src/test/compile-fail/unsized6.rs | 2 +- src/test/compile-fail/unsized7.rs | 2 +- .../associated-types-conditional-dispatch.rs | 2 +- ...sociated-types-normalize-in-bounds-ufcs.rs | 2 +- .../associated-types-normalize-in-bounds.rs | 2 +- 42 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..a5e44dc1ddcff 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -120,7 +120,7 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf}; /// Allocating extension methods for slices. #[unstable = "needs associated types, may merge with other traits"] -pub trait SliceExt for Sized? { +pub trait SliceExt { type Item; /// Sorts the slice, in place, using `compare` to compare @@ -989,7 +989,7 @@ impl SliceExt for [T] { //////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices -pub trait SliceConcatExt for Sized? { +pub trait SliceConcatExt { /// Flattens a slice of `T` into a single value `U`. #[stable] fn concat(&self) -> U; diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ecf17820d2d8f..0f33d21ef02c1 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -401,7 +401,7 @@ Section: Trait implementations */ /// Any string that can be represented as a slice. -pub trait StrExt for Sized?: ops::Slice { +pub trait StrExt: ops::Slice { /// Escapes each char in `s` with `char::escape_default`. #[unstable = "return type may change to be an iterator"] fn escape_default(&self) -> String { diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d8d..6695cae6a1cf6 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -53,13 +53,13 @@ use option::Option; use self::Cow::*; /// A trait for borrowing data. -pub trait BorrowFrom for Sized? { +pub trait BorrowFrom { /// Immutably borrow from an owned value. fn borrow_from(owned: &Owned) -> &Self; } /// A trait for mutably borrowing data. -pub trait BorrowFromMut for Sized? : BorrowFrom { +pub trait BorrowFromMut : BorrowFrom { /// Mutably borrow from an owned value. fn borrow_from_mut(owned: &mut Owned) -> &mut Self; } @@ -103,7 +103,7 @@ impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { } /// A generalization of Clone to borrowed data. -pub trait ToOwned for Sized?: BorrowFrom { +pub trait ToOwned: BorrowFrom { /// Create owned data from borrowed data, usually by copying. fn to_owned(&self) -> Owned; } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 13f9f5ccee916..c4ed0a75a4ec8 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -69,7 +69,7 @@ use option::Option::{self, Some, None}; /// only if `a != b`. #[lang="eq"] #[stable] -pub trait PartialEq for Sized? { +pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable] fn eq(&self, other: &Rhs) -> bool; @@ -90,7 +90,7 @@ pub trait PartialEq for Sized? { /// - symmetric: `a == b` implies `b == a`; and /// - transitive: `a == b` and `b == c` implies `a == c`. #[stable] -pub trait Eq for Sized?: PartialEq { +pub trait Eq: PartialEq { // FIXME #13101: this method is used solely by #[deriving] to // assert that every component of a type implements #[deriving] // itself, the current deriving infrastructure means doing this @@ -164,7 +164,7 @@ impl Ordering { /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for /// both `==` and `>`. #[stable] -pub trait Ord for Sized?: Eq + PartialOrd { +pub trait Ord: Eq + PartialOrd { /// This method returns an ordering between `self` and `other` values. /// /// By convention, `self.cmp(&other)` returns the ordering matching @@ -224,7 +224,7 @@ impl PartialOrd for Ordering { /// 5.11). #[lang="ord"] #[stable] -pub trait PartialOrd for Sized?: PartialEq { +pub trait PartialOrd: PartialEq { /// This method returns an ordering between `self` and `other` values /// if one exists. #[stable] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 102836f8d3024..bde2fb7525211 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -222,7 +222,7 @@ impl<'a> Show for Arguments<'a> { /// to this trait. There is not an explicit way of selecting this trait to be /// used for formatting, it is only if no other format is specified. #[unstable = "I/O and core have yet to be reconciled"] -pub trait Show for Sized? { +pub trait Show { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } @@ -230,49 +230,49 @@ pub trait Show for Sized? { /// Format trait for the `o` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait Octal for Sized? { +pub trait Octal { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `b` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait Binary for Sized? { +pub trait Binary { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `x` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait LowerHex for Sized? { +pub trait LowerHex { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `X` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait UpperHex for Sized? { +pub trait UpperHex { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `p` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait Pointer for Sized? { +pub trait Pointer { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `e` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait LowerExp for Sized? { +pub trait LowerExp { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `E` character #[unstable = "I/O and core have yet to be reconciled"] -pub trait UpperExp for Sized? { +pub trait UpperExp { /// Formats the value using the given formatter. fn fmt(&self, &mut Formatter) -> Result; } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index b0a5ec9fe12ed..d929e12a073c7 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -76,7 +76,7 @@ pub mod sip; /// A hashable type. The `S` type parameter is an abstract hash state that is /// used by the `Hash` to compute the hash. It defaults to /// `std::hash::sip::SipState`. -pub trait Hash for Sized? { +pub trait Hash { /// Computes the hash of a value. fn hash(&self, state: &mut S); } diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index e50aaef5f09f3..4769c783e5829 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -19,19 +19,19 @@ /// Types able to be transferred across task boundaries. #[lang="send"] -pub unsafe trait Send for Sized? : 'static { +pub unsafe trait Send : 'static { // empty. } /// Types with a constant size known at compile-time. #[lang="sized"] -pub trait Sized for Sized? { +pub trait Sized { // Empty. } /// Types that can be copied by simply copying bits (i.e. `memcpy`). #[lang="copy"] -pub trait Copy for Sized? { +pub trait Copy { // Empty. } @@ -81,7 +81,7 @@ pub trait Copy for Sized? { /// reference; not doing this is undefined behaviour (for example, /// `transmute`-ing from `&T` to `&mut T` is illegal). #[lang="sync"] -pub unsafe trait Sync for Sized? { +pub unsafe trait Sync { // Empty } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index c9b71092f9072..ef9f7f25c6a66 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -721,7 +721,7 @@ shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } #[cfg(stage0)] #[allow(missing_docs)] #[lang="index"] -pub trait Index for Sized? { +pub trait Index { /// The method for the indexing (`Foo[Bar]`) operation fn index<'a>(&'a self, index: &Index) -> &'a Result; } @@ -757,7 +757,7 @@ pub trait Index for Sized? { /// ``` #[cfg(not(stage0))] // NOTE(stage0) remove cfg after a snapshot #[lang="index"] -pub trait Index for Sized? { +pub trait Index { type Sized? Output; /// The method for the indexing (`Foo[Bar]`) operation @@ -768,7 +768,7 @@ pub trait Index for Sized? { #[cfg(stage0)] #[allow(missing_docs)] #[lang="index_mut"] -pub trait IndexMut for Sized? { +pub trait IndexMut { /// The method for the indexing (`Foo[Bar]`) operation fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result; } @@ -804,7 +804,7 @@ pub trait IndexMut for Sized? { /// ``` #[cfg(not(stage0))] // NOTE(stage0) remove cfg after a snapshot #[lang="index_mut"] -pub trait IndexMut for Sized? { +pub trait IndexMut { type Sized? Output; /// The method for the indexing (`Foo[Bar]`) operation @@ -849,7 +849,7 @@ pub trait IndexMut for Sized? { /// } /// ``` #[lang="slice"] -pub trait Slice for Sized? { +pub trait Slice { /// The method for the slicing operation foo[] fn as_slice_<'a>(&'a self) -> &'a Result; /// The method for the slicing operation foo[from..] @@ -898,7 +898,7 @@ pub trait Slice for Sized? { /// } /// ``` #[lang="slice_mut"] -pub trait SliceMut for Sized? { +pub trait SliceMut { /// The method for the slicing operation foo[] fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result; /// The method for the slicing operation foo[from..] @@ -1025,7 +1025,7 @@ pub struct RangeTo { /// } /// ``` #[lang="deref"] -pub trait Deref for Sized? { +pub trait Deref { type Sized? Target; /// The method called to dereference a value @@ -1082,7 +1082,7 @@ impl<'a, Sized? T> Deref for &'a mut T { /// } /// ``` #[lang="deref_mut"] -pub trait DerefMut for Sized? : Deref { +pub trait DerefMut : Deref { /// The method called to mutably dereference a value fn deref_mut<'a>(&'a mut self) -> &'a mut ::Target; } @@ -1093,14 +1093,14 @@ impl<'a, Sized? T> DerefMut for &'a mut T { /// A version of the call operator that takes an immutable receiver. #[lang="fn"] -pub trait Fn for Sized? { +pub trait Fn { /// This is called when the call operator is used. extern "rust-call" fn call(&self, args: Args) -> Result; } /// A version of the call operator that takes a mutable receiver. #[lang="fn_mut"] -pub trait FnMut for Sized? { +pub trait FnMut { /// This is called when the call operator is used. extern "rust-call" fn call_mut(&mut self, args: Args) -> Result; } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 3bef1d1536377..0e91d6123f5cc 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -52,7 +52,7 @@ pub struct TraitObject { /// This trait is meant to map equivalences between raw structs and their /// corresponding rust values. -pub trait Repr for Sized? { +pub trait Repr { /// This function "unwraps" a rust value (without consuming it) into its raw /// struct representation. This can be used to read/write different values /// for the struct. This is a safe method because by default it does not diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f17a775cf4240..9aa3f76b525e7 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -64,7 +64,7 @@ use raw::Slice as RawSlice; /// Extension methods for slices. #[allow(missing_docs)] // docs in libcollections -pub trait SliceExt for Sized? { +pub trait SliceExt { type Item; fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item]; @@ -636,7 +636,7 @@ impl ops::SliceMut for [T] { /// Data that is viewable as a slice. #[experimental = "will be replaced by slice syntax"] -pub trait AsSlice for Sized? { +pub trait AsSlice { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a [T]; } @@ -1377,7 +1377,7 @@ pub mod bytes { use slice::SliceExt; /// A trait for operations on mutable `[u8]`s. - pub trait MutableByteVector for Sized? { + pub trait MutableByteVector { /// Sets all bytes of the receiver to the given value. fn set_memory(&mut self, value: u8); } @@ -1461,7 +1461,7 @@ impl PartialOrd for [T] { /// Extension methods for slices containing integers. #[experimental] -pub trait IntSliceExt for Sized? { +pub trait IntSliceExt { /// Converts the slice to an immutable slice of unsigned integers with the same width. fn as_unsigned<'a>(&'a self) -> &'a [U]; /// Converts the slice to an immutable slice of signed integers with the same width. diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..ccbc444963c9d 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1130,7 +1130,7 @@ pub mod traits { #[unstable = "Instead of taking this bound generically, this trait will be \ replaced with one of slicing syntax, deref coercions, or \ a more generic conversion trait"] -pub trait Str for Sized? { +pub trait Str { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a str; } @@ -1171,7 +1171,7 @@ delegate_iter!{pattern forward &'a str in RSplitN<'a, P>} /// Methods for string slices #[allow(missing_docs)] -pub trait StrExt for Sized? { +pub trait StrExt { // NB there are no docs here are they're all located on the StrExt trait in // libcollections, not here. diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index ab8888f9a33eb..8152f7e284fe4 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -93,7 +93,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { // seen. This is necessary to prevent infinite // recursion in some cases. One common case is when // people define `trait Sized { }` rather than `trait - // Sized for Sized? { }`. + // Sized { }`. predicates.retain(|r| self.visited.insert(r.clone())); self.stack.push(StackEntry { position: 0, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9639af5ca1cd5..0c7c9513719ac 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -38,7 +38,7 @@ use syntax::{ast, ast_util}; use syntax::owned_slice::OwnedSlice; /// Produces a string suitable for debugging output. -pub trait Repr<'tcx> for Sized? { +pub trait Repr<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String; } diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index f59d152fa473c..9ec0c822bf5fe 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -63,7 +63,7 @@ impl RegClass { } } -trait ClassList for Sized? { +trait ClassList { fn is_pass_byval(&self) -> bool; fn is_ret_bysret(&self) -> bool; } diff --git a/src/librustc_trans/trans/llrepr.rs b/src/librustc_trans/trans/llrepr.rs index dcf3a53215788..de0f714276d0d 100644 --- a/src/librustc_trans/trans/llrepr.rs +++ b/src/librustc_trans/trans/llrepr.rs @@ -12,7 +12,7 @@ use trans::context::CrateContext; use trans::type_::Type; use llvm::ValueRef; -pub trait LlvmRepr for Sized? { +pub trait LlvmRepr { fn llrepr(&self, ccx: &CrateContext) -> String; } diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 44bf5f8977870..11a49cd712f25 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -70,7 +70,7 @@ static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 0123456789-_"; /// A trait for converting a value to base64 encoding. -pub trait ToBase64 for Sized? { +pub trait ToBase64 { /// Converts the value of `self` to a base64 value following the specified /// format configuration, returning the owned string. fn to_base64(&self, config: Config) -> String; @@ -170,7 +170,7 @@ impl ToBase64 for [u8] { } /// A trait for converting from base64 encoded values. -pub trait FromBase64 for Sized? { +pub trait FromBase64 { /// Converts the value of `self`, interpreted as base64 encoded data, into /// an owned vector of bytes, returning the vector. fn from_base64(&self) -> Result, FromBase64Error>; diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index c915ddaaa9c04..542d0678526b9 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -18,7 +18,7 @@ use std::fmt; use std::error; /// A trait for converting a value to hexadecimal encoding -pub trait ToHex for Sized? { +pub trait ToHex { /// Converts the value of `self` to a hex value, returning the owned /// string. fn to_hex(&self) -> String; @@ -54,7 +54,7 @@ impl ToHex for [u8] { } /// A trait for converting hexadecimal encoded values -pub trait FromHex for Sized? { +pub trait FromHex { /// Converts the value of `self`, interpreted as hexadecimal encoded data, /// into an owned vector of bytes, returning the vector. fn from_hex(&self) -> Result, FromHexError>; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index e8bd46815e6ac..c8af8e309a39b 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -2323,7 +2323,7 @@ impl ::Decoder for Decoder { } /// A trait for converting values to JSON -pub trait ToJson for Sized? { +pub trait ToJson { /// Converts the value of `self` to an instance of JSON fn to_json(&self) -> Json; } diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0646ee1758fc0..943843c6cc837 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -190,7 +190,7 @@ pub trait Decoder { fn error(&mut self, err: &str) -> Self::Error; } -pub trait Encodable for Sized? { +pub trait Encodable { fn encode(&self, s: &mut S) -> Result<(), S::Error>; } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index bcd87f6786d35..c0b9bbbbc297d 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -38,7 +38,7 @@ pub trait OwnedAsciiExt { /// Extension methods for ASCII-subset only operations on string slices #[experimental = "would prefer to do this in a more general way"] -pub trait AsciiExt for Sized? { +pub trait AsciiExt { /// Check if within the ASCII range. fn is_ascii(&self) -> bool; diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 9c96a9cac7831..a7f0bc3532fbe 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -295,7 +295,7 @@ impl fmt::Show for CString { } /// A generic trait for converting a value to a CString. -pub trait ToCStr for Sized? { +pub trait ToCStr { /// Copy the receiver into a CString. /// /// # Panics diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index bf9ffbffe7d50..ac281439ce545 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -786,7 +786,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { } /// A trait that represents something bytes-like (e.g. a &[u8] or a &str) -pub trait BytesContainer for Sized? { +pub trait BytesContainer { /// Returns a &[u8] representing the receiver fn container_as_bytes<'a>(&'a self) -> &'a [u8]; /// Returns the receiver interpreted as a utf-8 string, if possible diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index e46bd7ac4bc73..f1b52fa33c386 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -85,14 +85,14 @@ pub mod rt { */ // FIXME: Move this trait to pprust and get rid of *_to_str? - pub trait ToSource for Sized? { + pub trait ToSource { // Takes a thing and generates a string containing rust code for it. fn to_source(&self) -> String; } // FIXME (Issue #16472): This should go away after ToToken impls // are revised to go directly to token-trees. - trait ToSourceWithHygiene for Sized? : ToSource { + trait ToSourceWithHygiene : ToSource { // Takes a thing and generates a string containing rust code // for it, encoding Idents as special byte sequences to // maintain hygiene across serialization and deserialization. diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 7e7f36f6e83fa..d6b9b6ecaaecc 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -39,7 +39,7 @@ fn local_sort(v: &mut [T]) { } /// Trait that provides simple descriptive statistics on a univariate set of numeric samples. -pub trait Stats for Sized? { +pub trait Stats { /// Sum of the samples. /// diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 90949437774f1..13672a7b480af 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -37,7 +37,7 @@ pub struct Words<'a> { /// Methods for Unicode string slices #[allow(missing_docs)] // docs in libcollections -pub trait UnicodeStr for Sized? { +pub trait UnicodeStr { fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>; fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>; fn words<'a>(&'a self) -> Words<'a>; diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index e6bae4628874c..e99a8f0b87737 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -12,7 +12,7 @@ #![feature(lang_items)] #[lang="sized"] -pub trait Sized for Sized? {} +pub trait Sized {} #[lang="panic"] fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} } diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 5743216b6ca69..6265392663dec 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -16,7 +16,7 @@ #![no_std] #[lang="sized"] -pub trait Sized for Sized? { +pub trait Sized { // Empty. } diff --git a/src/test/compile-fail/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs index 99c63c3c6e95e..4e5a6be1bc7c6 100644 --- a/src/test/compile-fail/dst-object-from-unsized-type.rs +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -10,7 +10,7 @@ // Test that we cannot create objects from unsized types. -trait Foo for Sized? {} +trait Foo {} impl Foo for str {} fn test1(t: &T) { diff --git a/src/test/compile-fail/issue-18959.rs b/src/test/compile-fail/issue-18959.rs index 1a792eb6e76ae..7aba1bc8e65c7 100644 --- a/src/test/compile-fail/issue-18959.rs +++ b/src/test/compile-fail/issue-18959.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Foo for Sized? { fn foo(&self, ext_thing: &T); } -pub trait Bar for Sized?: Foo { } +pub trait Foo { fn foo(&self, ext_thing: &T); } +pub trait Bar: Foo { } impl Bar for T { } pub struct Thing; diff --git a/src/test/compile-fail/issue-19009.rs b/src/test/compile-fail/issue-19009.rs index aa7c4c3060bdb..3c1853b9990a7 100644 --- a/src/test/compile-fail/issue-19009.rs +++ b/src/test/compile-fail/issue-19009.rs @@ -11,7 +11,7 @@ #![feature(lang_items)] #![no_std] #![crate_type="rlib"] -#[lang="sized"] pub trait Sized for Sized? {} +#[lang="sized"] pub trait Sized {} fn ice(f: for <'s> || :'s //~ ERROR use of undeclared lifetime name `'s` diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index 70e7e2df98a69..3d8b3eda044d4 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -11,7 +11,7 @@ #![feature(globs, lang_items)] #![no_std] // makes debugging this test *a lot* easier (during resolve) -#[lang = "sized"] pub trait Sized for Sized? {} +#[lang = "sized"] pub trait Sized {} #[lang="copy"] pub trait Copy {} // Test to make sure that private items imported through globs remain private diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index dd11ec645b42e..ae561878e9ba0 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -11,7 +11,7 @@ #![feature(lang_items)] #![no_std] -#[lang="sized"] pub trait Sized for Sized? {} +#[lang="sized"] pub trait Sized {} // error-pattern:requires `start` lang_item diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 06a934063927a..75f2a1744db15 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -18,7 +18,7 @@ trait Foo { fn dummy(&self, t: T, u: U, v: V); } -trait Eq for Sized? { } +trait Eq { } impl Eq for X { } fn eq() where A : Eq { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 16d6b217872ae..2b2327277a2d1 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -20,7 +20,7 @@ trait Foo { fn dummy(&self, t: T, u: U); } -trait Eq for Sized? { } +trait Eq { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index e08d84944c02a..9ec6428de27a0 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -20,7 +20,7 @@ trait Foo { fn dummy(&self, t: T, u: U); } -trait Eq for Sized? { } +trait Eq { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index a938f126c1607..a2225b0615b01 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -21,7 +21,7 @@ trait Foo<'a,T,U> { fn dummy(&'a self) -> &'a (T,U); } -trait Eq for Sized? { } +trait Eq { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 0a75240f2d89d..76a6f01b18322 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -20,7 +20,7 @@ fn f2(x: &X) { } // Bounded. -trait T for Sized? {} +trait T {} fn f3(x: &X) { f4::(x); //~^ ERROR the trait `core::kinds::Sized` is not implemented diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 0efd178f75b8c..4fcf7707f07fe 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -11,7 +11,7 @@ // Test `Sized?` local variables. -trait T for Sized? {} +trait T {} fn f1(x: &X) { let _: X; // <-- this is OK, no bindings created, no initializer. diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index c0e6ae1db92c4..e919f04971319 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -10,7 +10,7 @@ // Test sized-ness checking in substitution in impls. -trait T for Sized? {} +trait T {} // I would like these to fail eventually. // impl - bounded diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index 3b53203d218e0..213775d86f40d 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -18,7 +18,7 @@ use std::ops::Deref; -pub trait MyEq for Sized? { +pub trait MyEq { fn eq(&self, u: &U) -> bool; } diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs index 0fd477204215e..8f1523e736dc5 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs @@ -16,7 +16,7 @@ struct Splits<'a, T, P>; struct SplitsN; -trait SliceExt2 for Sized? { +trait SliceExt2 { type Item; fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs index f09c27029d7fa..f00c822bee0a5 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -16,7 +16,7 @@ struct Splits<'a, T, P>; struct SplitsN; -trait SliceExt2 for Sized? { +trait SliceExt2 { type Item; fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> From c26f5801f5bfca0840c7fc3e01e4c14f8437ef58 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 4 Jan 2015 21:47:03 -0500 Subject: [PATCH 069/106] remove unused `Sized` imports --- src/libcollections/str.rs | 1 - src/libcore/raw.rs | 1 - src/libcore/slice.rs | 1 - src/libstd/ascii.rs | 1 - 4 files changed, 4 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 0f33d21ef02c1..9ba1264f51e73 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -59,7 +59,6 @@ use core::char::CharExt; use core::clone::Clone; use core::iter::AdditiveIterator; use core::iter::{range, Iterator, IteratorExt}; -use core::kinds::Sized; use core::ops; use core::option::Option::{self, Some, None}; use core::slice::AsSlice; diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 0e91d6123f5cc..5ef6f6b2623aa 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -20,7 +20,6 @@ use kinds::Copy; use mem; -use kinds::Sized; /// The representation of a Rust slice #[repr(C)] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 9aa3f76b525e7..1fde906062ec4 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1372,7 +1372,6 @@ pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] { /// Operations on `[u8]`. #[experimental = "needs review"] pub mod bytes { - use kinds::Sized; use ptr; use slice::SliceExt; diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index c0b9bbbbc297d..abd4c7faa5bda 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -14,7 +14,6 @@ #![unstable = "unsure about placement and naming"] -use core::kinds::Sized; use iter::IteratorExt; use ops::FnMut; use slice::SliceExt; From eb50d3ee019d7914e491bc387206b0ff29e132bf Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 4 Jan 2015 21:48:57 -0500 Subject: [PATCH 070/106] undo one `for Sized?` removal that was in a comment --- src/librustc/middle/traits/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 8152f7e284fe4..ab8888f9a33eb 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -93,7 +93,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { // seen. This is necessary to prevent infinite // recursion in some cases. One common case is when // people define `trait Sized { }` rather than `trait - // Sized { }`. + // Sized for Sized? { }`. predicates.retain(|r| self.visited.insert(r.clone())); self.stack.push(StackEntry { position: 0, From bbf7e4e58a9b565342b5990cb3e750932a90a1b6 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 4 Jan 2015 23:20:17 -0500 Subject: [PATCH 071/106] update comment to reflect new `Sized` semantics --- src/librustc/middle/traits/util.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index ab8888f9a33eb..229d34fe4237c 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -92,8 +92,8 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { // Only keep those bounds that we haven't already // seen. This is necessary to prevent infinite // recursion in some cases. One common case is when - // people define `trait Sized { }` rather than `trait - // Sized for Sized? { }`. + // people define `trait Sized: Sized { }` rather than `trait + // Sized { }`. predicates.retain(|r| self.visited.insert(r.clone())); self.stack.push(StackEntry { position: 0, From 4ed2800701fa0634c2aa73e7b090e84be665166a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 5 Jan 2015 13:51:29 -0500 Subject: [PATCH 072/106] syntax: obsolete the `for Sized?` syntax --- src/libsyntax/parse/obsolete.rs | 6 ++++++ src/libsyntax/parse/parser.rs | 8 ++++++-- src/test/compile-fail/obsolete-for-sized.rs | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/obsolete-for-sized.rs diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index e1e456f880ed7..d63f432589dd1 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -24,6 +24,7 @@ use ptr::P; /// The specific types of unsupported syntax #[derive(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { + ObsoleteForSized, ObsoleteOwnedType, ObsoleteOwnedExpr, ObsoleteOwnedPattern, @@ -55,6 +56,11 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { + ObsoleteForSized => ( + "for Sized?", + "no longer required, traits apply to sized and unsized types by default, use \ + `: Sized` to opt-out of unsized types", + ), ObsoleteProcType => ( "the `proc` type", "use unboxed closures instead", diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cc67079e53879..aedfaac59c581 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5003,6 +5003,7 @@ impl<'a> Parser<'a> { // re-jigged shortly in any case, so leaving the hacky version for now. if self.eat_keyword(keywords::For) { let span = self.span; + let mut ate_question = false; if self.eat(&token::Question) { ate_question = true; @@ -5020,8 +5021,11 @@ impl<'a> Parser<'a> { "expected `?Sized` after `for` in trait item"); return None; } - let tref = Parser::trait_ref_from_ident(ident, span); - Some(tref) + let _tref = Parser::trait_ref_from_ident(ident, span); + + self.obsolete(span, ObsoleteForSized); + + None } else { None } diff --git a/src/test/compile-fail/obsolete-for-sized.rs b/src/test/compile-fail/obsolete-for-sized.rs new file mode 100644 index 0000000000000..1b86d08a50dff --- /dev/null +++ b/src/test/compile-fail/obsolete-for-sized.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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. + +// Test that we generate obsolete syntax errors around usages of `for Sized?` + +trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized? + +trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized? + +fn main() { } From 73806ddd0fd91066d7b903a00a080cbadcc04311 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Mon, 15 Sep 2014 19:29:47 -0700 Subject: [PATCH 073/106] Use $crate and macro reexport to reduce duplicated code Many of libstd's macros are now re-exported from libcore and libcollections. Their libstd definitions have moved to a macros_stage0 module and can disappear after the next snapshot. Where the two crates had already diverged, I took the libstd versions as they're generally newer and better-tested. See e.g. d3c831b, which was a fix to libstd's assert_eq!() that didn't make it into libcore's. Fixes #16806. --- src/libcollections/lib.rs | 3 + src/libcollections/macros.rs | 12 + src/libcore/fmt/mod.rs | 5 +- src/libcore/lib.rs | 1 + src/libcore/macros.rs | 199 +++++++- src/libstd/collections/hash/set.rs | 4 +- src/libstd/io/buffered.rs | 5 +- src/libstd/lib.rs | 12 +- src/libstd/macros.rs | 217 +-------- src/libstd/macros_stage0.rs | 649 ++++++++++++++++++++++++++ src/libstd/rand/os.rs | 5 +- src/libstd/time/duration.rs | 6 +- src/test/run-pass/vec-macro-no-std.rs | 39 ++ 13 files changed, 913 insertions(+), 244 deletions(-) create mode 100644 src/libstd/macros_stage0.rs create mode 100644 src/test/run-pass/vec-macro-no-std.rs diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index db2367950387b..27ab791b60425 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -51,6 +51,9 @@ pub use string::String; pub use vec::Vec; pub use vec_map::VecMap; +// Needed for the vec! macro +pub use alloc::boxed; + mod macros; pub mod binary_heap; diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index ce4b1e467739e..0dbc71269a670 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -11,6 +11,8 @@ #![macro_escape] /// Creates a `std::vec::Vec` containing the arguments. +// NOTE: remove after the next snapshot +#[cfg(stage0)] macro_rules! vec { ($($e:expr),*) => ({ // leading _ to allow empty construction without a warning. @@ -21,3 +23,13 @@ macro_rules! vec { ($($e:expr),+,) => (vec!($($e),+)) } +/// Creates a `Vec` containing the arguments. +#[cfg(not(stage0))] +#[macro_export] +macro_rules! vec { + ($($x:expr),*) => ({ + let xs: $crate::boxed::Box<[_]> = box [$($x),*]; + $crate::slice::SliceExt::into_vec(xs) + }); + ($($x:expr,)*) => (vec![$($x),*]) +} diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 102836f8d3024..b7c225c276ab9 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -20,12 +20,15 @@ use mem; use option::Option; use option::Option::{Some, None}; use ops::{Deref, FnOnce}; -use result::Result::{Ok, Err}; +use result::Result::Ok; use result; use slice::SliceExt; use slice; use str::{self, StrExt, Utf8Error}; +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::Err; + pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d646245510d50..0cda2e4a9c692 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -130,6 +130,7 @@ mod array; #[doc(hidden)] mod core { pub use panicking; + pub use fmt; } #[doc(hidden)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index e8fbd9d930f33..3b21a68a292f4 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -30,7 +30,26 @@ macro_rules! panic { }); } -/// Runtime assertion, for details see std::macros +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `panic!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// # Example +/// +/// ``` +/// // the panic message for these assertions is the stringified value of the +/// // expression given. +/// assert!(true); +/// # fn some_computation() -> bool { true } +/// assert!(some_computation()); +/// +/// // assert with a custom message +/// # let x = true; +/// assert!(x, "x wasn't true!"); +/// # let a = 3i; let b = 27i; +/// assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` #[macro_export] macro_rules! assert { ($cond:expr) => ( @@ -38,61 +57,197 @@ macro_rules! assert { panic!(concat!("assertion failed: ", stringify!($cond))) } ); - ($cond:expr, $($arg:tt)*) => ( + ($cond:expr, $($arg:expr),+) => ( if !$cond { - panic!($($arg)*) + panic!($($arg),+) } ); } -/// Runtime assertion for equality, for details see std::macros +/// Asserts that two expressions are equal to each other, testing equality in +/// both directions. +/// +/// On panic, this macro will print the values of the expressions. +/// +/// # Example +/// +/// ``` +/// let a = 3i; +/// let b = 1i + 2i; +/// assert_eq!(a, b); +/// ``` #[macro_export] macro_rules! assert_eq { - ($cond1:expr, $cond2:expr) => ({ - let c1 = $cond1; - let c2 = $cond2; - if c1 != c2 || c2 != c1 { - panic!("expressions not equal, left: {}, right: {}", c1, c2); + ($left:expr , $right:expr) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + // check both directions of equality.... + if !((*left_val == *right_val) && + (*right_val == *left_val)) { + panic!("assertion failed: `(left == right) && (right == left)` \ + (left: `{}`, right: `{}`)", *left_val, *right_val) + } + } } }) } -/// Runtime assertion for equality, only without `--cfg ndebug` +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `panic!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing +/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for +/// checks that are too expensive to be present in a release build but may be +/// helpful during development. +/// +/// # Example +/// +/// ``` +/// // the panic message for these assertions is the stringified value of the +/// // expression given. +/// debug_assert!(true); +/// # fn some_expensive_computation() -> bool { true } +/// debug_assert!(some_expensive_computation()); +/// +/// // assert with a custom message +/// # let x = true; +/// debug_assert!(x, "x wasn't true!"); +/// # let a = 3i; let b = 27i; +/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` +#[macro_export] +macro_rules! debug_assert { + ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) +} + +/// Asserts that two expressions are equal to each other, testing equality in +/// both directions. +/// +/// On panic, this macro will print the values of the expressions. +/// +/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by +/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` +/// useful for checks that are too expensive to be present in a release build +/// but may be helpful during development. +/// +/// # Example +/// +/// ``` +/// let a = 3i; +/// let b = 1i + 2i; +/// debug_assert_eq!(a, b); +/// ``` #[macro_export] macro_rules! debug_assert_eq { - ($($a:tt)*) => ({ - if cfg!(not(ndebug)) { - assert_eq!($($a)*); - } - }) + ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) } -/// Runtime assertion, disableable at compile time with `--cfg ndebug` +#[cfg(stage0)] #[macro_export] -macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) +macro_rules! try { + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) } /// Short circuiting evaluation on Err +/// +/// `libstd` contains a more general `try!` macro that uses `FromError`. +#[cfg(not(stage0))] #[macro_export] macro_rules! try { - ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) + ($e:expr) => ({ + use $crate::result::Result::{Ok, Err}; + + match $e { + Ok(e) => e, + Err(e) => return Err(e), + } + }) } -/// Writing a formatted string into a writer +/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// # #![allow(unused_must_use)] +/// +/// let mut w = Vec::new(); +/// write!(&mut w, "test"); +/// write!(&mut w, "formatted {}", "arguments"); +/// ``` #[macro_export] macro_rules! write { ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) } -/// Writing a formatted string plus a newline into a writer +/// Equivalent to the `write!` macro, except that a newline is appended after +/// the message is written. #[macro_export] +#[stable] macro_rules! writeln { ($dst:expr, $fmt:expr $($arg:tt)*) => ( write!($dst, concat!($fmt, "\n") $($arg)*) ) } +/// A utility macro for indicating unreachable code. +/// +/// This is useful any time that the compiler can't determine that some code is unreachable. For +/// example: +/// +/// * Match arms with guard conditions. +/// * Loops that dynamically terminate. +/// * Iterators that dynamically terminate. +/// +/// # Panics +/// +/// This will always panic. +/// +/// # Examples +/// +/// Match arms: +/// +/// ```rust +/// fn foo(x: Option) { +/// match x { +/// Some(n) if n >= 0 => println!("Some(Non-negative)"), +/// Some(n) if n < 0 => println!("Some(Negative)"), +/// Some(_) => unreachable!(), // compile error if commented out +/// None => println!("None") +/// } +/// } +/// ``` +/// +/// Iterators: +/// +/// ```rust +/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 +/// for i in std::iter::count(0_u32, 1) { +/// if 3*i < i { panic!("u32 overflow"); } +/// if x < 3*i { return i-1; } +/// } +/// unreachable!(); +/// } +/// ``` #[macro_export] -macro_rules! unreachable { () => (panic!("unreachable code")) } +macro_rules! unreachable { + () => ({ + panic!("internal error: entered unreachable code") + }); + ($msg:expr) => ({ + unreachable!("{}", $msg) + }); + ($fmt:expr, $($arg:tt)*) => ({ + panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + }); +} +/// A standardised placeholder for marking unfinished code. It panics with the +/// message `"not yet implemented"` when executed. +#[macro_export] +macro_rules! unimplemented { + () => (panic!("not yet implemented")) +} diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b1824db93aad1..b1906da43558f 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -21,7 +21,9 @@ use hash::{Hash, Hasher, RandomSipHasher}; use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend}; use ops::{BitOr, BitAnd, BitXor, Sub}; use option::Option::{Some, None, self}; -use result::Result::{Ok, Err}; + +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::{Ok, Err}; use super::map::{self, HashMap, Keys, INITIAL_CAPACITY}; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c56acd38e810f..0882efde232fe 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -18,11 +18,14 @@ use iter::ExactSizeIterator; use ops::Drop; use option::Option; use option::Option::{Some, None}; -use result::Result::{Ok, Err}; +use result::Result::Ok; use slice::{SliceExt}; use slice; use vec::Vec; +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::Err; + /// Wraps a Reader and buffers input from it /// /// It can be excessively inefficient to work directly with a `Reader`. For diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 608ad9882b977..eba90d39b4ab5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -117,13 +117,18 @@ #![reexport_test_harness_main = "test_main"] +#![macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq, + unreachable, unimplemented, write, writeln, vec)] + #[cfg(test)] #[phase(plugin, link)] extern crate log; -extern crate alloc; -extern crate unicode; +#[phase(plugin, link)] extern crate core; +#[phase(plugin, link)] extern crate "collections" as core_collections; extern crate "rand" as core_rand; +extern crate alloc; +extern crate unicode; extern crate libc; // Make std testable by not duplicating lang items. See #2912 @@ -167,7 +172,8 @@ pub use unicode::char; /* Exported macros */ -pub mod macros; +#[cfg(stage0)] pub mod macros_stage0; +#[cfg(not(stage0))] pub mod macros; pub mod bitflags; mod rtdeps; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 63fd3209cc019..e833acb968df3 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -57,179 +57,6 @@ macro_rules! panic { }); } -/// Ensure that a boolean expression is `true` at runtime. -/// -/// This will invoke the `panic!` macro if the provided expression cannot be -/// evaluated to `true` at runtime. -/// -/// # Example -/// -/// ``` -/// // the panic message for these assertions is the stringified value of the -/// // expression given. -/// assert!(true); -/// # fn some_computation() -> bool { true } -/// assert!(some_computation()); -/// -/// // assert with a custom message -/// # let x = true; -/// assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; -/// assert!(a + b == 30, "a = {}, b = {}", a, b); -/// ``` -#[macro_export] -macro_rules! assert { - ($cond:expr) => ( - if !$cond { - panic!(concat!("assertion failed: ", stringify!($cond))) - } - ); - ($cond:expr, $($arg:expr),+) => ( - if !$cond { - panic!($($arg),+) - } - ); -} - -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. -/// -/// On panic, this macro will print the values of the expressions. -/// -/// # Example -/// -/// ``` -/// let a = 3i; -/// let b = 1i + 2i; -/// assert_eq!(a, b); -/// ``` -#[macro_export] -macro_rules! assert_eq { - ($left:expr , $right:expr) => ({ - match (&($left), &($right)) { - (left_val, right_val) => { - // check both directions of equality.... - if !((*left_val == *right_val) && - (*right_val == *left_val)) { - panic!("assertion failed: `(left == right) && (right == left)` \ - (left: `{}`, right: `{}`)", *left_val, *right_val) - } - } - } - }) -} - -/// Ensure that a boolean expression is `true` at runtime. -/// -/// This will invoke the `panic!` macro if the provided expression cannot be -/// evaluated to `true` at runtime. -/// -/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing -/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for -/// checks that are too expensive to be present in a release build but may be -/// helpful during development. -/// -/// # Example -/// -/// ``` -/// // the panic message for these assertions is the stringified value of the -/// // expression given. -/// debug_assert!(true); -/// # fn some_expensive_computation() -> bool { true } -/// debug_assert!(some_expensive_computation()); -/// -/// // assert with a custom message -/// # let x = true; -/// debug_assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; -/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); -/// ``` -#[macro_export] -macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) -} - -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. -/// -/// On panic, this macro will print the values of the expressions. -/// -/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by -/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` -/// useful for checks that are too expensive to be present in a release build -/// but may be helpful during development. -/// -/// # Example -/// -/// ``` -/// let a = 3i; -/// let b = 1i + 2i; -/// debug_assert_eq!(a, b); -/// ``` -#[macro_export] -macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) -} - -/// A utility macro for indicating unreachable code. -/// -/// This is useful any time that the compiler can't determine that some code is unreachable. For -/// example: -/// -/// * Match arms with guard conditions. -/// * Loops that dynamically terminate. -/// * Iterators that dynamically terminate. -/// -/// # Panics -/// -/// This will always panic. -/// -/// # Examples -/// -/// Match arms: -/// -/// ```rust -/// fn foo(x: Option) { -/// match x { -/// Some(n) if n >= 0 => println!("Some(Non-negative)"), -/// Some(n) if n < 0 => println!("Some(Negative)"), -/// Some(_) => unreachable!(), // compile error if commented out -/// None => println!("None") -/// } -/// } -/// ``` -/// -/// Iterators: -/// -/// ```rust -/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 -/// for i in std::iter::count(0_u32, 1) { -/// if 3*i < i { panic!("u32 overflow"); } -/// if x < 3*i { return i-1; } -/// } -/// unreachable!(); -/// } -/// ``` -#[macro_export] -macro_rules! unreachable { - () => ({ - panic!("internal error: entered unreachable code") - }); - ($msg:expr) => ({ - unreachable!("{}", $msg) - }); - ($fmt:expr, $($arg:tt)*) => ({ - panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) - }); -} - -/// A standardised placeholder for marking unfinished code. It panics with the -/// message `"not yet implemented"` when executed. -#[macro_export] -macro_rules! unimplemented { - () => (panic!("not yet implemented")) -} - /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// @@ -246,34 +73,6 @@ macro_rules! format { ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) } -/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// # #![allow(unused_must_use)] -/// -/// let mut w = Vec::new(); -/// write!(&mut w, "test"); -/// write!(&mut w, "formatted {}", "arguments"); -/// ``` -#[macro_export] -#[stable] -macro_rules! write { - ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) -} - -/// Equivalent to the `write!` macro, except that a newline is appended after -/// the message is written. -#[macro_export] -#[stable] -macro_rules! writeln { - ($dst:expr, $fmt:expr $($arg:tt)*) => ( - write!($dst, concat!($fmt, "\n") $($arg)*) - ) -} - /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] @@ -306,23 +105,15 @@ macro_rules! println { #[macro_export] macro_rules! try { ($expr:expr) => ({ + use $crate::result::Result::{Ok, Err}; + match $expr { Ok(val) => val, - Err(err) => return Err(::std::error::FromError::from_error(err)) + Err(err) => return Err($crate::error::FromError::from_error(err)), } }) } -/// Create a `std::vec::Vec` containing the arguments. -#[macro_export] -macro_rules! vec { - ($($x:expr),*) => ({ - let xs: ::std::boxed::Box<[_]> = box [$($x),*]; - ::std::slice::SliceExt::into_vec(xs) - }); - ($($x:expr,)*) => (vec![$($x),*]) -} - /// A macro to select an event from a number of receivers. /// /// This macro is used to wait for the first event to occur on a number of @@ -358,7 +149,7 @@ macro_rules! select { ( $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ ) => ({ - use std::sync::mpsc::Select; + use $crate::sync::mpsc::Select; let sel = Select::new(); $( let mut $rx = sel.handle(&$rx); )+ unsafe { diff --git a/src/libstd/macros_stage0.rs b/src/libstd/macros_stage0.rs new file mode 100644 index 0000000000000..63fd3209cc019 --- /dev/null +++ b/src/libstd/macros_stage0.rs @@ -0,0 +1,649 @@ +// 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. + +//! Standard library macros +//! +//! This modules contains a set of macros which are exported from the standard +//! library. Each macro is available for use when linking against the standard +//! library. + +#![experimental] +#![macro_escape] + +/// The entry point for panic of Rust tasks. +/// +/// This macro is used to inject panic into a Rust task, causing the task to +/// unwind and panic entirely. Each task's panic can be reaped as the +/// `Box` type, and the single-argument form of the `panic!` macro will be +/// the value which is transmitted. +/// +/// The multi-argument form of this macro panics with a string and has the +/// `format!` syntax for building a string. +/// +/// # Example +/// +/// ```should_fail +/// # #![allow(unreachable_code)] +/// panic!(); +/// panic!("this is a terrible mistake!"); +/// panic!(4i); // panic with the value of 4 to be collected elsewhere +/// panic!("this is a {} {message}", "fancy", message = "message"); +/// ``` +#[macro_export] +macro_rules! panic { + () => ({ + panic!("explicit panic") + }); + ($msg:expr) => ({ + // static requires less code at runtime, more constant data + static _FILE_LINE: (&'static str, uint) = (file!(), line!()); + ::std::rt::begin_unwind($msg, &_FILE_LINE) + }); + ($fmt:expr, $($arg:tt)*) => ({ + // The leading _'s are to avoid dead code warnings if this is + // used inside a dead function. Just `#[allow(dead_code)]` is + // insufficient, since the user may have + // `#[forbid(dead_code)]` and which cannot be overridden. + static _FILE_LINE: (&'static str, uint) = (file!(), line!()); + ::std::rt::begin_unwind_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) + + }); +} + +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `panic!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// # Example +/// +/// ``` +/// // the panic message for these assertions is the stringified value of the +/// // expression given. +/// assert!(true); +/// # fn some_computation() -> bool { true } +/// assert!(some_computation()); +/// +/// // assert with a custom message +/// # let x = true; +/// assert!(x, "x wasn't true!"); +/// # let a = 3i; let b = 27i; +/// assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` +#[macro_export] +macro_rules! assert { + ($cond:expr) => ( + if !$cond { + panic!(concat!("assertion failed: ", stringify!($cond))) + } + ); + ($cond:expr, $($arg:expr),+) => ( + if !$cond { + panic!($($arg),+) + } + ); +} + +/// Asserts that two expressions are equal to each other, testing equality in +/// both directions. +/// +/// On panic, this macro will print the values of the expressions. +/// +/// # Example +/// +/// ``` +/// let a = 3i; +/// let b = 1i + 2i; +/// assert_eq!(a, b); +/// ``` +#[macro_export] +macro_rules! assert_eq { + ($left:expr , $right:expr) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + // check both directions of equality.... + if !((*left_val == *right_val) && + (*right_val == *left_val)) { + panic!("assertion failed: `(left == right) && (right == left)` \ + (left: `{}`, right: `{}`)", *left_val, *right_val) + } + } + } + }) +} + +/// Ensure that a boolean expression is `true` at runtime. +/// +/// This will invoke the `panic!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. +/// +/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing +/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for +/// checks that are too expensive to be present in a release build but may be +/// helpful during development. +/// +/// # Example +/// +/// ``` +/// // the panic message for these assertions is the stringified value of the +/// // expression given. +/// debug_assert!(true); +/// # fn some_expensive_computation() -> bool { true } +/// debug_assert!(some_expensive_computation()); +/// +/// // assert with a custom message +/// # let x = true; +/// debug_assert!(x, "x wasn't true!"); +/// # let a = 3i; let b = 27i; +/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); +/// ``` +#[macro_export] +macro_rules! debug_assert { + ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) +} + +/// Asserts that two expressions are equal to each other, testing equality in +/// both directions. +/// +/// On panic, this macro will print the values of the expressions. +/// +/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by +/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` +/// useful for checks that are too expensive to be present in a release build +/// but may be helpful during development. +/// +/// # Example +/// +/// ``` +/// let a = 3i; +/// let b = 1i + 2i; +/// debug_assert_eq!(a, b); +/// ``` +#[macro_export] +macro_rules! debug_assert_eq { + ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) +} + +/// A utility macro for indicating unreachable code. +/// +/// This is useful any time that the compiler can't determine that some code is unreachable. For +/// example: +/// +/// * Match arms with guard conditions. +/// * Loops that dynamically terminate. +/// * Iterators that dynamically terminate. +/// +/// # Panics +/// +/// This will always panic. +/// +/// # Examples +/// +/// Match arms: +/// +/// ```rust +/// fn foo(x: Option) { +/// match x { +/// Some(n) if n >= 0 => println!("Some(Non-negative)"), +/// Some(n) if n < 0 => println!("Some(Negative)"), +/// Some(_) => unreachable!(), // compile error if commented out +/// None => println!("None") +/// } +/// } +/// ``` +/// +/// Iterators: +/// +/// ```rust +/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 +/// for i in std::iter::count(0_u32, 1) { +/// if 3*i < i { panic!("u32 overflow"); } +/// if x < 3*i { return i-1; } +/// } +/// unreachable!(); +/// } +/// ``` +#[macro_export] +macro_rules! unreachable { + () => ({ + panic!("internal error: entered unreachable code") + }); + ($msg:expr) => ({ + unreachable!("{}", $msg) + }); + ($fmt:expr, $($arg:tt)*) => ({ + panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + }); +} + +/// A standardised placeholder for marking unfinished code. It panics with the +/// message `"not yet implemented"` when executed. +#[macro_export] +macro_rules! unimplemented { + () => (panic!("not yet implemented")) +} + +/// Use the syntax described in `std::fmt` to create a value of type `String`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10i, y = 30i); +/// ``` +#[macro_export] +#[stable] +macro_rules! format { + ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) +} + +/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. +/// See `std::fmt` for more information. +/// +/// # Example +/// +/// ``` +/// # #![allow(unused_must_use)] +/// +/// let mut w = Vec::new(); +/// write!(&mut w, "test"); +/// write!(&mut w, "formatted {}", "arguments"); +/// ``` +#[macro_export] +#[stable] +macro_rules! write { + ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) +} + +/// Equivalent to the `write!` macro, except that a newline is appended after +/// the message is written. +#[macro_export] +#[stable] +macro_rules! writeln { + ($dst:expr, $fmt:expr $($arg:tt)*) => ( + write!($dst, concat!($fmt, "\n") $($arg)*) + ) +} + +/// Equivalent to the `println!` macro except that a newline is not printed at +/// the end of the message. +#[macro_export] +#[stable] +macro_rules! print { + ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*))) +} + +/// Macro for printing to a task's stdout handle. +/// +/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. +/// The syntax of this macro is the same as that used for `format!`. For more +/// information, see `std::fmt` and `std::io::stdio`. +/// +/// # Example +/// +/// ``` +/// println!("hello there!"); +/// println!("format {} arguments", "some"); +/// ``` +#[macro_export] +#[stable] +macro_rules! println { + ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*))) +} + +/// Helper macro for unwrapping `Result` values while returning early with an +/// error if the value of the expression is `Err`. For more information, see +/// `std::io`. +#[macro_export] +macro_rules! try { + ($expr:expr) => ({ + match $expr { + Ok(val) => val, + Err(err) => return Err(::std::error::FromError::from_error(err)) + } + }) +} + +/// Create a `std::vec::Vec` containing the arguments. +#[macro_export] +macro_rules! vec { + ($($x:expr),*) => ({ + let xs: ::std::boxed::Box<[_]> = box [$($x),*]; + ::std::slice::SliceExt::into_vec(xs) + }); + ($($x:expr,)*) => (vec![$($x),*]) +} + +/// A macro to select an event from a number of receivers. +/// +/// This macro is used to wait for the first event to occur on a number of +/// receivers. It places no restrictions on the types of receivers given to +/// this macro, this can be viewed as a heterogeneous select. +/// +/// # Example +/// +/// ``` +/// use std::thread::Thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx1, rx1) = channel(); +/// let (tx2, rx2) = channel(); +/// # fn long_running_task() {} +/// # fn calculate_the_answer() -> int { 42i } +/// +/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach(); +/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); +/// +/// select! ( +/// _ = rx1.recv() => println!("the long running task finished first"), +/// answer = rx2.recv() => { +/// println!("the answer was: {}", answer.unwrap()); +/// } +/// ) +/// ``` +/// +/// For more information about select, see the `std::sync::mpsc::Select` structure. +#[macro_export] +#[experimental] +macro_rules! select { + ( + $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ + ) => ({ + use std::sync::mpsc::Select; + let sel = Select::new(); + $( let mut $rx = sel.handle(&$rx); )+ + unsafe { + $( $rx.add(); )+ + } + let ret = sel.wait(); + $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ + { unreachable!() } + }) +} + +// When testing the standard library, we link to the liblog crate to get the +// logging macros. In doing so, the liblog crate was linked against the real +// version of libstd, and uses a different std::fmt module than the test crate +// uses. To get around this difference, we redefine the log!() macro here to be +// just a dumb version of what it should be. +#[cfg(test)] +macro_rules! log { + ($lvl:expr, $($args:tt)*) => ( + if log_enabled!($lvl) { println!($($args)*) } + ) +} + +/// Built-in macros to the compiler itself. +/// +/// These macros do not have any corresponding definition with a `macro_rules!` +/// macro, but are documented here. Their implementations can be found hardcoded +/// into libsyntax itself. +#[cfg(dox)] +pub mod builtin { + /// The core macro for formatted string creation & output. + /// + /// This macro produces a value of type `fmt::Arguments`. This value can be + /// passed to the functions in `std::fmt` for performing useful functions. + /// All other formatting macros (`format!`, `write!`, `println!`, etc) are + /// proxied through this one. + /// + /// For more information, see the documentation in `std::fmt`. + /// + /// # Example + /// + /// ```rust + /// use std::fmt; + /// + /// let s = fmt::format(format_args!("hello {}", "world")); + /// assert_eq!(s, format!("hello {}", "world")); + /// + /// ``` + #[macro_export] + macro_rules! format_args { ($fmt:expr $($args:tt)*) => ({ + /* compiler built-in */ + }) } + + /// Inspect an environment variable at compile time. + /// + /// This macro will expand to the value of the named environment variable at + /// compile time, yielding an expression of type `&'static str`. + /// + /// If the environment variable is not defined, then a compilation error + /// will be emitted. To not emit a compile error, use the `option_env!` + /// macro instead. + /// + /// # Example + /// + /// ```rust + /// let path: &'static str = env!("PATH"); + /// println!("the $PATH variable at the time of compiling was: {}", path); + /// ``` + #[macro_export] + macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } + + /// Optionally inspect an environment variable at compile time. + /// + /// If the named environment variable is present at compile time, this will + /// expand into an expression of type `Option<&'static str>` whose value is + /// `Some` of the value of the environment variable. If the environment + /// variable is not present, then this will expand to `None`. + /// + /// A compile time error is never emitted when using this macro regardless + /// of whether the environment variable is present or not. + /// + /// # Example + /// + /// ```rust + /// let key: Option<&'static str> = option_env!("SECRET_KEY"); + /// println!("the secret key might be: {}", key); + /// ``` + #[macro_export] + macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } + + /// Concatenate literals into a static byte slice. + /// + /// This macro takes any number of comma-separated literal expressions, + /// yielding an expression of type `&'static [u8]` which is the + /// concatenation (left to right) of all the literals in their byte format. + /// + /// This extension currently only supports string literals, character + /// literals, and integers less than 256. The byte slice returned is the + /// utf8-encoding of strings and characters. + /// + /// # Example + /// + /// ``` + /// let rust = bytes!("r", 'u', "st", 255); + /// assert_eq!(rust[1], b'u'); + /// assert_eq!(rust[4], 255); + /// ``` + #[macro_export] + macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) } + + /// Concatenate identifiers into one identifier. + /// + /// This macro takes any number of comma-separated identifiers, and + /// concatenates them all into one, yielding an expression which is a new + /// identifier. Note that hygiene makes it such that this macro cannot + /// capture local variables, and macros are only allowed in item, + /// statement or expression position, meaning this macro may be difficult to + /// use in some situations. + /// + /// # Example + /// + /// ``` + /// #![feature(concat_idents)] + /// + /// # fn main() { + /// fn foobar() -> int { 23 } + /// + /// let f = concat_idents!(foo, bar); + /// println!("{}", f()); + /// # } + /// ``` + #[macro_export] + macro_rules! concat_idents { + ($($e:ident),*) => ({ /* compiler built-in */ }) + } + + /// Concatenates literals into a static string slice. + /// + /// This macro takes any number of comma-separated literals, yielding an + /// expression of type `&'static str` which represents all of the literals + /// concatenated left-to-right. + /// + /// Integer and floating point literals are stringified in order to be + /// concatenated. + /// + /// # Example + /// + /// ``` + /// let s = concat!("test", 10i, 'b', true); + /// assert_eq!(s, "test10btrue"); + /// ``` + #[macro_export] + macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } + + /// A macro which expands to the line number on which it was invoked. + /// + /// The expanded expression has type `uint`, and the returned line is not + /// the invocation of the `line!()` macro itself, but rather the first macro + /// invocation leading up to the invocation of the `line!()` macro. + /// + /// # Example + /// + /// ``` + /// let current_line = line!(); + /// println!("defined on line: {}", current_line); + /// ``` + #[macro_export] + macro_rules! line { () => ({ /* compiler built-in */ }) } + + /// A macro which expands to the column number on which it was invoked. + /// + /// The expanded expression has type `uint`, and the returned column is not + /// the invocation of the `column!()` macro itself, but rather the first macro + /// invocation leading up to the invocation of the `column!()` macro. + /// + /// # Example + /// + /// ``` + /// let current_col = column!(); + /// println!("defined on column: {}", current_col); + /// ``` + #[macro_export] + macro_rules! column { () => ({ /* compiler built-in */ }) } + + /// A macro which expands to the file name from which it was invoked. + /// + /// The expanded expression has type `&'static str`, and the returned file + /// is not the invocation of the `file!()` macro itself, but rather the + /// first macro invocation leading up to the invocation of the `file!()` + /// macro. + /// + /// # Example + /// + /// ``` + /// let this_file = file!(); + /// println!("defined in file: {}", this_file); + /// ``` + #[macro_export] + macro_rules! file { () => ({ /* compiler built-in */ }) } + + /// A macro which stringifies its argument. + /// + /// This macro will yield an expression of type `&'static str` which is the + /// stringification of all the tokens passed to the macro. No restrictions + /// are placed on the syntax of the macro invocation itself. + /// + /// # Example + /// + /// ``` + /// let one_plus_one = stringify!(1 + 1); + /// assert_eq!(one_plus_one, "1 + 1"); + /// ``` + #[macro_export] + macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } + + /// Includes a utf8-encoded file as a string. + /// + /// This macro will yield an expression of type `&'static str` which is the + /// contents of the filename specified. The file is located relative to the + /// current file (similarly to how modules are found), + /// + /// # Example + /// + /// ```rust,ignore + /// let secret_key = include_str!("secret-key.ascii"); + /// ``` + #[macro_export] + macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) } + + /// Includes a file as a byte slice. + /// + /// This macro will yield an expression of type `&'static [u8]` which is + /// the contents of the filename specified. The file is located relative to + /// the current file (similarly to how modules are found), + /// + /// # Example + /// + /// ```rust,ignore + /// let secret_key = include_bytes!("secret-key.bin"); + /// ``` + #[macro_export] + macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) } + + /// Deprecated alias for `include_bytes!()`. + #[macro_export] + macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */}) } + + /// Expands to a string that represents the current module path. + /// + /// The current module path can be thought of as the hierarchy of modules + /// leading back up to the crate root. The first component of the path + /// returned is the name of the crate currently being compiled. + /// + /// # Example + /// + /// ```rust + /// mod test { + /// pub fn foo() { + /// assert!(module_path!().ends_with("test")); + /// } + /// } + /// + /// test::foo(); + /// ``` + #[macro_export] + macro_rules! module_path { () => ({ /* compiler built-in */ }) } + + /// Boolean evaluation of configuration flags. + /// + /// In addition to the `#[cfg]` attribute, this macro is provided to allow + /// boolean expression evaluation of configuration flags. This frequently + /// leads to less duplicated code. + /// + /// The syntax given to this macro is the same syntax as the `cfg` + /// attribute. + /// + /// # Example + /// + /// ```rust + /// let my_directory = if cfg!(windows) { + /// "windows-specific-directory" + /// } else { + /// "unix-directory" + /// }; + /// ``` + #[macro_export] + macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) } +} diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 6ae6a238c952a..a79a6e35ebcfd 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -23,11 +23,14 @@ mod imp { use path::Path; use rand::Rng; use rand::reader::ReaderRng; - use result::Result::{Ok, Err}; + use result::Result::Ok; use slice::SliceExt; use mem; use os::errno; + // NOTE: for old macros; remove after the next snapshot + #[cfg(stage0)] use result::Result::Err; + #[cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "x86", diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index d48b0342b3bf7..ac1f0c5d803ac 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -17,8 +17,10 @@ use ops::{Add, Sub, Mul, Div, Neg, FnOnce}; use option::Option; use option::Option::{Some, None}; use num::Int; -use result::Result; -use result::Result::{Ok, Err}; +use result::Result::Ok; + +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::Err; /// The number of nanoseconds in a microsecond. const NANOS_PER_MICRO: i32 = 1000; diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs new file mode 100644 index 0000000000000..b01cad43603a9 --- /dev/null +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -0,0 +1,39 @@ +// 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. + +#![feature(phase, lang_items)] +#![no_std] + +#[phase(plugin, link)] +extern crate core; +extern crate libc; + +#[phase(plugin, link)] +extern crate collections; + +use core::option::Option::Some; +use core::slice::SliceExt; +use collections::vec::Vec; + +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } + +// Issue #16806 + +#[start] +fn start(_argc: int, _argv: *const *const u8) -> int { + let x: Vec = vec![0, 1, 2]; + match x.last() { + Some(&2) => (), + _ => panic!(), + } + 0 +} From fc584793237c388e9dca76ef406d1af34e453fe2 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 18 Dec 2014 20:09:57 -0800 Subject: [PATCH 074/106] Stop using macro_escape as an inner attribute In preparation for the rename. --- src/libcollections/lib.rs | 1 + src/libcollections/macros.rs | 2 -- src/libcore/lib.rs | 15 ++++++++++++--- src/libcore/macros.rs | 2 -- src/libcore/num/float_macros.rs | 1 - src/libcore/num/int_macros.rs | 1 - src/libcore/num/uint_macros.rs | 1 - src/libcoretest/num/int_macros.rs | 2 -- src/libcoretest/num/mod.rs | 5 +++++ src/libcoretest/num/uint_macros.rs | 2 -- src/liblog/lib.rs | 2 ++ src/liblog/macros.rs | 2 -- src/librustc/lint/mod.rs | 2 -- src/librustc_trans/trans/macros.rs | 2 -- src/librustc_trans/trans/mod.rs | 4 +++- src/librustdoc/lib.rs | 5 +++-- src/libstd/bitflags.rs | 1 - src/libstd/io/mod.rs | 4 +++- src/libstd/io/test.rs | 2 -- src/libstd/lib.rs | 27 ++++++++++++++++++++++----- src/libstd/macros.rs | 1 - src/libstd/macros_stage0.rs | 1 - src/libstd/num/float_macros.rs | 1 - src/libstd/num/int_macros.rs | 1 - src/libstd/num/uint_macros.rs | 1 - src/libstd/rt/macros.rs | 2 -- src/libstd/thread_local/mod.rs | 2 +- src/libstd/thread_local/scoped.rs | 1 - src/libsyntax/diagnostics/macros.rs | 2 -- src/libsyntax/parse/mod.rs | 4 +++- src/libsyntax/parse/parser.rs | 2 -- src/test/auxiliary/lint_stability.rs | 1 - 32 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 27ab791b60425..9214ec7e65b4c 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -54,6 +54,7 @@ pub use vec_map::VecMap; // Needed for the vec! macro pub use alloc::boxed; +#[macro_escape] mod macros; pub mod binary_heap; diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 0dbc71269a670..0c5929e8661d6 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - /// Creates a `std::vec::Vec` containing the arguments. // NOTE: remove after the next snapshot #[cfg(stage0)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0cda2e4a9c692..588421dfa10ba 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -62,11 +62,20 @@ #![feature(default_type_params, unboxed_closures, associated_types)] #![deny(missing_docs)] +#[macro_escape] mod macros; -#[path = "num/float_macros.rs"] mod float_macros; -#[path = "num/int_macros.rs"] mod int_macros; -#[path = "num/uint_macros.rs"] mod uint_macros; +#[path = "num/float_macros.rs"] +#[macro_escape] +mod float_macros; + +#[path = "num/int_macros.rs"] +#[macro_escape] +mod int_macros; + +#[path = "num/uint_macros.rs"] +#[macro_escape] +mod uint_macros; #[path = "num/int.rs"] pub mod int; #[path = "num/i8.rs"] pub mod i8; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 3b21a68a292f4..a579f9db4161c 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - /// Entry point of task panic, for details, see std::macros #[macro_export] macro_rules! panic { diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs index 97de61d7e272e..20300d29fa0c5 100644 --- a/src/libcore/num/float_macros.rs +++ b/src/libcore/num/float_macros.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] #![doc(hidden)] macro_rules! assert_approx_eq { diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 522eab9180c86..61cd8cbf7c101 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] #![doc(hidden)] macro_rules! int_module { ($T:ty, $bits:expr) => ( diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 82eca0d465982..535765840a0fc 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] #![doc(hidden)] macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => ( diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 8885d3a52082c..965ffde70970b 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - macro_rules! int_module (($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 651e8640e912a..01868675c7615 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -14,13 +14,18 @@ use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::kinds::Copy; +#[macro_escape] mod int_macros; + mod i8; mod i16; mod i32; mod i64; mod int; + +#[macro_escape] mod uint_macros; + mod u8; mod u16; mod u32; diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 2311c19d5573a..eff238c816eee 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - macro_rules! uint_module (($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 0508402ff19d8..61523c6fd0fb9 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -183,7 +183,9 @@ use regex::Regex; use directive::LOG_LEVEL_NAMES; +#[macro_escape] pub mod macros; + mod directive; /// Maximum logging level of a module that can be specified. Common logging diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 233d1c049f4e5..66682dba7b6df 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -10,8 +10,6 @@ //! Logging macros -#![macro_escape] - /// The standard logging macro /// /// This macro will generically log over a provided level (of type u32) with a diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 461a67ba93793..e9778fa05ff17 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -28,8 +28,6 @@ //! example) requires more effort. See `emit_lint` and `GatherNodeLevels` //! in `context.rs`. -#![macro_escape] - pub use self::Level::*; pub use self::LintSource::*; diff --git a/src/librustc_trans/trans/macros.rs b/src/librustc_trans/trans/macros.rs index ab202975bfc15..77efcc6fb0030 100644 --- a/src/librustc_trans/trans/macros.rs +++ b/src/librustc_trans/trans/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - macro_rules! unpack_datum { ($bcx: ident, $inp: expr) => ( { diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 72c4def15a215..9b7f282f8bb4b 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -16,8 +16,10 @@ pub use self::base::trans_crate; pub use self::context::CrateContext; pub use self::common::gensym_name; -mod doc; +#[macro_escape] mod macros; + +mod doc; mod inline; mod monomorphize; mod controlflow; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 106fe452f46a6..a454760c8b5df 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -49,11 +49,12 @@ use rustc::session::search_paths::SearchPaths; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; +#[macro_escape] +pub mod externalfiles; + pub mod clean; pub mod core; pub mod doctree; -#[macro_escape] -pub mod externalfiles; pub mod fold; pub mod html { pub mod highlight; diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index 65cbce08543cc..ed3f2cbe1a1da 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -9,7 +9,6 @@ // except according to those terms. #![experimental] -#![macro_escape] //! A typesafe bitmask flag generator. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 3fa0b5645c528..bf373a145e4cc 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -282,10 +282,12 @@ pub mod net; pub mod pipe; pub mod process; pub mod stdio; -pub mod test; pub mod timer; pub mod util; +#[macro_escape] +pub mod test; + /// The default buffer size for various I/O operations // libuv recommends 64k buffers to maximize throughput // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 3ce56c907b33d..6eeef175f73d5 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -10,8 +10,6 @@ //! Various utility functions useful for writing I/O tests -#![macro_escape] - use prelude::v1::*; use libc; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index eba90d39b4ab5..5ffd3ebc7ad21 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -172,8 +172,15 @@ pub use unicode::char; /* Exported macros */ -#[cfg(stage0)] pub mod macros_stage0; -#[cfg(not(stage0))] pub mod macros; +#[cfg(stage0)] +#[macro_escape] +pub mod macros_stage0; + +#[cfg(not(stage0))] +#[macro_escape] +pub mod macros; + +#[macro_escape] pub mod bitflags; mod rtdeps; @@ -185,9 +192,17 @@ pub mod prelude; /* Primitive types */ -#[path = "num/float_macros.rs"] mod float_macros; -#[path = "num/int_macros.rs"] mod int_macros; -#[path = "num/uint_macros.rs"] mod uint_macros; +#[path = "num/float_macros.rs"] +#[macro_escape] +mod float_macros; + +#[path = "num/int_macros.rs"] +#[macro_escape] +mod int_macros; + +#[path = "num/uint_macros.rs"] +#[macro_escape] +mod uint_macros; #[path = "num/int.rs"] pub mod int; #[path = "num/i8.rs"] pub mod i8; @@ -214,7 +229,9 @@ pub mod num; /* Runtime and platform support */ +#[macro_escape] pub mod thread_local; + pub mod c_str; pub mod c_vec; pub mod dynamic_lib; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index e833acb968df3..6bf1ba2355f8d 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -15,7 +15,6 @@ //! library. #![experimental] -#![macro_escape] /// The entry point for panic of Rust tasks. /// diff --git a/src/libstd/macros_stage0.rs b/src/libstd/macros_stage0.rs index 63fd3209cc019..48d62e73e13ed 100644 --- a/src/libstd/macros_stage0.rs +++ b/src/libstd/macros_stage0.rs @@ -15,7 +15,6 @@ //! library. #![experimental] -#![macro_escape] /// The entry point for panic of Rust tasks. /// diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs index fd00f15662a72..4c52f29b12d76 100644 --- a/src/libstd/num/float_macros.rs +++ b/src/libstd/num/float_macros.rs @@ -9,7 +9,6 @@ // except according to those terms. #![experimental] -#![macro_escape] #![doc(hidden)] macro_rules! assert_approx_eq { diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index fce150c4ad1e3..ebcb20861879c 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -9,7 +9,6 @@ // except according to those terms. #![experimental] -#![macro_escape] #![doc(hidden)] macro_rules! int_module { ($T:ty) => ( diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 7818f4a053497..08ea1b024c993 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -9,7 +9,6 @@ // except according to those terms. #![experimental] -#![macro_escape] #![doc(hidden)] #![allow(unsigned_negation)] diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs index 0f35500a04a73..bbc96d0b19f12 100644 --- a/src/libstd/rt/macros.rs +++ b/src/libstd/rt/macros.rs @@ -13,8 +13,6 @@ //! These macros call functions which are only accessible in the `rt` module, so //! they aren't defined anywhere outside of the `rt` module. -#![macro_escape] - macro_rules! rterrln { ($fmt:expr $($arg:tt)*) => ( { ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*)) diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index d3b4fab96810b..1ed01c034b53f 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -34,13 +34,13 @@ //! will want to make use of some form of **interior mutability** through the //! `Cell` or `RefCell` types. -#![macro_escape] #![stable] use prelude::v1::*; use cell::UnsafeCell; +#[macro_escape] pub mod scoped; // Sure wish we had macro hygiene, no? diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index dc36fda3a020e..714b71d5dbd4e 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -38,7 +38,6 @@ //! }); //! ``` -#![macro_escape] #![unstable = "scoped TLS has yet to have wide enough use to fully consider \ stabilizing its interface"] diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 3107508a96a5c..34a193dffd3db 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - #[macro_export] macro_rules! register_diagnostic { ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 3e4f2c8d4e237..05ed535ee36b1 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,8 +24,10 @@ use std::num::Int; use std::str; use std::iter; -pub mod lexer; +#[macro_escape] pub mod parser; + +pub mod lexer; pub mod token; pub mod attr; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 62bda20473f76..5539abb16b461 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - pub use self::PathParsingMode::*; use self::ItemOrViewItem::*; diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 82af18b189b68..5ef1acae6c7ed 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -11,7 +11,6 @@ #![crate_type = "lib"] #![feature(macro_rules)] -#![macro_escape] #[deprecated] pub fn deprecated() {} From 5bf385be6a5ce267ac7cd9d1725178488e33131c Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 18 Dec 2014 20:48:26 -0800 Subject: [PATCH 075/106] Rename macro_escape to macro_use In the future we want to support #[macro_use(foo, bar)] mod macros; but it's not an essential part of macro reform. Reserve the syntax for now. --- src/libcollections/lib.rs | 3 +- src/libcore/lib.rs | 12 +++-- src/libcoretest/num/mod.rs | 6 ++- src/liblog/lib.rs | 3 +- src/librustc_driver/driver.rs | 2 +- src/librustc_trans/trans/mod.rs | 3 +- src/librustdoc/lib.rs | 3 +- src/libstd/io/mod.rs | 3 +- src/libstd/lib.rs | 21 ++++++--- src/libstd/rt/mod.rs | 2 + src/libstd/thread_local/mod.rs | 3 +- src/libsyntax/ext/expand.rs | 45 +++++++++++-------- src/libsyntax/parse/mod.rs | 3 +- .../module-macro_use-arguments.rs | 16 +++++++ src/test/run-pass/cfg-macros-foo.rs | 4 +- src/test/run-pass/cfg-macros-notfoo.rs | 4 +- .../run-pass/deprecated-macro_escape-inner.rs | 19 ++++++++ src/test/run-pass/deprecated-macro_escape.rs | 18 ++++++++ 18 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 src/test/compile-fail/module-macro_use-arguments.rs create mode 100644 src/test/run-pass/deprecated-macro_escape-inner.rs create mode 100644 src/test/run-pass/deprecated-macro_escape.rs diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 9214ec7e65b4c..142ac6f34e02f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -54,7 +54,8 @@ pub use vec_map::VecMap; // Needed for the vec! macro pub use alloc::boxed; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; pub mod binary_heap; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 588421dfa10ba..aff0065c52744 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -62,19 +62,23 @@ #![feature(default_type_params, unboxed_closures, associated_types)] #![deny(missing_docs)] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; #[path = "num/float_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod float_macros; #[path = "num/int_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod int_macros; #[path = "num/uint_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod uint_macros; #[path = "num/int.rs"] pub mod int; diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 01868675c7615..f86c85f821638 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -14,7 +14,8 @@ use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::kinds::Copy; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod int_macros; mod i8; @@ -23,7 +24,8 @@ mod i32; mod i64; mod int; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod uint_macros; mod u8; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 61523c6fd0fb9..c210873563c5d 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -183,7 +183,8 @@ use regex::Regex; use directive::LOG_LEVEL_NAMES; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod macros; mod directive; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 5056ada6a8c11..027af6619ab91 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -182,7 +182,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // strip before expansion to allow macros to depend on // configuration variables e.g/ in // - // #[macro_escape] #[cfg(foo)] + // #[macro_use] #[cfg(foo)] // mod bar { macro_rules! baz!(() => {{}}) } // // baz! should not use this definition unless foo is enabled. diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 9b7f282f8bb4b..fa9cd5a698bbe 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -16,7 +16,8 @@ pub use self::base::trans_crate; pub use self::context::CrateContext; pub use self::common::gensym_name; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; mod doc; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a454760c8b5df..319eee8731772 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -49,7 +49,8 @@ use rustc::session::search_paths::SearchPaths; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod externalfiles; pub mod clean; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index bf373a145e4cc..e9386c30a6dad 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -285,7 +285,8 @@ pub mod stdio; pub mod timer; pub mod util; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod test; /// The default buffer size for various I/O operations diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5ffd3ebc7ad21..abe968849c2b8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -173,14 +173,17 @@ pub use unicode::char; /* Exported macros */ #[cfg(stage0)] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod macros_stage0; #[cfg(not(stage0))] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod macros; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod bitflags; mod rtdeps; @@ -193,15 +196,18 @@ pub mod prelude; /* Primitive types */ #[path = "num/float_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod float_macros; #[path = "num/int_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod int_macros; #[path = "num/uint_macros.rs"] -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod uint_macros; #[path = "num/int.rs"] pub mod int; @@ -229,7 +235,8 @@ pub mod num; /* Runtime and platform support */ -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod thread_local; pub mod c_str; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 2b0639c570537..e556888a470a2 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -39,6 +39,8 @@ pub use alloc::heap; pub mod backtrace; // Internals +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; // These should be refactored/moved/made private over time diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 1ed01c034b53f..e0cbaa8ca50ed 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -40,7 +40,8 @@ use prelude::v1::*; use cell::UnsafeCell; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod scoped; // Sure wish we had macro hygiene, no? diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d4be46d025ecf..13cbc83f73070 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -440,9 +440,9 @@ pub fn expand_item(it: P, fld: &mut MacroExpander) if valid_ident { fld.cx.mod_push(it.ident); } - let macro_escape = contains_macro_escape(new_attrs[]); + let macro_use = contains_macro_use(fld, new_attrs[]); let result = with_exts_frame!(fld.cx.syntax_env, - macro_escape, + macro_use, noop_fold_item(it, fld)); if valid_ident { fld.cx.mod_pop(); @@ -522,9 +522,28 @@ fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Ite } } -// does this attribute list contain "macro_escape" ? -fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { - attr::contains_name(attrs, "macro_escape") +// does this attribute list contain "macro_use" ? +fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool { + for attr in attrs.iter() { + let mut is_use = attr.check_name("macro_use"); + if attr.check_name("macro_escape") { + fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use"); + is_use = true; + if let ast::AttrInner = attr.node.style { + fld.cx.span_help(attr.span, "consider an outer attribute, \ + #[macro_use] mod ..."); + } + }; + + if is_use { + match attr.node.value.node { + ast::MetaWord(..) => (), + _ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"), + } + return true; + } + } + false } // Support for item-position macro invocations, exactly the same @@ -1299,7 +1318,7 @@ impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> { #[cfg(test)] mod test { - use super::{pattern_bindings, expand_crate, contains_macro_escape}; + use super::{pattern_bindings, expand_crate, contains_macro_use}; use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig}; use ast; use ast::{Attribute_, AttrOuter, MetaWord, Name}; @@ -1396,9 +1415,9 @@ mod test { expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); } - // macro_escape modules should allow macros to escape + // macro_use modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { - let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\ + let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1408,16 +1427,6 @@ mod test { expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast); } - #[test] fn test_contains_flatten (){ - let attr1 = make_dummy_attr ("foo"); - let attr2 = make_dummy_attr ("bar"); - let escape_attr = make_dummy_attr ("macro_escape"); - let attrs1 = vec!(attr1.clone(), escape_attr, attr2.clone()); - assert_eq!(contains_macro_escape(attrs1[]),true); - let attrs2 = vec!(attr1,attr2); - assert_eq!(contains_macro_escape(attrs2[]),false); - } - // make a MetaWord outer attribute with the given name fn make_dummy_attr(s: &str) -> ast::Attribute { Spanned { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 05ed535ee36b1..ee7edceaf6969 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,7 +24,8 @@ use std::num::Int; use std::str; use std::iter; -#[macro_escape] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod parser; pub mod lexer; diff --git a/src/test/compile-fail/module-macro_use-arguments.rs b/src/test/compile-fail/module-macro_use-arguments.rs new file mode 100644 index 0000000000000..6d3038b4820d6 --- /dev/null +++ b/src/test/compile-fail/module-macro_use-arguments.rs @@ -0,0 +1,16 @@ +// 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. +// +// 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. + +#[macro_use(foo, bar)] //~ ERROR arguments to macro_use are not allowed here +mod foo { +} + +fn main() { +} diff --git a/src/test/run-pass/cfg-macros-foo.rs b/src/test/run-pass/cfg-macros-foo.rs index ec9ef38150136..548057e9e6050 100644 --- a/src/test/run-pass/cfg-macros-foo.rs +++ b/src/test/run-pass/cfg-macros-foo.rs @@ -16,7 +16,7 @@ #![feature(macro_rules)] #[cfg(foo)] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { true } @@ -24,7 +24,7 @@ mod foo { } #[cfg(not(foo))] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { false } diff --git a/src/test/run-pass/cfg-macros-notfoo.rs b/src/test/run-pass/cfg-macros-notfoo.rs index fb44176ec2212..bf4f7e6bc403b 100644 --- a/src/test/run-pass/cfg-macros-notfoo.rs +++ b/src/test/run-pass/cfg-macros-notfoo.rs @@ -16,7 +16,7 @@ #![feature(macro_rules)] #[cfg(foo)] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { true } @@ -24,7 +24,7 @@ mod foo { } #[cfg(not(foo))] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { false } diff --git a/src/test/run-pass/deprecated-macro_escape-inner.rs b/src/test/run-pass/deprecated-macro_escape-inner.rs new file mode 100644 index 0000000000000..7960a91bdc4fc --- /dev/null +++ b/src/test/run-pass/deprecated-macro_escape-inner.rs @@ -0,0 +1,19 @@ +// 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. +// +// 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-pretty + +mod foo { + #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use + //~^ HELP consider an outer attribute +} + +fn main() { +} diff --git a/src/test/run-pass/deprecated-macro_escape.rs b/src/test/run-pass/deprecated-macro_escape.rs new file mode 100644 index 0000000000000..b03905e1a0d63 --- /dev/null +++ b/src/test/run-pass/deprecated-macro_escape.rs @@ -0,0 +1,18 @@ +// 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. +// +// 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-pretty + +#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use +mod foo { +} + +fn main() { +} From 5171b325bd2c5600649cc98e65db0ef2e72c3f89 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 20 Dec 2014 22:36:50 -0800 Subject: [PATCH 076/106] creader: Convert free functions to Env methods --- src/librustc/metadata/creader.rs | 531 ++++++++++++++++--------------- 1 file changed, 267 insertions(+), 264 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index b0cf322b0688e..7d716135efe60 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -35,6 +35,7 @@ use syntax::parse::token::InternedString; use syntax::parse::token; use syntax::visit; use util::fs; +use log; struct Env<'a> { sess: &'a Session, @@ -49,9 +50,11 @@ pub fn read_crates(sess: &Session, sess: sess, next_crate_num: sess.cstore.next_crate_num(), }; - visit_crate(&e, krate); + e.visit_crate(krate); visit::walk_crate(&mut e, krate); - dump_crates(&sess.cstore); + if log_enabled!(log::DEBUG) { + dump_crates(&sess.cstore); + } warn_if_multiple_versions(sess.diagnostic(), &sess.cstore); for &(ref name, kind) in sess.opts.libs.iter() { @@ -61,11 +64,11 @@ pub fn read_crates(sess: &Session, impl<'a, 'v> visit::Visitor<'v> for Env<'a> { fn visit_view_item(&mut self, a: &ast::ViewItem) { - visit_view_item(self, a); + self.process_view_item(a); visit::walk_view_item(self, a); } fn visit_item(&mut self, a: &ast::Item) { - visit_item(self, a); + self.process_item(a); visit::walk_item(self, a); } } @@ -105,15 +108,6 @@ fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) { } } -fn visit_crate(e: &Env, c: &ast::Crate) { - for a in c.attrs.iter().filter(|m| m.name() == "link_args") { - match a.value_str() { - Some(ref linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()), - None => { /* fallthrough */ } - } - } -} - fn should_link(i: &ast::ViewItem) -> bool { i.attrs.iter().all(|attr| { attr.name().get() != "phase" || @@ -123,26 +117,6 @@ fn should_link(i: &ast::ViewItem) -> bool { }) } -fn visit_view_item(e: &mut Env, i: &ast::ViewItem) { - if !should_link(i) { - return; - } - - match extract_crate_info(e, i) { - Some(info) => { - let (cnum, _, _) = resolve_crate(e, - &None, - info.ident[], - info.name[], - None, - i.span, - PathKind::Crate); - e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); - } - None => () - } -} - struct CrateInfo { ident: String, name: String, @@ -150,32 +124,6 @@ struct CrateInfo { should_link: bool, } -fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option { - match i.node { - ast::ViewItemExternCrate(ident, ref path_opt, id) => { - let ident = token::get_ident(ident); - debug!("resolving extern crate stmt. ident: {} path_opt: {}", - ident, path_opt); - let name = match *path_opt { - Some((ref path_str, _)) => { - let name = path_str.get().to_string(); - validate_crate_name(Some(e.sess), name[], - Some(i.span)); - name - } - None => ident.get().to_string(), - }; - Some(CrateInfo { - ident: ident.get().to_string(), - name: name, - id: id, - should_link: should_link(i), - }) - } - _ => None - } -} - pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { let err = |&: s: &str| { match (sp, sess) { @@ -198,85 +146,6 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { } } -fn visit_item(e: &Env, i: &ast::Item) { - match i.node { - ast::ItemForeignMod(ref fm) => { - if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic { - return; - } - - // First, add all of the custom link_args attributes - let link_args = i.attrs.iter() - .filter_map(|at| if at.name() == "link_args" { - Some(at) - } else { - None - }) - .collect::>(); - for m in link_args.iter() { - match m.value_str() { - Some(linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()), - None => { /* fallthrough */ } - } - } - - // Next, process all of the #[link(..)]-style arguments - let link_args = i.attrs.iter() - .filter_map(|at| if at.name() == "link" { - Some(at) - } else { - None - }) - .collect::>(); - for m in link_args.iter() { - match m.meta_item_list() { - Some(items) => { - let kind = items.iter().find(|k| { - k.name() == "kind" - }).and_then(|a| a.value_str()); - let kind = match kind { - Some(k) => { - if k == "static" { - cstore::NativeStatic - } else if e.sess.target.target.options.is_like_osx - && k == "framework" { - cstore::NativeFramework - } else if k == "framework" { - cstore::NativeFramework - } else if k == "dylib" { - cstore::NativeUnknown - } else { - e.sess.span_err(m.span, - format!("unknown kind: `{}`", - k)[]); - cstore::NativeUnknown - } - } - None => cstore::NativeUnknown - }; - let n = items.iter().find(|n| { - n.name() == "name" - }).and_then(|a| a.value_str()); - let n = match n { - Some(n) => n, - None => { - e.sess.span_err(m.span, - "#[link(...)] specified without \ - `name = \"foo\"`"); - InternedString::new("foo") - } - }; - register_native_lib(e.sess, Some(m.span), - n.get().to_string(), kind); - } - None => {} - } - } - } - _ => { } - } -} - fn register_native_lib(sess: &Session, span: Option, name: String, @@ -304,143 +173,278 @@ fn register_native_lib(sess: &Session, sess.cstore.add_used_library(name, kind); } -fn existing_match(e: &Env, name: &str, - hash: Option<&Svh>) -> Option { - let mut ret = None; - e.sess.cstore.iter_crate_data(|cnum, data| { - if data.name != name { return } +impl<'a> Env<'a> { + fn visit_crate(&self, c: &ast::Crate) { + for a in c.attrs.iter().filter(|m| m.name() == "link_args") { + match a.value_str() { + Some(ref linkarg) => self.sess.cstore.add_used_link_args(linkarg.get()), + None => { /* fallthrough */ } + } + } + } + + fn process_view_item(&mut self, i: &ast::ViewItem) { + if !should_link(i) { + return; + } + + match self.extract_crate_info(i) { + Some(info) => { + let (cnum, _, _) = self.resolve_crate(&None, + info.ident[], + info.name[], + None, + i.span, + PathKind::Crate); + self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); + } + None => () + } + } - match hash { - Some(hash) if *hash == data.hash() => { ret = Some(cnum); return } - Some(..) => return, - None => {} + fn extract_crate_info(&self, i: &ast::ViewItem) -> Option { + match i.node { + ast::ViewItemExternCrate(ident, ref path_opt, id) => { + let ident = token::get_ident(ident); + debug!("resolving extern crate stmt. ident: {} path_opt: {}", + ident, path_opt); + let name = match *path_opt { + Some((ref path_str, _)) => { + let name = path_str.get().to_string(); + validate_crate_name(Some(self.sess), name[], + Some(i.span)); + name + } + None => ident.get().to_string(), + }; + Some(CrateInfo { + ident: ident.get().to_string(), + name: name, + id: id, + should_link: should_link(i), + }) + } + _ => None } + } + + fn process_item(&self, i: &ast::Item) { + match i.node { + ast::ItemForeignMod(ref fm) => { + if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic { + return; + } + + // First, add all of the custom link_args attributes + let link_args = i.attrs.iter() + .filter_map(|at| if at.name() == "link_args" { + Some(at) + } else { + None + }) + .collect::>(); + for m in link_args.iter() { + match m.value_str() { + Some(linkarg) => self.sess.cstore.add_used_link_args(linkarg.get()), + None => { /* fallthrough */ } + } + } - // When the hash is None we're dealing with a top-level dependency in - // which case we may have a specification on the command line for this - // library. Even though an upstream library may have loaded something of - // the same name, we have to make sure it was loaded from the exact same - // location as well. - // - // We're also sure to compare *paths*, not actual byte slices. The - // `source` stores paths which are normalized which may be different - // from the strings on the command line. - let source = e.sess.cstore.get_used_crate_source(cnum).unwrap(); - match e.sess.opts.externs.get(name) { - Some(locs) => { - let found = locs.iter().any(|l| { - let l = fs::realpath(&Path::new(l[])).ok(); - l == source.dylib || l == source.rlib - }); - if found { - ret = Some(cnum); + // Next, process all of the #[link(..)]-style arguments + let link_args = i.attrs.iter() + .filter_map(|at| if at.name() == "link" { + Some(at) + } else { + None + }) + .collect::>(); + for m in link_args.iter() { + match m.meta_item_list() { + Some(items) => { + let kind = items.iter().find(|k| { + k.name() == "kind" + }).and_then(|a| a.value_str()); + let kind = match kind { + Some(k) => { + if k == "static" { + cstore::NativeStatic + } else if self.sess.target.target.options.is_like_osx + && k == "framework" { + cstore::NativeFramework + } else if k == "framework" { + cstore::NativeFramework + } else if k == "dylib" { + cstore::NativeUnknown + } else { + self.sess.span_err(m.span, + format!("unknown kind: `{}`", + k)[]); + cstore::NativeUnknown + } + } + None => cstore::NativeUnknown + }; + let n = items.iter().find(|n| { + n.name() == "name" + }).and_then(|a| a.value_str()); + let n = match n { + Some(n) => n, + None => { + self.sess.span_err(m.span, + "#[link(...)] specified without \ + `name = \"foo\"`"); + InternedString::new("foo") + } + }; + register_native_lib(self.sess, Some(m.span), + n.get().to_string(), kind); + } + None => {} + } } } - None => ret = Some(cnum), + _ => { } } - }); - return ret; -} + } -fn register_crate<'a>(e: &mut Env, - root: &Option, - ident: &str, - name: &str, - span: Span, - lib: loader::Library) - -> (ast::CrateNum, Rc, - cstore::CrateSource) { - // Claim this crate number and cache it - let cnum = e.next_crate_num; - e.next_crate_num += 1; - - // Stash paths for top-most crate locally if necessary. - let crate_paths = if root.is_none() { - Some(CratePaths { - ident: ident.to_string(), - dylib: lib.dylib.clone(), - rlib: lib.rlib.clone(), - }) - } else { - None - }; - // Maintain a reference to the top most crate. - let root = if root.is_some() { root } else { &crate_paths }; + fn existing_match(&self, name: &str, + hash: Option<&Svh>) -> Option { + let mut ret = None; + self.sess.cstore.iter_crate_data(|cnum, data| { + if data.name != name { return } + + match hash { + Some(hash) if *hash == data.hash() => { ret = Some(cnum); return } + Some(..) => return, + None => {} + } + + // When the hash is None we're dealing with a top-level dependency in + // which case we may have a specification on the command line for this + // library. Even though an upstream library may have loaded something of + // the same name, we have to make sure it was loaded from the exact same + // location as well. + // + // We're also sure to compare *paths*, not actual byte slices. The + // `source` stores paths which are normalized which may be different + // from the strings on the command line. + let source = self.sess.cstore.get_used_crate_source(cnum).unwrap(); + match self.sess.opts.externs.get(name) { + Some(locs) => { + let found = locs.iter().any(|l| { + let l = fs::realpath(&Path::new(l[])).ok(); + l == source.dylib || l == source.rlib + }); + if found { + ret = Some(cnum); + } + } + None => ret = Some(cnum), + } + }); + return ret; + } - let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span); + fn register_crate(&mut self, + root: &Option, + ident: &str, + name: &str, + span: Span, + lib: loader::Library) + -> (ast::CrateNum, Rc, + cstore::CrateSource) { + // Claim this crate number and cache it + let cnum = self.next_crate_num; + self.next_crate_num += 1; + + // Stash paths for top-most crate locally if necessary. + let crate_paths = if root.is_none() { + Some(CratePaths { + ident: ident.to_string(), + dylib: lib.dylib.clone(), + rlib: lib.rlib.clone(), + }) + } else { + None + }; + // Maintain a reference to the top most crate. + let root = if root.is_some() { root } else { &crate_paths }; - let loader::Library{ dylib, rlib, metadata } = lib; + let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span); - let cmeta = Rc::new( cstore::crate_metadata { - name: name.to_string(), - data: metadata, - cnum_map: cnum_map, - cnum: cnum, - span: span, - }); + let loader::Library{ dylib, rlib, metadata } = lib; - let source = cstore::CrateSource { - dylib: dylib, - rlib: rlib, - cnum: cnum, - }; + let cmeta = Rc::new( cstore::crate_metadata { + name: name.to_string(), + data: metadata, + cnum_map: cnum_map, + cnum: cnum, + span: span, + }); - e.sess.cstore.set_crate_data(cnum, cmeta.clone()); - e.sess.cstore.add_used_crate_source(source.clone()); - (cnum, cmeta, source) -} + let source = cstore::CrateSource { + dylib: dylib, + rlib: rlib, + cnum: cnum, + }; + + self.sess.cstore.set_crate_data(cnum, cmeta.clone()); + self.sess.cstore.add_used_crate_source(source.clone()); + (cnum, cmeta, source) + } -fn resolve_crate(e: &mut Env, - root: &Option, - ident: &str, - name: &str, - hash: Option<&Svh>, - span: Span, - kind: PathKind) - -> (ast::CrateNum, Rc, - cstore::CrateSource) { - match existing_match(e, name, hash) { - None => { - let mut load_ctxt = loader::Context { - sess: e.sess, - span: span, - ident: ident, - crate_name: name, - hash: hash.map(|a| &*a), - filesearch: e.sess.target_filesearch(kind), - triple: e.sess.opts.target_triple[], - root: root, - rejected_via_hash: vec!(), - rejected_via_triple: vec!(), - should_match_name: true, - }; - let library = load_ctxt.load_library_crate(); - register_crate(e, root, ident, name, span, library) + fn resolve_crate(&mut self, + root: &Option, + ident: &str, + name: &str, + hash: Option<&Svh>, + span: Span, + kind: PathKind) + -> (ast::CrateNum, Rc, + cstore::CrateSource) { + match self.existing_match(name, hash) { + None => { + let mut load_ctxt = loader::Context { + sess: self.sess, + span: span, + ident: ident, + crate_name: name, + hash: hash.map(|a| &*a), + filesearch: self.sess.target_filesearch(kind), + triple: self.sess.opts.target_triple[], + root: root, + rejected_via_hash: vec!(), + rejected_via_triple: vec!(), + should_match_name: true, + }; + let library = load_ctxt.load_library_crate(); + self.register_crate(root, ident, name, span, library) + } + Some(cnum) => (cnum, + self.sess.cstore.get_crate_data(cnum), + self.sess.cstore.get_used_crate_source(cnum).unwrap()) } - Some(cnum) => (cnum, - e.sess.cstore.get_crate_data(cnum), - e.sess.cstore.get_used_crate_source(cnum).unwrap()) } -} -// Go through the crate metadata and load any crates that it references -fn resolve_crate_deps(e: &mut Env, - root: &Option, - cdata: &[u8], span : Span) - -> cstore::cnum_map { - debug!("resolving deps of external crate"); - // The map from crate numbers in the crate we're resolving to local crate - // numbers - decoder::get_crate_deps(cdata).iter().map(|dep| { - debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); - let (local_cnum, _, _) = resolve_crate(e, root, - dep.name[], - dep.name[], - Some(&dep.hash), - span, - PathKind::Dependency); - (dep.cnum, local_cnum) - }).collect() + // Go through the crate metadata and load any crates that it references + fn resolve_crate_deps(&mut self, + root: &Option, + cdata: &[u8], span : Span) + -> cstore::cnum_map { + debug!("resolving deps of external crate"); + // The map from crate numbers in the crate we're resolving to local crate + // numbers + decoder::get_crate_deps(cdata).iter().map(|dep| { + debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); + let (local_cnum, _, _) = self.resolve_crate(root, + dep.name[], + dep.name[], + Some(&dep.hash), + span, + PathKind::Dependency); + (dep.cnum, local_cnum) + }).collect() + } } pub struct PluginMetadataReader<'a> { @@ -459,7 +463,7 @@ impl<'a> PluginMetadataReader<'a> { pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata { - let info = extract_crate_info(&self.env, krate).unwrap(); + let info = self.env.extract_crate_info(krate).unwrap(); let target_triple = self.env.sess.opts.target_triple[]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; @@ -516,11 +520,10 @@ impl<'a> PluginMetadataReader<'a> { macros: macros, registrar_symbol: registrar, }; - if should_link && existing_match(&self.env, info.name[], - None).is_none() { + if should_link && self.env.existing_match(info.name[], None).is_none() { // register crate now to avoid double-reading metadata - register_crate(&mut self.env, &None, info.ident[], - info.name[], krate.span, library); + self.env.register_crate(&None, info.ident[], + info.name[], krate.span, library); } pc } From 24aa7f0e387e2a04795e80bc91b8b8adf6a1c98f Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 20 Dec 2014 23:02:38 -0800 Subject: [PATCH 077/106] creader: Use a single struct --- src/librustc/metadata/creader.rs | 94 ++++++++++++++------------------ src/librustc/plugin/load.rs | 6 +- src/librustc_driver/driver.rs | 4 +- 3 files changed, 46 insertions(+), 58 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 7d716135efe60..2e6dbf077eed1 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -37,32 +37,12 @@ use syntax::visit; use util::fs; use log; -struct Env<'a> { +pub struct CrateReader<'a> { sess: &'a Session, next_crate_num: ast::CrateNum, } -// Traverses an AST, reading all the information about use'd crates and extern -// libraries necessary for later resolving, typechecking, linking, etc. -pub fn read_crates(sess: &Session, - krate: &ast::Crate) { - let mut e = Env { - sess: sess, - next_crate_num: sess.cstore.next_crate_num(), - }; - e.visit_crate(krate); - visit::walk_crate(&mut e, krate); - if log_enabled!(log::DEBUG) { - dump_crates(&sess.cstore); - } - warn_if_multiple_versions(sess.diagnostic(), &sess.cstore); - - for &(ref name, kind) in sess.opts.libs.iter() { - register_native_lib(sess, None, name.clone(), kind); - } -} - -impl<'a, 'v> visit::Visitor<'v> for Env<'a> { +impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> { fn visit_view_item(&mut self, a: &ast::ViewItem) { self.process_view_item(a); visit::walk_view_item(self, a); @@ -173,8 +153,31 @@ fn register_native_lib(sess: &Session, sess.cstore.add_used_library(name, kind); } -impl<'a> Env<'a> { - fn visit_crate(&self, c: &ast::Crate) { +impl<'a> CrateReader<'a> { + pub fn new(sess: &'a Session) -> CrateReader<'a> { + CrateReader { + sess: sess, + next_crate_num: sess.cstore.next_crate_num(), + } + } + + // Traverses an AST, reading all the information about use'd crates and extern + // libraries necessary for later resolving, typechecking, linking, etc. + pub fn read_crates(&mut self, krate: &ast::Crate) { + self.process_crate(krate); + visit::walk_crate(self, krate); + + if log_enabled!(log::DEBUG) { + dump_crates(&self.sess.cstore); + } + warn_if_multiple_versions(self.sess.diagnostic(), &self.sess.cstore); + + for &(ref name, kind) in self.sess.opts.libs.iter() { + register_native_lib(self.sess, None, name.clone(), kind); + } + } + + fn process_crate(&self, c: &ast::Crate) { for a in c.attrs.iter().filter(|m| m.name() == "link_args") { match a.value_str() { Some(ref linkarg) => self.sess.cstore.add_used_link_args(linkarg.get()), @@ -445,35 +448,20 @@ impl<'a> Env<'a> { (dep.cnum, local_cnum) }).collect() } -} - -pub struct PluginMetadataReader<'a> { - env: Env<'a>, -} - -impl<'a> PluginMetadataReader<'a> { - pub fn new(sess: &'a Session) -> PluginMetadataReader<'a> { - PluginMetadataReader { - env: Env { - sess: sess, - next_crate_num: sess.cstore.next_crate_num(), - } - } - } pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata { - let info = self.env.extract_crate_info(krate).unwrap(); - let target_triple = self.env.sess.opts.target_triple[]; + let info = self.extract_crate_info(krate).unwrap(); + let target_triple = self.sess.opts.target_triple[]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; let mut load_ctxt = loader::Context { - sess: self.env.sess, + sess: self.sess, span: krate.span, ident: info.ident[], crate_name: info.name[], hash: None, - filesearch: self.env.sess.host_filesearch(PathKind::Crate), + filesearch: self.sess.host_filesearch(PathKind::Crate), triple: config::host_triple(), root: &None, rejected_via_hash: vec!(), @@ -486,17 +474,17 @@ impl<'a> PluginMetadataReader<'a> { // try loading from target crates (only valid if there are // no syntax extensions) load_ctxt.triple = target_triple; - load_ctxt.filesearch = self.env.sess.target_filesearch(PathKind::Crate); + load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); let lib = load_ctxt.load_library_crate(); if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() { let message = format!("crate `{}` contains a plugin_registrar fn but \ - only a version for triple `{}` could be found (need {})", - info.ident, target_triple, config::host_triple()); - self.env.sess.span_err(krate.span, message[]); + only a version for triple `{}` could be found (need {})", + info.ident, target_triple, config::host_triple()); + self.sess.span_err(krate.span, message[]); // need to abort now because the syntax expansion // code will shortly attempt to load and execute // code from the found library. - self.env.sess.abort_if_errors(); + self.sess.abort_if_errors(); } should_link = info.should_link; lib @@ -510,8 +498,8 @@ impl<'a> PluginMetadataReader<'a> { if library.dylib.is_none() && registrar.is_some() { let message = format!("plugin crate `{}` only found in rlib format, \ but must be available in dylib format", - info.ident); - self.env.sess.span_err(krate.span, message[]); + info.ident); + self.sess.span_err(krate.span, message[]); // No need to abort because the loading code will just ignore this // empty dylib. } @@ -520,10 +508,10 @@ impl<'a> PluginMetadataReader<'a> { macros: macros, registrar_symbol: registrar, }; - if should_link && self.env.existing_match(info.name[], None).is_none() { + if should_link && self.existing_match(info.name[], None).is_none() { // register crate now to avoid double-reading metadata - self.env.register_crate(&None, info.ident[], - info.name[], krate.span, library); + self.register_crate(&None, info.ident[], + info.name[], krate.span, library); } pc } diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index a2e334543206c..19d7c24c9536f 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -11,7 +11,7 @@ //! Used by `rustc` when loading a plugin. use session::Session; -use metadata::creader::PluginMetadataReader; +use metadata::creader::CrateReader; use plugin::registry::Registry; use std::mem; @@ -48,7 +48,7 @@ pub struct Plugins { struct PluginLoader<'a> { sess: &'a Session, - reader: PluginMetadataReader<'a>, + reader: CrateReader<'a>, plugins: Plugins, } @@ -56,7 +56,7 @@ impl<'a> PluginLoader<'a> { fn new(sess: &'a Session) -> PluginLoader<'a> { PluginLoader { sess: sess, - reader: PluginMetadataReader::new(sess), + reader: CrateReader::new(sess), plugins: Plugins { macros: vec!(), registrars: vec!(), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 027af6619ab91..f23cddf833cc9 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -12,7 +12,7 @@ use rustc::session::Session; use rustc::session::config::{self, Input, OutputFilenames}; use rustc::session::search_paths::PathKind; use rustc::lint; -use rustc::metadata::creader; +use rustc::metadata::creader::CrateReader; use rustc::middle::{stability, ty, reachable}; use rustc::middle::dependency_format; use rustc::middle; @@ -354,7 +354,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let krate = ast_map.krate(); time(time_passes, "external crate/lib resolution", (), |_| - creader::read_crates(&sess, krate)); + CrateReader::new(&sess).read_crates(krate)); let lang_items = time(time_passes, "language item collection", (), |_| middle::lang_items::collect_language_items(krate, &sess)); From 677b7cad3d0ca1347f65ae9b409078343a5f302e Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Tue, 30 Dec 2014 19:10:46 -0800 Subject: [PATCH 078/106] Reformat metadata for exported macros Instead of copy-pasting the whole macro_rules! item from the original .rs file, we serialize a separate name, attributes list, and body, the latter as pretty-printed TTs. The compilation of macro_rules! macros is decoupled somewhat from the expansion of macros in item position. This filters out comments, and facilitates selective imports. --- src/librustc/metadata/common.rs | 8 +++-- src/librustc/metadata/creader.rs | 40 ++++++++++++++++++--- src/librustc/metadata/decoder.rs | 15 ++++---- src/librustc/metadata/encoder.rs | 35 +++++++++--------- src/librustc/plugin/load.rs | 33 +++++++---------- src/librustdoc/visit_ast.rs | 14 ++++---- src/libsyntax/ast.rs | 15 +++++++- src/libsyntax/ext/base.rs | 22 +----------- src/libsyntax/ext/expand.rs | 55 ++++++++++++----------------- src/libsyntax/ext/tt/macro_rules.rs | 29 ++++++--------- src/libsyntax/fold.rs | 6 +++- src/libsyntax/parse/mod.rs | 4 +++ 12 files changed, 143 insertions(+), 133 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index ca7c65c8e2bc2..de9a09ffe44c1 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -206,8 +206,8 @@ pub const tag_native_libraries_name: uint = 0x89; pub const tag_native_libraries_kind: uint = 0x8a; pub const tag_plugin_registrar_fn: uint = 0x8b; -pub const tag_exported_macros: uint = 0x8c; -pub const tag_macro_def: uint = 0x8d; + +// GAP 0x8c, 0x8d pub const tag_method_argument_names: uint = 0x8e; pub const tag_method_argument_name: uint = 0x8f; @@ -261,3 +261,7 @@ pub const tag_associated_type_names: uint = 0xb2; pub const tag_associated_type_name: uint = 0xb3; pub const tag_polarity: uint = 0xb4; + +pub const tag_macro_defs: uint = 0xb5; +pub const tag_macro_def: uint = 0xb6; +pub const tag_macro_def_body: uint = 0xb7; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 2e6dbf077eed1..3bf0e41ae9caa 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -29,8 +29,9 @@ use syntax::ast; use syntax::abi; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::codemap::{Span}; +use syntax::codemap::{Span, mk_sp}; use syntax::diagnostic::SpanHandler; +use syntax::parse; use syntax::parse::token::InternedString; use syntax::parse::token; use syntax::visit; @@ -491,7 +492,36 @@ impl<'a> CrateReader<'a> { } None => { load_ctxt.report_load_errs(); unreachable!() }, }; - let macros = decoder::get_exported_macros(library.metadata.as_slice()); + + // Read exported macros + let imported_from = Some(token::intern(info.ident[]).ident()); + let source_name = format!("<{} macros>", info.ident[]); + let mut macros = vec![]; + decoder::each_exported_macro(library.metadata.as_slice(), &*self.sess.cstore.intr, + |name, attrs, body| { + // NB: Don't use parse::parse_tts_from_source_str because it parses with + // quote_depth > 0. + let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess, + self.sess.opts.cfg.clone(), + source_name.clone(), + body); + let lo = p.span.lo; + let body = p.parse_all_token_trees(); + let span = mk_sp(lo, p.last_span.hi); + p.abort_if_errors(); + macros.push(ast::MacroDef { + ident: name.ident(), + attrs: attrs, + id: ast::DUMMY_NODE_ID, + span: span, + imported_from: imported_from, + body: body, + }); + true + } + ); + + // Look for a plugin registrar let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| { decoder::get_symbol(library.metadata.as_slice(), id) }); @@ -504,9 +534,11 @@ impl<'a> CrateReader<'a> { // empty dylib. } let pc = PluginMetadata { - lib: library.dylib.clone(), macros: macros, - registrar_symbol: registrar, + registrar: match (library.dylib.as_ref(), registrar) { + (Some(dylib), Some(reg)) => Some((dylib.clone(), reg)), + _ => None, + }, }; if should_link && self.existing_match(info.name[], None).is_none() { // register crate now to avoid double-reading metadata diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 97f5228f0330b..0e1fbcfcb891e 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1353,15 +1353,16 @@ pub fn get_plugin_registrar_fn(data: &[u8]) -> Option { .map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap()) } -pub fn get_exported_macros(data: &[u8]) -> Vec { - let macros = reader::get_doc(rbml::Doc::new(data), - tag_exported_macros); - let mut result = Vec::new(); +pub fn each_exported_macro(data: &[u8], intr: &IdentInterner, mut f: F) where + F: FnMut(ast::Name, Vec, String) -> bool, +{ + let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs); reader::tagged_docs(macros, tag_macro_def, |macro_doc| { - result.push(macro_doc.as_str().to_string()); - true + let name = item_name(intr, macro_doc); + let attrs = get_attributes(macro_doc); + let body = reader::get_doc(macro_doc, tag_macro_def_body); + f(name, attrs, body.as_str().to_string()) }); - result } pub fn get_dylib_dependency_formats(cdata: Cmd) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 59679f0bc7cd0..37f0692631757 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -42,6 +42,7 @@ use syntax::attr::AttrMetaMethods; use syntax::diagnostic::SpanHandler; use syntax::parse::token::special_idents; use syntax::parse::token; +use syntax::print::pprust; use syntax::ptr::P; use syntax::visit::Visitor; use syntax::visit; @@ -1818,25 +1819,21 @@ fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) { } } -/// Given a span, write the text of that span into the output stream -/// as an exported macro -fn encode_macro_def(ecx: &EncodeContext, - rbml_w: &mut Encoder, - span: &syntax::codemap::Span) { - let def = ecx.tcx.sess.codemap().span_to_snippet(*span) - .expect("Unable to find source for macro"); - rbml_w.start_tag(tag_macro_def); - rbml_w.wr_str(def[]); - rbml_w.end_tag(); -} - /// Serialize the text of the exported macros -fn encode_macro_defs(ecx: &EncodeContext, - krate: &ast::Crate, - rbml_w: &mut Encoder) { - rbml_w.start_tag(tag_exported_macros); - for item in krate.exported_macros.iter() { - encode_macro_def(ecx, rbml_w, &item.span); +fn encode_macro_defs(rbml_w: &mut Encoder, + krate: &ast::Crate) { + rbml_w.start_tag(tag_macro_defs); + for def in krate.exported_macros.iter() { + rbml_w.start_tag(tag_macro_def); + + encode_name(rbml_w, def.ident.name); + encode_attributes(rbml_w, def.attrs[]); + + rbml_w.start_tag(tag_macro_def_body); + rbml_w.wr_str(pprust::tts_to_string(def.body[])[]); + rbml_w.end_tag(); + + rbml_w.end_tag(); } rbml_w.end_tag(); } @@ -2154,7 +2151,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, // Encode macro definitions i = rbml_w.writer.tell().unwrap(); - encode_macro_defs(&ecx, krate, &mut rbml_w); + encode_macro_defs(&mut rbml_w, krate); stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i; // Encode the types of all unboxed closures in this crate. diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 19d7c24c9536f..9aa7d8fe9906d 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Used by `rustc` when loading a plugin. +//! Used by `rustc` when loading a plugin, or a crate with exported macros. use session::Session; use metadata::creader::CrateReader; @@ -21,17 +21,14 @@ use syntax::ast; use syntax::attr; use syntax::visit; use syntax::visit::Visitor; -use syntax::ext::expand::ExportedMacros; use syntax::attr::AttrMetaMethods; -/// Plugin-related crate metadata. +/// Metadata for a single plugin crate. pub struct PluginMetadata { - /// Source code of macros exported by the crate. - pub macros: Vec, - /// Path to the shared library file. - pub lib: Option, - /// Symbol name of the plugin registrar function. - pub registrar_symbol: Option, + /// Macros exported by the crate. + pub macros: Vec, + /// Path to the shared library file, and registrar function symbol. + pub registrar: Option<(Path, String)>, } /// Pointer to a registrar function. @@ -40,8 +37,8 @@ pub type PluginRegistrarFun = /// Information about loaded plugins. pub struct Plugins { - /// Source code of exported macros. - pub macros: Vec, + /// Imported macros. + pub macros: Vec, /// Registrars, as function pointers. pub registrars: Vec, } @@ -90,7 +87,7 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { fn visit_view_item(&mut self, vi: &ast::ViewItem) { match vi.node { - ast::ViewItemExternCrate(name, _, _) => { + ast::ViewItemExternCrate(_, _, _) => { let mut plugin_phase = false; for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) { @@ -107,17 +104,13 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { if !plugin_phase { return; } - let PluginMetadata { macros, lib, registrar_symbol } = + let PluginMetadata { macros, registrar } = self.reader.read_plugin_metadata(vi); - self.plugins.macros.push(ExportedMacros { - crate_name: name, - macros: macros, - }); + self.plugins.macros.extend(macros.into_iter()); - match (lib, registrar_symbol) { - (Some(lib), Some(symbol)) - => self.dylink_registrar(vi, lib, symbol), + match registrar { + Some((lib, symbol)) => self.dylink_registrar(vi, lib, symbol), _ => (), } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c98ec97ab87f0..ad67672ea6ea7 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { None); // attach the crate's exported macros to the top-level module: self.module.macros = krate.exported_macros.iter() - .map(|it| self.visit_macro(&**it)).collect(); + .map(|def| self.visit_macro(def)).collect(); self.module.is_crate = true; } @@ -363,13 +363,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } // convert each exported_macro into a doc item - fn visit_macro(&self, item: &ast::Item) -> Macro { + fn visit_macro(&self, def: &ast::MacroDef) -> Macro { Macro { - id: item.id, - attrs: item.attrs.clone(), - name: item.ident, - whence: item.span, - stab: self.stability(item.id), + id: def.id, + attrs: def.attrs.clone(), + name: def.ident, + whence: def.span, + stab: self.stability(def.id), } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 55aa73b4faaee..36fc8a691dc30 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -476,7 +476,7 @@ pub struct Crate { pub attrs: Vec, pub config: CrateConfig, pub span: Span, - pub exported_macros: Vec> + pub exported_macros: Vec, } pub type MetaItem = Spanned; @@ -1698,6 +1698,19 @@ pub enum InlinedItem { IIForeign(P), } +/// A macro definition, in this crate or imported from another. +/// +/// Not parsed directly, but created on macro import or `macro_rules!` expansion. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct MacroDef { + pub ident: Ident, + pub attrs: Vec, + pub id: NodeId, + pub span: Span, + pub imported_from: Option, + pub body: Vec, +} + #[cfg(test)] mod test { use serialize::json; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 4b38e6c0cb231..9a06745967f0d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -28,19 +28,6 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; -// new-style macro! tt code: -// -// MacResult, NormalTT, IdentTT -// -// also note that ast::Mac used to have a bunch of extraneous cases and -// is now probably a redundant AST node, can be merged with -// ast::MacInvocTT. - -pub struct MacroDef { - pub name: String, - pub ext: SyntaxExtension -} - pub trait ItemDecorator { fn expand(&self, ecx: &mut ExtCtxt, @@ -140,13 +127,6 @@ impl IdentMacroExpander for F /// methods are spliced into the AST at the callsite of the macro (or /// just into the compiler's internal macro table, for `make_def`). pub trait MacResult { - /// Attempt to define a new macro. - // this should go away; the idea that a macro might expand into - // either a macro definition or an expression, depending on what - // the context wants, is kind of silly. - fn make_def(&mut self) -> Option { - None - } /// Create an expression. fn make_expr(self: Box) -> Option> { None @@ -469,7 +449,7 @@ pub struct ExtCtxt<'a> { pub mod_path: Vec , pub trace_mac: bool, - pub exported_macros: Vec>, + pub exported_macros: Vec, pub syntax_env: SyntaxEnv, pub recursion_count: uint, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 13cbc83f73070..d56df2d7fb4e0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -432,7 +432,7 @@ pub fn expand_item(it: P, fld: &mut MacroExpander) } let mut new_items = match it.node { - ast::ItemMac(..) => expand_item_mac(it, None, fld), + ast::ItemMac(..) => expand_item_mac(it, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { let valid_ident = it.ident.name != parse::token::special_idents::invalid.name; @@ -549,7 +549,6 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. pub fn expand_item_mac(it: P, - imported_from: Option, fld: &mut MacroExpander) -> SmallVector> { let (extname, path_span, tts) = match it.node { ItemMac(codemap::Spanned { @@ -630,18 +629,20 @@ pub fn expand_item_mac(it: P, } }); // DON'T mark before expansion. - let MacroDef { name, ext } - = macro_rules::add_new_extension(fld.cx, it.span, it.ident, - imported_from, tts); - - fld.cx.syntax_env.insert(intern(name.as_slice()), ext); - - if match imported_from { - None => attr::contains_name(it.attrs.as_slice(), "macro_export"), - Some(_) => fld.cx.ecfg.reexported_macros.iter() - .any(|e| e.as_slice() == name.as_slice()), - } { - fld.cx.exported_macros.push(it); + + let def = ast::MacroDef { + ident: it.ident, + attrs: it.attrs.clone(), + id: ast::DUMMY_NODE_ID, + span: it.span, + imported_from: None, + body: tts, + }; + let ext = macro_rules::compile(fld.cx, &def); + fld.cx.syntax_env.insert(def.ident.name, ext); + + if attr::contains_name(def.attrs.as_slice(), "macro_export") { + fld.cx.exported_macros.push(def); } // macro_rules! has a side effect but expands to nothing. @@ -680,9 +681,6 @@ pub fn expand_item_mac(it: P, } /// Expand a stmt -// -// I don't understand why this returns a vector... it looks like we're -// half done adding machinery to allow macros to expand into multiple statements. fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector> { let (mac, style) = match s.node { StmtMac(mac, style) => (mac, style), @@ -1195,30 +1193,23 @@ impl ExpansionConfig { } } -pub struct ExportedMacros { - pub crate_name: Ident, - pub macros: Vec, -} - pub fn expand_crate(parse_sess: &parse::ParseSess, cfg: ExpansionConfig, // these are the macros being imported to this crate: - imported_macros: Vec, + imported_macros: Vec, user_exts: Vec, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander::new(&mut cx); - for ExportedMacros { crate_name, macros } in imported_macros.into_iter() { - let name = format!("<{} macros>", token::get_ident(crate_name)); + for def in imported_macros.iter() { + let ext = macro_rules::compile(expander.cx, def); + expander.cx.syntax_env.insert(def.ident.name, ext); + + if expander.cx.ecfg.reexported_macros.iter() + .any(|e| e[] == token::get_ident(def.ident).get()) { - for source in macros.into_iter() { - let item = parse::parse_item_from_source_str(name.clone(), - source, - expander.cx.cfg(), - expander.cx.parse_sess()) - .expect("expected a serialized item"); - expand_item_mac(item, Some(crate_name), &mut expander); + expander.cx.exported_macros.push(def.clone()); } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a278604b16756..cf0d2c6474b2c 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -11,7 +11,7 @@ use ast::{Ident, TtDelimited, TtSequence, TtToken}; use ast; use codemap::{Span, DUMMY_SP}; -use ext::base::{ExtCtxt, MacResult, MacroDef}; +use ext::base::{ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; @@ -208,15 +208,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // // Holy self-referential! -/// This procedure performs the expansion of the -/// macro_rules! macro. It parses the RHS and adds -/// an extension to the current context. -pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, - sp: Span, - name: Ident, - imported_from: Option, - arg: Vec ) - -> MacroDef { +/// Converts a `macro_rules!` invocation into a syntax extension. +pub fn compile<'cx>(cx: &'cx mut ExtCtxt, + def: &ast::MacroDef) -> SyntaxExtension { let lhs_nm = gensym_ident("lhs"); let rhs_nm = gensym_ident("rhs"); @@ -254,7 +248,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic, None, None, - arg.clone()); + def.body.clone()); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader, @@ -263,23 +257,20 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, // Extract the arguments: let lhses = match *argument_map[lhs_nm] { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), - _ => cx.span_bug(sp, "wrong-structured lhs") + _ => cx.span_bug(def.span, "wrong-structured lhs") }; let rhses = match *argument_map[rhs_nm] { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), - _ => cx.span_bug(sp, "wrong-structured rhs") + _ => cx.span_bug(def.span, "wrong-structured rhs") }; let exp = box MacroRulesMacroExpander { - name: name, - imported_from: imported_from, + name: def.ident, + imported_from: def.imported_from, lhses: lhses, rhses: rhses, }; - MacroDef { - name: token::get_ident(name).to_string(), - ext: NormalTT(exp, Some(sp)) - } + NormalTT(exp, Some(def.span)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 35b2e5dbc5381..6b5d333ef8fc1 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1115,7 +1115,7 @@ pub fn noop_fold_mod(Mod {inner, view_items, items}: Mod, folder: &mu } } -pub fn noop_fold_crate(Crate {module, attrs, config, exported_macros, span}: Crate, +pub fn noop_fold_crate(Crate {module, attrs, config, mut exported_macros, span}: Crate, folder: &mut T) -> Crate { let config = folder.fold_meta_items(config); @@ -1146,6 +1146,10 @@ pub fn noop_fold_crate(Crate {module, attrs, config, exported_macros, }, Vec::new(), span) }; + for def in exported_macros.iter_mut() { + def.id = folder.new_id(def.id); + } + Crate { module: module, attrs: attrs, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ee7edceaf6969..b0969a573e66b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -169,6 +169,8 @@ pub fn parse_stmt_from_source_str(name: String, // Note: keep in sync with `with_hygiene::parse_tts_from_source_str` // until #16472 is resolved. +// +// Warning: This parses with quote_depth > 0, which is not the default. pub fn parse_tts_from_source_str(name: String, source: String, cfg: ast::CrateConfig, @@ -310,6 +312,8 @@ pub mod with_hygiene { // Note: keep this in sync with `super::parse_tts_from_source_str` until // #16472 is resolved. + // + // Warning: This parses with quote_depth > 0, which is not the default. pub fn parse_tts_from_source_str(name: String, source: String, cfg: ast::CrateConfig, From cd4205a970b07a9f4e8a2a6363ebe535df530386 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 5 Jan 2015 15:19:38 -0500 Subject: [PATCH 079/106] tweak the obsolete syntax message --- src/libsyntax/parse/obsolete.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index d63f432589dd1..cb8b82b204196 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -58,8 +58,8 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { let (kind_str, desc) = match kind { ObsoleteForSized => ( "for Sized?", - "no longer required, traits apply to sized and unsized types by default, use \ - `: Sized` to opt-out of unsized types", + "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \ + by default", ), ObsoleteProcType => ( "the `proc` type", From 8733b8b19c510737faed35b83fdecc1c41a96a27 Mon Sep 17 00:00:00 2001 From: FakeKane Date: Mon, 5 Jan 2015 16:22:03 -0500 Subject: [PATCH 080/106] examples added for element access --- src/libstd/tuple.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index a12844f039ec6..0c8273abde40a 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -15,7 +15,7 @@ //! //! Indexing starts from zero, so `0` returns first value, `1` //! returns second value, and so on. In general, a tuple with _S_ -//! elements provides aforementioned fields from `0` to `S-1` +//! elements provides aforementioned fields from `0` to `S-1`. //! //! If every type inside a tuple implements one of the following //! traits, then a tuple itself also implements it. @@ -28,6 +28,17 @@ //! * `Default` //! //! # Examples +//! +//! Accessing elements of a tuple at specified indices: +//! +//! ``` +//! let x = ("colorless", "green", "ideas", "sleep", "furiously"); +//! assert_eq!(x.3, "sleep"); +//! +//! let v = (3i, 3i); +//! let u = (1i, -5i); +//! assert_eq!(v.0 * u.0 + v.1 * u.1, -12i); +//! ``` //! //! Using traits implemented for tuples: //! From f7f5d0958b079a893678af2f439ef6a735365b18 Mon Sep 17 00:00:00 2001 From: FakeKane Date: Mon, 5 Jan 2015 16:46:46 -0500 Subject: [PATCH 081/106] removing whitespace --- src/libstd/tuple.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 0c8273abde40a..e76dcef226ddc 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -28,13 +28,13 @@ //! * `Default` //! //! # Examples -//! +//! //! Accessing elements of a tuple at specified indices: -//! +//! //! ``` //! let x = ("colorless", "green", "ideas", "sleep", "furiously"); //! assert_eq!(x.3, "sleep"); -//! +//! //! let v = (3i, 3i); //! let u = (1i, -5i); //! assert_eq!(v.0 * u.0 + v.1 * u.1, -12i); From 64ec47c9d2a75c8150d153450e7e7b7db60208dc Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Sun, 4 Jan 2015 08:43:27 -0800 Subject: [PATCH 082/106] Final alpha stabilization of core::iter This commit wraps up the adjustments to the iterator for recent language changes. * Moves `rposition` from `ExactSizeIterator` to `IteratorExt` using a `where` clause, thereby removing the `ExactSizeIterator: DoubleEndedIterator` constraint. * Merges `MutableDoubleEndedIterator` into `IteratorExt`, renaming `reverse_` to `reverse_in_place`. * Merges `IteratorOrdExt`, `IteratorCloneExt` and `CloneIteratorExt` into `IteratorExt` using `where` clauses. Marks as `#[stable]`: * the `iter` module itself * `FromIterator`, `Extend` * `Iterator`, `IteratorExt` * `map` * `filter` * `filter_map` * `skip_while` * `take_while` * `scan` * `flat_map` * `inspect` * `collect` * `fold` * `all` * `any` * `find` * `rposition` * `max`, `min` * Various adapter types related to the above methods Because of the trait merging, this is a: [breaking-change] --- src/libcore/iter.rs | 708 ++++++++++++++++++++++---------------------- 1 file changed, 347 insertions(+), 361 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 29077deb21de1..4782a763dc89a 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -54,6 +54,8 @@ //! //! This `for` loop syntax can be applied to any iterator over any type. +#![stable] + use self::MinMaxResult::*; use clone::Clone; @@ -79,11 +81,13 @@ use uint; /// it wishes, either by returning `None` infinitely, or by doing something /// else. #[lang="iterator"] -#[unstable = "just split up for object safety"] +#[stable] pub trait Iterator { + #[stable] type Item; /// Advance the iterator and return the next value. Return `None` when the end is reached. + #[stable] fn next(&mut self) -> Option; /// Returns a lower and upper bound on the remaining length of the iterator. @@ -91,26 +95,80 @@ pub trait Iterator { /// An upper bound of `None` means either there is no known upper bound, or the upper bound /// does not fit within a `uint`. #[inline] + #[stable] fn size_hint(&self) -> (uint, Option) { (0, None) } } /// Conversion from an `Iterator` -#[unstable = "may be replaced by a more general conversion trait"] +#[stable] pub trait FromIterator { /// Build a container with elements from an external iterator. fn from_iter>(iterator: T) -> Self; } /// A type growable from an `Iterator` implementation -#[unstable = "just renamed as part of collections reform"] +#[stable] pub trait Extend { /// Extend a container with the elements yielded by an arbitrary iterator fn extend>(&mut self, iterator: T); } -#[unstable = "new convention for extension traits"] /// An extension trait providing numerous methods applicable to all iterators. +#[stable] pub trait IteratorExt: Iterator + Sized { + /// Counts the number of elements in this iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.count() == 5); + /// ``` + #[inline] + #[stable] + fn count(self) -> uint { + self.fold(0, |cnt, _x| cnt + 1) + } + + /// Loops through the entire iterator, returning the last element of the + /// iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// assert!(a.iter().last().unwrap() == &5); + /// ``` + #[inline] + #[stable] + fn last(mut self) -> Option< ::Item> { + let mut last = None; + for x in self { last = Some(x); } + last + } + + /// Loops through `n` iterations, returning the `n`th element of the + /// iterator. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.nth(2).unwrap() == &3); + /// assert!(it.nth(2) == None); + /// ``` + #[inline] + #[stable] + fn nth(&mut self, mut n: uint) -> Option< ::Item> { + for x in *self { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + /// Chain this iterator with another, returning a new iterator that will /// finish iterating over the current iterator, and then iterate /// over the other specified iterator. @@ -169,7 +227,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn map(self, f: F) -> Map< ::Item, B, Self, F> where F: FnMut(::Item) -> B, { @@ -189,7 +247,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn filter

(self, predicate: P) -> Filter< ::Item, Self, P> where P: FnMut(&::Item) -> bool, { @@ -209,7 +267,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn filter_map(self, f: F) -> FilterMap< ::Item, B, Self, F> where F: FnMut(::Item) -> Option, { @@ -258,9 +316,9 @@ pub trait IteratorExt: Iterator + Sized { Peekable{iter: self, peeked: None} } - /// Creates an iterator that invokes the predicate on elements until it - /// returns false. Once the predicate returns false, all further elements are - /// yielded. + /// Creates an iterator that invokes the predicate on elements + /// until it returns false. Once the predicate returns false, that + /// element and all further elements are yielded. /// /// # Example /// @@ -273,7 +331,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn skip_while

(self, predicate: P) -> SkipWhile< ::Item, Self, P> where P: FnMut(&::Item) -> bool, { @@ -294,7 +352,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures, may want to require peek"] + #[stable] fn take_while

(self, predicate: P) -> TakeWhile< ::Item, Self, P> where P: FnMut(&::Item) -> bool, { @@ -359,7 +417,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next().is_none()); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn scan( self, initial_state: St, @@ -389,7 +447,7 @@ pub trait IteratorExt: Iterator + Sized { /// } /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn flat_map(self, f: F) -> FlatMap< ::Item, B, Self, U, F> where U: Iterator, F: FnMut(::Item) -> U, @@ -449,7 +507,7 @@ pub trait IteratorExt: Iterator + Sized { /// println!("{}", sum); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn inspect(self, f: F) -> Inspect< ::Item, Self, F> where F: FnMut(&::Item), { @@ -487,7 +545,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(a.as_slice() == b.as_slice()); /// ``` #[inline] - #[unstable = "waiting for general conversion traits, just changed to take self by value"] + #[stable] fn collect::Item>>(self) -> B { FromIterator::from_iter(self) } @@ -522,44 +580,6 @@ pub trait IteratorExt: Iterator + Sized { (left, right) } - /// Loops through `n` iterations, returning the `n`th element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.nth(2).unwrap() == &3); - /// assert!(it.nth(2) == None); - /// ``` - #[inline] - #[stable] - fn nth(&mut self, mut n: uint) -> Option< ::Item> { - for x in *self { - if n == 0 { return Some(x) } - n -= 1; - } - None - } - - /// Loops through the entire iterator, returning the last element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// assert!(a.iter().last().unwrap() == &5); - /// ``` - #[inline] - #[unstable = "just changed to take self by value"] - fn last(mut self) -> Option< ::Item> { - let mut last = None; - for x in self { last = Some(x); } - last - } - /// Performs a fold operation over the entire iterator, returning the /// eventual state at the end of the iteration. /// @@ -570,7 +590,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); /// ``` #[inline] - #[unstable = "waiting for unboxed closures, just changed to take self by value"] + #[stable] fn fold(mut self, init: B, mut f: F) -> B where F: FnMut(B, ::Item) -> B, { @@ -581,21 +601,6 @@ pub trait IteratorExt: Iterator + Sized { accum } - /// Counts the number of elements in this iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.count() == 5); - /// ``` - #[inline] - #[unstable = "just changed to take self by value"] - fn count(self) -> uint { - self.fold(0, |cnt, _x| cnt + 1) - } - /// Tests whether the predicate holds true for all elements in the iterator. /// /// # Example @@ -606,7 +611,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(!a.iter().all(|x| *x > 2)); /// ``` #[inline] - #[unstable = "waiting for unboxed closures, just changed to take self by value"] + #[stable] fn all(mut self, mut f: F) -> bool where F: FnMut(::Item) -> bool { for x in self { if !f(x) { return false; } } true @@ -624,7 +629,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(!it.any(|x| *x == 3)); /// ``` #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn any(&mut self, mut f: F) -> bool where F: FnMut(::Item) -> bool { for x in *self { if f(x) { return true; } } false @@ -634,7 +639,7 @@ pub trait IteratorExt: Iterator + Sized { /// /// Does not consume the iterator past the first found element. #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn find

(&mut self, mut predicate: P) -> Option< ::Item> where P: FnMut(&::Item) -> bool, { @@ -646,7 +651,7 @@ pub trait IteratorExt: Iterator + Sized { /// Return the index of the first element satisfying the specified predicate #[inline] - #[unstable = "waiting for unboxed closures"] + #[stable] fn position

(&mut self, mut predicate: P) -> Option where P: FnMut(::Item) -> bool, { @@ -660,6 +665,145 @@ pub trait IteratorExt: Iterator + Sized { None } + /// Return the index of the last element satisfying the specified predicate + /// + /// If no element matches, None is returned. + #[inline] + #[stable] + fn rposition

(&mut self, mut predicate: P) -> Option where + P: FnMut(::Item) -> bool, + Self: ExactSizeIterator + DoubleEndedIterator + { + let len = self.len(); + for i in range(0, len).rev() { + if predicate(self.next_back().expect("rposition: incorrect ExactSizeIterator")) { + return Some(i); + } + } + None + } + + /// Consumes the entire iterator to return the maximum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// assert!(a.iter().max().unwrap() == &5); + /// ``` + #[inline] + #[stable] + fn max(self) -> Option< ::Item> where + ::Item: Ord + { + self.fold(None, |max, x| { + match max { + None => Some(x), + Some(y) => Some(cmp::max(x, y)) + } + }) + } + + /// Consumes the entire iterator to return the minimum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// assert!(a.iter().min().unwrap() == &1); + /// ``` + #[inline] + #[stable] + fn min(self) -> Option< ::Item> where + ::Item: Ord + { + self.fold(None, |min, x| { + match min { + None => Some(x), + Some(y) => Some(cmp::min(x, y)) + } + }) + } + + /// `min_max` finds the minimum and maximum elements in the iterator. + /// + /// The return type `MinMaxResult` is an enum of three variants: + /// + /// - `NoElements` if the iterator is empty. + /// - `OneElement(x)` if the iterator has exactly one element. + /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two + /// values are equal if and only if there is more than one + /// element in the iterator and all elements are equal. + /// + /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, + /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. + /// + /// # Example + /// + /// ```rust + /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let v: [int; 0] = []; + /// assert_eq!(v.iter().min_max(), NoElements); + /// + /// let v = [1i]; + /// assert!(v.iter().min_max() == OneElement(&1)); + /// + /// let v = [1i, 2, 3, 4, 5]; + /// assert!(v.iter().min_max() == MinMax(&1, &5)); + /// + /// let v = [1i, 2, 3, 4, 5, 6]; + /// assert!(v.iter().min_max() == MinMax(&1, &6)); + /// + /// let v = [1i, 1, 1, 1]; + /// assert!(v.iter().min_max() == MinMax(&1, &1)); + /// ``` + #[unstable = "return type may change"] + fn min_max(mut self) -> MinMaxResult< ::Item> where + ::Item: Ord + { + let (mut min, mut max) = match self.next() { + None => return NoElements, + Some(x) => { + match self.next() { + None => return OneElement(x), + Some(y) => if x < y {(x, y)} else {(y,x)} + } + } + }; + + loop { + // `first` and `second` are the two next elements we want to look at. + // We first compare `first` and `second` (#1). The smaller one is then compared to + // current minimum (#2). The larger one is compared to current maximum (#3). This + // way we do 3 comparisons for 2 elements. + let first = match self.next() { + None => break, + Some(x) => x + }; + let second = match self.next() { + None => { + if first < min { + min = first; + } else if first > max { + max = first; + } + break; + } + Some(x) => x + }; + if first < second { + if first < min {min = first;} + if max < second {max = second;} + } else { + if second < min {min = second;} + if max < first {max = first;} + } + } + + MinMax(min, max) + } + /// Return the element that gives the maximum value from the /// specified function. /// @@ -672,7 +816,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); /// ``` #[inline] - #[unstable = "waiting for unboxed closures, just changed to take self by value"] + #[unstable = "may want to produce an Ordering directly; see #15311"] fn max_by(self, mut f: F) -> Option< ::Item> where F: FnMut(&::Item) -> B, { @@ -701,7 +845,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); /// ``` #[inline] - #[unstable = "waiting for unboxed closures, just changed to take self by value"] + #[unstable = "may want to produce an Ordering directly; see #15311"] fn min_by(self, mut f: F) -> Option< ::Item> where F: FnMut(&::Item) -> B, { @@ -740,6 +884,7 @@ pub trait IteratorExt: Iterator + Sized { /// /// Loops through the entire iterator, collecting the first component of /// each item into one new container, and the second component into another. + #[unstable = "recent addition"] fn unzip(mut self) -> (FromA, FromB) where FromA: Default + Extend, FromB: Default + Extend, @@ -759,56 +904,73 @@ pub trait IteratorExt: Iterator + Sized { let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - ts.extend(SizeHint(lo, hi)); - us.extend(SizeHint(lo, hi)); + ts.extend(SizeHint(lo, hi)); + us.extend(SizeHint(lo, hi)); + + for (t, u) in self { + ts.extend(Some(t).into_iter()); + us.extend(Some(u).into_iter()); + } + + (ts, us) + } + + /// Creates an iterator that clones the elements it yields. Useful for converting an + /// Iterator<&T> to an Iterator. + #[unstable = "recent addition"] + fn cloned(self) -> Cloned where + Self: Iterator, + D: Deref, + T: Clone, + { + Cloned { it: self } + } + + /// Repeats an iterator endlessly + /// + /// # Example + /// + /// ```rust + /// use std::iter::count; + /// + /// let a = count(1i,1i).take(1); + /// let mut cy = a.cycle(); + /// assert_eq!(cy.next(), Some(1)); + /// assert_eq!(cy.next(), Some(1)); + /// ``` + #[stable] + #[inline] + fn cycle(self) -> Cycle where Self: Clone { + Cycle{orig: self.clone(), iter: self} + } - for (t, u) in self { - ts.extend(Some(t).into_iter()); - us.extend(Some(u).into_iter()); + /// Use an iterator to reverse a container in place. + #[experimental = "uncertain about placement or widespread use"] + fn reverse_in_place<'a, T: 'a>(&mut self) where + Self: Iterator + DoubleEndedIterator + { + loop { + match (self.next(), self.next_back()) { + (Some(x), Some(y)) => mem::swap(x, y), + _ => break + } } - - (ts, us) } } -#[unstable = "trait is unstable"] +#[stable] impl IteratorExt for I where I: Iterator {} /// A range iterator able to yield elements from both ends /// /// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust /// elements from the *same* range, and do not work independently of each other. -#[unstable = "recently split into two traits"] +#[stable] pub trait DoubleEndedIterator: Iterator { /// Yield an element from the end of the range, returning `None` if the range is empty. fn next_back(&mut self) -> Option< ::Item>; } -/// A double-ended iterator yielding mutable references -#[experimental = "not widely used"] -pub trait MutableDoubleEndedIterator { - // FIXME: #5898: should be called `reverse` - /// Use an iterator to reverse a container in-place - fn reverse_(&mut self); -} - -#[experimental = "trait is experimental"] -impl<'a, T:'a, I> MutableDoubleEndedIterator for I where - I: DoubleEndedIterator + Iterator, -{ - // FIXME: #5898: should be called `reverse` - /// Use an iterator to reverse a container in-place - fn reverse_(&mut self) { - loop { - match (self.next(), self.next_back()) { - (Some(x), Some(y)) => mem::swap(x, y), - _ => break - } - } - } -} - - /// An object implementing random access indexing by `uint` /// /// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. @@ -832,24 +994,8 @@ pub trait RandomAccessIterator: Iterator { /// /// `Iterator::size_hint` *must* return the exact size of the iterator. /// Note that the size must fit in `uint`. -#[unstable = "could move DoubleEndedIterator bound onto rposition with method-level where clauses"] -pub trait ExactSizeIterator: DoubleEndedIterator { - /// Return the index of the last element satisfying the specified predicate - /// - /// If no element matches, None is returned. - #[inline] - fn rposition

(&mut self, mut predicate: P) -> Option where - P: FnMut(::Item) -> bool, - { - let len = self.len(); - for i in range(0, len).rev() { - if predicate(self.next_back().expect("rposition: incorrect ExactSizeIterator")) { - return Some(i); - } - } - None - } - +#[stable] +pub trait ExactSizeIterator: Iterator { #[inline] /// Return the exact length of the iterator. fn len(&self) -> uint { @@ -865,21 +1011,21 @@ pub trait ExactSizeIterator: DoubleEndedIterator { // All adaptors that preserve the size of the wrapped iterator are fine // Adaptors that may overflow in `size_hint` are not, i.e. `Chain`. -#[unstable = "trait is unstable"] +#[stable] impl ExactSizeIterator for Enumerate where I: ExactSizeIterator {} -#[unstable = "trait is unstable"] +#[stable] impl ExactSizeIterator for Inspect where I: ExactSizeIterator + Iterator, F: FnMut(&A), {} -#[unstable = "trait is unstable"] -impl ExactSizeIterator for Rev where I: ExactSizeIterator {} -#[unstable = "trait is unstable"] +#[stable] +impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} +#[stable] impl ExactSizeIterator for Map where I: ExactSizeIterator + Iterator, F: FnMut(A) -> B, {} -#[unstable = "trait is unstable"] +#[stable] impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} /// An double-ended iterator with the direction inverted @@ -890,7 +1036,7 @@ pub struct Rev { iter: T } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Rev where I: DoubleEndedIterator { type Item = ::Item; @@ -900,7 +1046,7 @@ impl Iterator for Rev where I: DoubleEndedIterator { fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option< ::Item> { self.iter.next() } @@ -924,7 +1070,7 @@ pub struct ByRef<'a, I:'a> { iter: &'a mut I, } -#[unstable = "trait is unstable"] +#[stable] impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator { type Item = ::Item; @@ -934,7 +1080,7 @@ impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator { fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } } -#[unstable = "trait is unstable"] +#[stable] impl<'a, I> DoubleEndedIterator for ByRef<'a, I> where I: 'a + DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option< ::Item> { self.iter.next_back() } @@ -1025,134 +1171,9 @@ impl_multiplicative! { uint, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } -/// A trait for iterators over elements which can be compared to one another. -#[unstable = "recently renamed for new extension trait conventions"] -pub trait IteratorOrdExt { - /// Consumes the entire iterator to return the maximum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// assert!(a.iter().max().unwrap() == &5); - /// ``` - fn max(self) -> Option; - - /// Consumes the entire iterator to return the minimum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// assert!(a.iter().min().unwrap() == &1); - /// ``` - fn min(self) -> Option; - - /// `min_max` finds the minimum and maximum elements in the iterator. - /// - /// The return type `MinMaxResult` is an enum of three variants: - /// - /// - `NoElements` if the iterator is empty. - /// - `OneElement(x)` if the iterator has exactly one element. - /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two - /// values are equal if and only if there is more than one - /// element in the iterator and all elements are equal. - /// - /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. - /// - /// # Example - /// - /// ```rust - /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; - /// - /// let v: [int; 0] = []; - /// assert_eq!(v.iter().min_max(), NoElements); - /// - /// let v = [1i]; - /// assert!(v.iter().min_max() == OneElement(&1)); - /// - /// let v = [1i, 2, 3, 4, 5]; - /// assert!(v.iter().min_max() == MinMax(&1, &5)); - /// - /// let v = [1i, 2, 3, 4, 5, 6]; - /// assert!(v.iter().min_max() == MinMax(&1, &6)); - /// - /// let v = [1i, 1, 1, 1]; - /// assert!(v.iter().min_max() == MinMax(&1, &1)); - /// ``` - fn min_max(self) -> MinMaxResult; -} - -#[unstable = "trait is unstable"] -impl IteratorOrdExt for I where I: Iterator, T: Ord { - #[inline] - fn max(self) -> Option { - self.fold(None, |max, x| { - match max { - None => Some(x), - Some(y) => Some(cmp::max(x, y)) - } - }) - } - - #[inline] - fn min(self) -> Option { - self.fold(None, |min, x| { - match min { - None => Some(x), - Some(y) => Some(cmp::min(x, y)) - } - }) - } - - fn min_max(mut self) -> MinMaxResult { - let (mut min, mut max) = match self.next() { - None => return NoElements, - Some(x) => { - match self.next() { - None => return OneElement(x), - Some(y) => if x < y {(x, y)} else {(y,x)} - } - } - }; - - loop { - // `first` and `second` are the two next elements we want to look at. - // We first compare `first` and `second` (#1). The smaller one is then compared to - // current minimum (#2). The larger one is compared to current maximum (#3). This - // way we do 3 comparisons for 2 elements. - let first = match self.next() { - None => break, - Some(x) => x - }; - let second = match self.next() { - None => { - if first < min { - min = first; - } else if first > max { - max = first; - } - break; - } - Some(x) => x - }; - if first < second { - if first < min {min = first;} - if max < second {max = second;} - } else { - if second < min {min = second;} - if max < first {max = first;} - } - } - - MinMax(min, max) - } -} - /// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail. #[derive(Clone, PartialEq, Show)] -#[unstable = "waiting on namespaced enum conventions"] +#[unstable = "unclear whether such a fine-grained result is widely useful"] pub enum MinMaxResult { /// Empty iterator NoElements, @@ -1164,7 +1185,6 @@ pub enum MinMaxResult { MinMax(T, T) } -#[stable] impl MinMaxResult { /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant @@ -1185,6 +1205,7 @@ impl MinMaxResult { /// let r = MinMax(1i,2i); /// assert_eq!(r.into_option(), Some((1,2))); /// ``` + #[unstable = "type is unstable"] pub fn into_option(self) -> Option<(T,T)> { match self { NoElements => None, @@ -1194,30 +1215,15 @@ impl MinMaxResult { } } -/// A trait for iterators that contain cloneable elements -#[unstable = "recently renamed for extension trait conventions"] -pub trait IteratorCloneExt { - /// Creates an iterator that clones the elements it yields. Useful for converting an - /// Iterator<&T> to an Iterator. - fn cloned(self) -> Cloned; -} - -#[unstable = "trait is unstable"] -impl IteratorCloneExt for I where - T: Clone, - D: Deref, - I: Iterator, -{ - fn cloned(self) -> Cloned { - Cloned { it: self } - } -} - /// An iterator that clones the elements of an underlying iterator +#[unstable = "recent addition"] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] pub struct Cloned { it: I, } +#[stable] impl Iterator for Cloned where T: Clone, D: Deref, @@ -1234,6 +1240,7 @@ impl Iterator for Cloned where } } +#[stable] impl DoubleEndedIterator for Cloned where T: Clone, D: Deref, @@ -1244,39 +1251,13 @@ impl DoubleEndedIterator for Cloned where } } -#[unstable = "trait is unstable"] +#[stable] impl ExactSizeIterator for Cloned where T: Clone, D: Deref, I: ExactSizeIterator + Iterator, {} -#[unstable = "recently renamed for extension trait conventions"] -/// An extension trait for cloneable iterators. -pub trait CloneIteratorExt { - /// Repeats an iterator endlessly - /// - /// # Example - /// - /// ```rust - /// use std::iter::{CloneIteratorExt, count}; - /// - /// let a = count(1i,1i).take(1); - /// let mut cy = a.cycle(); - /// assert_eq!(cy.next(), Some(1)); - /// assert_eq!(cy.next(), Some(1)); - /// ``` - #[stable] - fn cycle(self) -> Cycle; -} - -impl CloneIteratorExt for I where I: Iterator + Clone { - #[inline] - fn cycle(self) -> Cycle { - Cycle{orig: self.clone(), iter: self} - } -} - /// An iterator that repeats endlessly #[derive(Clone, Copy)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1286,6 +1267,7 @@ pub struct Cycle { iter: I, } +#[stable] impl Iterator for Cycle where I: Clone + Iterator { type Item = ::Item; @@ -1345,7 +1327,7 @@ pub struct Chain { flag: bool, } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Chain where A: Iterator, B: Iterator { type Item = T; @@ -1379,7 +1361,7 @@ impl Iterator for Chain where A: Iterator, B: Iterator DoubleEndedIterator for Chain where A: DoubleEndedIterator + Iterator, B: DoubleEndedIterator + Iterator, @@ -1424,7 +1406,7 @@ pub struct Zip { b: B } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Zip where A: Iterator, B: Iterator, @@ -1460,10 +1442,10 @@ impl Iterator for Zip where } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Zip where - A: ExactSizeIterator + Iterator, - B: ExactSizeIterator + Iterator, + A: ExactSizeIterator + Iterator + DoubleEndedIterator, + B: ExactSizeIterator + Iterator + DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option<(T, U)> { @@ -1539,7 +1521,7 @@ impl Map where I: Iterator, F: FnMut(A) -> B { } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Map where I: Iterator, F: FnMut(A) -> B { type Item = B; @@ -1555,7 +1537,7 @@ impl Iterator for Map where I: Iterator, F: FnMu } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Map where I: DoubleEndedIterator + Iterator, F: FnMut(A) -> B, @@ -1606,7 +1588,7 @@ impl Clone for Filter where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Filter where I: Iterator, P: FnMut(&A) -> bool { type Item = A; @@ -1629,7 +1611,7 @@ impl Iterator for Filter where I: Iterator, P: FnMut(& } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Filter where I: DoubleEndedIterator + Iterator, P: FnMut(&A) -> bool, @@ -1667,7 +1649,7 @@ impl Clone for FilterMap where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for FilterMap where I: Iterator, F: FnMut(A) -> Option, @@ -1692,7 +1674,7 @@ impl Iterator for FilterMap where } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for FilterMap where I: DoubleEndedIterator + Iterator, F: FnMut(A) -> Option, @@ -1718,7 +1700,7 @@ pub struct Enumerate { count: uint } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Enumerate where I: Iterator { type Item = (uint, ::Item); @@ -1740,8 +1722,10 @@ impl Iterator for Enumerate where I: Iterator { } } -#[unstable = "trait is unstable"] -impl DoubleEndedIterator for Enumerate where I: ExactSizeIterator { +#[stable] +impl DoubleEndedIterator for Enumerate where + I: ExactSizeIterator + DoubleEndedIterator +{ #[inline] fn next_back(&mut self) -> Option<(uint, ::Item)> { match self.iter.next_back() { @@ -1779,6 +1763,7 @@ pub struct Peekable where I: Iterator { peeked: Option, } +#[stable] impl Iterator for Peekable where I: Iterator { type Item = T; @@ -1850,7 +1835,7 @@ impl Clone for SkipWhile where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for SkipWhile where I: Iterator, P: FnMut(&A) -> bool { type Item = A; @@ -1896,7 +1881,7 @@ impl Clone for TakeWhile where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for TakeWhile where I: Iterator, P: FnMut(&A) -> bool { type Item = A; @@ -1935,7 +1920,7 @@ pub struct Skip { n: uint } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Skip where I: Iterator { type Item = ::Item; @@ -2005,7 +1990,7 @@ pub struct Take { n: uint } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Take where I: Iterator{ type Item = ::Item; @@ -2054,7 +2039,7 @@ impl RandomAccessIterator for Take where I: RandomAccessIterator{ /// An iterator to maintain state while iterating another iterator #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[unstable = "waiting for unboxed closures"] +#[stable] pub struct Scan where I: Iterator, F: FnMut(&mut St, A) -> Option { iter: I, f: F, @@ -2079,7 +2064,7 @@ impl Clone for Scan where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Scan where I: Iterator, F: FnMut(&mut St, A) -> Option, @@ -2102,7 +2087,7 @@ impl Iterator for Scan where /// and yields the elements of the produced iterators /// #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[unstable = "waiting for unboxed closures"] +#[stable] pub struct FlatMap where I: Iterator, U: Iterator, @@ -2131,7 +2116,7 @@ impl Clone for FlatMap where } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for FlatMap where I: Iterator, U: Iterator, @@ -2166,7 +2151,7 @@ impl Iterator for FlatMap where } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for FlatMap where I: DoubleEndedIterator + Iterator, U: DoubleEndedIterator + Iterator, @@ -2199,7 +2184,7 @@ pub struct Fuse { done: bool } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Fuse where I: Iterator { type Item = ::Item; @@ -2228,7 +2213,7 @@ impl Iterator for Fuse where I: Iterator { } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option< ::Item> { @@ -2260,11 +2245,11 @@ impl RandomAccessIterator for Fuse where I: RandomAccessIterator { } } -#[experimental = "seems marginal"] impl Fuse { /// Resets the fuse such that the next call to .next() or .next_back() will /// call the underlying iterator again even if it previously returned None. #[inline] + #[experimental = "seems marginal"] pub fn reset_fuse(&mut self) { self.done = false } @@ -2273,7 +2258,7 @@ impl Fuse { /// An iterator that calls a function with a reference to each /// element before yielding it. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[unstable = "waiting for unboxed closures"] +#[stable] pub struct Inspect where I: Iterator, F: FnMut(&A) { iter: I, f: F, @@ -2305,7 +2290,7 @@ impl Inspect where I: Iterator, F: FnMut(&A) { } } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Inspect where I: Iterator, F: FnMut(&A) { type Item = A; @@ -2321,7 +2306,7 @@ impl Iterator for Inspect where I: Iterator, F: FnMut( } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Inspect where I: DoubleEndedIterator + Iterator, F: FnMut(&A), @@ -2435,7 +2420,7 @@ impl Iterator for Unfold where F: FnMut(&mut St) -> Option { /// The current state the counter is at (next value to be yielded) state: A, @@ -2445,12 +2430,12 @@ pub struct Counter { /// Creates a new counter with the specified start/step #[inline] -#[unstable = "may be renamed"] +#[unstable = "may be renamed or replaced by range notation adapaters"] pub fn count(start: A, step: A) -> Counter { Counter{state: start, step: step} } -#[unstable = "trait is unstable"] +#[stable] impl + Clone> Iterator for Counter { type Item = A; @@ -2469,7 +2454,7 @@ impl + Clone> Iterator for Counter { /// An iterator over the range [start, stop) #[derive(Clone, Copy)] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "will be replaced by range notation"] pub struct Range { state: A, stop: A, @@ -2490,6 +2475,7 @@ pub struct Range { /// } /// ``` #[inline] +#[unstable = "will be replaced by range notation"] pub fn range(start: A, stop: A) -> Range { Range { state: start, @@ -2499,7 +2485,7 @@ pub fn range(start: A, stop: A) -> Range { } // FIXME: #10414: Unfortunate type bound -#[unstable = "trait is unstable"] +#[unstable = "will be replaced by range notation"] impl Iterator for Range { type Item = A; @@ -2549,7 +2535,7 @@ impl Iterator for Range { /// `Int` is required to ensure the range will be the same regardless of /// the direction it is consumed. -#[unstable = "trait is unstable"] +#[unstable = "will be replaced by range notation"] impl DoubleEndedIterator for Range { #[inline] fn next_back(&mut self) -> Option { @@ -2564,7 +2550,7 @@ impl DoubleEndedIterator for Range { /// An iterator over the range [start, stop] #[derive(Clone)] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub struct RangeInclusive { range: Range, done: bool, @@ -2572,7 +2558,7 @@ pub struct RangeInclusive { /// Return an iterator over the range [start, stop] #[inline] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { RangeInclusive { range: range(start, stop), @@ -2580,7 +2566,7 @@ pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { } } -#[unstable = "trait is unstable"] +#[unstable = "likely to be replaced by range notation and adapters"] impl Iterator for RangeInclusive { type Item = A; @@ -2615,7 +2601,7 @@ impl Iterator for RangeInclusive { } } -#[unstable = "trait is unstable"] +#[unstable = "likely to be replaced by range notation and adapters"] impl DoubleEndedIterator for RangeInclusive { #[inline] fn next_back(&mut self) -> Option { @@ -2634,7 +2620,7 @@ impl DoubleEndedIterator for RangeInclusive { /// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. #[derive(Clone)] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub struct RangeStep { state: A, stop: A, @@ -2644,13 +2630,13 @@ pub struct RangeStep { /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. #[inline] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub fn range_step(start: A, stop: A, step: A) -> RangeStep { let rev = step < Int::zero(); RangeStep{state: start, stop: stop, step: step, rev: rev} } -#[unstable = "trait is unstable"] +#[unstable = "likely to be replaced by range notation and adapters"] impl Iterator for RangeStep { type Item = A; @@ -2671,7 +2657,7 @@ impl Iterator for RangeStep { /// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. #[derive(Clone)] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub struct RangeStepInclusive { state: A, stop: A, @@ -2682,7 +2668,7 @@ pub struct RangeStepInclusive { /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. #[inline] -#[unstable = "may be refactored due to numerics reform or ops reform"] +#[unstable = "likely to be replaced by range notation and adapters"] pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive { let rev = step < Int::zero(); RangeStepInclusive { @@ -2694,7 +2680,7 @@ pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepIncl } } -#[unstable = "trait is unstable"] +#[unstable = "likely to be replaced by range notation and adapters"] impl Iterator for RangeStepInclusive { type Item = A; @@ -2719,7 +2705,7 @@ impl Iterator for RangeStepInclusive { /// directions. The `steps_between` function provides a way to /// compare two Step objects (it could be provided using `step()` and `Ord`, /// but the implementation would be so inefficient as to be useless). -#[unstable = "Trait is unstable."] +#[unstable = "design of range notation/iteration is in flux"] pub trait Step: Ord { /// Change self to the next object. fn step(&mut self); @@ -2779,7 +2765,7 @@ pub struct Repeat { element: A } -#[unstable = "trait is unstable"] +#[stable] impl Iterator for Repeat { type Item = A; @@ -2789,7 +2775,7 @@ impl Iterator for Repeat { fn size_hint(&self) -> (uint, Option) { (uint::MAX, None) } } -#[unstable = "trait is unstable"] +#[stable] impl DoubleEndedIterator for Repeat { #[inline] fn next_back(&mut self) -> Option { self.idx(0) } @@ -2855,7 +2841,7 @@ pub fn repeat(elt: T) -> Repeat { /// /// If two sequences are equal up until the point where one ends, /// the shorter sequence compares less. -#[experimental = "likely to be removed after cmp reform"] +#[unstable = "needs review and revision"] pub mod order { use cmp; use cmp::{Eq, Ord, PartialOrd, PartialEq}; From e921afddd8c12d676205bb951deff1aa5761bedf Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Sun, 4 Jan 2015 15:42:51 -0800 Subject: [PATCH 083/106] Stabilize core::ops This commit marks as stable those parts of `core::ops` that are in their final planned form: `Drop`, all of the mathematical operators (`Add`, `Sub`, etc), `Deref`/`DerefMut`. It leaves the `Index*`, `Slice*` and `Fn*` traits unstable, as they are still undergoing active changes. --- src/libcore/ops.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index c9b71092f9072..da2e95832e71a 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -59,6 +59,8 @@ //! See the documentation for each trait for a minimum implementation that prints //! something to the screen. +#![stable] + use clone::Clone; use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator}; use kinds::Sized; @@ -86,8 +88,10 @@ use option::Option::{self, Some, None}; /// } /// ``` #[lang="drop"] +#[stable] pub trait Drop { /// The `drop` method, called when the value goes out of scope. + #[stable] fn drop(&mut self); } @@ -120,15 +124,19 @@ pub trait Drop { /// } /// ``` #[lang="add"] +#[stable] pub trait Add { + #[stable] type Output; /// The method for the `+` operator + #[stable] fn add(self, rhs: RHS) -> Self::Output; } macro_rules! add_impl { ($($t:ty)*) => ($( + #[stable] impl Add for $t { type Output = $t; @@ -169,15 +177,19 @@ add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// } /// ``` #[lang="sub"] +#[stable] pub trait Sub { + #[stable] type Output; /// The method for the `-` operator + #[stable] fn sub(self, rhs: RHS) -> Self::Output; } macro_rules! sub_impl { ($($t:ty)*) => ($( + #[stable] impl Sub for $t { type Output = $t; @@ -218,15 +230,19 @@ sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// } /// ``` #[lang="mul"] +#[stable] pub trait Mul { + #[stable] type Output; /// The method for the `*` operator + #[stable] fn mul(self, rhs: RHS) -> Self::Output; } macro_rules! mul_impl { ($($t:ty)*) => ($( + #[stable] impl Mul for $t { type Output = $t; @@ -267,15 +283,19 @@ mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// } /// ``` #[lang="div"] +#[stable] pub trait Div { + #[stable] type Output; /// The method for the `/` operator + #[stable] fn div(self, rhs: RHS) -> Self::Output; } macro_rules! div_impl { ($($t:ty)*) => ($( + #[stable] impl Div for $t { type Output = $t; @@ -316,15 +336,19 @@ div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 } /// } /// ``` #[lang="rem"] +#[stable] pub trait Rem { + #[stable] type Output = Self; /// The method for the `%` operator + #[stable] fn rem(self, rhs: RHS) -> Self::Output; } macro_rules! rem_impl { ($($t:ty)*) => ($( + #[stable] impl Rem for $t { type Output = $t; @@ -336,6 +360,7 @@ macro_rules! rem_impl { macro_rules! rem_float_impl { ($t:ty, $fmod:ident) => { + #[stable] impl Rem for $t { type Output = $t; @@ -382,19 +407,25 @@ rem_float_impl! { f64, fmod } /// } /// ``` #[lang="neg"] +#[stable] pub trait Neg { + #[stable] type Output; /// The method for the unary `-` operator + #[stable] fn neg(self) -> Self::Output; } macro_rules! neg_impl { ($($t:ty)*) => ($( + #[stable] impl Neg for $t { + #[stable] type Output = $t; #[inline] + #[stable] fn neg(self) -> $t { -self } } )*) @@ -402,6 +433,7 @@ macro_rules! neg_impl { macro_rules! neg_uint_impl { ($t:ty, $t_signed:ty) => { + #[stable] impl Neg for $t { type Output = $t; @@ -450,15 +482,19 @@ neg_uint_impl! { u64, i64 } /// } /// ``` #[lang="not"] +#[stable] pub trait Not { + #[stable] type Output; /// The method for the unary `!` operator + #[stable] fn not(self) -> Self::Output; } macro_rules! not_impl { ($($t:ty)*) => ($( + #[stable] impl Not for $t { type Output = $t; @@ -499,15 +535,19 @@ not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="bitand"] +#[stable] pub trait BitAnd { + #[stable] type Output; /// The method for the `&` operator + #[stable] fn bitand(self, rhs: RHS) -> Self::Output; } macro_rules! bitand_impl { ($($t:ty)*) => ($( + #[stable] impl BitAnd for $t { type Output = $t; @@ -548,15 +588,19 @@ bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="bitor"] +#[stable] pub trait BitOr { + #[stable] type Output; /// The method for the `|` operator + #[stable] fn bitor(self, rhs: RHS) -> Self::Output; } macro_rules! bitor_impl { ($($t:ty)*) => ($( + #[stable] impl BitOr for $t { type Output = $t; @@ -597,15 +641,19 @@ bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="bitxor"] +#[stable] pub trait BitXor { + #[stable] type Output; /// The method for the `^` operator + #[stable] fn bitxor(self, rhs: RHS) -> Self::Output; } macro_rules! bitxor_impl { ($($t:ty)*) => ($( + #[stable] impl BitXor for $t { type Output = $t; @@ -646,15 +694,19 @@ bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="shl"] +#[stable] pub trait Shl { + #[stable] type Output; /// The method for the `<<` operator + #[stable] fn shl(self, rhs: RHS) -> Self::Output; } macro_rules! shl_impl { ($($t:ty)*) => ($( + #[stable] impl Shl for $t { type Output = $t; @@ -697,10 +749,13 @@ shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="shr"] +#[stable] pub trait Shr { + #[stable] type Output; /// The method for the `>>` operator + #[stable] fn shr(self, rhs: RHS) -> Self::Output; } @@ -913,11 +968,13 @@ pub trait SliceMut for Sized? { /// An unbounded range. #[derive(Copy)] #[lang="full_range"] +#[unstable = "API still in development"] pub struct FullRange; /// A (half-open) range which is bounded at both ends. #[derive(Copy)] #[lang="range"] +#[unstable = "API still in development"] pub struct Range { /// The lower bound of the range (inclusive). pub start: Idx, @@ -968,6 +1025,7 @@ impl ExactSizeIterator for Range {} /// A range which is only bounded below. #[derive(Copy)] #[lang="range_from"] +#[unstable = "API still in development"] pub struct RangeFrom { /// The lower bound of the range (inclusive). pub start: Idx, @@ -988,6 +1046,7 @@ impl Iterator for RangeFrom { /// A range which is only bounded above. #[derive(Copy)] #[lang="range_to"] +#[unstable = "API still in development"] pub struct RangeTo { /// The upper bound of the range (exclusive). pub end: Idx, @@ -1025,19 +1084,24 @@ pub struct RangeTo { /// } /// ``` #[lang="deref"] +#[stable] pub trait Deref for Sized? { + #[stable] type Sized? Target; /// The method called to dereference a value + #[stable] fn deref<'a>(&'a self) -> &'a Self::Target; } +#[stable] impl<'a, Sized? T> Deref for &'a T { type Target = T; fn deref(&self) -> &T { *self } } +#[stable] impl<'a, Sized? T> Deref for &'a mut T { type Target = T; @@ -1082,17 +1146,21 @@ impl<'a, Sized? T> Deref for &'a mut T { /// } /// ``` #[lang="deref_mut"] +#[stable] pub trait DerefMut for Sized? : Deref { /// The method called to mutably dereference a value + #[stable] fn deref_mut<'a>(&'a mut self) -> &'a mut ::Target; } +#[stable] impl<'a, Sized? T> DerefMut for &'a mut T { fn deref_mut(&mut self) -> &mut T { *self } } /// A version of the call operator that takes an immutable receiver. #[lang="fn"] +#[unstable = "uncertain about variadic generics, input versus associated types"] pub trait Fn for Sized? { /// This is called when the call operator is used. extern "rust-call" fn call(&self, args: Args) -> Result; @@ -1100,6 +1168,7 @@ pub trait Fn for Sized? { /// A version of the call operator that takes a mutable receiver. #[lang="fn_mut"] +#[unstable = "uncertain about variadic generics, input versus associated types"] pub trait FnMut for Sized? { /// This is called when the call operator is used. extern "rust-call" fn call_mut(&mut self, args: Args) -> Result; @@ -1107,6 +1176,7 @@ pub trait FnMut for Sized? { /// A version of the call operator that takes a by-value receiver. #[lang="fn_once"] +#[unstable = "uncertain about variadic generics, input versus associated types"] pub trait FnOnce { /// This is called when the call operator is used. extern "rust-call" fn call_once(self, args: Args) -> Result; From 121f6c66734301c1d29014f2ef0b58f21fcf1811 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Sun, 4 Jan 2015 15:53:00 -0800 Subject: [PATCH 084/106] Final alpha stabilization of std::slice Marks as `#[stable]`: * Various iterator structs for stable methods, e.g. `Chunks` and `Windows`. * The `SliceExt` trait itself. --- src/libcollections/slice.rs | 6 ++++-- src/libcore/slice.rs | 12 ++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..ceccca561aec7 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -86,6 +86,7 @@ //! * Further iterators exist that split, chunk or permute the slice. #![doc(primitive = "slice")] +#![stable] use alloc::boxed::Box; use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; @@ -119,8 +120,9 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf}; //////////////////////////////////////////////////////////////////////////////// /// Allocating extension methods for slices. -#[unstable = "needs associated types, may merge with other traits"] +#[stable] pub trait SliceExt for Sized? { + #[stable] type Item; /// Sorts the slice, in place, using `compare` to compare @@ -699,7 +701,7 @@ pub trait SliceExt for Sized? { fn into_vec(self: Box) -> Vec; } -#[unstable = "trait is unstable"] +#[stable] impl SliceExt for [T] { type Item = T; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f17a775cf4240..8174596e65e52 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1083,6 +1083,7 @@ impl> Iterator for GenericSplitN { /// An iterator over subslices separated by elements that match a predicate /// function, limited to a given number of splits. +#[stable] pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> } @@ -1090,12 +1091,14 @@ pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { /// An iterator over subslices separated by elements that match a /// predicate function, limited to a given number of splits, starting /// from the end of the slice. +#[stable] pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> } /// An iterator over subslices separated by elements that match a predicate /// function, limited to a given number of splits. +#[stable] pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> } @@ -1103,6 +1106,7 @@ pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { /// An iterator over subslices separated by elements that match a /// predicate function, limited to a given number of splits, starting /// from the end of the slice. +#[stable] pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { inner: GenericSplitN> } @@ -1134,7 +1138,7 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } /// An iterator over overlapping subslices of length `size`. #[derive(Clone)] -#[experimental = "needs review"] +#[stable] pub struct Windows<'a, T:'a> { v: &'a [T], size: uint @@ -1171,7 +1175,7 @@ impl<'a, T> Iterator for Windows<'a, T> { /// When the slice len is not evenly divided by the chunk size, the last slice /// of the iteration will be the remainder. #[derive(Clone)] -#[experimental = "needs review"] +#[stable] pub struct Chunks<'a, T:'a> { v: &'a [T], size: uint @@ -1246,7 +1250,7 @@ impl<'a, T> RandomAccessIterator for Chunks<'a, T> { /// An iterator over a slice in (non-overlapping) mutable chunks (`size` /// elements at a time). When the slice len is not evenly divided by the chunk /// size, the last slice of the iteration will be the remainder. -#[experimental = "needs review"] +#[stable] pub struct ChunksMut<'a, T:'a> { v: &'a mut [T], chunk_size: uint @@ -1360,7 +1364,7 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { /// not being able to provide a non-aliasing guarantee of the returned mutable /// slice. #[inline] -#[unstable = "jshould be renamed to from_raw_parts_mut"] +#[unstable = "should be renamed to from_raw_parts_mut"] pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] { transmute(RawSlice { data: *p as *const T, len: len }) } From cb765ce7e190c70313858738e7427d99338a4f3f Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Sun, 4 Jan 2015 16:35:20 -0800 Subject: [PATCH 085/106] Stabilize collection modules The earlier collections stabilization did not cover the modules themselves. This commit marks as stable those modules whose types have been stabilized. --- src/libcollections/binary_heap.rs | 1 + src/libcollections/dlist.rs | 2 ++ src/libcollections/lib.rs | 4 ++++ src/libcollections/ring_buf.rs | 2 ++ src/libstd/collections/mod.rs | 4 +++- 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 4a550e5ce277d..619a6e9427199 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -148,6 +148,7 @@ //! ``` #![allow(missing_docs)] +#![stable] use core::prelude::*; diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index ca8e75ac43c8d..14d61edca0438 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -19,6 +19,8 @@ // Backlinks over DList::prev are raw pointers that form a full chain in // the reverse direction. +#![stable] + use core::prelude::*; use alloc::boxed::Box; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index db2367950387b..72cdae8ba3102 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -65,19 +65,23 @@ pub mod string; pub mod vec; pub mod vec_map; +#[stable] pub mod bitv { pub use bit::{Bitv, Iter}; } +#[stable] pub mod bitv_set { pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference}; pub use bit::SetIter as Iter; } +#[stable] pub mod btree_map { pub use btree::map::*; } +#[stable] pub mod btree_set { pub use btree::set::*; } diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index e86c40bed212f..cc0debb23a0e5 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -12,6 +12,8 @@ //! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are //! not required to be copyable, and the queue will be sendable if the contained type is sendable. +#![stable] + use core::prelude::*; use core::cmp::Ordering; diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index c0445fb5aea97..ef9d28bbbb2e8 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -309,7 +309,7 @@ //! } //! ``` -#![experimental] +#![stable] pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet}; pub use core_collections::{DList, RingBuf, VecMap}; @@ -322,11 +322,13 @@ pub use self::hash_set::HashSet; mod hash; +#[stable] pub mod hash_map { //! A hashmap pub use super::hash::map::*; } +#[stable] pub mod hash_set { //! A hashset pub use super::hash::set::*; From 6e68fd09edc7ed37fd76f703247b5410cd338bfe Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 4 Jan 2015 20:35:06 -0500 Subject: [PATCH 086/106] Implement new orphan rule that requires that impls of remote traits meet the following two criteria: - the self type includes some local type; and, - type parameters in the self type must be constrained by a local type. A type parameter is called *constrained* if it appears in some type-parameter of a local type. Here are some examples that are accepted. In all of these examples, I assume that `Foo` is a trait defined in another crate. If `Foo` were defined in the local crate, then all the examples would be legal. - `impl Foo for LocalType` - `impl Foo for LocalType` -- T does not appear in Self, so it is OK - `impl Foo for LocalType` -- T here is constrained by LocalType - `impl Foo for (LocalType, T)` -- T here is constrained by LocalType Here are some illegal examples (again, these examples assume that `Foo` is not local to the current crate): - `impl Foo for int` -- the Self type is not local - `impl Foo for T` -- T appears in Self unconstrained by a local type - `impl Foo for (LocalType, T)` -- T appears in Self unconstrained by a local type This is a [breaking-change]. For the time being, you can opt out of the new rules by placing `#[old_orphan_check]` on the trait (and enabling the feature gate where the trait is defined). Longer term, you should restructure your traits to avoid the problem. Usually this means changing the order of parameters so that the "central" type parameter is in the `Self` position. As an example of that refactoring, consider the `BorrowFrom` trait: ```rust pub trait BorrowFrom for Sized? { fn borrow_from(owned: &Owned) -> &Self; } ``` As defined, this trait is commonly implemented for custom pointer types, such as `Arc`. Those impls follow the pattern: ```rust impl BorrowFrom> for T {...} ``` Unfortunately, this impl is illegal because the self type `T` is not local to the current crate. Therefore, we are going to change the order of the parameters, so that `BorrowFrom` becomes `Borrow`: ```rust pub trait Borrow for Sized? { fn borrow_from(owned: &Self) -> &Borrowed; } ``` Now the `Arc` impl is written: ```rust impl Borrow for Arc { ... } ``` This impl is legal because the self type (`Arc`) is local. --- src/libcore/borrow.rs | 4 ++ src/libcore/cmp.rs | 1 + src/librustc/lint/builtin.rs | 3 + src/librustc/middle/traits/coherence.rs | 56 ++++++++----------- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 26 ++++++--- src/libsyntax/feature_gate.rs | 8 +++ src/test/compile-fail/coherence-all-remote.rs | 2 +- .../coherence-bigint-int.rs | 2 +- .../compile-fail/coherence-bigint-param.rs | 2 +- .../coherence-bigint-vecint.rs | 2 +- .../coherence-cross-crate-conflict.rs | 2 +- .../coherence-lone-type-parameter.rs | 2 +- src/test/compile-fail/coherence-orphan.rs | 2 +- .../coherence-overlapping-pairs.rs | 2 +- .../coherence-pair-covered-uncovered.rs | 2 +- src/test/compile-fail/drop-on-non-struct.rs | 2 +- .../coherence-iterator-vec-any-elem.rs | 1 - 18 files changed, 68 insertions(+), 53 deletions(-) rename src/test/{run-pass => compile-fail}/coherence-bigint-int.rs (92%) rename src/test/{run-pass => compile-fail}/coherence-bigint-vecint.rs (91%) rename src/test/{compile-fail => run-pass}/coherence-iterator-vec-any-elem.rs (92%) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d8d..ebb4bd88cf139 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -53,12 +53,14 @@ use option::Option; use self::Cow::*; /// A trait for borrowing data. +#[old_orphan_check] pub trait BorrowFrom for Sized? { /// Immutably borrow from an owned value. fn borrow_from(owned: &Owned) -> &Self; } /// A trait for mutably borrowing data. +#[old_orphan_check] pub trait BorrowFromMut for Sized? : BorrowFrom { /// Mutably borrow from an owned value. fn borrow_from_mut(owned: &mut Owned) -> &mut Self; @@ -91,6 +93,7 @@ impl<'a, T, Sized? B> BorrowFrom> for B where B: ToOwned { } /// Trait for moving into a `Cow` +#[old_orphan_check] pub trait IntoCow<'a, T, Sized? B> { /// Moves `self` into `Cow` fn into_cow(self) -> Cow<'a, T, B>; @@ -103,6 +106,7 @@ impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { } /// A generalization of Clone to borrowed data. +#[old_orphan_check] pub trait ToOwned for Sized?: BorrowFrom { /// Create owned data from borrowed data, usually by copying. fn to_owned(&self) -> Owned; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 13f9f5ccee916..90ff174c2bdbd 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -69,6 +69,7 @@ use option::Option::{self, Some, None}; /// only if `a != b`. #[lang="eq"] #[stable] +#[old_orphan_check] pub trait PartialEq for Sized? { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 8f03f8821285a..cf5ca5956f4b3 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -670,6 +670,9 @@ impl LintPass for UnusedAttributes { "must_use", "stable", "unstable", + + // FIXME: #19470 this shouldn't be needed forever + "old_orphan_check", ]; static CRATE_ATTRS: &'static [&'static str] = &[ diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index e6805cddae05a..96b94ab298ad0 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -14,7 +14,7 @@ use super::SelectionContext; use super::{Obligation, ObligationCause}; use super::util; -use middle::subst::Subst; +use middle::subst::{Subst}; use middle::ty::{self, Ty}; use middle::infer::InferCtxt; use std::collections::HashSet; @@ -53,20 +53,20 @@ pub fn impl_can_satisfy(infcx: &InferCtxt, } #[allow(missing_copy_implementations)] -pub enum OrphanCheckErr { +pub enum OrphanCheckErr<'tcx> { NoLocalInputType, - UncoveredTypeParameter(ty::ParamTy), + UncoveredTy(Ty<'tcx>), } /// Checks the coherence orphan rules. `impl_def_id` should be the /// def-id of a trait impl. To pass, either the trait must be local, or else /// two conditions must be satisfied: /// -/// 1. At least one of the input types must involve a local type. -/// 2. All type parameters must be covered by a local type. -pub fn orphan_check(tcx: &ty::ctxt, - impl_def_id: ast::DefId) - -> Result<(), OrphanCheckErr> +/// 1. All type parameters in `Self` must be "covered" by some local type constructor. +/// 2. Some local type must appear in `Self`. +pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>, + impl_def_id: ast::DefId) + -> Result<(), OrphanCheckErr<'tcx>> { debug!("impl_is_local({})", impl_def_id.repr(tcx)); @@ -82,31 +82,21 @@ pub fn orphan_check(tcx: &ty::ctxt, return Ok(()); } - // Check condition 1: at least one type must be local. - if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) { - return Err(OrphanCheckErr::NoLocalInputType); + // Otherwise, check that (1) all type parameters are covered. + let covered_params = type_parameters_covered_by_ty(tcx, trait_ref.self_ty()); + let all_params = type_parameters_reachable_from_ty(trait_ref.self_ty()); + for ¶m in all_params.difference(&covered_params) { + return Err(OrphanCheckErr::UncoveredTy(param)); } - // Check condition 2: type parameters must be "covered" by a local type. - let covered_params: HashSet<_> = - trait_ref.input_types().iter() - .flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter()) - .collect(); - let all_params: HashSet<_> = - trait_ref.input_types().iter() - .flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter()) - .collect(); - for ¶m in all_params.difference(&covered_params) { - return Err(OrphanCheckErr::UncoveredTypeParameter(param)); + // And (2) some local type appears. + if !trait_ref.self_ty().walk().any(|t| ty_is_local_constructor(tcx, t)) { + return Err(OrphanCheckErr::NoLocalInputType); } return Ok(()); } -fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - ty.walk().any(|t| ty_is_local_constructor(tcx, t)) -} - fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { debug!("ty_is_local_constructor({})", ty.repr(tcx)); @@ -154,8 +144,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { } fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>, - ty: Ty<'tcx>) - -> HashSet + ty: Ty<'tcx>) + -> HashSet> { if ty_is_local_constructor(tcx, ty) { type_parameters_reachable_from_ty(ty) @@ -165,14 +155,14 @@ fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>, } /// All type parameters reachable from `ty` -fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet { +fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet> { ty.walk() - .filter_map(|t| { + .filter(|&t| { match t.sty { - ty::ty_param(ref param_ty) => Some(param_ty.clone()), - _ => None, + // FIXME(#20590) straighten story about projection types + ty::ty_projection(..) | ty::ty_param(..) => true, + _ => false, } }) .collect() } - diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 153c6463fbebb..0bc76e1baab84 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -22,7 +22,7 @@ use super::TupleArgumentsFlag; use super::write_call; use middle::infer; -use middle::ty::{mod, Ty}; +use middle::ty::{self, Ty}; use syntax::ast; use syntax::codemap::Span; use syntax::parse::token; diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 1da49799712bd..dc22fd597e689 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -72,20 +72,30 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { ast::ItemImpl(_, _, Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); + let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id; match traits::orphan_check(self.tcx, def_id) { Ok(()) => { } Err(traits::OrphanCheckErr::NoLocalInputType) => { - span_err!(self.tcx.sess, item.span, E0117, - "cannot provide an extension implementation \ - where both trait and type are not defined in this crate"); + if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { + let self_ty = ty::lookup_item_type(self.tcx, def_id).ty; + span_err!( + self.tcx.sess, item.span, E0117, + "the type `{}` does not reference any \ + types defined in this crate; \ + only traits defined in the current crate can be \ + implemented for arbitrary types", + self_ty.user_string(self.tcx)); + } } - Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => { - if !self.tcx.sess.features.borrow().old_orphan_check { + Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { + if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { self.tcx.sess.span_err( item.span, - format!("type parameter `{}` must also appear as a type parameter \ - of some type defined within this crate", - param_ty.user_string(self.tcx)).as_slice()); + format!( + "type parameter `{}` is not constrained by any local type; \ + only traits defined in the current crate can be implemented \ + for a type parameter", + param_ty.user_string(self.tcx)).as_slice()); self.tcx.sess.span_note( item.span, format!("for a limited time, you can add \ diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f75873ac1c0f7..f08c40ff0997b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -301,6 +301,14 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { removed in the future"); } + if attr::contains_name(i.attrs[], + "old_orphan_check") { + self.gate_feature( + "old_orphan_check", + i.span, + "the new orphan check rules will eventually be strictly enforced"); + } + for item in items.iter() { match *item { ast::MethodImplItem(_) => {} diff --git a/src/test/compile-fail/coherence-all-remote.rs b/src/test/compile-fail/coherence-all-remote.rs index 67d96aa95a6a2..d88b8751ea7b0 100644 --- a/src/test/compile-fail/coherence-all-remote.rs +++ b/src/test/compile-fail/coherence-all-remote.rs @@ -14,6 +14,6 @@ extern crate "coherence-lib" as lib; use lib::Remote; impl Remote for int { } -//~^ ERROR cannot provide an extension implementation +//~^ ERROR E0117 fn main() { } diff --git a/src/test/run-pass/coherence-bigint-int.rs b/src/test/compile-fail/coherence-bigint-int.rs similarity index 92% rename from src/test/run-pass/coherence-bigint-int.rs rename to src/test/compile-fail/coherence-bigint-int.rs index 1e90453980f86..b4917d0c29f37 100644 --- a/src/test/run-pass/coherence-bigint-int.rs +++ b/src/test/compile-fail/coherence-bigint-int.rs @@ -15,6 +15,6 @@ use lib::Remote1; pub struct BigInt; -impl Remote1 for int { } +impl Remote1 for int { } //~ ERROR E0117 fn main() { } diff --git a/src/test/compile-fail/coherence-bigint-param.rs b/src/test/compile-fail/coherence-bigint-param.rs index a04dfd36c98f1..b8e48436a4143 100644 --- a/src/test/compile-fail/coherence-bigint-param.rs +++ b/src/test/compile-fail/coherence-bigint-param.rs @@ -16,6 +16,6 @@ use lib::Remote1; pub struct BigInt; impl Remote1 for T { } -//~^ ERROR type parameter `T` must also appear +//~^ ERROR type parameter `T` is not constrained fn main() { } diff --git a/src/test/run-pass/coherence-bigint-vecint.rs b/src/test/compile-fail/coherence-bigint-vecint.rs similarity index 91% rename from src/test/run-pass/coherence-bigint-vecint.rs rename to src/test/compile-fail/coherence-bigint-vecint.rs index b100455eb339c..de4e656110f29 100644 --- a/src/test/run-pass/coherence-bigint-vecint.rs +++ b/src/test/compile-fail/coherence-bigint-vecint.rs @@ -15,6 +15,6 @@ use lib::Remote1; pub struct BigInt; -impl Remote1 for Vec { } +impl Remote1 for Vec { } //~ ERROR E0117 fn main() { } diff --git a/src/test/compile-fail/coherence-cross-crate-conflict.rs b/src/test/compile-fail/coherence-cross-crate-conflict.rs index 99446be43acaa..8bdd5c58f3199 100644 --- a/src/test/compile-fail/coherence-cross-crate-conflict.rs +++ b/src/test/compile-fail/coherence-cross-crate-conflict.rs @@ -16,7 +16,7 @@ extern crate trait_impl_conflict; use trait_impl_conflict::Foo; impl Foo for A { - //~^ ERROR E0117 + //~^ ERROR type parameter `A` is not constrained //~^^ ERROR E0119 } diff --git a/src/test/compile-fail/coherence-lone-type-parameter.rs b/src/test/compile-fail/coherence-lone-type-parameter.rs index 0223dacd8eca0..917438722de4e 100644 --- a/src/test/compile-fail/coherence-lone-type-parameter.rs +++ b/src/test/compile-fail/coherence-lone-type-parameter.rs @@ -13,6 +13,6 @@ extern crate "coherence-lib" as lib; use lib::Remote; -impl Remote for T { } //~ ERROR E0117 +impl Remote for T { } //~ ERROR type parameter `T` is not constrained fn main() { } diff --git a/src/test/compile-fail/coherence-orphan.rs b/src/test/compile-fail/coherence-orphan.rs index c44b0da5b154f..30a382c143dab 100644 --- a/src/test/compile-fail/coherence-orphan.rs +++ b/src/test/compile-fail/coherence-orphan.rs @@ -18,7 +18,7 @@ struct TheType; impl TheTrait for int { } //~ ERROR E0117 -impl TheTrait for int { } +impl TheTrait for int { } //~ ERROR E0117 impl TheTrait for TheType { } diff --git a/src/test/compile-fail/coherence-overlapping-pairs.rs b/src/test/compile-fail/coherence-overlapping-pairs.rs index d42bd529b6665..9354e66af0d81 100644 --- a/src/test/compile-fail/coherence-overlapping-pairs.rs +++ b/src/test/compile-fail/coherence-overlapping-pairs.rs @@ -16,6 +16,6 @@ use lib::Remote; struct Foo; impl Remote for lib::Pair { } -//~^ ERROR type parameter `T` must also appear +//~^ ERROR type parameter `T` is not constrained fn main() { } diff --git a/src/test/compile-fail/coherence-pair-covered-uncovered.rs b/src/test/compile-fail/coherence-pair-covered-uncovered.rs index 09895ec11db10..92a07b3585292 100644 --- a/src/test/compile-fail/coherence-pair-covered-uncovered.rs +++ b/src/test/compile-fail/coherence-pair-covered-uncovered.rs @@ -16,6 +16,6 @@ use lib::{Remote, Pair}; struct Local(T); impl Remote for Pair> { } -//~^ ERROR type parameter `T` must also appear +//~^ ERROR type parameter `T` is not constrained fn main() { } diff --git a/src/test/compile-fail/drop-on-non-struct.rs b/src/test/compile-fail/drop-on-non-struct.rs index 8304afa1141ee..238700254b8fd 100644 --- a/src/test/compile-fail/drop-on-non-struct.rs +++ b/src/test/compile-fail/drop-on-non-struct.rs @@ -10,7 +10,7 @@ impl Drop for int { //~^ ERROR the Drop trait may only be implemented on structures - //~^^ ERROR cannot provide an extension implementation + //~^^ ERROR E0117 fn drop(&mut self) { println!("kaboom"); } diff --git a/src/test/compile-fail/coherence-iterator-vec-any-elem.rs b/src/test/run-pass/coherence-iterator-vec-any-elem.rs similarity index 92% rename from src/test/compile-fail/coherence-iterator-vec-any-elem.rs rename to src/test/run-pass/coherence-iterator-vec-any-elem.rs index 2ed7a6db7ae1c..6dc2ff4588b67 100644 --- a/src/test/compile-fail/coherence-iterator-vec-any-elem.rs +++ b/src/test/run-pass/coherence-iterator-vec-any-elem.rs @@ -16,6 +16,5 @@ use lib::Remote1; struct Foo(T); impl Remote1 for Foo { } -//~^ ERROR type parameter `U` must also appear fn main() { } From c6f4a03d12d97162e2775c14ab006d355b04126d Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Sun, 4 Jan 2015 16:16:55 -0800 Subject: [PATCH 087/106] Stabilization of impls and fallout from stabilization --- src/liballoc/arc.rs | 6 +++--- src/liballoc/boxed.rs | 2 ++ src/liballoc/rc.rs | 6 +++--- src/libcollections/binary_heap.rs | 4 ++++ src/libcollections/lib.rs | 3 +-- src/libcollections/slice.rs | 1 + src/libcollections/str.rs | 6 ++++++ src/libcollections/string.rs | 8 ++++---- src/libcollections/vec.rs | 19 ++++++++++++++---- src/libcore/borrow.rs | 1 + src/libcore/cell.rs | 6 +++--- src/libcore/char.rs | 2 ++ src/libcore/iter.rs | 2 +- src/libcore/ops.rs | 4 ++++ src/libcore/option.rs | 9 +++++++++ src/libcore/prelude.rs | 3 +-- src/libcore/result.rs | 9 +++++++++ src/libcore/slice.rs | 31 +++++++++++++++--------------- src/libcore/str/mod.rs | 30 ++++++++++++++++++++++------- src/libstd/collections/hash/set.rs | 2 +- src/libstd/io/buffered.rs | 2 +- src/libstd/prelude/v1.rs | 2 -- src/libstd/sync/condvar.rs | 1 + src/libstd/sync/mpsc/mod.rs | 5 ++++- src/libstd/sync/mpsc/mpsc_queue.rs | 1 + src/libstd/sync/mutex.rs | 4 ++++ src/libstd/sync/rwlock.rs | 6 ++++++ src/libstd/sync/semaphore.rs | 1 + src/libstd/thread.rs | 1 + 29 files changed, 128 insertions(+), 49 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 88f02d6573eac..25f80ad11bd11 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -246,7 +246,7 @@ impl BorrowFrom> for T { } } -#[experimental = "Deref is experimental."] +#[stable] impl Deref for Arc { type Target = T; @@ -290,7 +290,7 @@ impl Arc { } #[unsafe_destructor] -#[experimental = "waiting on stability of Drop"] +#[stable] impl Drop for Arc { /// Drops the `Arc`. /// @@ -418,7 +418,7 @@ impl Clone for Weak { } #[unsafe_destructor] -#[experimental = "Weak pointers may not belong in this module."] +#[stable] impl Drop for Weak { /// Drops the `Weak`. /// diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2c318181b0995..33d1cc7f4c745 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -155,12 +155,14 @@ impl fmt::Show for Box { } } +#[stable] impl Deref for Box { type Target = T; fn deref(&self) -> &T { &**self } } +#[stable] impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c4b455aff5c53..175bba4e71dc4 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -354,7 +354,7 @@ impl BorrowFrom> for T { } } -#[experimental = "Deref is experimental."] +#[stable] impl Deref for Rc { type Target = T; @@ -365,7 +365,7 @@ impl Deref for Rc { } #[unsafe_destructor] -#[experimental = "Drop is experimental."] +#[stable] impl Drop for Rc { /// Drops the `Rc`. /// @@ -656,7 +656,7 @@ impl Weak { } #[unsafe_destructor] -#[experimental = "Weak pointers may not belong in this module."] +#[stable] impl Drop for Weak { /// Drops the `Weak`. /// diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 619a6e9427199..01693391abed5 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -562,11 +562,13 @@ impl BinaryHeap { } /// `BinaryHeap` iterator. +#[stable] pub struct Iter <'a, T: 'a> { iter: slice::Iter<'a, T>, } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` +#[stable] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { iter: self.iter.clone() } @@ -594,6 +596,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { impl<'a, T> ExactSizeIterator for Iter<'a, T> {} /// An iterator that moves out of a `BinaryHeap`. +#[stable] pub struct IntoIter { iter: vec::IntoIter, } @@ -619,6 +622,7 @@ impl DoubleEndedIterator for IntoIter { impl ExactSizeIterator for IntoIter {} /// An iterator that drains a `BinaryHeap`. +#[unstable = "recent addition"] pub struct Drain<'a, T: 'a> { iter: vec::Drain<'a, T>, } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 72cdae8ba3102..c9b090bfb2323 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -113,8 +113,7 @@ mod prelude { pub use core::iter::range; pub use core::iter::{FromIterator, Extend, IteratorExt}; pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator}; - pub use core::iter::{IteratorCloneExt, CloneIteratorExt}; - pub use core::iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator}; + pub use core::iter::{ExactSizeIterator}; pub use core::kinds::{Copy, Send, Sized, Sync}; pub use core::mem::drop; pub use core::ops::{Drop, Fn, FnMut, FnOnce}; diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ceccca561aec7..e3bf5d63b1dfd 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1092,6 +1092,7 @@ struct SizeDirection { dir: Direction, } +#[stable] impl Iterator for ElementSwaps { type Item = (uint, uint); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ecf17820d2d8f..9f3ab6dd5c0cb 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -165,6 +165,7 @@ enum DecompositionType { /// External iterator for a string's decomposition's characters. /// Use with the `std::iter` module. #[derive(Clone)] +#[unstable] pub struct Decompositions<'a> { kind: DecompositionType, iter: Chars<'a>, @@ -172,6 +173,7 @@ pub struct Decompositions<'a> { sorted: bool } +#[stable] impl<'a> Iterator for Decompositions<'a> { type Item = char; @@ -253,6 +255,7 @@ enum RecompositionState { /// External iterator for a string's recomposition's characters. /// Use with the `std::iter` module. #[derive(Clone)] +#[unstable] pub struct Recompositions<'a> { iter: Decompositions<'a>, state: RecompositionState, @@ -261,6 +264,7 @@ pub struct Recompositions<'a> { last_ccc: Option } +#[stable] impl<'a> Iterator for Recompositions<'a> { type Item = char; @@ -348,10 +352,12 @@ impl<'a> Iterator for Recompositions<'a> { /// External iterator for a string's UTF16 codeunits. /// Use with the `std::iter` module. #[derive(Clone)] +#[unstable] pub struct Utf16Units<'a> { encoder: Utf16Encoder> } +#[stable] impl<'a> Iterator for Utf16Units<'a> { type Item = u16; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e7451331908ae..8ffca7e57b20e 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -711,7 +711,7 @@ impl fmt::Show for FromUtf16Error { } } -#[experimental = "waiting on FromIterator stabilization"] +#[stable] impl FromIterator for String { fn from_iter>(iterator: I) -> String { let mut buf = String::new(); @@ -720,7 +720,7 @@ impl FromIterator for String { } } -#[experimental = "waiting on FromIterator stabilization"] +#[stable] impl<'a> FromIterator<&'a str> for String { fn from_iter>(iterator: I) -> String { let mut buf = String::new(); @@ -832,7 +832,7 @@ impl hash::Hash for String { } } -#[experimental = "waiting on Add stabilization"] +#[unstable = "recent addition, needs more experience"] impl<'a> Add<&'a str> for String { type Output = String; @@ -864,7 +864,7 @@ impl ops::Slice for String { } } -#[experimental = "waiting on Deref stabilization"] +#[stable] impl ops::Deref for String { type Target = str; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index b8f97799c9718..b8bcba84cee08 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1272,19 +1272,19 @@ impl ops::SliceMut for Vec { } } -#[experimental = "waiting on Deref stability"] +#[stable] impl ops::Deref for Vec { type Target = [T]; fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() } } -#[experimental = "waiting on DerefMut stability"] +#[stable] impl ops::DerefMut for Vec { fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() } } -#[experimental = "waiting on FromIterator stability"] +#[stable] impl FromIterator for Vec { #[inline] fn from_iter>(mut iterator: I) -> Vec { @@ -1414,6 +1414,7 @@ impl AsSlice for Vec { } } +#[unstable = "recent addition, needs more experience"] impl<'a, T: Clone> Add<&'a [T]> for Vec { type Output = Vec; @@ -1425,6 +1426,7 @@ impl<'a, T: Clone> Add<&'a [T]> for Vec { } #[unsafe_destructor] +#[stable] impl Drop for Vec { fn drop(&mut self) { // This is (and should always remain) a no-op if the fields are @@ -1470,6 +1472,7 @@ impl<'a> fmt::Writer for Vec { /// A clone-on-write vector pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; +#[unstable] impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { fn from_iter>(it: I) -> CowVec<'a, T> { Cow::Owned(FromIterator::from_iter(it)) @@ -1515,6 +1518,7 @@ impl IntoIter { } } +#[stable] impl Iterator for IntoIter { type Item = T; @@ -1551,6 +1555,7 @@ impl Iterator for IntoIter { } } +#[stable] impl DoubleEndedIterator for IntoIter { #[inline] fn next_back<'a>(&'a mut self) -> Option { @@ -1574,9 +1579,11 @@ impl DoubleEndedIterator for IntoIter { } } +#[stable] impl ExactSizeIterator for IntoIter {} #[unsafe_destructor] +#[stable] impl Drop for IntoIter { fn drop(&mut self) { // destroy the remaining elements @@ -1598,6 +1605,7 @@ pub struct Drain<'a, T> { marker: ContravariantLifetime<'a>, } +#[stable] impl<'a, T> Iterator for Drain<'a, T> { type Item = T; @@ -1634,6 +1642,7 @@ impl<'a, T> Iterator for Drain<'a, T> { } } +#[stable] impl<'a, T> DoubleEndedIterator for Drain<'a, T> { #[inline] fn next_back(&mut self) -> Option { @@ -1657,9 +1666,11 @@ impl<'a, T> DoubleEndedIterator for Drain<'a, T> { } } +#[stable] impl<'a, T> ExactSizeIterator for Drain<'a, T> {} #[unsafe_destructor] +#[stable] impl<'a, T> Drop for Drain<'a, T> { fn drop(&mut self) { // self.ptr == self.end == null if drop has already been called, @@ -1692,7 +1703,7 @@ impl<'a, T> Deref for DerefVec<'a, T> { // Prevent the inner `Vec` from attempting to deallocate memory. #[unsafe_destructor] -#[experimental] +#[stable] impl<'a, T> Drop for DerefVec<'a, T> { fn drop(&mut self) { self.x.len = 0; diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d8d..63b3be00f55f5 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -191,6 +191,7 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned { } } +#[stable] impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { type Target = B; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index eb772388dce22..fd18d6ac3f3b4 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -419,7 +419,7 @@ pub struct Ref<'b, T:'b> { _borrow: BorrowRef<'b>, } -#[unstable = "waiting for `Deref` to become stable"] +#[stable] impl<'b, T> Deref for Ref<'b, T> { type Target = T; @@ -477,7 +477,7 @@ pub struct RefMut<'b, T:'b> { _borrow: BorrowRefMut<'b>, } -#[unstable = "waiting for `Deref` to become stable"] +#[stable] impl<'b, T> Deref for RefMut<'b, T> { type Target = T; @@ -487,7 +487,7 @@ impl<'b, T> Deref for RefMut<'b, T> { } } -#[unstable = "waiting for `DerefMut` to become stable"] +#[stable] impl<'b, T> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut<'a>(&'a mut self) -> &'a mut T { diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 291b7f2ece445..caac894c0daa3 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -314,6 +314,7 @@ pub struct EscapeUnicode { } #[derive(Clone)] +#[unstable] enum EscapeUnicodeState { Backslash, Type, @@ -375,6 +376,7 @@ pub struct EscapeDefault { } #[derive(Clone)] +#[unstable] enum EscapeDefaultState { Backslash(char), Char(char), diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 4782a763dc89a..e5753f6cc2e78 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2401,7 +2401,7 @@ impl Unfold where F: FnMut(&mut St) -> Option { } } -#[experimental] +#[stable] impl Iterator for Unfold where F: FnMut(&mut St) -> Option { type Item = A; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index da2e95832e71a..74702c66f7ba5 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -984,6 +984,7 @@ pub struct Range { // FIXME(#19391) needs a snapshot //impl> Iterator for Range { +#[unstable = "API still in development"] impl Iterator for Range { type Item = Idx; @@ -1008,6 +1009,7 @@ impl Iterator for Range { } } +#[unstable = "API still in development"] impl DoubleEndedIterator for Range { #[inline] fn next_back(&mut self) -> Option { @@ -1020,6 +1022,7 @@ impl DoubleEndedIterator for Range { } } +#[unstable = "API still in development"] impl ExactSizeIterator for Range {} /// A range which is only bounded below. @@ -1031,6 +1034,7 @@ pub struct RangeFrom { pub start: Idx, } +#[unstable = "API still in development"] impl Iterator for RangeFrom { type Item = Idx; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a9a1857ec97bf..39d0f024d4d41 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -807,6 +807,7 @@ impl ExactSizeIterator for Item {} #[stable] pub struct Iter<'a, A: 'a> { inner: Item<&'a A> } +#[stable] impl<'a, A> Iterator for Iter<'a, A> { type Item = &'a A; @@ -816,11 +817,13 @@ impl<'a, A> Iterator for Iter<'a, A> { fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } +#[stable] impl<'a, A> DoubleEndedIterator for Iter<'a, A> { #[inline] fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() } } +#[stable] impl<'a, A> ExactSizeIterator for Iter<'a, A> {} #[stable] @@ -834,6 +837,7 @@ impl<'a, A> Clone for Iter<'a, A> { #[stable] pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> } +#[stable] impl<'a, A> Iterator for IterMut<'a, A> { type Item = &'a mut A; @@ -843,17 +847,20 @@ impl<'a, A> Iterator for IterMut<'a, A> { fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } +#[stable] impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { #[inline] fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() } } +#[stable] impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} /// An iterator over the item contained inside an Option. #[stable] pub struct IntoIter { inner: Item } +#[stable] impl Iterator for IntoIter { type Item = A; @@ -863,11 +870,13 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } } +#[stable] impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } } +#[stable] impl ExactSizeIterator for IntoIter {} ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index d4aca1bb73c23..e88cb73c8a9b7 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -43,8 +43,7 @@ pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; pub use iter::{Extend, IteratorExt}; pub use iter::{Iterator, DoubleEndedIterator}; -pub use iter::{IteratorCloneExt, CloneIteratorExt}; -pub use iter::{IteratorOrdExt, ExactSizeIterator}; +pub use iter::{ExactSizeIterator}; pub use option::Option::{self, Some, None}; pub use ptr::{PtrExt, MutPtrExt}; pub use result::Result::{self, Ok, Err}; diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 7135faaa76516..7293ed6455b08 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -807,6 +807,7 @@ impl AsSlice for Result { #[stable] pub struct Iter<'a, T: 'a> { inner: Option<&'a T> } +#[stable] impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; @@ -819,11 +820,13 @@ impl<'a, T> Iterator for Iter<'a, T> { } } +#[stable] impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a T> { self.inner.take() } } +#[stable] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} impl<'a, T> Clone for Iter<'a, T> { @@ -834,6 +837,7 @@ impl<'a, T> Clone for Iter<'a, T> { #[stable] pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> } +#[stable] impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; @@ -846,17 +850,20 @@ impl<'a, T> Iterator for IterMut<'a, T> { } } +#[stable] impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut T> { self.inner.take() } } +#[stable] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} /// An iterator over the value in a `Ok` variant of a `Result`. #[stable] pub struct IntoIter { inner: Option } +#[stable] impl Iterator for IntoIter { type Item = T; @@ -869,11 +876,13 @@ impl Iterator for IntoIter { } } +#[stable] impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.inner.take() } } +#[stable] impl ExactSizeIterator for IntoIter {} ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 8174596e65e52..7161bfdcd5a9e 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -672,7 +672,7 @@ impl<'a, T> Default for &'a [T] { // The shared definition of the `Iter` and `IterMut` iterators macro_rules! iterator { (struct $name:ident -> $ptr:ty, $elem:ty) => { - #[experimental = "needs review"] + #[stable] impl<'a, T> Iterator for $name<'a, T> { type Item = $elem; @@ -710,7 +710,7 @@ macro_rules! iterator { } } - #[experimental = "needs review"] + #[stable] impl<'a, T> DoubleEndedIterator for $name<'a, T> { #[inline] fn next_back(&mut self) -> Option<$elem> { @@ -793,7 +793,7 @@ impl<'a,T> Copy for Iter<'a,T> {} iterator!{struct Iter -> *const T, &'a T} -#[experimental = "needs review"] +#[stable] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[stable] @@ -801,7 +801,7 @@ impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { *self } } -#[experimental = "needs review"] +#[experimental = "trait is experimental"] impl<'a, T> RandomAccessIterator for Iter<'a, T> { #[inline] fn indexable(&self) -> uint { @@ -887,7 +887,7 @@ impl<'a, T> IterMut<'a, T> { iterator!{struct IterMut -> *mut T, &'a mut T} -#[experimental = "needs review"] +#[stable] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} /// An internal abstraction over the splitting iterators, so that @@ -919,7 +919,7 @@ impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool { } } -#[experimental = "needs review"] +#[stable] impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { type Item = &'a [T]; @@ -947,7 +947,7 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { } } -#[experimental = "needs review"] +#[stable] impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { @@ -992,7 +992,7 @@ impl<'a, T, P> SplitIter for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { } } -#[experimental = "needs review"] +#[stable] impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { type Item = &'a mut [T]; @@ -1027,7 +1027,7 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { } } -#[experimental = "needs review"] +#[stable] impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool, { @@ -1060,7 +1060,6 @@ struct GenericSplitN { invert: bool } -#[experimental = "needs review"] impl> Iterator for GenericSplitN { type Item = T; @@ -1113,6 +1112,7 @@ pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { macro_rules! forward_iterator { ($name:ident: $elem:ident, $iter_of:ty) => { + #[stable] impl<'a, $elem, P> Iterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool { @@ -1144,6 +1144,7 @@ pub struct Windows<'a, T:'a> { size: uint } +#[stable] impl<'a, T> Iterator for Windows<'a, T> { type Item = &'a [T]; @@ -1181,7 +1182,7 @@ pub struct Chunks<'a, T:'a> { size: uint } -#[experimental = "needs review"] +#[stable] impl<'a, T> Iterator for Chunks<'a, T> { type Item = &'a [T]; @@ -1210,7 +1211,7 @@ impl<'a, T> Iterator for Chunks<'a, T> { } } -#[experimental = "needs review"] +#[stable] impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { @@ -1226,7 +1227,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } } -#[experimental = "needs review"] +#[experimental = "trait is experimental"] impl<'a, T> RandomAccessIterator for Chunks<'a, T> { #[inline] fn indexable(&self) -> uint { @@ -1256,7 +1257,7 @@ pub struct ChunksMut<'a, T:'a> { chunk_size: uint } -#[experimental = "needs review"] +#[stable] impl<'a, T> Iterator for ChunksMut<'a, T> { type Item = &'a mut [T]; @@ -1286,7 +1287,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> { } } -#[experimental = "needs review"] +#[stable] impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..a3c6a3fe470c3 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -37,11 +37,8 @@ use uint; macro_rules! delegate_iter { (exact $te:ty in $ti:ty) => { delegate_iter!{$te in $ti} + #[stable] impl<'a> ExactSizeIterator for $ti { - #[inline] - fn rposition

(&mut self, predicate: P) -> Option where P: FnMut($te) -> bool{ - self.0.rposition(predicate) - } #[inline] fn len(&self) -> uint { self.0.len() @@ -49,6 +46,7 @@ macro_rules! delegate_iter { } }; ($te:ty in $ti:ty) => { + #[stable] impl<'a> Iterator for $ti { type Item = $te; @@ -61,6 +59,7 @@ macro_rules! delegate_iter { self.0.size_hint() } } + #[stable] impl<'a> DoubleEndedIterator for $ti { #[inline] fn next_back(&mut self) -> Option<$te> { @@ -69,6 +68,7 @@ macro_rules! delegate_iter { } }; (pattern $te:ty in $ti:ty) => { + #[stable] impl<'a, P: CharEq> Iterator for $ti { type Item = $te; @@ -81,6 +81,7 @@ macro_rules! delegate_iter { self.0.size_hint() } } + #[stable] impl<'a, P: CharEq> DoubleEndedIterator for $ti { #[inline] fn next_back(&mut self) -> Option<$te> { @@ -89,6 +90,7 @@ macro_rules! delegate_iter { } }; (pattern forward $te:ty in $ti:ty) => { + #[stable] impl<'a, P: CharEq> Iterator for $ti { type Item = $te; @@ -275,6 +277,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 { } } +#[stable] impl<'a> Iterator for Chars<'a> { type Item = char; @@ -320,6 +323,7 @@ impl<'a> Iterator for Chars<'a> { } } +#[stable] impl<'a> DoubleEndedIterator for Chars<'a> { #[inline] fn next_back(&mut self) -> Option { @@ -356,11 +360,13 @@ impl<'a> DoubleEndedIterator for Chars<'a> { /// External iterator for a string's characters and their byte offsets. /// Use with the `std::iter` module. #[derive(Clone)] +#[stable] pub struct CharIndices<'a> { front_offset: uint, iter: Chars<'a>, } +#[stable] impl<'a> Iterator for CharIndices<'a> { type Item = (uint, char); @@ -384,6 +390,7 @@ impl<'a> Iterator for CharIndices<'a> { } } +#[stable] impl<'a> DoubleEndedIterator for CharIndices<'a> { #[inline] fn next_back(&mut self) -> Option<(uint, char)> { @@ -465,6 +472,7 @@ impl<'a, Sep> CharSplits<'a, Sep> { } } +#[stable] impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> { type Item = &'a str; @@ -499,6 +507,7 @@ impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> { } } +#[stable] impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> { #[inline] fn next_back(&mut self) -> Option<&'a str> { @@ -540,6 +549,7 @@ impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> { } } +#[stable] impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> { type Item = &'a str; @@ -865,6 +875,7 @@ pub struct SplitStr<'a> { finished: bool } +#[stable] impl<'a> Iterator for MatchIndices<'a> { type Item = (uint, uint); @@ -881,6 +892,7 @@ impl<'a> Iterator for MatchIndices<'a> { } } +#[stable] impl<'a> Iterator for SplitStr<'a> { type Item = &'a str; @@ -1586,6 +1598,7 @@ impl<'a> Default for &'a str { fn default() -> &'a str { "" } } +#[stable] impl<'a> Iterator for Lines<'a> { type Item = &'a str; @@ -1593,11 +1606,13 @@ impl<'a> Iterator for Lines<'a> { fn next(&mut self) -> Option<&'a str> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } -} + +#[stable]} impl<'a> DoubleEndedIterator for Lines<'a> { #[inline] fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() } -} + +#[stable]} impl<'a> Iterator for LinesAny<'a> { type Item = &'a str; @@ -1605,7 +1620,8 @@ impl<'a> Iterator for LinesAny<'a> { fn next(&mut self) -> Option<&'a str> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option) { self.inner.size_hint() } -} + +#[stable]} impl<'a> DoubleEndedIterator for LinesAny<'a> { #[inline] fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b1824db93aad1..c44d6c34cd946 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -18,7 +18,7 @@ use default::Default; use fmt::Show; use fmt; use hash::{Hash, Hasher, RandomSipHasher}; -use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend}; +use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend}; use ops::{BitOr, BitAnd, BitXor, Sub}; use option::Option::{Some, None, self}; use result::Result::{Ok, Err}; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c56acd38e810f..c4e37264e2aee 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -14,7 +14,7 @@ use cmp; use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; -use iter::ExactSizeIterator; +use iter::{IteratorExt, ExactSizeIterator}; use ops::Drop; use option::Option; use option::Option::{Some, None}; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index f6bdcd53dff24..9e9a483e1a5e3 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -25,11 +25,9 @@ #[stable] #[doc(no_inline)] pub use char::CharExt; #[stable] #[doc(no_inline)] pub use clone::Clone; #[stable] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -#[stable] #[doc(no_inline)] pub use iter::CloneIteratorExt; #[stable] #[doc(no_inline)] pub use iter::DoubleEndedIterator; #[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator; #[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; -#[stable] #[doc(no_inline)] pub use iter::{IteratorCloneExt, IteratorOrdExt}; #[stable] #[doc(no_inline)] pub use option::Option::{self, Some, None}; #[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; #[stable] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 7734f655ed293..e97be51fdbc25 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -188,6 +188,7 @@ impl Condvar { pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } } } +#[stable] impl Drop for Condvar { fn drop(&mut self) { unsafe { self.inner.inner.destroy() } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6bc3f561bb3c7..09ff8f440f33e 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -657,6 +657,7 @@ impl Clone for Sender { } #[unsafe_destructor] +#[stable] impl Drop for Sender { fn drop(&mut self) { match *unsafe { self.inner_mut() } { @@ -720,6 +721,7 @@ impl Clone for SyncSender { } #[unsafe_destructor] +#[stable] impl Drop for SyncSender { fn drop(&mut self) { unsafe { (*self.inner.get()).drop_chan(); } @@ -935,7 +937,7 @@ impl select::Packet for Receiver { } } -#[unstable] +#[stable] impl<'a, T: Send> Iterator for Iter<'a, T> { type Item = T; @@ -943,6 +945,7 @@ impl<'a, T: Send> Iterator for Iter<'a, T> { } #[unsafe_destructor] +#[stable] impl Drop for Receiver { fn drop(&mut self) { match *unsafe { self.inner_mut() } { diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index 8f85dc6e043e2..9ad24a5a11ec5 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -138,6 +138,7 @@ impl Queue { } #[unsafe_destructor] +#[stable] impl Drop for Queue { fn drop(&mut self) { unsafe { diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index b158bd69c7b50..6b3dd89f33b07 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -228,6 +228,7 @@ impl Mutex { } #[unsafe_destructor] +#[stable] impl Drop for Mutex { fn drop(&mut self) { // This is actually safe b/c we know that there is no further usage of @@ -291,6 +292,7 @@ impl<'mutex, T> MutexGuard<'mutex, T> { } } +#[stable] impl<'mutex, T> Deref for MutexGuard<'mutex, T> { type Target = T; @@ -298,6 +300,7 @@ impl<'mutex, T> Deref for MutexGuard<'mutex, T> { unsafe { &*self.__data.get() } } } +#[stable] impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.__data.get() } @@ -305,6 +308,7 @@ impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { } #[unsafe_destructor] +#[stable] impl<'a, T> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index b2367ff8352fb..c8ca1b02aab1a 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -228,6 +228,7 @@ impl RWLock { } #[unsafe_destructor] +#[stable] impl Drop for RWLock { fn drop(&mut self) { unsafe { self.inner.lock.destroy() } @@ -327,16 +328,19 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { } } +#[stable] impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } +#[stable] impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } +#[stable] impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } @@ -344,6 +348,7 @@ impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> { } #[unsafe_destructor] +#[stable] impl<'a, T> Drop for RWLockReadGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.lock.read_unlock(); } @@ -351,6 +356,7 @@ impl<'a, T> Drop for RWLockReadGuard<'a, T> { } #[unsafe_destructor] +#[stable] impl<'a, T> Drop for RWLockWriteGuard<'a, T> { fn drop(&mut self) { self.__lock.poison.done(&self.__poison); diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index c0ff674ba0f7d..505819fbf8a24 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -99,6 +99,7 @@ impl Semaphore { } #[unsafe_destructor] +#[stable] impl<'a> Drop for SemaphoreGuard<'a> { fn drop(&mut self) { self.sem.release(); diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 63112327415d2..cc82d38ae2af1 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -423,6 +423,7 @@ impl JoinGuard { } #[unsafe_destructor] +#[stable] impl Drop for JoinGuard { fn drop(&mut self) { if !self.joined { From f031671c6ea79391eeb3e1ad8f06fe0e436103fb Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 2 Jan 2015 12:21:00 -0500 Subject: [PATCH 088/106] Remove i suffix in docs --- src/liballoc/arc.rs | 52 +- src/liballoc/rc.rs | 54 +- src/libcollections/binary_heap.rs | 22 +- src/libcollections/btree/set.rs | 20 +- src/libcollections/dlist.rs | 10 +- src/libcollections/ring_buf.rs | 72 +- src/libcollections/slice.rs | 800 +++++++++------- src/libcollections/vec.rs | 58 +- src/libcore/atomic.rs | 18 +- src/libcore/fmt/num.rs | 2 +- src/libcore/iter.rs | 78 +- src/libcore/mem.rs | 8 +- src/libcore/num/mod.rs | 2 +- src/libcore/option.rs | 12 +- src/liblog/macros.rs | 4 +- src/librand/lib.rs | 4 +- src/libstd/collections/hash/set.rs | 28 +- src/libstd/macros.rs | 20 +- src/libstd/sync/mpsc/mod.rs | 1420 ++++++++++++++-------------- src/libstd/sync/rwlock.rs | 2 +- 20 files changed, 1392 insertions(+), 1294 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 88f02d6573eac..080d34dbda573 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -35,7 +35,7 @@ //! use std::sync::Arc; //! use std::thread::Thread; //! -//! let five = Arc::new(5i); +//! let five = Arc::new(5); //! //! for i in range(0u, 10) { //! let five = five.clone(); @@ -52,7 +52,7 @@ //! use std::sync::{Arc, Mutex}; //! use std::thread::Thread; //! -//! let five = Arc::new(Mutex::new(5i)); +//! let five = Arc::new(Mutex::new(5)); //! //! for _ in range(0u, 10) { //! let five = five.clone(); @@ -154,7 +154,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// ``` #[inline] #[stable] @@ -176,7 +176,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// /// let weak_five = five.downgrade(); /// ``` @@ -220,7 +220,7 @@ impl Clone for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// /// five.clone(); /// ``` @@ -267,7 +267,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let mut five = Arc::new(5i); + /// let mut five = Arc::new(5); /// /// let mut_five = five.make_unique(); /// ``` @@ -303,14 +303,14 @@ impl Drop for Arc { /// use std::sync::Arc; /// /// { - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// /// // stuff /// /// drop(five); // explict drop /// } /// { - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// /// // stuff /// @@ -369,7 +369,7 @@ impl Weak { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// /// let weak_five = five.downgrade(); /// @@ -405,7 +405,7 @@ impl Clone for Weak { /// ``` /// use std::sync::Arc; /// - /// let weak_five = Arc::new(5i).downgrade(); + /// let weak_five = Arc::new(5).downgrade(); /// /// weak_five.clone(); /// ``` @@ -430,7 +430,7 @@ impl Drop for Weak { /// use std::sync::Arc; /// /// { - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// let weak_five = five.downgrade(); /// /// // stuff @@ -438,7 +438,7 @@ impl Drop for Weak { /// drop(weak_five); // explict drop /// } /// { - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// let weak_five = five.downgrade(); /// /// // stuff @@ -472,9 +472,9 @@ impl PartialEq for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five == Arc::new(5i); + /// five == Arc::new(5); /// ``` fn eq(&self, other: &Arc) -> bool { *(*self) == *(*other) } @@ -487,9 +487,9 @@ impl PartialEq for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five != Arc::new(5i); + /// five != Arc::new(5); /// ``` fn ne(&self, other: &Arc) -> bool { *(*self) != *(*other) } } @@ -504,9 +504,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five.partial_cmp(&Arc::new(5i)); + /// five.partial_cmp(&Arc::new(5)); /// ``` fn partial_cmp(&self, other: &Arc) -> Option { (**self).partial_cmp(&**other) @@ -521,9 +521,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five < Arc::new(5i); + /// five < Arc::new(5); /// ``` fn lt(&self, other: &Arc) -> bool { *(*self) < *(*other) } @@ -536,9 +536,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five <= Arc::new(5i); + /// five <= Arc::new(5); /// ``` fn le(&self, other: &Arc) -> bool { *(*self) <= *(*other) } @@ -551,9 +551,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five > Arc::new(5i); + /// five > Arc::new(5); /// ``` fn gt(&self, other: &Arc) -> bool { *(*self) > *(*other) } @@ -566,9 +566,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5i); + /// let five = Arc::new(5); /// - /// five >= Arc::new(5i); + /// five >= Arc::new(5); /// ``` fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c4b455aff5c53..d9239e93a0740 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -187,7 +187,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// ``` #[stable] pub fn new(value: T) -> Rc { @@ -214,7 +214,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// /// let weak_five = five.downgrade(); /// ``` @@ -247,7 +247,7 @@ pub fn strong_count(this: &Rc) -> uint { this.strong() } /// use std::rc; /// use std::rc::Rc; /// -/// let five = Rc::new(5i); +/// let five = Rc::new(5); /// /// rc::is_unique(&five); /// ``` @@ -329,7 +329,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let mut five = Rc::new(5i); + /// let mut five = Rc::new(5); /// /// let mut_five = five.make_unique(); /// ``` @@ -378,14 +378,14 @@ impl Drop for Rc { /// use std::rc::Rc; /// /// { - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// /// // stuff /// /// drop(five); // explict drop /// } /// { - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// /// // stuff /// @@ -424,7 +424,7 @@ impl Clone for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// /// five.clone(); /// ``` @@ -465,9 +465,9 @@ impl PartialEq for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five == Rc::new(5i); + /// five == Rc::new(5); /// ``` #[inline(always)] fn eq(&self, other: &Rc) -> bool { **self == **other } @@ -481,9 +481,9 @@ impl PartialEq for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five != Rc::new(5i); + /// five != Rc::new(5); /// ``` #[inline(always)] fn ne(&self, other: &Rc) -> bool { **self != **other } @@ -503,9 +503,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five.partial_cmp(&Rc::new(5i)); + /// five.partial_cmp(&Rc::new(5)); /// ``` #[inline(always)] fn partial_cmp(&self, other: &Rc) -> Option { @@ -521,9 +521,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five < Rc::new(5i); + /// five < Rc::new(5); /// ``` #[inline(always)] fn lt(&self, other: &Rc) -> bool { **self < **other } @@ -537,9 +537,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five <= Rc::new(5i); + /// five <= Rc::new(5); /// ``` #[inline(always)] fn le(&self, other: &Rc) -> bool { **self <= **other } @@ -553,9 +553,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five > Rc::new(5i); + /// five > Rc::new(5); /// ``` #[inline(always)] fn gt(&self, other: &Rc) -> bool { **self > **other } @@ -569,9 +569,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five >= Rc::new(5i); + /// five >= Rc::new(5); /// ``` #[inline(always)] fn ge(&self, other: &Rc) -> bool { **self >= **other } @@ -588,9 +588,9 @@ impl Ord for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// - /// five.partial_cmp(&Rc::new(5i)); + /// five.partial_cmp(&Rc::new(5)); /// ``` #[inline] fn cmp(&self, other: &Rc) -> Ordering { (**self).cmp(&**other) } @@ -639,7 +639,7 @@ impl Weak { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// /// let weak_five = five.downgrade(); /// @@ -668,7 +668,7 @@ impl Drop for Weak { /// use std::rc::Rc; /// /// { - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// let weak_five = five.downgrade(); /// /// // stuff @@ -676,7 +676,7 @@ impl Drop for Weak { /// drop(weak_five); // explict drop /// } /// { - /// let five = Rc::new(5i); + /// let five = Rc::new(5); /// let weak_five = five.downgrade(); /// /// // stuff @@ -710,7 +710,7 @@ impl Clone for Weak { /// ``` /// use std::rc::Rc; /// - /// let weak_five = Rc::new(5i).downgrade(); + /// let weak_five = Rc::new(5).downgrade(); /// /// weak_five.clone(); /// ``` diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 4a550e5ce277d..82002f16133ec 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -211,7 +211,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]); + /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]); /// ``` pub fn from_vec(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; @@ -230,7 +230,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); + /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order /// for x in heap.iter() { @@ -250,7 +250,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); + /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order /// for x in heap.into_iter() { @@ -272,7 +272,7 @@ impl BinaryHeap { /// let mut heap = BinaryHeap::new(); /// assert_eq!(heap.peek(), None); /// - /// heap.push(1i); + /// heap.push(1); /// heap.push(5); /// heap.push(2); /// assert_eq!(heap.peek(), Some(&5)); @@ -355,7 +355,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let mut heap = BinaryHeap::from_vec(vec![1i, 3]); + /// let mut heap = BinaryHeap::from_vec(vec![1, 3]); /// /// assert_eq!(heap.pop(), Some(3)); /// assert_eq!(heap.pop(), Some(1)); @@ -379,7 +379,7 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); - /// heap.push(3i); + /// heap.push(3); /// heap.push(5); /// heap.push(1); /// @@ -401,7 +401,7 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); - /// heap.push(1i); + /// heap.push(1); /// heap.push(5); /// /// assert_eq!(heap.push_pop(3), 5); @@ -433,7 +433,7 @@ impl BinaryHeap { /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// - /// assert_eq!(heap.replace(1i), None); + /// assert_eq!(heap.replace(1), None); /// assert_eq!(heap.replace(3), Some(1)); /// assert_eq!(heap.len(), 1); /// assert_eq!(heap.peek(), Some(&3)); @@ -456,7 +456,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); + /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4, 5, 6, 7]); /// let vec = heap.into_vec(); /// /// // Will print in some order @@ -474,12 +474,12 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// - /// let mut heap = BinaryHeap::from_vec(vec![1i, 2, 4, 5, 7]); + /// let mut heap = BinaryHeap::from_vec(vec![1, 2, 4, 5, 7]); /// heap.push(6); /// heap.push(3); /// /// let vec = heap.into_sorted_vec(); - /// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]); + /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]); /// ``` pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 0406edcdd32e7..80d01c07547d1 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -245,7 +245,7 @@ impl BTreeSet { /// /// let mut v = BTreeSet::new(); /// assert_eq!(v.len(), 0); - /// v.insert(1i); + /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` #[stable] @@ -260,7 +260,7 @@ impl BTreeSet { /// /// let mut v = BTreeSet::new(); /// assert!(v.is_empty()); - /// v.insert(1i); + /// v.insert(1); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -274,7 +274,7 @@ impl BTreeSet { /// use std::collections::BTreeSet; /// /// let mut v = BTreeSet::new(); - /// v.insert(1i); + /// v.insert(1); /// v.clear(); /// assert!(v.is_empty()); /// ``` @@ -294,7 +294,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let set: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` @@ -311,7 +311,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let a: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); /// let mut b: BTreeSet = BTreeSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); @@ -332,7 +332,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let sup: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let sup: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); /// let mut set: BTreeSet = BTreeSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); @@ -374,7 +374,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let sub: BTreeSet = [1i, 2].iter().map(|&x| x).collect(); + /// let sub: BTreeSet = [1, 2].iter().map(|&x| x).collect(); /// let mut set: BTreeSet = BTreeSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); @@ -401,8 +401,8 @@ impl BTreeSet { /// /// let mut set = BTreeSet::new(); /// - /// assert_eq!(set.insert(2i), true); - /// assert_eq!(set.insert(2i), false); + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); /// assert_eq!(set.len(), 1); /// ``` #[stable] @@ -424,7 +424,7 @@ impl BTreeSet { /// /// let mut set = BTreeSet::new(); /// - /// set.insert(2i); + /// set.insert(2); /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index ca8e75ac43c8d..5aec9973c8112 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -230,9 +230,9 @@ impl DList { /// /// let mut a = DList::new(); /// let mut b = DList::new(); - /// a.push_back(1i); + /// a.push_back(1); /// a.push_back(2); - /// b.push_back(3i); + /// b.push_back(3); /// b.push_back(4); /// /// a.append(b); @@ -375,7 +375,7 @@ impl DList { /// use std::collections::DList; /// /// let mut d = DList::new(); - /// d.push_back(1i); + /// d.push_back(1); /// d.push_back(3); /// assert_eq!(3, *d.back().unwrap()); /// ``` @@ -394,7 +394,7 @@ impl DList { /// /// let mut d = DList::new(); /// assert_eq!(d.pop_back(), None); - /// d.push_back(1i); + /// d.push_back(1); /// d.push_back(3); /// assert_eq!(d.pop_back(), Some(3)); /// ``` @@ -551,7 +551,7 @@ impl<'a, A> IterMut<'a, A> { /// } /// { /// let vec: Vec = list.into_iter().collect(); - /// assert_eq!(vec, vec![1i, 2, 3, 4]); + /// assert_eq!(vec, vec![1, 2, 3, 4]); /// } /// ``` #[inline] diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index e86c40bed212f..721f9a4a59d70 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -173,7 +173,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3i); + /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); /// assert_eq!(buf.get(1).unwrap(), &4); @@ -196,7 +196,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3i); + /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); /// match buf.get_mut(1) { @@ -230,7 +230,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3i); + /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); /// buf.swap(0, 2); @@ -379,7 +379,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5i); + /// buf.push_back(5); /// buf.push_back(3); /// buf.push_back(4); /// let b: &[_] = &[&5, &3, &4]; @@ -402,7 +402,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5i); + /// buf.push_back(5); /// buf.push_back(3); /// buf.push_back(4); /// for num in buf.iter_mut() { @@ -481,7 +481,7 @@ impl RingBuf { /// /// let mut v = RingBuf::new(); /// assert_eq!(v.len(), 0); - /// v.push_back(1i); + /// v.push_back(1); /// assert_eq!(v.len(), 1); /// ``` #[stable] @@ -496,7 +496,7 @@ impl RingBuf { /// /// let mut v = RingBuf::new(); /// assert!(v.is_empty()); - /// v.push_front(1i); + /// v.push_front(1); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -511,7 +511,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut v = RingBuf::new(); - /// v.push_back(1i); + /// v.push_back(1); /// assert_eq!(v.drain().next(), Some(1)); /// assert!(v.is_empty()); /// ``` @@ -531,7 +531,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut v = RingBuf::new(); - /// v.push_back(1i); + /// v.push_back(1); /// v.clear(); /// assert!(v.is_empty()); /// ``` @@ -552,9 +552,9 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.front(), None); /// - /// d.push_back(1i); - /// d.push_back(2i); - /// assert_eq!(d.front(), Some(&1i)); + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.front(), Some(&1)); /// ``` #[stable] pub fn front(&self) -> Option<&T> { @@ -572,13 +572,13 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.front_mut(), None); /// - /// d.push_back(1i); - /// d.push_back(2i); + /// d.push_back(1); + /// d.push_back(2); /// match d.front_mut() { - /// Some(x) => *x = 9i, + /// Some(x) => *x = 9, /// None => (), /// } - /// assert_eq!(d.front(), Some(&9i)); + /// assert_eq!(d.front(), Some(&9)); /// ``` #[stable] pub fn front_mut(&mut self) -> Option<&mut T> { @@ -596,9 +596,9 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.back(), None); /// - /// d.push_back(1i); - /// d.push_back(2i); - /// assert_eq!(d.back(), Some(&2i)); + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.back(), Some(&2)); /// ``` #[stable] pub fn back(&self) -> Option<&T> { @@ -616,13 +616,13 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.back(), None); /// - /// d.push_back(1i); - /// d.push_back(2i); + /// d.push_back(1); + /// d.push_back(2); /// match d.back_mut() { - /// Some(x) => *x = 9i, + /// Some(x) => *x = 9, /// None => (), /// } - /// assert_eq!(d.back(), Some(&9i)); + /// assert_eq!(d.back(), Some(&9)); /// ``` #[stable] pub fn back_mut(&mut self) -> Option<&mut T> { @@ -639,11 +639,11 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut d = RingBuf::new(); - /// d.push_back(1i); - /// d.push_back(2i); + /// d.push_back(1); + /// d.push_back(2); /// - /// assert_eq!(d.pop_front(), Some(1i)); - /// assert_eq!(d.pop_front(), Some(2i)); + /// assert_eq!(d.pop_front(), Some(1)); + /// assert_eq!(d.pop_front(), Some(2)); /// assert_eq!(d.pop_front(), None); /// ``` #[stable] @@ -665,9 +665,9 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut d = RingBuf::new(); - /// d.push_front(1i); - /// d.push_front(2i); - /// assert_eq!(d.front(), Some(&2i)); + /// d.push_front(1); + /// d.push_front(2); + /// assert_eq!(d.front(), Some(&2)); /// ``` #[stable] pub fn push_front(&mut self, t: T) { @@ -689,7 +689,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(1i); + /// buf.push_back(1); /// buf.push_back(3); /// assert_eq!(3, *buf.back().unwrap()); /// ``` @@ -715,7 +715,7 @@ impl RingBuf { /// /// let mut buf = RingBuf::new(); /// assert_eq!(buf.pop_back(), None); - /// buf.push_back(1i); + /// buf.push_back(1); /// buf.push_back(3); /// assert_eq!(buf.pop_back(), Some(3)); /// ``` @@ -748,7 +748,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(10i); + /// buf.push_back(10); /// buf.push_back(12); /// buf.insert(1,11); /// assert_eq!(Some(&11), buf.get(1)); @@ -950,9 +950,9 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5i); - /// buf.push_back(10i); - /// buf.push_back(12i); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(12); /// buf.push_back(15); /// buf.remove(2); /// assert_eq!(Some(&15), buf.get(2)); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..8050c44f54281 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -15,7 +15,7 @@ //! //! ```rust //! // slicing a Vec -//! let vec = vec!(1i, 2, 3); +//! let vec = vec!(1, 2, 3); //! let int_slice = vec.as_slice(); //! // coercing an array to a slice //! let str_slice: &[&str] = &["one", "two", "three"]; @@ -26,7 +26,7 @@ //! block of memory that a mutable slice points to: //! //! ```rust -//! let x: &mut[int] = &mut [1i, 2, 3]; +//! let x: &mut[int] = &mut [1, 2, 3]; //! x[1] = 7; //! assert_eq!(x[0], 1); //! assert_eq!(x[1], 7); @@ -54,9 +54,9 @@ //! ```rust //! #![feature(slicing_syntax)] //! fn main() { -//! let numbers = [0i, 1i, 2i]; +//! let numbers = [0, 1, 2]; //! let last_numbers = numbers[1..3]; -//! // last_numbers is now &[1i, 2i] +//! // last_numbers is now &[1, 2] //! } //! ``` //! @@ -76,7 +76,7 @@ //! type of the slice is `int`, the element type of the iterator is `&int`. //! //! ```rust -//! let numbers = [0i, 1i, 2i]; +//! let numbers = [0, 1, 2]; //! for &x in numbers.iter() { //! println!("{} is a number!", x); //! } @@ -89,40 +89,40 @@ use alloc::boxed::Box; use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; -use core::clone::Clone; -use core::cmp::Ordering::{self, Greater, Less}; -use core::cmp::{self, Ord, PartialEq}; -use core::iter::{Iterator, IteratorExt}; -use core::iter::{range, range_step, MultiplicativeIterator}; +use core::cmp; +use core::iter::{range_step, MultiplicativeIterator}; use core::kinds::Sized; use core::mem::size_of; use core::mem; -use core::ops::{FnMut, SliceMut}; -use core::option::Option::{self, Some, None}; -use core::ptr::PtrExt; +use core::ops::{FnMut,SliceMut}; +use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; +use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result}; use core::ptr; -use core::result::Result; use core::slice as core_slice; use self::Direction::*; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; -pub use core::slice::{Iter, IterMut}; +pub use core::slice::{Iter, IterMut, PartialEqSliceExt}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; pub use core::slice::{from_raw_buf, from_raw_mut_buf}; +#[deprecated = "use Iter instead"] +pub type Items<'a, T:'a> = Iter<'a, T>; + +#[deprecated = "use IterMut instead"] +pub type MutItems<'a, T:'a> = IterMut<'a, T>; + //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// /// Allocating extension methods for slices. #[unstable = "needs associated types, may merge with other traits"] -pub trait SliceExt for Sized? { - type Item; - +pub trait SliceExt for Sized? { /// Sorts the slice, in place, using `compare` to compare /// elements. /// @@ -132,7 +132,7 @@ pub trait SliceExt for Sized? { /// # Examples /// /// ```rust - /// let mut v = [5i, 4, 1, 3, 2]; + /// let mut v = [5, 4, 1, 3, 2]; /// v.sort_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); /// @@ -141,7 +141,7 @@ pub trait SliceExt for Sized? { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[stable] - fn sort_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; + fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; /// Consumes `src` and moves as many elements as it can into `self` /// from the range [start,end). @@ -158,14 +158,14 @@ pub trait SliceExt for Sized? { /// # Examples /// /// ```rust - /// let mut a = [1i, 2, 3, 4, 5]; - /// let b = vec![6i, 7, 8]; + /// let mut a = [1, 2, 3, 4, 5]; + /// let b = vec![6, 7, 8]; /// let num_moved = a.move_from(b, 0, 3); /// assert_eq!(num_moved, 3); - /// assert!(a == [6i, 7, 8, 4, 5]); + /// assert!(a == [6, 7, 8, 4, 5]); /// ``` #[experimental = "uncertain about this API approach"] - fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; + fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; /// Returns a subslice spanning the interval [`start`, `end`). /// @@ -174,7 +174,7 @@ pub trait SliceExt for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice(&self, start: uint, end: uint) -> &[Self::Item]; + fn slice(&self, start: uint, end: uint) -> &[T]; /// Returns a subslice from `start` to the end of the slice. /// @@ -182,7 +182,7 @@ pub trait SliceExt for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from(&self, start: uint) -> &[Self::Item]; + fn slice_from(&self, start: uint) -> &[T]; /// Returns a subslice from the start of the slice to `end`. /// @@ -190,7 +190,7 @@ pub trait SliceExt for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to(&self, end: uint) -> &[Self::Item]; + fn slice_to(&self, end: uint) -> &[T]; /// Divides one slice into two at an index. /// @@ -200,32 +200,32 @@ pub trait SliceExt for Sized? { /// /// Panics if `mid > len`. #[stable] - fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]); + fn split_at(&self, mid: uint) -> (&[T], &[T]); /// Returns an iterator over the slice #[stable] - fn iter(&self) -> Iter; + fn iter(&self) -> Iter; /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. #[stable] - fn split(&self, pred: F) -> Split - where F: FnMut(&Self::Item) -> bool; + fn split(&self, pred: F) -> Split + where F: FnMut(&T) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn(&self, n: uint, pred: F) -> SplitN - where F: FnMut(&Self::Item) -> bool; + fn splitn(&self, n: uint, pred: F) -> SplitN + where F: FnMut(&T) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn(&self, n: uint, pred: F) -> RSplitN - where F: FnMut(&Self::Item) -> bool; + fn rsplitn(&self, n: uint, pred: F) -> RSplitN + where F: FnMut(&T) -> bool; /// Returns an iterator over all contiguous windows of length /// `size`. The windows overlap. If the slice is shorter than @@ -241,13 +241,13 @@ pub trait SliceExt for Sized? { /// `[3,4]`): /// /// ```rust - /// let v = &[1i, 2, 3, 4]; + /// let v = &[1, 2, 3, 4]; /// for win in v.windows(2) { /// println!("{}", win); /// } /// ``` #[stable] - fn windows(&self, size: uint) -> Windows; + fn windows(&self, size: uint) -> Windows; /// Returns an iterator over `size` elements of the slice at a /// time. The chunks do not overlap. If `size` does not divide the @@ -264,39 +264,49 @@ pub trait SliceExt for Sized? { /// `[3,4]`, `[5]`): /// /// ```rust - /// let v = &[1i, 2, 3, 4, 5]; + /// let v = &[1, 2, 3, 4, 5]; /// for win in v.chunks(2) { /// println!("{}", win); /// } /// ``` #[stable] - fn chunks(&self, size: uint) -> Chunks; + fn chunks(&self, size: uint) -> Chunks; /// Returns the element of a slice at the given index, or `None` if the /// index is out of bounds. #[stable] - fn get(&self, index: uint) -> Option<&Self::Item>; + fn get(&self, index: uint) -> Option<&T>; /// Returns the first element of a slice, or `None` if it is empty. #[stable] - fn first(&self) -> Option<&Self::Item>; + fn first(&self) -> Option<&T>; + + /// Deprecated: renamed to `first`. + #[deprecated = "renamed to `first`"] + fn head(&self) -> Option<&T> { self.first() } /// Returns all but the first element of a slice. #[experimental = "likely to be renamed"] - fn tail(&self) -> &[Self::Item]; + fn tail(&self) -> &[T]; /// Returns all but the last element of a slice. #[experimental = "likely to be renamed"] - fn init(&self) -> &[Self::Item]; + fn init(&self) -> &[T]; /// Returns the last element of a slice, or `None` if it is empty. #[stable] - fn last(&self) -> Option<&Self::Item>; + fn last(&self) -> Option<&T>; /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable] - unsafe fn get_unchecked(&self, index: uint) -> &Self::Item; + unsafe fn get_unchecked(&self, index: uint) -> &T; + + /// Deprecated: renamed to `get_unchecked`. + #[deprecated = "renamed to get_unchecked"] + unsafe fn unsafe_get(&self, index: uint) -> &T { + self.get_unchecked(index) + } /// Returns an unsafe pointer to the slice's buffer /// @@ -306,7 +316,7 @@ pub trait SliceExt for Sized? { /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[stable] - fn as_ptr(&self) -> *const Self::Item; + fn as_ptr(&self) -> *const T; /// Binary search a sorted slice with a comparator function. /// @@ -327,7 +337,7 @@ pub trait SliceExt for Sized? { /// found; the fourth could match any position in `[1,4]`. /// /// ```rust - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// let s = s.as_slice(); /// /// let seek = 13; @@ -342,14 +352,14 @@ pub trait SliceExt for Sized? { /// ``` #[stable] fn binary_search_by(&self, f: F) -> Result where - F: FnMut(&Self::Item) -> Ordering; + F: FnMut(&T) -> Ordering; /// Return the number of elements in the slice /// /// # Example /// /// ``` - /// let a = [1i, 2, 3]; + /// let a = [1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` #[stable] @@ -360,7 +370,7 @@ pub trait SliceExt for Sized? { /// # Example /// /// ``` - /// let a = [1i, 2, 3]; + /// let a = [1, 2, 3]; /// assert!(!a.is_empty()); /// ``` #[inline] @@ -369,12 +379,12 @@ pub trait SliceExt for Sized? { /// Returns a mutable reference to the element at the given index, /// or `None` if the index is out of bounds #[stable] - fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>; + fn get_mut(&mut self, index: uint) -> Option<&mut T>; /// Work with `self` as a mut slice. /// Primarily intended for getting a &mut [T] from a [T; N]. #[stable] - fn as_mut_slice(&mut self) -> &mut [Self::Item]; + fn as_mut_slice(&mut self) -> &mut [T]; /// Returns a mutable subslice spanning the interval [`start`, `end`). /// @@ -383,7 +393,7 @@ pub trait SliceExt for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item]; + fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; /// Returns a mutable subslice from `start` to the end of the slice. /// @@ -391,7 +401,7 @@ pub trait SliceExt for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item]; + fn slice_from_mut(&mut self, start: uint) -> &mut [T]; /// Returns a mutable subslice from the start of the slice to `end`. /// @@ -399,48 +409,54 @@ pub trait SliceExt for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; + fn slice_to_mut(&mut self, end: uint) -> &mut [T]; /// Returns an iterator that allows modifying each value #[stable] - fn iter_mut(&mut self) -> IterMut; + fn iter_mut(&mut self) -> IterMut; /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty #[stable] - fn first_mut(&mut self) -> Option<&mut Self::Item>; + fn first_mut(&mut self) -> Option<&mut T>; + + /// Depreated: renamed to `first_mut`. + #[deprecated = "renamed to first_mut"] + fn head_mut(&mut self) -> Option<&mut T> { + self.first_mut() + } /// Returns all but the first element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn tail_mut(&mut self) -> &mut [Self::Item]; + fn tail_mut(&mut self) -> &mut [T]; /// Returns all but the last element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn init_mut(&mut self) -> &mut [Self::Item]; + fn init_mut(&mut self) -> &mut [T]; /// Returns a mutable pointer to the last item in the slice. #[stable] - fn last_mut(&mut self) -> Option<&mut Self::Item>; + fn last_mut(&mut self) -> Option<&mut T>; /// Returns an iterator over mutable subslices separated by elements that /// match `pred`. The matched element is not contained in the subslices. #[stable] - fn split_mut(&mut self, pred: F) -> SplitMut - where F: FnMut(&Self::Item) -> bool; + fn split_mut(&mut self, pred: F) -> SplitMut + where F: FnMut(&T) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut - where F: FnMut(&Self::Item) -> bool; + fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut + where F: FnMut(&T) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut - where F: FnMut(&Self::Item) -> bool; + fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut + where F: FnMut(&T) -> bool; /// Returns an iterator over `chunk_size` elements of the slice at a time. /// The chunks are mutable and do not overlap. If `chunk_size` does @@ -451,7 +467,7 @@ pub trait SliceExt for Sized? { /// /// Panics if `chunk_size` is 0. #[stable] - fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut; + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut; /// Swaps two elements in a slice. /// @@ -487,45 +503,51 @@ pub trait SliceExt for Sized? { /// # Example /// /// ```rust - /// let mut v = [1i, 2, 3, 4, 5, 6]; + /// let mut v = [1, 2, 3, 4, 5, 6]; /// /// // scoped to restrict the lifetime of the borrows /// { /// let (left, right) = v.split_at_mut(0); /// assert!(left == []); - /// assert!(right == [1i, 2, 3, 4, 5, 6]); + /// assert!(right == [1, 2, 3, 4, 5, 6]); /// } /// /// { /// let (left, right) = v.split_at_mut(2); - /// assert!(left == [1i, 2]); - /// assert!(right == [3i, 4, 5, 6]); + /// assert!(left == [1, 2]); + /// assert!(right == [3, 4, 5, 6]); /// } /// /// { /// let (left, right) = v.split_at_mut(6); - /// assert!(left == [1i, 2, 3, 4, 5, 6]); + /// assert!(left == [1, 2, 3, 4, 5, 6]); /// assert!(right == []); /// } /// ``` #[stable] - fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]); + fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); /// Reverse the order of elements in a slice, in place. /// /// # Example /// /// ```rust - /// let mut v = [1i, 2, 3]; + /// let mut v = [1, 2, 3]; /// v.reverse(); - /// assert!(v == [3i, 2, 1]); + /// assert!(v == [3, 2, 1]); /// ``` #[stable] fn reverse(&mut self); /// Returns an unsafe mutable pointer to the element in index #[stable] - unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item; + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T; + + /// Deprecated: renamed to `get_unchecked_mut`. + #[deprecated = "renamed to get_unchecked_mut"] + unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T { + self.get_unchecked_mut(index) + } /// Return an unsafe mutable pointer to the slice's buffer. /// @@ -536,173 +558,11 @@ pub trait SliceExt for Sized? { /// would also make any pointers to it invalid. #[inline] #[stable] - fn as_mut_ptr(&mut self) -> *mut Self::Item; - - /// Copies `self` into a new `Vec`. - #[stable] - fn to_vec(&self) -> Vec where Self::Item: Clone; - - /// Creates an iterator that yields every possible permutation of the - /// vector in succession. - /// - /// # Examples - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// for p in perms { - /// println!("{}", p); - /// } - /// ``` - /// - /// Iterating through permutations one by one. - /// - /// ```rust - /// let v = [1i, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); - /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); - /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); - /// ``` - #[unstable] - fn permutations(&self) -> Permutations where Self::Item: Clone; - - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. - /// - /// # Example - /// - /// ```rust - /// let mut dst = [0i, 0, 0]; - /// let src = [1i, 2]; - /// - /// assert!(dst.clone_from_slice(&src) == 2); - /// assert!(dst == [1, 2, 0]); - /// - /// let src2 = [3i, 4, 5, 6]; - /// assert!(dst.clone_from_slice(&src2) == 3); - /// assert!(dst == [3i, 4, 5]); - /// ``` - #[experimental] - fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; - - /// Sorts the slice, in place. - /// - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [-5i, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v == [-5i, -3, 1, 2, 4]); - /// ``` - #[stable] - fn sort(&mut self) where Self::Item: Ord; - - /// Binary search a sorted slice for a given element. - /// - /// If the value is found then `Ok` is returned, containing the - /// index of the matching element; if the value is not found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Example - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. - /// - /// ```rust - /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); - /// - /// assert_eq!(s.binary_search(&13), Ok(9)); - /// assert_eq!(s.binary_search(&4), Err(7)); - /// assert_eq!(s.binary_search(&100), Err(13)); - /// let r = s.binary_search(&1); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable] - fn binary_search(&self, x: &Self::Item) -> Result where Self::Item: Ord; - - /// Deprecated: use `binary_search` instead. - #[deprecated = "use binary_search instead"] - fn binary_search_elem(&self, x: &Self::Item) -> Result where Self::Item: Ord { - self.binary_search(x) - } - - /// Mutates the slice to the next lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// last-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [0i, 1, 2]; - /// v.next_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.next_permutation(); - /// let b: &mut [_] = &mut [1i, 0, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn next_permutation(&mut self) -> bool where Self::Item: Ord; - - /// Mutates the slice to the previous lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// first-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [1i, 0, 2]; - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 2, 1]; - /// assert!(v == b); - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0i, 1, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn prev_permutation(&mut self) -> bool where Self::Item: Ord; - - /// Find the first index containing a matching value. - #[experimental] - fn position_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; - - /// Find the last index containing a matching value. - #[experimental] - fn rposition_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; - - /// Return true if the slice contains an element with the given value. - #[stable] - fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; - - /// Returns true if `needle` is a prefix of the slice. - #[stable] - fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; - - /// Returns true if `needle` is a suffix of the slice. - #[stable] - fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; - - /// Convert `self` into a vector without clones or allocation. - #[experimental] - fn into_vec(self: Box) -> Vec; + fn as_mut_ptr(&mut self) -> *mut T; } #[unstable = "trait is unstable"] -impl SliceExt for [T] { - type Item = T; - +impl SliceExt for [T] { #[inline] fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { merge_sort(self, compare) @@ -917,76 +777,229 @@ impl SliceExt for [T] { fn as_mut_ptr(&mut self) -> *mut T { core_slice::SliceExt::as_mut_ptr(self) } +} + +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specifc kinds of data +//////////////////////////////////////////////////////////////////////////////// + +/// Extension methods for boxed slices. +#[experimental = "likely to merge into SliceExt if it survives"] +pub trait BoxedSliceExt { + /// Convert `self` into a vector without clones or allocation. + #[experimental] + fn into_vec(self) -> Vec; +} + +#[experimental = "trait is experimental"] +impl BoxedSliceExt for Box<[T]> { + fn into_vec(mut self) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); + mem::forget(self); + xs + } + } +} + +/// Allocating extension methods for slices containing `Clone` elements. +#[unstable = "likely to be merged into SliceExt"] +pub trait CloneSliceExt for Sized? { + /// Copies `self` into a new `Vec`. + #[stable] + fn to_vec(&self) -> Vec; + + /// Deprecated: use `iter().cloned().partition(f)` instead. + #[deprecated = "use iter().cloned().partition(f) instead"] + fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool; + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); + /// ``` + #[unstable] + fn permutations(&self) -> Permutations; + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0, 0, 0]; + /// let src = [1, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3, 4, 5]); + /// ``` + #[experimental] + fn clone_from_slice(&mut self, &[T]) -> uint; +} + + +#[unstable = "trait is unstable"] +impl CloneSliceExt for [T] { /// Returns a copy of `v`. #[inline] - fn to_vec(&self) -> Vec where T: Clone { + fn to_vec(&self) -> Vec { let mut vector = Vec::with_capacity(self.len()); vector.push_all(self); vector } + + #[inline] + fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { + self.iter().cloned().partition(f) + } + /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations where T: Clone { + fn permutations(&self) -> Permutations { Permutations{ swaps: ElementSwaps::new(self.len()), v: self.to_vec(), } } - fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { - core_slice::SliceExt::clone_from_slice(self, src) - } - - #[inline] - fn sort(&mut self) where T: Ord { - self.sort_by(|a, b| a.cmp(b)) + fn clone_from_slice(&mut self, src: &[T]) -> uint { + core_slice::CloneSliceExt::clone_from_slice(self, src) } +} - fn binary_search(&self, x: &T) -> Result where T: Ord { - core_slice::SliceExt::binary_search(self, x) - } +/// Allocating extension methods for slices on Ord values. +#[unstable = "likely to merge with SliceExt"] +pub trait OrdSliceExt for Sized? { + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5, -3, 1, 2, 4]); + /// ``` + #[stable] + fn sort(&mut self); - fn next_permutation(&mut self) -> bool where T: Ord { - core_slice::SliceExt::next_permutation(self) - } + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable] + fn binary_search(&self, x: &T) -> Result; - fn prev_permutation(&mut self) -> bool where T: Ord { - core_slice::SliceExt::prev_permutation(self) + /// Deprecated: use `binary_search` instead. + #[deprecated = "use binary_search instead"] + fn binary_search_elem(&self, x: &T) -> Result { + self.binary_search(x) } - fn position_elem(&self, t: &T) -> Option where T: PartialEq { - core_slice::SliceExt::position_elem(self, t) - } + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn next_permutation(&mut self) -> bool; - fn rposition_elem(&self, t: &T) -> Option where T: PartialEq { - core_slice::SliceExt::rposition_elem(self, t) - } + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn prev_permutation(&mut self) -> bool; +} - fn contains(&self, x: &T) -> bool where T: PartialEq { - core_slice::SliceExt::contains(self, x) +#[unstable = "trait is unstable"] +impl OrdSliceExt for [T] { + #[inline] + fn sort(&mut self) { + self.sort_by(|a, b| a.cmp(b)) } - fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { - core_slice::SliceExt::starts_with(self, needle) + fn binary_search(&self, x: &T) -> Result { + core_slice::OrdSliceExt::binary_search(self, x) } - fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { - core_slice::SliceExt::ends_with(self, needle) + fn next_permutation(&mut self) -> bool { + core_slice::OrdSliceExt::next_permutation(self) } - fn into_vec(mut self: Box) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } + fn prev_permutation(&mut self) -> bool { + core_slice::OrdSliceExt::prev_permutation(self) } } -//////////////////////////////////////////////////////////////////////////////// -// Extension traits for slices over specifc kinds of data -//////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices pub trait SliceConcatExt for Sized? { @@ -994,10 +1007,20 @@ pub trait SliceConcatExt for Sized? { #[stable] fn concat(&self) -> U; + #[deprecated = "renamed to concat"] + fn concat_vec(&self) -> U { + self.concat() + } + /// Flattens a slice of `T` into a single value `U`, placing a /// given seperator between each. #[stable] fn connect(&self, sep: &T) -> U; + + #[deprecated = "renamed to connect"] + fn connect_vec(&self, sep: &T) -> U { + self.connect(sep) + } } impl> SliceConcatExt> for [V] { @@ -1033,7 +1056,7 @@ impl> SliceConcatExt> for [V] { /// The last generated swap is always (0, 1), and it returns the /// sequence to its initial order. #[experimental] -#[derive(Clone)] +#[deriving(Clone)] pub struct ElementSwaps { sdir: Vec, /// If `true`, emit the last swap that returns the sequence to initial @@ -1080,19 +1103,17 @@ impl ToOwned> for [T] { // Iterators //////////////////////////////////////////////////////////////////////////////// -#[derive(Copy, Clone)] +#[deriving(Copy, Clone)] enum Direction { Pos, Neg } /// An `Index` and `Direction` together. -#[derive(Copy, Clone)] +#[deriving(Copy, Clone)] struct SizeDirection { size: uint, dir: Direction, } -impl Iterator for ElementSwaps { - type Item = (uint, uint); - +impl Iterator<(uint, uint)> for ElementSwaps { #[inline] fn next(&mut self) -> Option<(uint, uint)> { fn new_pos(i: uint, s: Direction) -> uint { @@ -1159,9 +1180,7 @@ pub struct Permutations { } #[unstable = "trait is unstable"] -impl Iterator for Permutations { - type Item = Vec; - +impl Iterator> for Permutations { #[inline] fn next(&mut self) -> Option> { match self.swaps.next() { @@ -1388,12 +1407,21 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order } } +/// Deprecated, unsafe operations +#[deprecated] +pub mod raw { + pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice}; + pub use core::slice::raw::{shift_ptr, pop_ptr}; +} + #[cfg(test)] mod tests { + use std::boxed::Box; use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; - use prelude::{SliceExt, Iterator, IteratorExt}; - use prelude::AsSlice; + use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; + use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; use prelude::{RandomAccessIterator, Ord, SliceConcatExt}; + use core::cell::Cell; use core::default::Default; use core::mem; use std::rand::{Rng, thread_rng}; @@ -1407,7 +1435,7 @@ mod tests { #[test] fn test_from_fn() { // Test on-stack from_fn. - let mut v = range(0, 3).map(square).collect::>(); + let mut v = Vec::from_fn(3u, square); { let v = v.as_slice(); assert_eq!(v.len(), 3u); @@ -1417,7 +1445,7 @@ mod tests { } // Test on-heap from_fn. - v = range(0, 5).map(square).collect::>(); + v = Vec::from_fn(5u, square); { let v = v.as_slice(); assert_eq!(v.len(), 5u); @@ -1432,7 +1460,7 @@ mod tests { #[test] fn test_from_elem() { // Test on-stack from_elem. - let mut v = vec![10u, 10u]; + let mut v = Vec::from_elem(2u, 10u); { let v = v.as_slice(); assert_eq!(v.len(), 2u); @@ -1441,7 +1469,7 @@ mod tests { } // Test on-heap from_elem. - v = vec![20u, 20u, 20u, 20u, 20u, 20u]; + v = Vec::from_elem(6u, 20u); { let v = v.as_slice(); assert_eq!(v[0], 20u); @@ -1483,23 +1511,23 @@ mod tests { } #[test] - fn test_first() { + fn test_head() { let mut a = vec![]; - assert_eq!(a.as_slice().first(), None); + assert_eq!(a.as_slice().head(), None); a = vec![11i]; - assert_eq!(a.as_slice().first().unwrap(), &11); + assert_eq!(a.as_slice().head().unwrap(), &11); a = vec![11i, 12]; - assert_eq!(a.as_slice().first().unwrap(), &11); + assert_eq!(a.as_slice().head().unwrap(), &11); } #[test] - fn test_first_mut() { + fn test_head_mut() { let mut a = vec![]; - assert_eq!(a.first_mut(), None); + assert_eq!(a.head_mut(), None); a = vec![11i]; - assert_eq!(*a.first_mut().unwrap(), 11); + assert_eq!(*a.head_mut().unwrap(), 11); a = vec![11i, 12]; - assert_eq!(*a.first_mut().unwrap(), 11); + assert_eq!(*a.head_mut().unwrap(), 11); } #[test] @@ -1703,6 +1731,42 @@ mod tests { assert_eq!(v.as_slice()[1], 2); } + #[test] + fn test_grow() { + // Test on-stack grow(). + let mut v = vec![]; + v.grow(2u, 1i); + { + let v = v.as_slice(); + assert_eq!(v.len(), 2u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 1); + } + + // Test on-heap grow(). + v.grow(3u, 2i); + { + let v = v.as_slice(); + assert_eq!(v.len(), 5u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 1); + assert_eq!(v[2], 2); + assert_eq!(v[3], 2); + assert_eq!(v[4], 2); + } + } + + #[test] + fn test_grow_fn() { + let mut v = vec![]; + v.grow_fn(3u, square); + let v = v.as_slice(); + assert_eq!(v.len(), 3u); + assert_eq!(v[0], 0u); + assert_eq!(v[1], 1u); + assert_eq!(v[2], 4u); + } + #[test] fn test_truncate() { let mut v = vec![box 6i,box 5,box 4]; @@ -2035,6 +2099,22 @@ mod tests { } } + #[test] + fn test_partition() { + assert_eq!((vec![]).partition(|x: &int| *x < 3), (vec![], vec![])); + assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![])); + assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3])); + assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3])); + } + + #[test] + fn test_partitioned() { + assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![])); + assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![])); + assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3])); + assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3])); + } + #[test] fn test_concat() { let v: [Vec; 0] = []; @@ -2052,14 +2132,14 @@ mod tests { #[test] fn test_connect() { let v: [Vec; 0] = []; - assert_eq!(v.connect(&0), vec![]); - assert_eq!([vec![1i], vec![2i, 3]].connect(&0), vec![1, 0, 2, 3]); - assert_eq!([vec![1i], vec![2i], vec![3i]].connect(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect_vec(&0), vec![]); + assert_eq!([vec![1i], vec![2i, 3]].connect_vec(&0), vec![1, 0, 2, 3]); + assert_eq!([vec![1i], vec![2i], vec![3i]].connect_vec(&0), vec![1, 0, 2, 0, 3]); let v: [&[int]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); + assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]); let v: [&[int]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]); } #[test] @@ -2132,6 +2212,55 @@ mod tests { assert_eq!(v[1], 3); } + + #[test] + #[should_fail] + fn test_from_fn_fail() { + Vec::from_fn(100, |v| { + if v == 50 { panic!() } + box 0i + }); + } + + #[test] + #[should_fail] + fn test_from_elem_fail() { + + struct S { + f: Cell, + boxes: (Box, Rc) + } + + impl Clone for S { + fn clone(&self) -> S { + self.f.set(self.f.get() + 1); + if self.f.get() == 10 { panic!() } + S { + f: self.f.clone(), + boxes: self.boxes.clone(), + } + } + } + + let s = S { + f: Cell::new(0), + boxes: (box 0, Rc::new(0)), + }; + let _ = Vec::from_elem(100, s); + } + + #[test] + #[should_fail] + fn test_grow_fn_fail() { + let mut v = vec![]; + v.grow_fn(100, |i| { + if i == 50 { + panic!() + } + (box 0i, Rc::new(0i)) + }) + } + #[test] #[should_fail] fn test_permute_fail() { @@ -2549,7 +2678,7 @@ mod tests { assert!(values == [2, 3, 5, 6, 7]); } - #[derive(Clone, PartialEq)] + #[deriving(Clone, PartialEq)] struct Foo; #[test] @@ -2720,7 +2849,6 @@ mod bench { use prelude::*; use core::mem; use core::ptr; - use core::iter::repeat; use std::rand::{weak_rng, Rng}; use test::{Bencher, black_box}; @@ -2728,7 +2856,7 @@ mod bench { fn iterator(b: &mut Bencher) { // peculiar numbers to stop LLVM from optimising the summation // out. - let v = range(0u, 100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect::>(); + let v = Vec::from_fn(100, |i| i ^ (i << 1) ^ (i >> 1)); b.iter(|| { let mut sum = 0; @@ -2742,7 +2870,7 @@ mod bench { #[bench] fn mut_iterator(b: &mut Bencher) { - let mut v = repeat(0i).take(100).collect::>(); + let mut v = Vec::from_elem(100, 0i); b.iter(|| { let mut i = 0i; @@ -2756,7 +2884,7 @@ mod bench { #[bench] fn concat(b: &mut Bencher) { let xss: Vec> = - range(0, 100u).map(|i| range(0, i).collect()).collect(); + Vec::from_fn(100, |i| range(0u, i).collect()); b.iter(|| { xss.as_slice().concat(); }); @@ -2765,9 +2893,9 @@ mod bench { #[bench] fn connect(b: &mut Bencher) { let xss: Vec> = - range(0, 100u).map(|i| range(0, i).collect()).collect(); + Vec::from_fn(100, |i| range(0u, i).collect()); b.iter(|| { - xss.as_slice().connect(&0) + xss.as_slice().connect_vec(&0) }); } @@ -2782,7 +2910,7 @@ mod bench { #[bench] fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec = range(0, 100).collect(); + let vec: Vec = Vec::from_fn(100, |i| i); b.iter(|| { vec.as_slice().starts_with(vec.as_slice()) }) @@ -2798,8 +2926,8 @@ mod bench { #[bench] fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec = range(0, 100).collect(); - let mut match_vec: Vec = range(0, 99).collect(); + let vec: Vec = Vec::from_fn(100, |i| i); + let mut match_vec: Vec = Vec::from_fn(99, |i| i); match_vec.push(0); b.iter(|| { vec.as_slice().starts_with(match_vec.as_slice()) @@ -2808,7 +2936,7 @@ mod bench { #[bench] fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec = range(0, 100).collect(); + let vec: Vec = Vec::from_fn(100, |i| i); b.iter(|| { vec.as_slice().ends_with(vec.as_slice()) }) @@ -2824,8 +2952,8 @@ mod bench { #[bench] fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec = range(0, 100).collect(); - let mut match_vec: Vec = range(0, 100).collect(); + let vec: Vec = Vec::from_fn(100, |i| i); + let mut match_vec: Vec = Vec::from_fn(100, |i| i); match_vec.as_mut_slice()[0] = 200; b.iter(|| { vec.as_slice().starts_with(match_vec.as_slice()) @@ -2834,7 +2962,7 @@ mod bench { #[bench] fn contains_last_element(b: &mut Bencher) { - let vec: Vec = range(0, 100).collect(); + let vec: Vec = Vec::from_fn(100, |i| i); b.iter(|| { vec.contains(&99u) }) @@ -2843,7 +2971,7 @@ mod bench { #[bench] fn zero_1kb_from_elem(b: &mut Bencher) { b.iter(|| { - repeat(0u8).take(1024).collect::>() + Vec::from_elem(1024, 0u8) }); } @@ -2891,24 +3019,24 @@ mod bench { fn random_inserts(b: &mut Bencher) { let mut rng = weak_rng(); b.iter(|| { - let mut v = repeat((0u, 0u)).take(30).collect::>(); - for _ in range(0u, 100) { - let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); - } - }) + let mut v = Vec::from_elem(30, (0u, 0u)); + for _ in range(0u, 100) { + let l = v.len(); + v.insert(rng.gen::() % (l + 1), + (1, 1)); + } + }) } #[bench] fn random_removes(b: &mut Bencher) { let mut rng = weak_rng(); b.iter(|| { - let mut v = repeat((0u, 0u)).take(130).collect::>(); - for _ in range(0u, 100) { - let l = v.len(); - v.remove(rng.gen::() % l); - } - }) + let mut v = Vec::from_elem(130, (0u, 0u)); + for _ in range(0u, 100) { + let l = v.len(); + v.remove(rng.gen::() % l); + } + }) } #[bench] @@ -2943,7 +3071,7 @@ mod bench { #[bench] fn sort_sorted(b: &mut Bencher) { - let mut v = range(0u, 10000).collect::>(); + let mut v = Vec::from_fn(10000, |i| i); b.iter(|| { v.sort(); }); @@ -2987,7 +3115,7 @@ mod bench { #[bench] fn sort_big_sorted(b: &mut Bencher) { - let mut v = range(0, 10000u).map(|i| (i, i, i, i)).collect::>(); + let mut v = Vec::from_fn(10000u, |i| (i, i, i, i)); b.iter(|| { v.sort(); }); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index b8f97799c9718..027f50791b8b8 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -25,13 +25,13 @@ //! ``` //! let ys: Vec = vec![]; //! -//! let zs = vec![1i32, 2, 3, 4, 5]; +//! let zs = vec![1, 2, 3, 4, 5]; //! ``` //! //! Push: //! //! ``` -//! let mut xs = vec![1i32, 2]; +//! let mut xs = vec![1, 2]; //! //! xs.push(3); //! ``` @@ -39,7 +39,7 @@ //! And pop: //! //! ``` -//! let mut xs = vec![1i32, 2]; +//! let mut xs = vec![1, 2]; //! //! let two = xs.pop(); //! ``` @@ -71,8 +71,8 @@ use core::uint; /// /// ``` /// let mut vec = Vec::new(); -/// vec.push(1i); -/// vec.push(2i); +/// vec.push(1); +/// vec.push(2); /// /// assert_eq!(vec.len(), 2); /// assert_eq!(vec[0], 1); @@ -80,7 +80,7 @@ use core::uint; /// assert_eq!(vec.pop(), Some(2)); /// assert_eq!(vec.len(), 1); /// -/// vec[0] = 7i; +/// vec[0] = 7; /// assert_eq!(vec[0], 7); /// /// vec.push_all(&[1, 2, 3]); @@ -88,13 +88,13 @@ use core::uint; /// for x in vec.iter() { /// println!("{}", x); /// } -/// assert_eq!(vec, vec![7i, 1, 2, 3]); +/// assert_eq!(vec, vec![7, 1, 2, 3]); /// ``` /// /// The `vec!` macro is provided to make initialization more convenient: /// /// ``` -/// let mut vec = vec![1i, 2i, 3i]; +/// let mut vec = vec![1, 2, 3]; /// vec.push(4); /// assert_eq!(vec, vec![1, 2, 3, 4]); /// ``` @@ -104,9 +104,9 @@ use core::uint; /// ``` /// let mut stack = Vec::new(); /// -/// stack.push(1i); -/// stack.push(2i); -/// stack.push(3i); +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); /// /// loop { /// let top = match stack.pop() { @@ -218,7 +218,7 @@ impl Vec { /// use std::mem; /// /// fn main() { - /// let mut v = vec![1i, 2, 3]; + /// let mut v = vec![1, 2, 3]; /// /// // Pull out the various important pieces of information about `v` /// let p = v.as_mut_ptr(); @@ -237,7 +237,7 @@ impl Vec { /// /// // Put everything back together into a Vec /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, vec![4i, 5i, 6i]); + /// assert_eq!(rebuilt, vec![4, 5, 6]); /// } /// } /// ``` @@ -392,7 +392,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1i, 2, 3, 4]; + /// let mut vec = vec![1, 2, 3, 4]; /// vec.truncate(2); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -416,7 +416,7 @@ impl Vec { /// ``` /// fn foo(slice: &mut [int]) {} /// - /// let mut vec = vec![1i, 2]; + /// let mut vec = vec![1, 2]; /// foo(vec.as_mut_slice()); /// ``` #[inline] @@ -519,7 +519,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1i, 2, 3]; + /// let mut vec = vec![1, 2, 3]; /// vec.insert(1, 4); /// assert_eq!(vec, vec![1, 4, 2, 3]); /// vec.insert(4, 5); @@ -557,7 +557,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut v = vec![1i, 2, 3]; + /// let mut v = vec![1, 2, 3]; /// assert_eq!(v.remove(1), 2); /// assert_eq!(v, vec![1, 3]); /// ``` @@ -591,7 +591,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1i, 2, 3, 4]; + /// let mut vec = vec![1, 2, 3, 4]; /// vec.retain(|&x| x%2 == 0); /// assert_eq!(vec, vec![2, 4]); /// ``` @@ -624,7 +624,7 @@ impl Vec { /// # Examples /// /// ```rust - /// let mut vec = vec!(1i, 2); + /// let mut vec = vec!(1, 2); /// vec.push(3); /// assert_eq!(vec, vec!(1, 2, 3)); /// ``` @@ -662,7 +662,7 @@ impl Vec { /// # Examples /// /// ```rust - /// let mut vec = vec![1i, 2, 3]; + /// let mut vec = vec![1, 2, 3]; /// assert_eq!(vec.pop(), Some(3)); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -716,7 +716,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut v = vec![1i, 2, 3]; + /// let mut v = vec![1, 2, 3]; /// /// v.clear(); /// @@ -733,7 +733,7 @@ impl Vec { /// # Examples /// /// ``` - /// let a = vec![1i, 2, 3]; + /// let a = vec![1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` #[inline] @@ -748,7 +748,7 @@ impl Vec { /// let mut v = Vec::new(); /// assert!(v.is_empty()); /// - /// v.push(1i); + /// v.push(1); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -965,7 +965,7 @@ impl Vec { /// vec.resize(3, "world"); /// assert_eq!(vec, vec!["hello", "world", "world"]); /// - /// let mut vec = vec![1i, 2, 3, 4]; + /// let mut vec = vec![1, 2, 3, 4]; /// vec.resize(2, 0); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -988,8 +988,8 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1i]; - /// vec.push_all(&[2i, 3, 4]); + /// let mut vec = vec![1]; + /// vec.push_all(&[2, 3, 4]); /// assert_eq!(vec, vec![1, 2, 3, 4]); /// ``` #[inline] @@ -1021,11 +1021,11 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1i, 2, 2, 3, 2]; + /// let mut vec = vec![1, 2, 2, 3, 2]; /// /// vec.dedup(); /// - /// assert_eq!(vec, vec![1i, 2, 3, 2]); + /// assert_eq!(vec, vec![1, 2, 3, 2]); /// ``` #[stable] pub fn dedup(&mut self) { @@ -1399,7 +1399,7 @@ impl AsSlice for Vec { /// ``` /// fn foo(slice: &[int]) {} /// - /// let vec = vec![1i, 2]; + /// let vec = vec![1, 2]; /// foo(vec.as_slice()); /// ``` #[inline] diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 0ac0dc396cc1a..ebc01ae14fc81 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -793,7 +793,7 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::AtomicPtr; /// - /// let ptr = &mut 5i; + /// let ptr = &mut 5; /// let atomic_ptr = AtomicPtr::new(ptr); /// ``` #[inline] @@ -815,7 +815,7 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5i; + /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let value = some_ptr.load(Ordering::Relaxed); @@ -837,10 +837,10 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5i; + /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10i; + /// let other_ptr = &mut 10; /// /// some_ptr.store(other_ptr, Ordering::Relaxed); /// ``` @@ -863,10 +863,10 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5i; + /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10i; + /// let other_ptr = &mut 10; /// /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed); /// ``` @@ -888,11 +888,11 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5i; + /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10i; - /// let another_ptr = &mut 10i; + /// let other_ptr = &mut 10; + /// let another_ptr = &mut 10; /// /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed); /// ``` diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index e0724fc2da5f5..c9646bb3d3506 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -145,7 +145,7 @@ pub struct RadixFmt(T, R); /// /// ``` /// use std::fmt::radix; -/// assert_eq!(format!("{}", radix(55i, 36)), "1j".to_string()); +/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string()); /// ``` #[unstable = "may be renamed or move to a different module"] pub fn radix(x: T, base: u8) -> RadixFmt { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 29077deb21de1..e7e32cec177ec 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -33,7 +33,7 @@ //! translated to the `loop` below. //! //! ```rust -//! let values = vec![1i, 2, 3]; +//! let values = vec![1, 2, 3]; //! //! // "Syntactical sugar" taking advantage of an iterator //! for &x in values.iter() { @@ -118,8 +118,8 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [0i]; - /// let b = [1i]; + /// let a = [0]; + /// let b = [1]; /// let mut it = a.iter().chain(b.iter()); /// assert_eq!(it.next().unwrap(), &0); /// assert_eq!(it.next().unwrap(), &1); @@ -141,10 +141,10 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [0i]; - /// let b = [1i]; + /// let a = [0]; + /// let b = [1]; /// let mut it = a.iter().zip(b.iter()); - /// let (x0, x1) = (0i, 1i); + /// let (x0, x1) = (0, 1); /// assert_eq!(it.next().unwrap(), (&x0, &x1)); /// assert!(it.next().is_none()); /// ``` @@ -162,7 +162,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2]; + /// let a = [1, 2]; /// let mut it = a.iter().map(|&x| 2 * x); /// assert_eq!(it.next().unwrap(), 2); /// assert_eq!(it.next().unwrap(), 4); @@ -183,7 +183,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2]; + /// let a = [1, 2]; /// let mut it = a.iter().filter(|&x| *x > 1); /// assert_eq!(it.next().unwrap(), &2); /// assert!(it.next().is_none()); @@ -203,7 +203,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2]; + /// let a = [1, 2]; /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); /// assert_eq!(it.next().unwrap(), 4); /// assert!(it.next().is_none()); @@ -222,9 +222,9 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [100i, 200]; + /// let a = [100, 200]; /// let mut it = a.iter().enumerate(); - /// let (x100, x200) = (100i, 200i); + /// let (x100, x200) = (100, 200); /// assert_eq!(it.next().unwrap(), (0, &x100)); /// assert_eq!(it.next().unwrap(), (1, &x200)); /// assert!(it.next().is_none()); @@ -241,7 +241,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let xs = [100i, 200, 300]; + /// let xs = [100, 200, 300]; /// let mut it = xs.iter().map(|x| *x).peekable(); /// assert_eq!(*it.peek().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 100); @@ -265,7 +265,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 2, 1]; + /// let a = [1, 2, 3, 2, 1]; /// let mut it = a.iter().skip_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &3); /// assert_eq!(it.next().unwrap(), &2); @@ -287,7 +287,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 2, 1]; + /// let a = [1, 2, 3, 2, 1]; /// let mut it = a.iter().take_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -307,7 +307,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().skip(3); /// assert_eq!(it.next().unwrap(), &4); /// assert_eq!(it.next().unwrap(), &5); @@ -325,7 +325,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().take(3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -346,7 +346,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().scan(1, |fac, &x| { /// *fac = *fac * x; /// Some(*fac) @@ -419,9 +419,9 @@ pub trait IteratorExt: Iterator + Sized { /// } /// sum /// } - /// let x = vec![1i,2,3,7,8,9]; + /// let x = vec![1,2,3,7,8,9]; /// assert_eq!(process(x.into_iter()), 6); - /// let x = vec![1i,2,3]; + /// let x = vec![1,2,3]; /// assert_eq!(process(x.into_iter()), 1006); /// ``` #[inline] @@ -482,7 +482,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let b: Vec = a.iter().map(|&x| x).collect(); /// assert!(a.as_slice() == b.as_slice()); /// ``` @@ -498,7 +498,7 @@ pub trait IteratorExt: Iterator + Sized { /// do not. /// /// ``` - /// let vec = vec![1i, 2i, 3i, 4i]; + /// let vec = vec![1, 2, 3, 4]; /// let (even, odd): (Vec, Vec) = vec.into_iter().partition(|&n| n % 2 == 0); /// assert_eq!(even, vec![2, 4]); /// assert_eq!(odd, vec![1, 3]); @@ -528,7 +528,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.nth(2).unwrap() == &3); /// assert!(it.nth(2) == None); @@ -549,7 +549,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().last().unwrap() == &5); /// ``` #[inline] @@ -566,7 +566,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); /// ``` #[inline] @@ -586,7 +586,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.count() == 5); /// ``` @@ -601,7 +601,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().all(|x| *x > 0)); /// assert!(!a.iter().all(|x| *x > 2)); /// ``` @@ -618,7 +618,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.any(|x| *x == 3)); /// assert!(!it.any(|x| *x == 3)); @@ -668,7 +668,7 @@ pub trait IteratorExt: Iterator + Sized { /// ```rust /// use core::num::SignedInt; /// - /// let xs = [-3i, 0, 1, 5, -10]; + /// let xs = [-3, 0, 1, 5, -10]; /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); /// ``` #[inline] @@ -697,7 +697,7 @@ pub trait IteratorExt: Iterator + Sized { /// ```rust /// use core::num::SignedInt; /// - /// let xs = [-3i, 0, 1, 5, -10]; + /// let xs = [-3, 0, 1, 5, -10]; /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); /// ``` #[inline] @@ -950,7 +950,7 @@ pub trait AdditiveIterator { /// ```rust /// use std::iter::AdditiveIterator; /// - /// let a = [1i, 2, 3, 4, 5]; + /// let a: [i32] = [1, 2, 3, 4, 5]; /// let mut it = a.iter().map(|&x| x); /// assert!(it.sum() == 15); /// ``` @@ -1033,7 +1033,7 @@ pub trait IteratorOrdExt { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().max().unwrap() == &5); /// ``` fn max(self) -> Option; @@ -1043,7 +1043,7 @@ pub trait IteratorOrdExt { /// # Example /// /// ```rust - /// let a = [1i, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// assert!(a.iter().min().unwrap() == &1); /// ``` fn min(self) -> Option; @@ -1069,16 +1069,16 @@ pub trait IteratorOrdExt { /// let v: [int; 0] = []; /// assert_eq!(v.iter().min_max(), NoElements); /// - /// let v = [1i]; + /// let v = [1]; /// assert!(v.iter().min_max() == OneElement(&1)); /// - /// let v = [1i, 2, 3, 4, 5]; + /// let v = [1, 2, 3, 4, 5]; /// assert!(v.iter().min_max() == MinMax(&1, &5)); /// - /// let v = [1i, 2, 3, 4, 5, 6]; + /// let v = [1, 2, 3, 4, 5, 6]; /// assert!(v.iter().min_max() == MinMax(&1, &6)); /// - /// let v = [1i, 1, 1, 1]; + /// let v = [1, 1, 1, 1]; /// assert!(v.iter().min_max() == MinMax(&1, &1)); /// ``` fn min_max(self) -> MinMaxResult; @@ -1179,10 +1179,10 @@ impl MinMaxResult { /// let r: MinMaxResult = NoElements; /// assert_eq!(r.into_option(), None); /// - /// let r = OneElement(1i); + /// let r = OneElement(1); /// assert_eq!(r.into_option(), Some((1,1))); /// - /// let r = MinMax(1i,2i); + /// let r = MinMax(1, 2); /// assert_eq!(r.into_option(), Some((1,2))); /// ``` pub fn into_option(self) -> Option<(T,T)> { @@ -1261,7 +1261,7 @@ pub trait CloneIteratorExt { /// ```rust /// use std::iter::{CloneIteratorExt, count}; /// - /// let a = count(1i,1i).take(1); + /// let a = count(1, 1).take(1); /// let mut cy = a.cycle(); /// assert_eq!(cy.next(), Some(1)); /// assert_eq!(cy.next(), Some(1)); diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 2620928acc1ac..9cf3433e1ab89 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -187,13 +187,13 @@ pub unsafe fn uninitialized() -> T { /// ``` /// use std::mem; /// -/// let x = &mut 5i; -/// let y = &mut 42i; +/// let x = &mut 5; +/// let y = &mut 42; /// /// mem::swap(x, y); /// -/// assert_eq!(42i, *x); -/// assert_eq!(5i, *y); +/// assert_eq!(42, *x); +/// assert_eq!(5, *y); /// ``` #[inline] #[stable] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 426c858d408ad..485d320cf5cc8 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -336,7 +336,7 @@ pub trait Int /// ```rust /// use std::num::Int; /// - /// assert_eq!(2i.pow(4), 16); + /// assert_eq!(2.pow(4), 16); /// ``` #[inline] fn pow(self, mut exp: uint) -> Self { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a9a1857ec97bf..9e55a3aa8c404 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -470,10 +470,10 @@ impl Option { /// /// ``` /// let x = Some("foo"); - /// assert_eq!(x.ok_or(0i), Ok("foo")); + /// assert_eq!(x.ok_or(0), Ok("foo")); /// /// let x: Option<&str> = None; - /// assert_eq!(x.ok_or(0i), Err(0i)); + /// assert_eq!(x.ok_or(0), Err(0)); /// ``` #[inline] #[experimental] @@ -491,10 +491,10 @@ impl Option { /// /// ``` /// let x = Some("foo"); - /// assert_eq!(x.ok_or_else(|| 0i), Ok("foo")); + /// assert_eq!(x.ok_or_else(|| 0), Ok("foo")); /// /// let x: Option<&str> = None; - /// assert_eq!(x.ok_or_else(|| 0i), Err(0i)); + /// assert_eq!(x.ok_or_else(|| 0), Err(0)); /// ``` #[inline] #[experimental] @@ -728,8 +728,8 @@ impl Option { /// let good_year = good_year_from_input.parse().unwrap_or_default(); /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); /// - /// assert_eq!(1909i, good_year); - /// assert_eq!(0i, bad_year); + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); /// ``` #[inline] #[stable] diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 233d1c049f4e5..f41a4a8b901a8 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -125,7 +125,7 @@ macro_rules! warn { /// #[phase(plugin, link)] extern crate log; /// /// fn main() { -/// let ret = 3i; +/// let ret = 3; /// info!("this function is about to return: {}", ret); /// } /// ``` @@ -152,7 +152,7 @@ macro_rules! info { /// #[phase(plugin, link)] extern crate log; /// /// fn main() { -/// debug!("x = {x}, y = {y}", x=10i, y=20i); +/// debug!("x = {x}, y = {y}", x=10, y=20); /// } /// ``` /// diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0f8dbc78cde32..1d37b061c9712 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -269,7 +269,7 @@ pub trait Rng : Sized { /// ``` /// use std::rand::{thread_rng, Rng}; /// - /// let choices = [1i, 2, 4, 8, 16, 32]; + /// let choices = [1, 2, 4, 8, 16, 32]; /// let mut rng = thread_rng(); /// println!("{}", rng.choose(&choices)); /// # // replace with slicing syntax when it's stable! @@ -291,7 +291,7 @@ pub trait Rng : Sized { /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); - /// let mut y = [1i, 2, 3]; + /// let mut y = [1, 2, 3]; /// rng.shuffle(&mut y); /// println!("{}", y.as_slice()); /// rng.shuffle(&mut y); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b1824db93aad1..7877e783ed699 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -164,7 +164,7 @@ impl, S, H: Hasher> HashSet { /// /// let h = SipHasher::new(); /// let mut set = HashSet::with_capacity_and_hasher(10u, h); - /// set.insert(1i); + /// set.insert(1); /// ``` #[inline] #[unstable = "hasher stuff is unclear"] @@ -283,8 +283,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { @@ -292,12 +292,12 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.difference(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1i].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [1].iter().map(|&x| x).collect()); /// /// // Note that difference is not symmetric, /// // and `b - a` means something else: /// let diff: HashSet = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [4].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn difference<'a>(&'a self, other: &'a HashSet) -> Difference<'a, T, H> { @@ -313,8 +313,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 4 in arbitrary order. /// for x in a.symmetric_difference(&b) { @@ -325,7 +325,7 @@ impl, S, H: Hasher> HashSet { /// let diff2: HashSet = b.symmetric_difference(&a).map(|&x| x).collect(); /// /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); + /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet) @@ -339,8 +339,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 2, 3 in arbitrary order. /// for x in a.intersection(&b) { @@ -348,7 +348,7 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn intersection<'a>(&'a self, other: &'a HashSet) -> Intersection<'a, T, H> { @@ -364,8 +364,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 2, 3, 4 in arbitrary order. /// for x in a.union(&b) { @@ -373,7 +373,7 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, H> { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 63fd3209cc019..fb2d23b01b464 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -33,7 +33,7 @@ /// # #![allow(unreachable_code)] /// panic!(); /// panic!("this is a terrible mistake!"); -/// panic!(4i); // panic with the value of 4 to be collected elsewhere +/// panic!(4); // panic with the value of 4 to be collected elsewhere /// panic!("this is a {} {message}", "fancy", message = "message"); /// ``` #[macro_export] @@ -74,7 +74,7 @@ macro_rules! panic { /// // assert with a custom message /// # let x = true; /// assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; +/// # let a = 3; let b = 27; /// assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] @@ -99,8 +99,8 @@ macro_rules! assert { /// # Example /// /// ``` -/// let a = 3i; -/// let b = 1i + 2i; +/// let a = 3; +/// let b = 1 + 2; /// assert_eq!(a, b); /// ``` #[macro_export] @@ -141,7 +141,7 @@ macro_rules! assert_eq { /// // assert with a custom message /// # let x = true; /// debug_assert!(x, "x wasn't true!"); -/// # let a = 3i; let b = 27i; +/// # let a = 3; let b = 27; /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] @@ -162,8 +162,8 @@ macro_rules! debug_assert { /// # Example /// /// ``` -/// let a = 3i; -/// let b = 1i + 2i; +/// let a = 3; +/// let b = 1 + 2; /// debug_assert_eq!(a, b); /// ``` #[macro_export] @@ -238,7 +238,7 @@ macro_rules! unimplemented { /// ``` /// format!("test"); /// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10i, y = 30i); +/// format!("x = {}, y = {y}", 10, y = 30); /// ``` #[macro_export] #[stable] @@ -338,7 +338,7 @@ macro_rules! vec { /// let (tx1, rx1) = channel(); /// let (tx2, rx2) = channel(); /// # fn long_running_task() {} -/// # fn calculate_the_answer() -> int { 42i } +/// # fn calculate_the_answer() -> int { 42 } /// /// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach(); /// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); @@ -507,7 +507,7 @@ pub mod builtin { /// # Example /// /// ``` - /// let s = concat!("test", 10i, 'b', true); + /// let s = concat!("test", 10, 'b', true); /// assert_eq!(s, "test10btrue"); /// ``` #[macro_export] diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6bc3f561bb3c7..338cadafff724 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Multi-producer, single-consumer communication primitives threads +//! Communication primitives for concurrent tasks +//! +//! Rust makes it very difficult to share data among tasks to prevent race +//! conditions and to improve parallelism, but there is often a need for +//! communication between concurrent tasks. The primitives defined in this +//! module are the building blocks for synchronization in rust. //! //! This module provides message-based communication over channels, concretely //! defined among three types: @@ -18,10 +23,12 @@ //! * `Receiver` //! //! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both -//! senders are clone-able (multi-producer) such that many threads can send -//! simultaneously to one receiver (single-consumer). +//! senders are clone-able such that many tasks can send simultaneously to one +//! receiver. These channels are *task blocking*, not *thread blocking*. This +//! means that if one task is blocked on a channel, other tasks can continue to +//! make progress. //! -//! These channels come in two flavors: +//! Rust channels come in one of two flavors: //! //! 1. An asynchronous, infinitely buffered channel. The `channel()` function //! will return a `(Sender, Receiver)` tuple where all sends will be @@ -36,39 +43,36 @@ //! "rendezvous" channel where each sender atomically hands off a message to //! a receiver. //! -//! ## Disconnection +//! ## Panic Propagation //! -//! The send and receive operations on channels will all return a `Result` -//! indicating whether the operation succeeded or not. An unsuccessful operation -//! is normally indicative of the other half of a channel having "hung up" by -//! being dropped in its corresponding thread. +//! In addition to being a core primitive for communicating in rust, channels +//! are the points at which panics are propagated among tasks. Whenever the one +//! half of channel is closed, the other half will have its next operation +//! `panic!`. The purpose of this is to allow propagation of panics among tasks +//! that are linked to one another via channels. //! -//! Once half of a channel has been deallocated, most operations can no longer -//! continue to make progress, so `Err` will be returned. Many applications will -//! continue to `unwrap()` the results returned from this module, instigating a -//! propagation of failure among threads if one unexpectedly dies. +//! There are methods on both of senders and receivers to perform their +//! respective operations without panicking, however. //! -//! # Examples +//! # Example //! //! Simple usage: //! //! ``` //! use std::thread::Thread; -//! use std::sync::mpsc::channel; //! //! // Create a simple streaming channel //! let (tx, rx) = channel(); //! Thread::spawn(move|| { -//! tx.send(10i).unwrap(); +//! tx.send(10); //! }).detach(); -//! assert_eq!(rx.recv().unwrap(), 10i); +//! assert_eq!(rx.recv(), 10); //! ``` //! //! Shared usage: //! //! ``` //! use std::thread::Thread; -//! use std::sync::mpsc::channel; //! //! // Create a shared channel that can be sent along from many threads //! // where tx is the sending half (tx for transmission), and rx is the receiving @@ -77,40 +81,37 @@ //! for i in range(0i, 10i) { //! let tx = tx.clone(); //! Thread::spawn(move|| { -//! tx.send(i).unwrap(); +//! tx.send(i); //! }).detach() //! } //! //! for _ in range(0i, 10i) { -//! let j = rx.recv().unwrap(); +//! let j = rx.recv(); //! assert!(0 <= j && j < 10); //! } //! ``` //! //! Propagating panics: //! -//! ``` -//! use std::sync::mpsc::channel; -//! -//! // The call to recv() will return an error because the channel has already -//! // hung up (or been deallocated) +//! ```should_fail +//! // The call to recv() will panic!() because the channel has already hung +//! // up (or been deallocated) //! let (tx, rx) = channel::(); //! drop(tx); -//! assert!(rx.recv().is_err()); +//! rx.recv(); //! ``` //! //! Synchronous channels: //! //! ``` //! use std::thread::Thread; -//! use std::sync::mpsc::sync_channel; //! //! let (tx, rx) = sync_channel::(0); //! Thread::spawn(move|| { //! // This will wait for the parent task to start receiving -//! tx.send(53).unwrap(); +//! tx.send(53); //! }).detach(); -//! rx.recv().unwrap(); +//! rx.recv(); //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together @@ -119,7 +120,6 @@ //! after 10 seconds no matter what: //! //! ```no_run -//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -129,8 +129,8 @@ //! //! loop { //! select! { -//! val = rx.recv() => println!("Received {}", val.unwrap()), -//! _ = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val), +//! () = timeout.recv() => { //! println!("timed out, total time was more than 10 seconds"); //! break; //! } @@ -143,7 +143,6 @@ //! has been inactive for 5 seconds: //! //! ```no_run -//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -154,8 +153,8 @@ //! let timeout = timer.oneshot(Duration::seconds(5)); //! //! select! { -//! val = rx.recv() => println!("Received {}", val.unwrap()), -//! _ = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val), +//! () = timeout.recv() => { //! println!("timed out, no message received in 5 seconds"); //! break; //! } @@ -313,19 +312,38 @@ // And now that you've seen all the races that I found and attempted to fix, // here's the code for you to find some more! -use prelude::v1::*; +use core::prelude::*; -use sync::Arc; -use fmt; -use kinds::marker; -use mem; -use cell::UnsafeCell; +pub use self::TryRecvError::*; +pub use self::TrySendError::*; + +use alloc::arc::Arc; +use core::kinds; +use core::kinds::marker; +use core::mem; +use core::cell::UnsafeCell; pub use self::select::{Select, Handle}; use self::select::StartResult; use self::select::StartResult::*; use self::blocking::SignalToken; +macro_rules! test { + { fn $name:ident() $b:block $(#[$a:meta])*} => ( + mod $name { + #![allow(unused_imports)] + + use super::*; + use comm::*; + use thread::Thread; + use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option}; + use prelude::{Vec, Buffer, from_str, Clone}; + + $(#[$a])* #[test] fn f() { $b } + } + ) +} + mod blocking; mod oneshot; mod select; @@ -337,7 +355,7 @@ mod spsc_queue; /// The receiving-half of Rust's channel type. This half can only be owned by /// one task -#[stable] +#[unstable] pub struct Receiver { inner: UnsafeCell>, } @@ -349,14 +367,14 @@ unsafe impl Send for Receiver { } /// An iterator over messages on a receiver, this iterator will block /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. -#[stable] -pub struct Iter<'a, T:'a> { +#[unstable] +pub struct Messages<'a, T:'a> { rx: &'a Receiver } /// The sending-half of Rust's asynchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[stable] +#[unstable] pub struct Sender { inner: UnsafeCell>, } @@ -367,50 +385,30 @@ unsafe impl Send for Sender { } /// The sending-half of Rust's synchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[stable] +#[unstable = "this type may be renamed, but it will always exist"] pub struct SyncSender { inner: Arc>>, // can't share in an arc _marker: marker::NoSync, } -/// An error returned from the `send` function on channels. -/// -/// A `send` operation can only fail if the receiving end of a channel is -/// disconnected, implying that the data could never be received. The error -/// contains the data being sent as a payload so it can be recovered. -#[derive(PartialEq, Eq)] -#[stable] -pub struct SendError(pub T); - -/// An error returned from the `recv` function on a `Receiver`. -/// -/// The `recv` operation can only fail if the sending half of a channel is -/// disconnected, implying that no further messages will ever be received. -#[derive(PartialEq, Eq, Clone, Copy)] -#[stable] -pub struct RecvError; - /// This enumeration is the list of the possible reasons that try_recv could not /// return data when called. -#[derive(PartialEq, Clone, Copy)] -#[stable] +#[deriving(PartialEq, Clone, Copy, Show)] +#[experimental = "this is likely to be removed in changing try_recv()"] pub enum TryRecvError { /// This channel is currently empty, but the sender(s) have not yet /// disconnected, so data may yet become available. - #[stable] Empty, - /// This channel's sending half has become disconnected, and there will /// never be any more data received on this channel - #[stable] Disconnected, } /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. -#[derive(PartialEq, Clone)] -#[stable] +#[deriving(PartialEq, Clone, Show)] +#[experimental = "this is likely to be removed in changing try_send()"] pub enum TrySendError { /// The data could not be sent on the channel because it would require that /// the callee block to send the data. @@ -418,13 +416,10 @@ pub enum TrySendError { /// If this is a buffered channel, then the buffer is full at this time. If /// this is not a buffered channel, then there is no receiver available to /// acquire the data. - #[stable] Full(T), - /// This channel's receiving half has disconnected, so the data could not be /// sent. The data is returned back to the callee in this case. - #[stable] - Disconnected(T), + RecvDisconnected(T), } enum Flavor { @@ -463,7 +458,6 @@ impl UnsafeFlavor for Receiver { /// # Example /// /// ``` -/// use std::sync::mpsc::channel; /// use std::thread::Thread; /// /// // tx is is the sending half (tx for transmission), and rx is the receiving @@ -473,15 +467,15 @@ impl UnsafeFlavor for Receiver { /// // Spawn off an expensive computation /// Thread::spawn(move|| { /// # fn expensive_computation() {} -/// tx.send(expensive_computation()).unwrap(); +/// tx.send(expensive_computation()); /// }).detach(); /// /// // Do some useful work for awhile /// /// // Let's see what that answer was -/// println!("{}", rx.recv().unwrap()); +/// println!("{}", rx.recv()); /// ``` -#[stable] +#[unstable] pub fn channel() -> (Sender, Receiver) { let a = Arc::new(RacyCell::new(oneshot::Packet::new())); (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) @@ -505,23 +499,23 @@ pub fn channel() -> (Sender, Receiver) { /// # Example /// /// ``` -/// use std::sync::mpsc::sync_channel; /// use std::thread::Thread; /// /// let (tx, rx) = sync_channel(1); /// /// // this returns immediately -/// tx.send(1i).unwrap(); +/// tx.send(1); /// /// Thread::spawn(move|| { /// // this will block until the previous message has been received -/// tx.send(2i).unwrap(); +/// tx.send(2); /// }).detach(); /// -/// assert_eq!(rx.recv().unwrap(), 1i); -/// assert_eq!(rx.recv().unwrap(), 2i); +/// assert_eq!(rx.recv(), 1); +/// assert_eq!(rx.recv(), 2); /// ``` -#[stable] +#[unstable = "this function may be renamed to more accurately reflect the type \ + of channel that is is creating"] pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { let a = Arc::new(RacyCell::new(sync::Packet::new(bound))); (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) @@ -538,6 +532,33 @@ impl Sender { } } + /// Sends a value along this channel to be received by the corresponding + /// receiver. + /// + /// Rust channels are infinitely buffered so this method will never block. + /// + /// # Panics + /// + /// This function will panic if the other end of the channel has hung up. + /// This means that if the corresponding receiver has fallen out of scope, + /// this function will trigger a panic message saying that a message is + /// being sent on a closed channel. + /// + /// Note that if this function does *not* panic, it does not mean that the + /// data will be successfully received. All sends are placed into a queue, + /// so it is possible for a send to succeed (the other end is alive), but + /// then the other end could immediately disconnect. + /// + /// The purpose of this functionality is to propagate panics among tasks. + /// If a panic is not desired, then consider using the `send_opt` method + #[experimental = "this function is being considered candidate for removal \ + to adhere to the general guidelines of rust"] + pub fn send(&self, t: T) { + if self.send_opt(t).is_err() { + panic!("sending on a closed channel"); + } + } + /// Attempts to send a value on this channel, returning it back if it could /// not be sent. /// @@ -549,34 +570,37 @@ impl Sender { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns `Ok`. /// - /// This method will never block the current thread. + /// Like `send`, this method will never block. + /// + /// # Panics + /// + /// This method will never panic, it will return the message back to the + /// caller if the other end is disconnected /// /// # Example /// /// ``` - /// use std::sync::mpsc::channel; - /// /// let (tx, rx) = channel(); /// /// // This send is always successful - /// tx.send(1i).unwrap(); + /// assert_eq!(tx.send_opt(1), Ok(())); /// /// // This send will fail because the receiver is gone /// drop(rx); - /// assert_eq!(tx.send(1i).err().unwrap().0, 1); + /// assert_eq!(tx.send_opt(1), Err(1)); /// ``` - pub fn send(&self, t: T) -> Result<(), SendError> { + #[unstable = "this function may be renamed to send() in the future"] + pub fn send_opt(&self, t: T) -> Result<(), T> { let (new_inner, ret) = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { unsafe { let p = p.get(); if !(*p).sent() { - return (*p).send(t).map_err(SendError); + return (*p).send(t); } else { let a = Arc::new(RacyCell::new(stream::Packet::new())); - let rx = Receiver::new(Flavor::Stream(a.clone())); - match (*p).upgrade(rx) { + match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) { oneshot::UpSuccess => { let ret = (*a.get()).send(t); (a, ret) @@ -594,12 +618,8 @@ impl Sender { } } } - Flavor::Stream(ref p) => return unsafe { - (*p.get()).send(t).map_err(SendError) - }, - Flavor::Shared(ref p) => return unsafe { - (*p.get()).send(t).map_err(SendError) - }, + Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) }, + Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) }, Flavor::Sync(..) => unreachable!(), }; @@ -607,7 +627,7 @@ impl Sender { let tmp = Sender::new(Flavor::Stream(new_inner)); mem::swap(self.inner_mut(), tmp.inner_mut()); } - ret.map_err(SendError) + return ret; } } @@ -619,8 +639,7 @@ impl Clone for Sender { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - let rx = Receiver::new(Flavor::Shared(a.clone())); - match (*p.get()).upgrade(rx) { + match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { oneshot::UpSuccess | oneshot::UpDisconnected => (a, None, guard), oneshot::UpWoke(task) => (a, Some(task), guard) @@ -631,8 +650,7 @@ impl Clone for Sender { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - let rx = Receiver::new(Flavor::Shared(a.clone())); - match (*p.get()).upgrade(rx) { + match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { stream::UpSuccess | stream::UpDisconnected => (a, None, guard), stream::UpWoke(task) => (a, Some(task), guard), @@ -683,29 +701,59 @@ impl SyncSender { /// available or a receiver is available to hand off the message to. /// /// Note that a successful send does *not* guarantee that the receiver will - /// ever see the data if there is a buffer on this channel. Items may be + /// ever see the data if there is a buffer on this channel. Messages may be /// enqueued in the internal buffer for the receiver to receive at a later /// time. If the buffer size is 0, however, it can be guaranteed that the /// receiver has indeed received the data if this function returns success. /// - /// This function will never panic, but it may return `Err` if the - /// `Receiver` has disconnected and is no longer able to receive - /// information. - #[stable] - pub fn send(&self, t: T) -> Result<(), SendError> { - unsafe { (*self.inner.get()).send(t).map_err(SendError) } + /// # Panics + /// + /// Similarly to `Sender::send`, this function will panic if the + /// corresponding `Receiver` for this channel has disconnected. This + /// behavior is used to propagate panics among tasks. + /// + /// If a panic is not desired, you can achieve the same semantics with the + /// `SyncSender::send_opt` method which will not panic if the receiver + /// disconnects. + #[experimental = "this function is being considered candidate for removal \ + to adhere to the general guidelines of rust"] + pub fn send(&self, t: T) { + if self.send_opt(t).is_err() { + panic!("sending on a closed channel"); + } + } + + /// Send a value on a channel, returning it back if the receiver + /// disconnected + /// + /// This method will *block* to send the value `t` on the channel, but if + /// the value could not be sent due to the receiver disconnecting, the value + /// is returned back to the callee. This function is similar to `try_send`, + /// except that it will block if the channel is currently full. + /// + /// # Panics + /// + /// This function cannot panic. + #[unstable = "this function may be renamed to send() in the future"] + pub fn send_opt(&self, t: T) -> Result<(), T> { + unsafe { (*self.inner.get()).send(t) } } /// Attempts to send a value on this channel without blocking. /// - /// This method differs from `send` by returning immediately if the + /// This method differs from `send_opt` by returning immediately if the /// channel's buffer is full or no receiver is waiting to acquire some - /// data. Compared with `send`, this function has two failure cases + /// data. Compared with `send_opt`, this function has two failure cases /// instead of one (one for disconnection, one for a full buffer). /// /// See `SyncSender::send` for notes about guarantees of whether the /// receiver has received the data or not if this function is successful. - #[stable] + /// + /// # Panics + /// + /// This function cannot panic + #[unstable = "the return type of this function is candidate for \ + modification"] pub fn try_send(&self, t: T) -> Result<(), TrySendError> { unsafe { (*self.inner.get()).try_send(t) } } @@ -735,6 +783,34 @@ impl Receiver { Receiver { inner: UnsafeCell::new(inner) } } + /// Blocks waiting for a value on this receiver + /// + /// This function will block if necessary to wait for a corresponding send + /// on the channel from its paired `Sender` structure. This receiver will + /// be woken up when data is ready, and the data will be returned. + /// + /// # Panics + /// + /// Similar to channels, this method will trigger a task panic if the + /// other end of the channel has hung up (been deallocated). The purpose of + /// this is to propagate panics among tasks. + /// + /// If a panic is not desired, then there are two options: + /// + /// * If blocking is still desired, the `recv_opt` method will return `None` + /// when the other end hangs up + /// + /// * If blocking is not desired, then the `try_recv` method will attempt to + /// peek at a value on this receiver. + #[experimental = "this function is being considered candidate for removal \ + to adhere to the general guidelines of rust"] + pub fn recv(&self) -> T { + match self.recv_opt() { + Ok(t) => t, + Err(()) => panic!("receiving on a closed channel"), + } + } + /// Attempts to return a pending value on this receiver without blocking /// /// This method will never block the caller in order to wait for data to @@ -743,46 +819,42 @@ impl Receiver { /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. - #[stable] + /// + /// # Panics + /// + /// This function cannot panic. + #[unstable = "the return type of this function may be altered"] pub fn try_recv(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(oneshot::Empty) => return Err(TryRecvError::Empty), - Err(oneshot::Disconnected) => { - return Err(TryRecvError::Disconnected) - } + Err(oneshot::Empty) => return Err(Empty), + Err(oneshot::Disconnected) => return Err(Disconnected), Err(oneshot::Upgraded(rx)) => rx, } } Flavor::Stream(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(stream::Empty) => return Err(TryRecvError::Empty), - Err(stream::Disconnected) => { - return Err(TryRecvError::Disconnected) - } + Err(stream::Empty) => return Err(Empty), + Err(stream::Disconnected) => return Err(Disconnected), Err(stream::Upgraded(rx)) => rx, } } Flavor::Shared(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(shared::Empty) => return Err(TryRecvError::Empty), - Err(shared::Disconnected) => { - return Err(TryRecvError::Disconnected) - } + Err(shared::Empty) => return Err(Empty), + Err(shared::Disconnected) => return Err(Disconnected), } } Flavor::Sync(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(sync::Empty) => return Err(TryRecvError::Empty), - Err(sync::Disconnected) => { - return Err(TryRecvError::Disconnected) - } + Err(sync::Empty) => return Err(Empty), + Err(sync::Disconnected) => return Err(Disconnected), } } }; @@ -793,26 +865,27 @@ impl Receiver { } } - /// Attempt to wait for a value on this receiver, returning an error if the + /// Attempt to wait for a value on this receiver, but does not panic if the /// corresponding channel has hung up. /// - /// This function will always block the current thread if there is no data - /// available and it's possible for more data to be sent. Once a message is - /// sent to the corresponding `Sender`, then this receiver will wake up and - /// return that message. + /// This implementation of iterators for ports will always block if there is + /// not data available on the receiver, but it will not panic in the case + /// that the channel has been deallocated. /// - /// If the corresponding `Sender` has disconnected, or it disconnects while - /// this call is blocking, this call will wake up and return `Err` to - /// indicate that no more messages can ever be received on this channel. - #[stable] - pub fn recv(&self) -> Result { + /// In other words, this function has the same semantics as the `recv` + /// method except for the panic aspect. + /// + /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of + /// the value found on the receiver is returned. + #[unstable = "this function may be renamed to recv()"] + pub fn recv_opt(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(oneshot::Empty) => return unreachable!(), - Err(oneshot::Disconnected) => return Err(RecvError), + Err(oneshot::Disconnected) => return Err(()), Err(oneshot::Upgraded(rx)) => rx, } } @@ -820,7 +893,7 @@ impl Receiver { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(stream::Empty) => return unreachable!(), - Err(stream::Disconnected) => return Err(RecvError), + Err(stream::Disconnected) => return Err(()), Err(stream::Upgraded(rx)) => rx, } } @@ -828,12 +901,10 @@ impl Receiver { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(shared::Empty) => return unreachable!(), - Err(shared::Disconnected) => return Err(RecvError), + Err(shared::Disconnected) => return Err(()), } } - Flavor::Sync(ref p) => return unsafe { - (*p.get()).recv().map_err(|()| RecvError) - } + Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() } }; unsafe { mem::swap(self.inner_mut(), new_port.inner_mut()); @@ -843,9 +914,9 @@ impl Receiver { /// Returns an iterator that will block waiting for messages, but never /// `panic!`. It will return `None` when the channel has hung up. - #[stable] - pub fn iter(&self) -> Iter { - Iter { rx: self } + #[unstable] + pub fn iter<'a>(&'a self) -> Messages<'a, T> { + Messages { rx: self } } } @@ -936,10 +1007,8 @@ impl select::Packet for Receiver { } #[unstable] -impl<'a, T: Send> Iterator for Iter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { self.rx.recv().ok() } +impl<'a, T: Send> Iterator for Messages<'a, T> { + fn next(&mut self) -> Option { self.rx.recv_opt().ok() } } #[unsafe_destructor] @@ -972,425 +1041,368 @@ impl RacyCell { unsafe impl Send for RacyCell { } -unsafe impl Sync for RacyCell { } // Oh dear - -impl fmt::Show for SendError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - "sending on a closed channel".fmt(f) - } -} - -impl fmt::Show for TrySendError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - TrySendError::Full(..) => { - "sending on a full channel".fmt(f) - } - TrySendError::Disconnected(..) => { - "sending on a closed channel".fmt(f) - } - } - } -} - -impl fmt::Show for RecvError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - "receiving on a closed channel".fmt(f) - } -} +unsafe impl kinds::Sync for RacyCell { } // Oh dear -impl fmt::Show for TryRecvError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - TryRecvError::Empty => { - "receiving on an empty channel".fmt(f) - } - TryRecvError::Disconnected => { - "receiving on a closed channel".fmt(f) - } - } - } -} #[cfg(test)] mod test { - use prelude::v1::*; - - use os; use super::*; - use thread::Thread; + use prelude::{spawn, range, Some, None, from_str, Clone, Str}; + use os; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => val.parse().unwrap(), + Some(val) => from_str::(val.as_slice()).unwrap(), None => 1, } } - #[test] - fn smoke() { + test! { fn smoke() { let (tx, rx) = channel::(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } + tx.send(1); + assert_eq!(rx.recv(), 1); + } } - #[test] - fn drop_full() { + test! { fn drop_full() { let (tx, _rx) = channel(); - tx.send(box 1i).unwrap(); - } + tx.send(box 1i); + } } - #[test] - fn drop_full_shared() { + test! { fn drop_full_shared() { let (tx, _rx) = channel(); drop(tx.clone()); drop(tx.clone()); - tx.send(box 1i).unwrap(); - } + tx.send(box 1i); + } } - #[test] - fn smoke_shared() { + test! { fn smoke_shared() { let (tx, rx) = channel::(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); + tx.send(1); + assert_eq!(rx.recv(), 1); let tx = tx.clone(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } + tx.send(1); + assert_eq!(rx.recv(), 1); + } } - #[test] - fn smoke_threads() { + test! { fn smoke_threads() { let (tx, rx) = channel::(); - let _t = Thread::spawn(move|| { - tx.send(1).unwrap(); + spawn(move|| { + tx.send(1); }); - assert_eq!(rx.recv().unwrap(), 1); - } + assert_eq!(rx.recv(), 1); + } } - #[test] - fn smoke_port_gone() { + test! { fn smoke_port_gone() { let (tx, rx) = channel::(); drop(rx); - assert!(tx.send(1).is_err()); - } + tx.send(1); + } #[should_fail] } - #[test] - fn smoke_shared_port_gone() { + test! { fn smoke_shared_port_gone() { let (tx, rx) = channel::(); drop(rx); - assert!(tx.send(1).is_err()) - } + tx.send(1); + } #[should_fail] } - #[test] - fn smoke_shared_port_gone2() { + test! { fn smoke_shared_port_gone2() { let (tx, rx) = channel::(); drop(rx); let tx2 = tx.clone(); drop(tx); - assert!(tx2.send(1).is_err()); - } + tx2.send(1); + } #[should_fail] } - #[test] - fn port_gone_concurrent() { + test! { fn port_gone_concurrent() { let (tx, rx) = channel::(); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); + spawn(move|| { + rx.recv(); }); - while tx.send(1).is_ok() {} - } + loop { tx.send(1) } + } #[should_fail] } - #[test] - fn port_gone_concurrent_shared() { + test! { fn port_gone_concurrent_shared() { let (tx, rx) = channel::(); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); + spawn(move|| { + rx.recv(); }); - while tx.send(1).is_ok() && tx2.send(1).is_ok() {} - } + loop { + tx.send(1); + tx2.send(1); + } + } #[should_fail] } - #[test] - fn smoke_chan_gone() { + test! { fn smoke_chan_gone() { let (tx, rx) = channel::(); drop(tx); - assert!(rx.recv().is_err()); - } + rx.recv(); + } #[should_fail] } - #[test] - fn smoke_chan_gone_shared() { + test! { fn smoke_chan_gone_shared() { let (tx, rx) = channel::<()>(); let tx2 = tx.clone(); drop(tx); drop(tx2); - assert!(rx.recv().is_err()); - } + rx.recv(); + } #[should_fail] } - #[test] - fn chan_gone_concurrent() { + test! { fn chan_gone_concurrent() { let (tx, rx) = channel::(); - let _t = Thread::spawn(move|| { - tx.send(1).unwrap(); - tx.send(1).unwrap(); + spawn(move|| { + tx.send(1); + tx.send(1); }); - while rx.recv().is_ok() {} - } + loop { rx.recv(); } + } #[should_fail] } - #[test] - fn stress() { + test! { fn stress() { let (tx, rx) = channel::(); - let t = Thread::spawn(move|| { - for _ in range(0u, 10000) { tx.send(1i).unwrap(); } + spawn(move|| { + for _ in range(0u, 10000) { tx.send(1i); } }); for _ in range(0u, 10000) { - assert_eq!(rx.recv().unwrap(), 1); + assert_eq!(rx.recv(), 1); } - t.join().ok().unwrap(); - } + } } - #[test] - fn stress_shared() { + test! { fn stress_shared() { static AMT: uint = 10000; static NTHREADS: uint = 8; let (tx, rx) = channel::(); + let (dtx, drx) = channel::<()>(); - let t = Thread::spawn(move|| { + spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv().unwrap(), 1); + assert_eq!(rx.recv(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } + dtx.send(()); }); for _ in range(0, NTHREADS) { let tx = tx.clone(); - Thread::spawn(move|| { - for _ in range(0, AMT) { tx.send(1).unwrap(); } - }).detach(); + spawn(move|| { + for _ in range(0, AMT) { tx.send(1); } + }); } drop(tx); - t.join().ok().unwrap(); - } + drx.recv(); + } } #[test] fn send_from_outside_runtime() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::(); - let t1 = Thread::spawn(move|| { - tx1.send(()).unwrap(); + let (tx3, rx3) = channel::<()>(); + let tx4 = tx3.clone(); + spawn(move|| { + tx1.send(()); for _ in range(0i, 40) { - assert_eq!(rx2.recv().unwrap(), 1); + assert_eq!(rx2.recv(), 1); } + tx3.send(()); }); - rx1.recv().unwrap(); - let t2 = Thread::spawn(move|| { + rx1.recv(); + spawn(move|| { for _ in range(0i, 40) { - tx2.send(1).unwrap(); + tx2.send(1); } + tx4.send(()); }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + rx3.recv(); + rx3.recv(); } #[test] fn recv_from_outside_runtime() { let (tx, rx) = channel::(); - let t = Thread::spawn(move|| { + let (dtx, drx) = channel(); + spawn(move|| { for _ in range(0i, 40) { - assert_eq!(rx.recv().unwrap(), 1); + assert_eq!(rx.recv(), 1); } + dtx.send(()); }); for _ in range(0u, 40) { - tx.send(1).unwrap(); + tx.send(1); } - t.join().ok().unwrap(); + drx.recv(); } #[test] fn no_runtime() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); - let t1 = Thread::spawn(move|| { - assert_eq!(rx1.recv().unwrap(), 1); - tx2.send(2).unwrap(); + let (tx3, rx3) = channel::<()>(); + let tx4 = tx3.clone(); + spawn(move|| { + assert_eq!(rx1.recv(), 1); + tx2.send(2); + tx4.send(()); }); - let t2 = Thread::spawn(move|| { - tx1.send(1).unwrap(); - assert_eq!(rx2.recv().unwrap(), 2); + spawn(move|| { + tx1.send(1); + assert_eq!(rx2.recv(), 2); + tx3.send(()); }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + rx3.recv(); + rx3.recv(); } - #[test] - fn oneshot_single_thread_close_port_first() { + test! { fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = channel::(); drop(rx); - } + } } - #[test] - fn oneshot_single_thread_close_chan_first() { + test! { fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = channel::(); drop(tx); - } + } } - #[test] - fn oneshot_single_thread_send_port_close() { + test! { fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = channel::>(); drop(rx); - assert!(tx.send(box 0).is_err()); - } + tx.send(box 0); + } #[should_fail] } - #[test] - fn oneshot_single_thread_recv_chan_close() { + test! { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = channel::(); drop(tx); - rx.recv().unwrap(); + rx.recv(); }).join(); // What is our res? assert!(res.is_err()); - } + } } - #[test] - fn oneshot_single_thread_send_then_recv() { + test! { fn oneshot_single_thread_send_then_recv() { let (tx, rx) = channel::>(); - tx.send(box 10).unwrap(); - assert!(rx.recv().unwrap() == box 10); - } + tx.send(box 10); + assert!(rx.recv() == box 10); + } } - #[test] - fn oneshot_single_thread_try_send_open() { + test! { fn oneshot_single_thread_try_send_open() { let (tx, rx) = channel::(); - assert!(tx.send(10).is_ok()); - assert!(rx.recv().unwrap() == 10); - } + assert!(tx.send_opt(10).is_ok()); + assert!(rx.recv() == 10); + } } - #[test] - fn oneshot_single_thread_try_send_closed() { + test! { fn oneshot_single_thread_try_send_closed() { let (tx, rx) = channel::(); drop(rx); - assert!(tx.send(10).is_err()); - } + assert!(tx.send_opt(10).is_err()); + } } - #[test] - fn oneshot_single_thread_try_recv_open() { + test! { fn oneshot_single_thread_try_recv_open() { let (tx, rx) = channel::(); - tx.send(10).unwrap(); - assert!(rx.recv() == Ok(10)); - } + tx.send(10); + assert!(rx.recv_opt() == Ok(10)); + } } - #[test] - fn oneshot_single_thread_try_recv_closed() { + test! { fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = channel::(); drop(tx); - assert!(rx.recv().is_err()); - } + assert!(rx.recv_opt() == Err(())); + } } - #[test] - fn oneshot_single_thread_peek_data() { + test! { fn oneshot_single_thread_peek_data() { let (tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - tx.send(10).unwrap(); + assert_eq!(rx.try_recv(), Err(Empty)); + tx.send(10); assert_eq!(rx.try_recv(), Ok(10)); - } + } } - #[test] - fn oneshot_single_thread_peek_close() { + test! { fn oneshot_single_thread_peek_close() { let (tx, rx) = channel::(); drop(tx); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - } + assert_eq!(rx.try_recv(), Err(Disconnected)); + assert_eq!(rx.try_recv(), Err(Disconnected)); + } } - #[test] - fn oneshot_single_thread_peek_open() { + test! { fn oneshot_single_thread_peek_open() { let (_tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - } + assert_eq!(rx.try_recv(), Err(Empty)); + } } - #[test] - fn oneshot_multi_task_recv_then_send() { + test! { fn oneshot_multi_task_recv_then_send() { let (tx, rx) = channel::>(); - let _t = Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box 10); + spawn(move|| { + assert!(rx.recv() == box 10); }); - tx.send(box 10).unwrap(); - } + tx.send(box 10); + } } - #[test] - fn oneshot_multi_task_recv_then_close() { + test! { fn oneshot_multi_task_recv_then_close() { let (tx, rx) = channel::>(); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box 10); + assert!(rx.recv() == box 10); }).join(); assert!(res.is_err()); - } + } } - #[test] - fn oneshot_multi_thread_close_stress() { + test! { fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(rx); }); drop(tx); } - } + } } - #[test] - fn oneshot_multi_thread_send_close_stress() { + test! { fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(rx); }); let _ = Thread::spawn(move|| { - tx.send(1).unwrap(); + tx.send(1); }).join(); } - } + } } - #[test] - fn oneshot_multi_thread_recv_close_stress() { + test! { fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - Thread::spawn(move|| { + spawn(move|| { let res = Thread::spawn(move|| { - rx.recv().unwrap(); + rx.recv(); }).join(); assert!(res.is_err()); - }).detach(); - let _t = Thread::spawn(move|| { - Thread::spawn(move|| { + }); + spawn(move|| { + spawn(move|| { drop(tx); - }).detach(); + }); }); } - } + } } - #[test] - fn oneshot_multi_thread_send_recv_stress() { + test! { fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { - tx.send(box 10i).unwrap(); + spawn(move|| { + tx.send(box 10i); + }); + spawn(move|| { + assert!(rx.recv() == box 10i); }); - assert!(rx.recv().unwrap() == box 10i); } - } + } } - #[test] - fn stream_send_recv_stress() { + test! { fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); @@ -1400,73 +1412,69 @@ mod test { fn send(tx: Sender>, i: int) { if i == 10 { return } - Thread::spawn(move|| { - tx.send(box i).unwrap(); + spawn(move|| { + tx.send(box i); send(tx, i + 1); - }).detach(); + }); } fn recv(rx: Receiver>, i: int) { if i == 10 { return } - Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box i); + spawn(move|| { + assert!(rx.recv() == box i); recv(rx, i + 1); - }).detach(); + }); } } - } + } } - #[test] - fn recv_a_lot() { + test! { fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = channel(); - for _ in range(0i, 10000) { tx.send(()).unwrap(); } - for _ in range(0i, 10000) { rx.recv().unwrap(); } - } + for _ in range(0i, 10000) { tx.send(()); } + for _ in range(0i, 10000) { rx.recv(); } + } } - #[test] - fn shared_chan_stress() { + test! { fn shared_chan_stress() { let (tx, rx) = channel(); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - Thread::spawn(move|| { - tx.send(()).unwrap(); - }).detach(); + spawn(move|| { + tx.send(()); + }); } for _ in range(0, total) { - rx.recv().unwrap(); + rx.recv(); } - } + } } - #[test] - fn test_nested_recv_iter() { + test! { fn test_nested_recv_iter() { let (tx, rx) = channel::(); let (total_tx, total_rx) = channel::(); - let _t = Thread::spawn(move|| { + spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc).unwrap(); + total_tx.send(acc); }); - tx.send(3).unwrap(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); + tx.send(3); + tx.send(1); + tx.send(2); drop(tx); - assert_eq!(total_rx.recv().unwrap(), 6); - } + assert_eq!(total_rx.recv(), 6); + } } - #[test] - fn test_recv_iter_break() { + test! { fn test_recv_iter_break() { let (tx, rx) = channel::(); let (count_tx, count_rx) = channel(); - let _t = Thread::spawn(move|| { + spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1475,51 +1483,49 @@ mod test { count += x; } } - count_tx.send(count).unwrap(); + count_tx.send(count); }); - tx.send(2).unwrap(); - tx.send(2).unwrap(); - tx.send(2).unwrap(); - let _ = tx.send(2); + tx.send(2); + tx.send(2); + tx.send(2); + let _ = tx.send_opt(2); drop(tx); - assert_eq!(count_rx.recv().unwrap(), 4); - } + assert_eq!(count_rx.recv(), 4); + } } - #[test] - fn try_recv_states() { + test! { fn try_recv_states() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); - let _t = Thread::spawn(move|| { - rx2.recv().unwrap(); - tx1.send(1).unwrap(); - tx3.send(()).unwrap(); - rx2.recv().unwrap(); + spawn(move|| { + rx2.recv(); + tx1.send(1); + tx3.send(()); + rx2.recv(); drop(tx1); - tx3.send(()).unwrap(); + tx3.send(()); }); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(Empty)); + tx2.send(()); + rx3.recv(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); - } + assert_eq!(rx1.try_recv(), Err(Empty)); + tx2.send(()); + rx3.recv(); + assert_eq!(rx1.try_recv(), Err(Disconnected)); + } } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - #[test] - fn destroy_upgraded_shared_port_when_sender_still_active() { + test! { fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = channel(); let (tx2, rx2) = channel(); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); // wait on a oneshot + spawn(move|| { + rx.recv(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()).unwrap(); + tx2.send(()); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1527,334 +1533,303 @@ mod test { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()).unwrap(); + t.send(()); // wait for the child task to exit before we exit - rx2.recv().unwrap(); - } + rx2.recv(); + }} } #[cfg(test)] mod sync_tests { - use prelude::v1::*; - + use prelude::*; use os; - use thread::Thread; - use super::*; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => val.parse().unwrap(), + Some(val) => from_str::(val.as_slice()).unwrap(), None => 1, } } - #[test] - fn smoke() { + test! { fn smoke() { let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } + tx.send(1); + assert_eq!(rx.recv(), 1); + } } - #[test] - fn drop_full() { + test! { fn drop_full() { let (tx, _rx) = sync_channel(1); - tx.send(box 1i).unwrap(); - } + tx.send(box 1i); + } } - #[test] - fn smoke_shared() { + test! { fn smoke_shared() { let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); + tx.send(1); + assert_eq!(rx.recv(), 1); let tx = tx.clone(); - tx.send(1).unwrap(); - assert_eq!(rx.recv().unwrap(), 1); - } + tx.send(1); + assert_eq!(rx.recv(), 1); + } } - #[test] - fn smoke_threads() { + test! { fn smoke_threads() { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { - tx.send(1).unwrap(); + spawn(move|| { + tx.send(1); }); - assert_eq!(rx.recv().unwrap(), 1); - } + assert_eq!(rx.recv(), 1); + } } - #[test] - fn smoke_port_gone() { + test! { fn smoke_port_gone() { let (tx, rx) = sync_channel::(0); drop(rx); - assert!(tx.send(1).is_err()); - } + tx.send(1); + } #[should_fail] } - #[test] - fn smoke_shared_port_gone2() { + test! { fn smoke_shared_port_gone2() { let (tx, rx) = sync_channel::(0); drop(rx); let tx2 = tx.clone(); drop(tx); - assert!(tx2.send(1).is_err()); - } + tx2.send(1); + } #[should_fail] } - #[test] - fn port_gone_concurrent() { + test! { fn port_gone_concurrent() { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); + spawn(move|| { + rx.recv(); }); - while tx.send(1).is_ok() {} - } + loop { tx.send(1) } + } #[should_fail] } - #[test] - fn port_gone_concurrent_shared() { + test! { fn port_gone_concurrent_shared() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); + spawn(move|| { + rx.recv(); }); - while tx.send(1).is_ok() && tx2.send(1).is_ok() {} - } + loop { + tx.send(1); + tx2.send(1); + } + } #[should_fail] } - #[test] - fn smoke_chan_gone() { + test! { fn smoke_chan_gone() { let (tx, rx) = sync_channel::(0); drop(tx); - assert!(rx.recv().is_err()); - } + rx.recv(); + } #[should_fail] } - #[test] - fn smoke_chan_gone_shared() { + test! { fn smoke_chan_gone_shared() { let (tx, rx) = sync_channel::<()>(0); let tx2 = tx.clone(); drop(tx); drop(tx2); - assert!(rx.recv().is_err()); - } + rx.recv(); + } #[should_fail] } - #[test] - fn chan_gone_concurrent() { + test! { fn chan_gone_concurrent() { let (tx, rx) = sync_channel::(0); - Thread::spawn(move|| { - tx.send(1).unwrap(); - tx.send(1).unwrap(); - }).detach(); - while rx.recv().is_ok() {} - } + spawn(move|| { + tx.send(1); + tx.send(1); + }); + loop { rx.recv(); } + } #[should_fail] } - #[test] - fn stress() { + test! { fn stress() { let (tx, rx) = sync_channel::(0); - Thread::spawn(move|| { - for _ in range(0u, 10000) { tx.send(1).unwrap(); } - }).detach(); + spawn(move|| { + for _ in range(0u, 10000) { tx.send(1); } + }); for _ in range(0u, 10000) { - assert_eq!(rx.recv().unwrap(), 1); + assert_eq!(rx.recv(), 1); } - } + } } - #[test] - fn stress_shared() { + test! { fn stress_shared() { static AMT: uint = 1000; static NTHREADS: uint = 8; let (tx, rx) = sync_channel::(0); let (dtx, drx) = sync_channel::<()>(0); - Thread::spawn(move|| { + spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv().unwrap(), 1); + assert_eq!(rx.recv(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } - dtx.send(()).unwrap(); - }).detach(); + dtx.send(()); + }); for _ in range(0, NTHREADS) { let tx = tx.clone(); - Thread::spawn(move|| { - for _ in range(0, AMT) { tx.send(1).unwrap(); } - }).detach(); + spawn(move|| { + for _ in range(0, AMT) { tx.send(1); } + }); } drop(tx); - drx.recv().unwrap(); - } + drx.recv(); + } } - #[test] - fn oneshot_single_thread_close_port_first() { + test! { fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = sync_channel::(0); drop(rx); - } + } } - #[test] - fn oneshot_single_thread_close_chan_first() { + test! { fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = sync_channel::(0); drop(tx); - } + } } - #[test] - fn oneshot_single_thread_send_port_close() { + test! { fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = sync_channel::>(0); drop(rx); - assert!(tx.send(box 0).is_err()); - } + tx.send(box 0); + } #[should_fail] } - #[test] - fn oneshot_single_thread_recv_chan_close() { + test! { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = sync_channel::(0); drop(tx); - rx.recv().unwrap(); + rx.recv(); }).join(); // What is our res? assert!(res.is_err()); - } + } } - #[test] - fn oneshot_single_thread_send_then_recv() { + test! { fn oneshot_single_thread_send_then_recv() { let (tx, rx) = sync_channel::>(1); - tx.send(box 10).unwrap(); - assert!(rx.recv().unwrap() == box 10); - } + tx.send(box 10); + assert!(rx.recv() == box 10); + } } - #[test] - fn oneshot_single_thread_try_send_open() { + test! { fn oneshot_single_thread_try_send_open() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(10), Ok(())); - assert!(rx.recv().unwrap() == 10); - } + assert!(rx.recv() == 10); + } } - #[test] - fn oneshot_single_thread_try_send_closed() { + test! { fn oneshot_single_thread_try_send_closed() { let (tx, rx) = sync_channel::(0); drop(rx); - assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10))); - } + assert_eq!(tx.try_send(10), Err(RecvDisconnected(10))); + } } - #[test] - fn oneshot_single_thread_try_send_closed2() { + test! { fn oneshot_single_thread_try_send_closed2() { let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); - } + assert_eq!(tx.try_send(10), Err(Full(10))); + } } - #[test] - fn oneshot_single_thread_try_recv_open() { + test! { fn oneshot_single_thread_try_recv_open() { let (tx, rx) = sync_channel::(1); - tx.send(10).unwrap(); - assert!(rx.recv() == Ok(10)); - } + tx.send(10); + assert!(rx.recv_opt() == Ok(10)); + } } - #[test] - fn oneshot_single_thread_try_recv_closed() { + test! { fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = sync_channel::(0); drop(tx); - assert!(rx.recv().is_err()); - } + assert!(rx.recv_opt() == Err(())); + } } - #[test] - fn oneshot_single_thread_peek_data() { + test! { fn oneshot_single_thread_peek_data() { let (tx, rx) = sync_channel::(1); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - tx.send(10).unwrap(); + assert_eq!(rx.try_recv(), Err(Empty)); + tx.send(10); assert_eq!(rx.try_recv(), Ok(10)); - } + } } - #[test] - fn oneshot_single_thread_peek_close() { + test! { fn oneshot_single_thread_peek_close() { let (tx, rx) = sync_channel::(0); drop(tx); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); - } + assert_eq!(rx.try_recv(), Err(Disconnected)); + assert_eq!(rx.try_recv(), Err(Disconnected)); + } } - #[test] - fn oneshot_single_thread_peek_open() { + test! { fn oneshot_single_thread_peek_open() { let (_tx, rx) = sync_channel::(0); - assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); - } + assert_eq!(rx.try_recv(), Err(Empty)); + } } - #[test] - fn oneshot_multi_task_recv_then_send() { + test! { fn oneshot_multi_task_recv_then_send() { let (tx, rx) = sync_channel::>(0); - let _t = Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box 10); + spawn(move|| { + assert!(rx.recv() == box 10); }); - tx.send(box 10).unwrap(); - } + tx.send(box 10); + } } - #[test] - fn oneshot_multi_task_recv_then_close() { + test! { fn oneshot_multi_task_recv_then_close() { let (tx, rx) = sync_channel::>(0); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box 10); + assert!(rx.recv() == box 10); }).join(); assert!(res.is_err()); - } + } } - #[test] - fn oneshot_multi_thread_close_stress() { + test! { fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(rx); }); drop(tx); } - } + } } - #[test] - fn oneshot_multi_thread_send_close_stress() { + test! { fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { + spawn(move|| { drop(rx); }); let _ = Thread::spawn(move || { - tx.send(1).unwrap(); + tx.send(1); }).join(); } - } + } } - #[test] - fn oneshot_multi_thread_recv_close_stress() { + test! { fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { + spawn(move|| { let res = Thread::spawn(move|| { - rx.recv().unwrap(); + rx.recv(); }).join(); assert!(res.is_err()); }); - let _t = Thread::spawn(move|| { - Thread::spawn(move|| { + spawn(move|| { + spawn(move|| { drop(tx); - }).detach(); + }); }); } - } + } } - #[test] - fn oneshot_multi_thread_send_recv_stress() { + test! { fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); - let _t = Thread::spawn(move|| { - tx.send(box 10i).unwrap(); + spawn(move|| { + tx.send(box 10i); + }); + spawn(move|| { + assert!(rx.recv() == box 10i); }); - assert!(rx.recv().unwrap() == box 10i); } - } + } } - #[test] - fn stream_send_recv_stress() { + test! { fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); @@ -1864,73 +1839,69 @@ mod sync_tests { fn send(tx: SyncSender>, i: int) { if i == 10 { return } - Thread::spawn(move|| { - tx.send(box i).unwrap(); + spawn(move|| { + tx.send(box i); send(tx, i + 1); - }).detach(); + }); } fn recv(rx: Receiver>, i: int) { if i == 10 { return } - Thread::spawn(move|| { - assert!(rx.recv().unwrap() == box i); + spawn(move|| { + assert!(rx.recv() == box i); recv(rx, i + 1); - }).detach(); + }); } } - } + } } - #[test] - fn recv_a_lot() { + test! { fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = sync_channel(10000); - for _ in range(0u, 10000) { tx.send(()).unwrap(); } - for _ in range(0u, 10000) { rx.recv().unwrap(); } - } + for _ in range(0u, 10000) { tx.send(()); } + for _ in range(0u, 10000) { rx.recv(); } + } } - #[test] - fn shared_chan_stress() { + test! { fn shared_chan_stress() { let (tx, rx) = sync_channel(0); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - Thread::spawn(move|| { - tx.send(()).unwrap(); - }).detach(); + spawn(move|| { + tx.send(()); + }); } for _ in range(0, total) { - rx.recv().unwrap(); + rx.recv(); } - } + } } - #[test] - fn test_nested_recv_iter() { + test! { fn test_nested_recv_iter() { let (tx, rx) = sync_channel::(0); let (total_tx, total_rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { + spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc).unwrap(); + total_tx.send(acc); }); - tx.send(3).unwrap(); - tx.send(1).unwrap(); - tx.send(2).unwrap(); + tx.send(3); + tx.send(1); + tx.send(2); drop(tx); - assert_eq!(total_rx.recv().unwrap(), 6); - } + assert_eq!(total_rx.recv(), 6); + } } - #[test] - fn test_recv_iter_break() { + test! { fn test_recv_iter_break() { let (tx, rx) = sync_channel::(0); let (count_tx, count_rx) = sync_channel(0); - let _t = Thread::spawn(move|| { + spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1939,51 +1910,49 @@ mod sync_tests { count += x; } } - count_tx.send(count).unwrap(); + count_tx.send(count); }); - tx.send(2).unwrap(); - tx.send(2).unwrap(); - tx.send(2).unwrap(); + tx.send(2); + tx.send(2); + tx.send(2); let _ = tx.try_send(2); drop(tx); - assert_eq!(count_rx.recv().unwrap(), 4); - } + assert_eq!(count_rx.recv(), 4); + } } - #[test] - fn try_recv_states() { + test! { fn try_recv_states() { let (tx1, rx1) = sync_channel::(1); let (tx2, rx2) = sync_channel::<()>(1); let (tx3, rx3) = sync_channel::<()>(1); - let _t = Thread::spawn(move|| { - rx2.recv().unwrap(); - tx1.send(1).unwrap(); - tx3.send(()).unwrap(); - rx2.recv().unwrap(); + spawn(move|| { + rx2.recv(); + tx1.send(1); + tx3.send(()); + rx2.recv(); drop(tx1); - tx3.send(()).unwrap(); + tx3.send(()); }); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(Empty)); + tx2.send(()); + rx3.recv(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); - } + assert_eq!(rx1.try_recv(), Err(Empty)); + tx2.send(()); + rx3.recv(); + assert_eq!(rx1.try_recv(), Err(Disconnected)); + } } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - #[test] - fn destroy_upgraded_shared_port_when_sender_still_active() { + test! { fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = sync_channel::<()>(0); let (tx2, rx2) = sync_channel::<()>(0); - let _t = Thread::spawn(move|| { - rx.recv().unwrap(); // wait on a oneshot + spawn(move|| { + rx.recv(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()).unwrap(); + tx2.send(()); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1991,91 +1960,92 @@ mod sync_tests { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()).unwrap(); + t.send(()); // wait for the child task to exit before we exit - rx2.recv().unwrap(); - } + rx2.recv(); + } } - #[test] - fn send1() { + test! { fn send_opt1() { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { rx.recv().unwrap(); }); - assert_eq!(tx.send(1), Ok(())); - } + spawn(move|| { rx.recv(); }); + assert_eq!(tx.send_opt(1), Ok(())); + } } - #[test] - fn send2() { + test! { fn send_opt2() { let (tx, rx) = sync_channel::(0); - let _t = Thread::spawn(move|| { drop(rx); }); - assert!(tx.send(1).is_err()); - } + spawn(move|| { drop(rx); }); + assert_eq!(tx.send_opt(1), Err(1)); + } } - #[test] - fn send3() { + test! { fn send_opt3() { let (tx, rx) = sync_channel::(1); - assert_eq!(tx.send(1), Ok(())); - let _t =Thread::spawn(move|| { drop(rx); }); - assert!(tx.send(1).is_err()); - } + assert_eq!(tx.send_opt(1), Ok(())); + spawn(move|| { drop(rx); }); + assert_eq!(tx.send_opt(1), Err(1)); + } } - #[test] - fn send4() { + test! { fn send_opt4() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); let (done, donerx) = channel(); let done2 = done.clone(); - let _t = Thread::spawn(move|| { - assert!(tx.send(1).is_err()); - done.send(()).unwrap(); + spawn(move|| { + assert_eq!(tx.send_opt(1), Err(1)); + done.send(()); }); - let _t = Thread::spawn(move|| { - assert!(tx2.send(2).is_err()); - done2.send(()).unwrap(); + spawn(move|| { + assert_eq!(tx2.send_opt(2), Err(2)); + done2.send(()); }); drop(rx); - donerx.recv().unwrap(); - donerx.recv().unwrap(); - } + donerx.recv(); + donerx.recv(); + } } - #[test] - fn try_send1() { + test! { fn try_send1() { let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); - } + assert_eq!(tx.try_send(1), Err(Full(1))); + } } - #[test] - fn try_send2() { + test! { fn try_send2() { let (tx, _rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); - assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); - } + assert_eq!(tx.try_send(1), Err(Full(1))); + } } - #[test] - fn try_send3() { + test! { fn try_send3() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); - assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); - } + assert_eq!(tx.try_send(1), Err(RecvDisconnected(1))); + } } - #[test] - fn issue_15761() { + test! { fn try_send4() { + let (tx, rx) = sync_channel::(0); + spawn(move|| { + for _ in range(0u, 1000) { Thread::yield_now(); } + assert_eq!(tx.try_send(1), Ok(())); + }); + assert_eq!(rx.recv(), 1); + } #[ignore(reason = "flaky on libnative")] } + + test! { fn issue_15761() { fn repro() { let (tx1, rx1) = sync_channel::<()>(3); let (tx2, rx2) = sync_channel::<()>(3); - let _t = Thread::spawn(move|| { - rx1.recv().unwrap(); + spawn(move|| { + rx1.recv(); tx2.try_send(()).unwrap(); }); tx1.try_send(()).unwrap(); - rx2.recv().unwrap(); + rx2.recv(); } for _ in range(0u, 100) { repro() } - } + } } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index b2367ff8352fb..bd98b09d77985 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -41,7 +41,7 @@ use sys_common::rwlock as sys; /// ``` /// use std::sync::RWLock; /// -/// let lock = RWLock::new(5i); +/// let lock = RWLock::new(5); /// /// // many reader locks can be held at once /// { From 595a08258700f2f5689ad63d99b5d65d5dfb5eab Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jan 2015 09:38:56 +1300 Subject: [PATCH 089/106] Remove the prefix in ObsoleteSyntax variants --- src/libsyntax/parse/obsolete.rs | 42 ++++++++++++++++----------------- src/libsyntax/parse/parser.rs | 26 ++++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index e1e456f880ed7..df18b41198a9f 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -13,8 +13,6 @@ //! //! Obsolete syntax that becomes too hard to parse can be removed. -pub use self::ObsoleteSyntax::*; - use ast::{Expr, ExprTup}; use codemap::Span; use parse::parser; @@ -24,16 +22,16 @@ use ptr::P; /// The specific types of unsupported syntax #[derive(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { - ObsoleteOwnedType, - ObsoleteOwnedExpr, - ObsoleteOwnedPattern, - ObsoleteOwnedVector, - ObsoleteOwnedSelf, - ObsoleteImportRenaming, - ObsoleteSubsliceMatch, - ObsoleteExternCrateRenaming, - ObsoleteProcType, - ObsoleteProcExpr, + OwnedType, + OwnedExpr, + OwnedPattern, + OwnedVector, + OwnedSelf, + ImportRenaming, + SubsliceMatch, + ExternCrateRenaming, + ProcType, + ProcExpr, } pub trait ParserObsoleteMethods { @@ -55,43 +53,43 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { - ObsoleteProcType => ( + ObsoleteSyntax::ProcType => ( "the `proc` type", "use unboxed closures instead", ), - ObsoleteProcExpr => ( + ObsoleteSyntax::ProcExpr => ( "`proc` expression", "use a `move ||` expression instead", ), - ObsoleteOwnedType => ( + ObsoleteSyntax::OwnedType => ( "`~` notation for owned pointers", "use `Box` in `std::owned` instead" ), - ObsoleteOwnedExpr => ( + ObsoleteSyntax::OwnedExpr => ( "`~` notation for owned pointer allocation", "use the `box` operator instead of `~`" ), - ObsoleteOwnedPattern => ( + ObsoleteSyntax::OwnedPattern => ( "`~` notation for owned pointer patterns", "use the `box` operator instead of `~`" ), - ObsoleteOwnedVector => ( + ObsoleteSyntax::OwnedVector => ( "`~[T]` is no longer a type", "use the `Vec` type instead" ), - ObsoleteOwnedSelf => ( + ObsoleteSyntax::OwnedSelf => ( "`~self` is no longer supported", "write `self: Box` instead" ), - ObsoleteImportRenaming => ( + ObsoleteSyntax::ImportRenaming => ( "`use foo = bar` syntax", "write `use bar as foo` instead" ), - ObsoleteSubsliceMatch => ( + ObsoleteSyntax::SubsliceMatch => ( "subslice match syntax", "instead of `..xs`, write `xs..` in a pattern" ), - ObsoleteExternCrateRenaming => ( + ObsoleteSyntax::ExternCrateRenaming => ( "`extern crate foo = bar` syntax", "write `extern crate bar as foo` instead" ) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cc67079e53879..cf7b93ac59f0f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1156,7 +1156,7 @@ impl<'a> Parser<'a> { let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); let _ = self.parse_ret_ty(); - self.obsolete(proc_span, ObsoleteProcType); + self.obsolete(proc_span, ObsoleteSyntax::ProcType); TyInfer } @@ -1521,8 +1521,10 @@ impl<'a> Parser<'a> { self.bump(); let last_span = self.last_span; match self.token { - token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), - _ => self.obsolete(last_span, ObsoleteOwnedType) + token::OpenDelim(token::Bracket) => { + self.obsolete(last_span, ObsoleteSyntax::OwnedVector) + } + _ => self.obsolete(last_span, ObsoleteSyntax::OwnedType) } TyTup(vec![self.parse_ty()]) } else if self.check(&token::BinOp(token::Star)) { @@ -2285,7 +2287,7 @@ impl<'a> Parser<'a> { let span = self.last_span; let _ = self.parse_proc_decl(); let _ = self.parse_expr(); - return self.obsolete_expr(span, ObsoleteProcExpr); + return self.obsolete_expr(span, ObsoleteSyntax::ProcExpr); } if self.eat_keyword(keywords::If) { return self.parse_if_expr(); @@ -2860,9 +2862,9 @@ impl<'a> Parser<'a> { let last_span = self.last_span; match self.token { token::OpenDelim(token::Bracket) => { - self.obsolete(last_span, ObsoleteOwnedVector) + self.obsolete(last_span, ObsoleteSyntax::OwnedVector) }, - _ => self.obsolete(last_span, ObsoleteOwnedExpr) + _ => self.obsolete(last_span, ObsoleteSyntax::OwnedExpr) } let e = self.parse_prefix_expr(); @@ -3233,7 +3235,7 @@ impl<'a> Parser<'a> { } else { let _ = self.parse_pat(); let span = self.span; - self.obsolete(span, ObsoleteSubsliceMatch); + self.obsolete(span, ObsoleteSyntax::SubsliceMatch); } continue } @@ -3349,7 +3351,7 @@ impl<'a> Parser<'a> { pat = PatBox(sub); let last_span = self.last_span; hi = last_span.hi; - self.obsolete(last_span, ObsoleteOwnedPattern); + self.obsolete(last_span, ObsoleteSyntax::OwnedPattern); return P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, @@ -4463,7 +4465,7 @@ impl<'a> Parser<'a> { self.bump(); drop(self.expect_self_ident()); let last_span = self.last_span; - self.obsolete(last_span, ObsoleteOwnedSelf) + self.obsolete(last_span, ObsoleteSyntax::OwnedSelf) } SelfStatic } @@ -4514,7 +4516,7 @@ impl<'a> Parser<'a> { self.bump(); drop(self.expect_self_ident()); let last_span = self.last_span; - self.obsolete(last_span, ObsoleteOwnedSelf); + self.obsolete(last_span, ObsoleteSyntax::OwnedSelf); SelfStatic } else { SelfStatic @@ -5343,7 +5345,7 @@ impl<'a> Parser<'a> { self.bump(); let path = self.parse_str(); let span = self.span; - self.obsolete(span, ObsoleteExternCrateRenaming); + self.obsolete(span, ObsoleteSyntax::ExternCrateRenaming); Some(path) } else if self.eat_keyword(keywords::As) { // skip the ident if there is one @@ -6000,7 +6002,7 @@ impl<'a> Parser<'a> { path.push(id); } let span = mk_sp(path_lo, self.span.hi); - self.obsolete(span, ObsoleteImportRenaming); + self.obsolete(span, ObsoleteSyntax::ImportRenaming); let path = ast::Path { span: span, global: false, From 48f50e1e98691d74427e23e82694f528b3fb4d56 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jan 2015 09:44:33 +1300 Subject: [PATCH 090/106] Obsolete `Sized? T` [breaking-change] Use `T: ?Sized` --- src/libsyntax/parse/obsolete.rs | 7 ++++++- src/libsyntax/parse/parser.rs | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index df18b41198a9f..d1b6034457d3a 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -22,6 +22,7 @@ use ptr::P; /// The specific types of unsupported syntax #[derive(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { + Sized, OwnedType, OwnedExpr, OwnedPattern, @@ -92,7 +93,11 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { ObsoleteSyntax::ExternCrateRenaming => ( "`extern crate foo = bar` syntax", "write `extern crate bar as foo` instead" - ) + ), + ObsoleteSyntax::Sized => ( + "`Sized? T` syntax for removing the `Sized` bound", + "write `T: ?Sized` instead" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cf7b93ac59f0f..673a9aefd8b62 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4092,8 +4092,8 @@ impl<'a> Parser<'a> { // unbound, and it may only be `Sized`. To avoid backtracking and other // complications, we parse an ident, then check for `?`. If we find it, // we use the ident as the unbound, otherwise, we use it as the name of - // type param. Even worse, for now, we need to check for `?` before or - // after the bound. + // type param. Even worse, we need to check for `?` before or after the + // bound. let mut span = self.span; let mut ident = self.parse_ident(); let mut unbound = None; @@ -4102,6 +4102,7 @@ impl<'a> Parser<'a> { unbound = Some(tref); span = self.span; ident = self.parse_ident(); + self.obsolete(span, ObsoleteSyntax::Sized); } let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified); From e0684e876954ad5a713e6f985570162cedcae8df Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jan 2015 10:16:49 +1300 Subject: [PATCH 091/106] Fallout --- src/liballoc/boxed.rs | 16 ++++---- src/libcollections/btree/map.rs | 26 ++++++------- src/libcollections/btree/node.rs | 4 +- src/libcollections/btree/set.rs | 4 +- src/libcollections/slice.rs | 2 +- src/libcore/borrow.rs | 38 +++++++++---------- src/libcore/clone.rs | 2 +- src/libcore/cmp.rs | 24 ++++++------ src/libcore/fmt/mod.rs | 8 ++-- src/libcore/hash/mod.rs | 8 ++-- src/libcore/hash/sip.rs | 6 +-- src/libcore/kinds.rs | 18 ++++----- src/libcore/mem.rs | 4 +- src/libcore/ops.rs | 28 +++++++------- src/libcore/slice.rs | 4 +- src/libcore/str/mod.rs | 2 +- src/libcoretest/hash/mod.rs | 2 +- src/libgraphviz/maybe_owned_vec.rs | 2 +- src/librustc/middle/intrinsicck.rs | 8 ++-- src/librustc/util/nodemap.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- src/libserialize/serialize.rs | 4 +- src/libserialize/serialize_stage0.rs | 4 +- src/libstd/c_str.rs | 2 +- src/libstd/collections/hash/map.rs | 34 ++++++++--------- src/libstd/collections/hash/set.rs | 4 +- src/libstd/collections/hash/table.rs | 2 +- src/libstd/hash.rs | 2 +- src/libstd/io/mod.rs | 8 ++-- src/libstd/path/mod.rs | 2 +- src/libstd/path/posix.rs | 2 +- src/libsyntax/parse/obsolete.rs | 2 +- src/libsyntax/util/interner.rs | 4 +- .../compile-fail/associated-types-unsized.rs | 2 +- src/test/compile-fail/dst-bad-assign-2.rs | 2 +- src/test/compile-fail/dst-bad-assign.rs | 2 +- src/test/compile-fail/dst-bad-coerce1.rs | 2 +- src/test/compile-fail/dst-bad-coerce2.rs | 2 +- src/test/compile-fail/dst-bad-coerce3.rs | 2 +- src/test/compile-fail/dst-bad-coerce4.rs | 2 +- src/test/compile-fail/dst-bad-coercions.rs | 2 +- src/test/compile-fail/dst-bad-deep.rs | 2 +- .../dst-object-from-unsized-type.rs | 4 +- .../compile-fail/transmute-fat-pointers.rs | 8 ++-- src/test/compile-fail/transmute-impl.rs | 4 +- .../unboxed-closure-sugar-default.rs | 6 +-- .../unboxed-closure-sugar-equiv.rs | 6 +-- .../unboxed-closure-sugar-lifetime-elision.rs | 6 +-- .../unboxed-closure-sugar-region.rs | 6 +-- src/test/compile-fail/unsized-bare-typaram.rs | 2 +- src/test/compile-fail/unsized-enum.rs | 10 ++--- .../unsized-inherent-impl-self-type.rs | 2 +- src/test/compile-fail/unsized-struct.rs | 10 ++--- .../unsized-trait-impl-self-type.rs | 4 +- .../unsized-trait-impl-trait-arg.rs | 4 +- src/test/compile-fail/unsized3.rs | 18 ++++----- src/test/compile-fail/unsized4.rs | 2 +- src/test/compile-fail/unsized5.rs | 8 ++-- src/test/compile-fail/unsized6.rs | 12 +++--- src/test/compile-fail/unsized7.rs | 4 +- src/test/run-pass-valgrind/dst-dtor-1.rs | 2 +- src/test/run-pass-valgrind/dst-dtor-2.rs | 2 +- .../associated-types-conditional-dispatch.rs | 2 +- src/test/run-pass/issue-18906.rs | 2 +- 64 files changed, 211 insertions(+), 211 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2c318181b0995..a574367ccf45f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -75,14 +75,14 @@ impl Clone for Box { } #[stable] -impl PartialEq for Box { +impl PartialEq for Box { #[inline] fn eq(&self, other: &Box) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &Box) -> bool { PartialEq::ne(&**self, &**other) } } #[stable] -impl PartialOrd for Box { +impl PartialOrd for Box { #[inline] fn partial_cmp(&self, other: &Box) -> Option { PartialOrd::partial_cmp(&**self, &**other) @@ -97,16 +97,16 @@ impl PartialOrd for Box { fn gt(&self, other: &Box) -> bool { PartialOrd::gt(&**self, &**other) } } #[stable] -impl Ord for Box { +impl Ord for Box { #[inline] fn cmp(&self, other: &Box) -> Ordering { Ord::cmp(&**self, &**other) } #[stable]} -impl Eq for Box {} +impl Eq for Box {} -impl> Hash for Box { +impl> Hash for Box { #[inline] fn hash(&self, state: &mut S) { (**self).hash(state); @@ -143,7 +143,7 @@ impl BoxAny for Box { } } -impl fmt::Show for Box { +impl fmt::Show for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } @@ -155,13 +155,13 @@ impl fmt::Show for Box { } } -impl Deref for Box { +impl Deref for Box { type Target = T; fn deref(&self) -> &T { &**self } } -impl DerefMut for Box { +impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } } diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index a9e09a584d687..43b3f3421403d 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -130,7 +130,7 @@ pub struct Values<'a, K: 'a, V: 'a> { #[stable] /// A view into a single entry in a map, which may either be vacant or occupied. -pub enum Entry<'a, Sized? Q:'a, K:'a, V:'a> { +pub enum Entry<'a, Q: ?Sized +'a, K:'a, V:'a> { /// A vacant Entry Vacant(VacantEntry<'a, Q, K, V>), /// An occupied Entry @@ -139,7 +139,7 @@ pub enum Entry<'a, Sized? Q:'a, K:'a, V:'a> { #[stable] /// A vacant Entry. -pub struct VacantEntry<'a, Sized? Q:'a, K:'a, V:'a> { +pub struct VacantEntry<'a, Q: ?Sized +'a, K:'a, V:'a> { key: &'a Q, stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>, } @@ -214,7 +214,7 @@ impl BTreeMap { /// assert_eq!(map.get(&2), None); /// ``` #[stable] - pub fn get(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord { + pub fn get(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord { let mut cur_node = &self.root; loop { match Node::search(cur_node, key) { @@ -246,7 +246,7 @@ impl BTreeMap { /// assert_eq!(map.contains_key(&2), false); /// ``` #[stable] - pub fn contains_key(&self, key: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains_key(&self, key: &Q) -> bool where Q: BorrowFrom + Ord { self.get(key).is_some() } @@ -270,7 +270,7 @@ impl BTreeMap { /// ``` // See `get` for implementation notes, this is basically a copy-paste with mut's added #[stable] - pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom + Ord { + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom + Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop { @@ -440,7 +440,7 @@ impl BTreeMap { /// assert_eq!(map.remove(&1), None); /// ``` #[stable] - pub fn remove(&mut self, key: &Q) -> Option where Q: BorrowFrom + Ord { + pub fn remove(&mut self, key: &Q) -> Option where Q: BorrowFrom + Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); loop { @@ -880,7 +880,7 @@ impl Show for BTreeMap { // NOTE(stage0): remove impl after a snapshot #[cfg(stage0)] #[stable] -impl Index for BTreeMap +impl Index for BTreeMap where Q: BorrowFrom + Ord { fn index(&self, key: &Q) -> &V { @@ -890,7 +890,7 @@ impl Index for BTreeMap #[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot #[stable] -impl Index for BTreeMap +impl Index for BTreeMap where Q: BorrowFrom + Ord { type Output = V; @@ -903,7 +903,7 @@ impl Index for BTreeMap // NOTE(stage0): remove impl after a snapshot #[cfg(stage0)] #[stable] -impl IndexMut for BTreeMap +impl IndexMut for BTreeMap where Q: BorrowFrom + Ord { fn index_mut(&mut self, key: &Q) -> &mut V { @@ -913,7 +913,7 @@ impl IndexMut for BTreeMap #[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot #[stable] -impl IndexMut for BTreeMap +impl IndexMut for BTreeMap where Q: BorrowFrom + Ord { type Output = V; @@ -1135,7 +1135,7 @@ impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { #[stable] impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {} -impl<'a, Sized? Q, K: Ord, V> Entry<'a, Q, K, V> { +impl<'a, Q: ?Sized, K: Ord, V> Entry<'a, Q, K, V> { #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> { @@ -1146,7 +1146,7 @@ impl<'a, Sized? Q, K: Ord, V> Entry<'a, Q, K, V> { } } -impl<'a, Sized? Q: ToOwned, K: Ord, V> VacantEntry<'a, Q, K, V> { +impl<'a, Q: ?Sized + ToOwned, K: Ord, V> VacantEntry<'a, Q, K, V> { #[stable] /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. @@ -1386,7 +1386,7 @@ impl BTreeMap { /// ``` /// The key must have the same ordering before or after `.to_owned()` is called. #[stable] - pub fn entry<'a, Sized? Q>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V> + pub fn entry<'a, Q: ?Sized>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V> where Q: Ord + ToOwned { // same basic logic of `swap` and `pop`, blended together diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 1f719da590b34..0a93bbf89c997 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -517,7 +517,7 @@ impl Node { /// Searches for the given key in the node. If it finds an exact match, /// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `GoDown` will be yielded with the index of the subtree the key must lie in. - pub fn search>>(node: NodeRef, key: &Q) + pub fn search>>(node: NodeRef, key: &Q) -> SearchResult where Q: BorrowFrom + Ord { // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // For the B configured as of this writing (B = 6), binary search was *significantly* @@ -536,7 +536,7 @@ impl Node { } } - fn search_linear(&self, key: &Q) -> (bool, uint) where Q: BorrowFrom + Ord { + fn search_linear(&self, key: &Q) -> (bool, uint) where Q: BorrowFrom + Ord { for (i, k) in self.keys().iter().enumerate() { match key.cmp(BorrowFrom::borrow_from(k)) { Greater => {}, diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 0406edcdd32e7..98f1633217060 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -299,7 +299,7 @@ impl BTreeSet { /// assert_eq!(set.contains(&4), false); /// ``` #[stable] - pub fn contains(&self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains(&self, value: &Q) -> bool where Q: BorrowFrom + Ord { self.map.contains_key(value) } @@ -429,7 +429,7 @@ impl BTreeSet { /// assert_eq!(set.remove(&2), false); /// ``` #[stable] - pub fn remove(&mut self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn remove(&mut self, value: &Q) -> bool where Q: BorrowFrom + Ord { self.map.remove(value).is_some() } } diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..efb73e7d7c8b5 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -989,7 +989,7 @@ impl SliceExt for [T] { //////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices -pub trait SliceConcatExt for Sized? { +pub trait SliceConcatExt for Sized? { /// Flattens a slice of `T` into a single value `U`. #[stable] fn concat(&self) -> U; diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d8d..54621f59c2f46 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -53,50 +53,50 @@ use option::Option; use self::Cow::*; /// A trait for borrowing data. -pub trait BorrowFrom for Sized? { +pub trait BorrowFrom for Sized? { /// Immutably borrow from an owned value. fn borrow_from(owned: &Owned) -> &Self; } /// A trait for mutably borrowing data. -pub trait BorrowFromMut for Sized? : BorrowFrom { +pub trait BorrowFromMut for Sized? : BorrowFrom { /// Mutably borrow from an owned value. fn borrow_from_mut(owned: &mut Owned) -> &mut Self; } -impl BorrowFrom for T { +impl BorrowFrom for T { fn borrow_from(owned: &T) -> &T { owned } } -impl BorrowFromMut for T { +impl BorrowFromMut for T { fn borrow_from_mut(owned: &mut T) -> &mut T { owned } } -impl<'a, Sized? T> BorrowFrom<&'a T> for T { +impl<'a, T: ?Sized> BorrowFrom<&'a T> for T { fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned } } -impl<'a, Sized? T> BorrowFrom<&'a mut T> for T { +impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T { fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned } } -impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T { +impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T { fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned } } -impl<'a, T, Sized? B> BorrowFrom> for B where B: ToOwned { +impl<'a, T, B: ?Sized> BorrowFrom> for B where B: ToOwned { fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B { &**owned } } /// Trait for moving into a `Cow` -pub trait IntoCow<'a, T, Sized? B> { +pub trait IntoCow<'a, T, B: ?Sized> { /// Moves `self` into `Cow` fn into_cow(self) -> Cow<'a, T, B>; } -impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { +impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { fn into_cow(self) -> Cow<'a, T, B> { self } @@ -129,7 +129,7 @@ impl ToOwned for T where T: Clone { /// } /// } /// ``` -pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned { +pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned { /// Borrowed data. Borrowed(&'a B), @@ -138,7 +138,7 @@ pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned { } #[stable] -impl<'a, T, Sized? B> Clone for Cow<'a, T, B> where B: ToOwned { +impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned { fn clone(&self) -> Cow<'a, T, B> { match *self { Borrowed(b) => Borrowed(b), @@ -150,7 +150,7 @@ impl<'a, T, Sized? B> Clone for Cow<'a, T, B> where B: ToOwned { } } -impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned { +impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned { /// Acquire a mutable reference to the owned form of the data. /// /// Copies the data if it is not already owned. @@ -191,7 +191,7 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned { } } -impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { +impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned { type Target = B; fn deref(&self) -> &B { @@ -203,10 +203,10 @@ impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned { } #[stable] -impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} +impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} #[stable] -impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned { +impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned { #[inline] fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering { Ord::cmp(&**self, &**other) @@ -214,7 +214,7 @@ impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned { } #[stable] -impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq> for Cow<'a, T, B> where +impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, T, B> where B: PartialEq + ToOwned, C: ToOwned, { @@ -225,14 +225,14 @@ impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq> for Cow<'a, T, B } #[stable] -impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { +impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { #[inline] fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned, T: fmt::Show { +impl<'a, T, B: ?Sized> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned, T: fmt::Show { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Borrowed(ref b) => fmt::Show::fmt(b, f), diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 159c2a505d51b..17991659f9789 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -43,7 +43,7 @@ pub trait Clone : Sized { } #[stable] -impl<'a, Sized? T> Clone for &'a T { +impl<'a, T: ?Sized> Clone for &'a T { /// Return a shallow copy of the reference. #[inline] fn clone(&self) -> &'a T { *self } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 13f9f5ccee916..933088f276528 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -69,7 +69,7 @@ use option::Option::{self, Some, None}; /// only if `a != b`. #[lang="eq"] #[stable] -pub trait PartialEq for Sized? { +pub trait PartialEq for Sized? { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable] fn eq(&self, other: &Rhs) -> bool; @@ -224,7 +224,7 @@ impl PartialOrd for Ordering { /// 5.11). #[lang="ord"] #[stable] -pub trait PartialOrd for Sized?: PartialEq { +pub trait PartialOrd for Sized?: PartialEq { /// This method returns an ordering between `self` and `other` values /// if one exists. #[stable] @@ -428,14 +428,14 @@ mod impls { // & pointers #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a A where A: PartialEq { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq { #[inline] fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) } #[inline] fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) } } #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b B> for &'a A where A: PartialOrd { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd { #[inline] fn partial_cmp(&self, other: &&'b B) -> Option { PartialOrd::partial_cmp(*self, *other) @@ -450,24 +450,24 @@ mod impls { fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) } } #[stable] - impl<'a, Sized? A> Ord for &'a A where A: Ord { + impl<'a, A: ?Sized> Ord for &'a A where A: Ord { #[inline] fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) } } #[stable] - impl<'a, Sized? A> Eq for &'a A where A: Eq {} + impl<'a, A: ?Sized> Eq for &'a A where A: Eq {} // &mut pointers #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { #[inline] fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } } #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { #[inline] fn partial_cmp(&self, other: &&'b mut B) -> Option { PartialOrd::partial_cmp(*self, *other) @@ -482,15 +482,15 @@ mod impls { fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) } } #[stable] - impl<'a, Sized? A> Ord for &'a mut A where A: Ord { + impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord { #[inline] fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) } } #[stable] - impl<'a, Sized? A> Eq for &'a mut A where A: Eq {} + impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {} #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a A where A: PartialEq { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq { #[inline] fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } #[inline] @@ -498,7 +498,7 @@ mod impls { } #[stable] - impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a mut A where A: PartialEq { + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq { #[inline] fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) } #[inline] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 102836f8d3024..9e9e2b92bb7ad 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -78,9 +78,9 @@ pub trait Writer { // This Adapter is needed to allow `self` (of type `&mut // Self`) to be cast to a FormatWriter (below) without // requiring a `Sized` bound. - struct Adapter<'a,Sized? T:'a>(&'a mut T); + struct Adapter<'a,T: ?Sized +'a>(&'a mut T); - impl<'a, Sized? T> Writer for Adapter<'a, T> + impl<'a, T: ?Sized> Writer for Adapter<'a, T> where T: Writer { fn write_str(&mut self, s: &str) -> Result { @@ -592,10 +592,10 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { // Implementations of the core formatting traits -impl<'a, Sized? T: Show> Show for &'a T { +impl<'a, T: ?Sized + Show> Show for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } -impl<'a, Sized? T: Show> Show for &'a mut T { +impl<'a, T: ?Sized + Show> Show for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index b0a5ec9fe12ed..aaae5c2717c7b 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -85,7 +85,7 @@ pub trait Hash for Sized? { /// containers like `HashMap`, which need a generic way hash multiple types. pub trait Hasher { /// Compute the hash of a value. - fn hash>(&self, value: &T) -> u64; + fn hash>(&self, value: &T) -> u64; } #[allow(missing_docs)] @@ -194,14 +194,14 @@ impl> Hash for [T] { } -impl<'a, S: Writer, Sized? T: Hash> Hash for &'a T { +impl<'a, S: Writer, T: ?Sized + Hash> Hash for &'a T { #[inline] fn hash(&self, state: &mut S) { (**self).hash(state); } } -impl<'a, S: Writer, Sized? T: Hash> Hash for &'a mut T { +impl<'a, S: Writer, T: ?Sized + Hash> Hash for &'a mut T { #[inline] fn hash(&self, state: &mut S) { (**self).hash(state); @@ -233,7 +233,7 @@ impl Hash for TypeId { } } -impl<'a, T, Sized? B, S> Hash for Cow<'a, T, B> where B: Hash + ToOwned { +impl<'a, T, B: ?Sized, S> Hash for Cow<'a, T, B> where B: Hash + ToOwned { #[inline] fn hash(&self, state: &mut S) { Hash::hash(&**self, state) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index f9da0493f3edb..c4d45e9c2c804 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -239,7 +239,7 @@ impl SipHasher { impl Hasher for SipHasher { #[inline] - fn hash>(&self, value: &T) -> u64 { + fn hash>(&self, value: &T) -> u64 { let mut state = SipState::new_with_keys(self.k0, self.k1); value.hash(&mut state); state.result() @@ -255,7 +255,7 @@ impl Default for SipHasher { /// Hashes a value using the SipHash algorithm. #[inline] -pub fn hash>(value: &T) -> u64 { +pub fn hash>(value: &T) -> u64 { let mut state = SipState::new(); value.hash(&mut state); state.result() @@ -263,7 +263,7 @@ pub fn hash>(value: &T) -> u64 { /// Hashes a value with the SipHash algorithm with the provided keys. #[inline] -pub fn hash_with_keys>(k0: u64, k1: u64, value: &T) -> u64 { +pub fn hash_with_keys>(k0: u64, k1: u64, value: &T) -> u64 { let mut state = SipState::new_with_keys(k0, k1); value.hash(&mut state); state.result() diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index e50aaef5f09f3..1911641034c94 100644 --- a/src/libcore/kinds.rs +++ b/src/libcore/kinds.rs @@ -133,10 +133,10 @@ pub mod marker { /// for some lifetime `'a`, but not the other way around). #[lang="covariant_type"] #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct CovariantType; + pub struct CovariantType; - impl Copy for CovariantType {} - impl Clone for CovariantType { + impl Copy for CovariantType {} + impl Clone for CovariantType { fn clone(&self) -> CovariantType { *self } } @@ -181,10 +181,10 @@ pub mod marker { /// arguments of type `U`, hence such a conversion is safe. #[lang="contravariant_type"] #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct ContravariantType; + pub struct ContravariantType; - impl Copy for ContravariantType {} - impl Clone for ContravariantType { + impl Copy for ContravariantType {} + impl Clone for ContravariantType { fn clone(&self) -> ContravariantType { *self } } @@ -211,10 +211,10 @@ pub mod marker { /// interior mutability. #[lang="invariant_type"] #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct InvariantType; + pub struct InvariantType; - impl Copy for InvariantType {} - impl Clone for InvariantType { + impl Copy for InvariantType {} + impl Clone for InvariantType { fn clone(&self) -> InvariantType { *self } } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 2620928acc1ac..c60569161213f 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -320,7 +320,7 @@ pub unsafe fn transmute_copy(src: &T) -> U { #[inline] #[unstable = "this function may be removed in the future due to its \ questionable utility"] -pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S, +pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S, ptr: &T) -> &'a T { transmute(ptr) } @@ -329,7 +329,7 @@ pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S, #[inline] #[unstable = "this function may be removed in the future due to its \ questionable utility"] -pub unsafe fn copy_mut_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a mut S, +pub unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { transmute(ptr) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index c9b71092f9072..d7f6d3bc15357 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -721,7 +721,7 @@ shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } #[cfg(stage0)] #[allow(missing_docs)] #[lang="index"] -pub trait Index for Sized? { +pub trait Index for Sized? { /// The method for the indexing (`Foo[Bar]`) operation fn index<'a>(&'a self, index: &Index) -> &'a Result; } @@ -757,8 +757,8 @@ pub trait Index for Sized? { /// ``` #[cfg(not(stage0))] // NOTE(stage0) remove cfg after a snapshot #[lang="index"] -pub trait Index for Sized? { - type Sized? Output; +pub trait Index for Sized? { + type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation fn index<'a>(&'a self, index: &Index) -> &'a Self::Output; @@ -768,7 +768,7 @@ pub trait Index for Sized? { #[cfg(stage0)] #[allow(missing_docs)] #[lang="index_mut"] -pub trait IndexMut for Sized? { +pub trait IndexMut for Sized? { /// The method for the indexing (`Foo[Bar]`) operation fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result; } @@ -804,8 +804,8 @@ pub trait IndexMut for Sized? { /// ``` #[cfg(not(stage0))] // NOTE(stage0) remove cfg after a snapshot #[lang="index_mut"] -pub trait IndexMut for Sized? { - type Sized? Output; +pub trait IndexMut for Sized? { + type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output; @@ -849,7 +849,7 @@ pub trait IndexMut for Sized? { /// } /// ``` #[lang="slice"] -pub trait Slice for Sized? { +pub trait Slice for Sized? { /// The method for the slicing operation foo[] fn as_slice_<'a>(&'a self) -> &'a Result; /// The method for the slicing operation foo[from..] @@ -898,7 +898,7 @@ pub trait Slice for Sized? { /// } /// ``` #[lang="slice_mut"] -pub trait SliceMut for Sized? { +pub trait SliceMut for Sized? { /// The method for the slicing operation foo[] fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result; /// The method for the slicing operation foo[from..] @@ -1026,19 +1026,19 @@ pub struct RangeTo { /// ``` #[lang="deref"] pub trait Deref for Sized? { - type Sized? Target; + type Target: ?Sized; /// The method called to dereference a value fn deref<'a>(&'a self) -> &'a Self::Target; } -impl<'a, Sized? T> Deref for &'a T { +impl<'a, T: ?Sized> Deref for &'a T { type Target = T; fn deref(&self) -> &T { *self } } -impl<'a, Sized? T> Deref for &'a mut T { +impl<'a, T: ?Sized> Deref for &'a mut T { type Target = T; fn deref(&self) -> &T { *self } @@ -1087,7 +1087,7 @@ pub trait DerefMut for Sized? : Deref { fn deref_mut<'a>(&'a mut self) -> &'a mut ::Target; } -impl<'a, Sized? T> DerefMut for &'a mut T { +impl<'a, T: ?Sized> DerefMut for &'a mut T { fn deref_mut(&mut self) -> &mut T { *self } } @@ -1112,8 +1112,8 @@ pub trait FnOnce { extern "rust-call" fn call_once(self, args: Args) -> Result; } -impl FnMut for F - where F : Fn +impl FnMut for F + where F : Fn { extern "rust-call" fn call_mut(&mut self, args: A) -> R { self.call(args) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f17a775cf4240..de57136d593a4 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -648,13 +648,13 @@ impl AsSlice for [T] { } #[experimental = "trait is experimental"] -impl<'a, T, Sized? U: AsSlice> AsSlice for &'a U { +impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } } #[experimental = "trait is experimental"] -impl<'a, T, Sized? U: AsSlice> AsSlice for &'a mut U { +impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a mut U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..74fac6b767838 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1140,7 +1140,7 @@ impl Str for str { fn as_slice<'a>(&'a self) -> &'a str { self } } -impl<'a, Sized? S> Str for &'a S where S: Str { +impl<'a, S: ?Sized> Str for &'a S where S: Str { #[inline] fn as_slice(&self) -> &str { Str::as_slice(*self) } } diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 23f9be124dadb..a4bafe754ffdd 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher, Writer}; struct MyWriterHasher; impl Hasher for MyWriterHasher { - fn hash>(&self, value: &T) -> u64 { + fn hash>(&self, value: &T) -> u64 { let mut state = MyWriter { hash: 0 }; value.hash(&mut state); state.hash diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs index 04aa6d1649538..567fe04c5afbc 100644 --- a/src/libgraphviz/maybe_owned_vec.rs +++ b/src/libgraphviz/maybe_owned_vec.rs @@ -25,7 +25,7 @@ use std::slice; // Note 2: Once Dynamically Sized Types (DST) lands, it might be // reasonable to replace this with something like `enum MaybeOwned<'a, -// Sized? U>{ Owned(Box), Borrowed(&'a U) }`; and then `U` could be +// U: ?Sized>{ Owned(Box), Borrowed(&'a U) }`; and then `U` could be // instantiated with `[T]` or `str`, etc. Of course, that would imply // removing the `Growable` variant, which relates to note 1 above. // Alternatively, we might add `MaybeOwned` for the general case but diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index e3763689ef41a..a83416667abdc 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { // However, it's not as simple as checking whether `T : // Sized`, because even if `T : Sized` does not hold, that // just means that `T` *may* not be sized. After all, even a - // type parameter `Sized? T` could be bound to a sized + // type parameter `T: ?Sized` could be bound to a sized // type. (Issue #20116) // // To handle this, we first check for "interior" type @@ -139,16 +139,16 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { // exhaustively checking all possible combinations. Here are some examples: // // ``` - // fn foo() { + // fn foo() { // // T=int, U=int // } // - // fn bar() { + // fn bar() { // // T=int, U=int // // T=[int], U=int // } // - // fn baz() { + // fn baz() { // // T=int, U=int // // T=[int], U=int // // T=int, U=[int] diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index 0da01cd358953..ee224d1ec80fe 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -75,7 +75,7 @@ pub struct FnvHasher; pub struct FnvState(u64); impl Hasher for FnvHasher { - fn hash>(&self, t: &T) -> u64 { + fn hash>(&self, t: &T) -> u64 { let mut state = FnvState(0xcbf29ce484222325); t.hash(&mut state); let FnvState(ret) = state; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9639af5ca1cd5..ffb7fd9e71b3c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -604,7 +604,7 @@ impl<'tcx> Repr<'tcx> for () { } } -impl<'a, 'tcx, Sized? T:Repr<'tcx>> Repr<'tcx> for &'a T { +impl<'a, 'tcx, T: ?Sized +Repr<'tcx>> Repr<'tcx> for &'a T { fn repr(&self, tcx: &ctxt<'tcx>) -> String { Repr::repr(*self, tcx) } diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0646ee1758fc0..c317b9674897c 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -396,13 +396,13 @@ impl Decodable for () { } } -impl<'a, Sized? T: Encodable> Encodable for &'a T { +impl<'a, T: ?Sized + Encodable> Encodable for &'a T { fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } } -impl Encodable for Box { +impl Encodable for Box { fn encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).encode(s) } diff --git a/src/libserialize/serialize_stage0.rs b/src/libserialize/serialize_stage0.rs index 558f9e603e159..c4317b99dce06 100644 --- a/src/libserialize/serialize_stage0.rs +++ b/src/libserialize/serialize_stage0.rs @@ -378,13 +378,13 @@ impl> Decodable for () { } } -impl<'a, E, S: Encoder, Sized? T: Encodable> Encodable for &'a T { +impl<'a, E, S: Encoder, T: ?Sized + Encodable> Encodable for &'a T { fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } } -impl, Sized? T: Encodable> Encodable for Box { +impl, T: ?Sized + Encodable> Encodable for Box { fn encode(&self, s: &mut S) -> Result<(), E> { (**self).encode(s) } diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 9c96a9cac7831..c8a59ce6bba4c 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -430,7 +430,7 @@ impl ToCStr for [u8] { } } -impl<'a, Sized? T: ToCStr> ToCStr for &'a T { +impl<'a, T: ?Sized + ToCStr> ToCStr for &'a T { #[inline] fn to_c_str(&self) -> CString { (**self).to_c_str() diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a6532707f3e36..300fc849ace28 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -440,14 +440,14 @@ impl SearchResult { } impl, V, S, H: Hasher> HashMap { - fn make_hash>(&self, x: &X) -> SafeHash { + fn make_hash>(&self, x: &X) -> SafeHash { table::make_hash(&self.hasher, x) } /// Search for a key, yielding the index if it's found in the hashtable. /// If you already have the hash for the key lying around, use /// search_hashed. - fn search<'a, Sized? Q>(&'a self, q: &Q) -> Option> + fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option> where Q: BorrowFrom + Eq + Hash { let hash = self.make_hash(q); @@ -455,7 +455,7 @@ impl, V, S, H: Hasher> HashMap { .into_option() } - fn search_mut<'a, Sized? Q>(&'a mut self, q: &Q) -> Option> + fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option> where Q: BorrowFrom + Eq + Hash { let hash = self.make_hash(q); @@ -923,7 +923,7 @@ impl, V, S, H: Hasher> HashMap { #[stable] /// Gets the given key's corresponding entry in the map for in-place manipulation. /// Regardless of whether or not `to_owned()` has been called, the key must hash the same way. - pub fn entry<'a, Sized? Q>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V> + pub fn entry<'a, Q: ?Sized>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V> where Q: Eq + Hash + ToOwned { // Gotta resize now. @@ -1030,7 +1030,7 @@ impl, V, S, H: Hasher> HashMap { /// assert_eq!(map.get(&2), None); /// ``` #[stable] - pub fn get(&self, k: &Q) -> Option<&V> + pub fn get(&self, k: &Q) -> Option<&V> where Q: Hash + Eq + BorrowFrom { self.search(k).map(|bucket| bucket.into_refs().1) @@ -1053,7 +1053,7 @@ impl, V, S, H: Hasher> HashMap { /// assert_eq!(map.contains_key(&2), false); /// ``` #[stable] - pub fn contains_key(&self, k: &Q) -> bool + pub fn contains_key(&self, k: &Q) -> bool where Q: Hash + Eq + BorrowFrom { self.search(k).is_some() @@ -1079,7 +1079,7 @@ impl, V, S, H: Hasher> HashMap { /// assert_eq!(map[1], "b"); /// ``` #[stable] - pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> + pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where Q: Hash + Eq + BorrowFrom { self.search_mut(k).map(|bucket| bucket.into_mut_refs().1) @@ -1131,7 +1131,7 @@ impl, V, S, H: Hasher> HashMap { /// assert_eq!(map.remove(&1), None); /// ``` #[stable] - pub fn remove(&mut self, k: &Q) -> Option + pub fn remove(&mut self, k: &Q) -> Option where Q: Hash + Eq + BorrowFrom { if self.table.size() == 0 { @@ -1142,7 +1142,7 @@ impl, V, S, H: Hasher> HashMap { } } -fn search_entry_hashed<'a, K, V, Sized? Q>(table: &'a mut RawTable, hash: SafeHash, k: &'a Q) +fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable, hash: SafeHash, k: &'a Q) -> Entry<'a, Q, K, V> where Q: Eq + ToOwned { @@ -1229,7 +1229,7 @@ impl, V, S, H: Hasher + Default> Default for HashMap // NOTE(stage0): remove impl after a snapshot #[cfg(stage0)] #[stable] -impl + Eq, Sized? Q, V, S, H: Hasher> Index for HashMap +impl + Eq, Q: ?Sized, V, S, H: Hasher> Index for HashMap where Q: BorrowFrom + Hash + Eq { #[inline] @@ -1240,7 +1240,7 @@ impl + Eq, Sized? Q, V, S, H: Hasher> Index for HashMap + Eq, Sized? Q, V, S, H: Hasher> Index for HashMap +impl + Eq, Q: ?Sized, V, S, H: Hasher> Index for HashMap where Q: BorrowFrom + Hash + Eq { type Output = V; @@ -1254,7 +1254,7 @@ impl + Eq, Sized? Q, V, S, H: Hasher> Index for HashMap + Eq, Sized? Q, V, S, H: Hasher> IndexMut for HashMap +impl + Eq, Q: ?Sized, V, S, H: Hasher> IndexMut for HashMap where Q: BorrowFrom + Hash + Eq { #[inline] @@ -1265,7 +1265,7 @@ impl + Eq, Sized? Q, V, S, H: Hasher> IndexMut for HashMap + Eq, Sized? Q, V, S, H: Hasher> IndexMut for HashMap +impl + Eq, Q: ?Sized, V, S, H: Hasher> IndexMut for HashMap where Q: BorrowFrom + Hash + Eq { type Output = V; @@ -1357,7 +1357,7 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> { #[stable] /// A view into a single empty location in a HashMap -pub struct VacantEntry<'a, Sized? Q: 'a, K: 'a, V: 'a> { +pub struct VacantEntry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { hash: SafeHash, key: &'a Q, elem: VacantEntryState>, @@ -1365,7 +1365,7 @@ pub struct VacantEntry<'a, Sized? Q: 'a, K: 'a, V: 'a> { #[stable] /// A view into a single location in a map, which may be vacant or occupied -pub enum Entry<'a, Sized? Q: 'a, K: 'a, V: 'a> { +pub enum Entry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { /// An occupied Entry Occupied(OccupiedEntry<'a, K, V>), /// A vacant Entry @@ -1435,7 +1435,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> { } } -impl<'a, Sized? Q, K, V> Entry<'a, Q, K, V> { +impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> { #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> { @@ -1481,7 +1481,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { } } -impl<'a, Sized? Q: 'a + ToOwned, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> { +impl<'a, Q: ?Sized + 'a + ToOwned, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> { #[stable] /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index b1824db93aad1..f77eaa237c1dd 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -451,7 +451,7 @@ impl, S, H: Hasher> HashSet { /// assert_eq!(set.contains(&4), false); /// ``` #[stable] - pub fn contains(&self, value: &Q) -> bool + pub fn contains(&self, value: &Q) -> bool where Q: BorrowFrom + Hash + Eq { self.map.contains_key(value) @@ -561,7 +561,7 @@ impl, S, H: Hasher> HashSet { /// assert_eq!(set.remove(&2), false); /// ``` #[stable] - pub fn remove(&mut self, value: &Q) -> bool + pub fn remove(&mut self, value: &Q) -> bool where Q: BorrowFrom + Hash + Eq { self.map.remove(value).is_some() diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index ab91beb4f9be1..1eb4408eedc40 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -138,7 +138,7 @@ impl SafeHash { /// We need to remove hashes of 0. That's reserved for empty buckets. /// This function wraps up `hash_keyed` to be the only way outside this /// module to generate a SafeHash. -pub fn make_hash, S, H: Hasher>(hasher: &H, t: &T) -> SafeHash { +pub fn make_hash, S, H: Hasher>(hasher: &H, t: &T) -> SafeHash { // We need to avoid 0u64 in order to prevent collisions with // EMPTY_HASH. We can maintain our precious uniform distribution // of initial indexes by unconditionally setting the MSB, diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index cdd0e9bf76f86..ac2b01e995e2c 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -90,7 +90,7 @@ impl RandomSipHasher { impl Hasher for RandomSipHasher { #[inline] - fn hash>(&self, value: &T) -> u64 { + fn hash>(&self, value: &T) -> u64 { self.hasher.hash(value) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 3fa0b5645c528..66416a21dd9a4 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1012,12 +1012,12 @@ pub trait Writer { fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> { // Create a shim which translates a Writer to a fmt::Writer and saves // off I/O errors. instead of discarding them - struct Adaptor<'a, Sized? T:'a> { + struct Adaptor<'a, T: ?Sized +'a> { inner: &'a mut T, error: IoResult<()>, } - impl<'a, Sized? T: Writer> fmt::Writer for Adaptor<'a, T> { + impl<'a, T: ?Sized + Writer> fmt::Writer for Adaptor<'a, T> { fn write_str(&mut self, s: &str) -> fmt::Result { match self.inner.write(s.as_bytes()) { Ok(()) => Ok(()), @@ -1597,11 +1597,11 @@ pub trait Acceptor { /// `Some`. The `Some` contains the `IoResult` representing whether the /// connection attempt was successful. A successful connection will be wrapped /// in `Ok`. A failed connection is represented as an `Err`. -pub struct IncomingConnections<'a, Sized? A:'a> { +pub struct IncomingConnections<'a, A: ?Sized +'a> { inc: &'a mut A, } -impl<'a, T, Sized? A: Acceptor> Iterator for IncomingConnections<'a, A> { +impl<'a, T, A: ?Sized + Acceptor> Iterator for IncomingConnections<'a, A> { type Item = IoResult; fn next(&mut self) -> Option> { diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index bf9ffbffe7d50..4f37e8a978aa9 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -896,7 +896,7 @@ impl BytesContainer for CString { } } -impl<'a, Sized? T: BytesContainer> BytesContainer for &'a T { +impl<'a, T: ?Sized + BytesContainer> BytesContainer for &'a T { #[inline] fn container_as_bytes(&self) -> &[u8] { (**self).container_as_bytes() diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index ae82e201cb855..777315b3ed66d 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -344,7 +344,7 @@ impl Path { /// Returns a normalized byte vector representation of a path, by removing all empty /// components, and unnecessary . and .. components. - fn normalize>(v: &V) -> Vec { + fn normalize>(v: &V) -> Vec { // borrowck is being very picky let val = { let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE; diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index d1b6034457d3a..299cf7e941b4e 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -95,7 +95,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { "write `extern crate bar as foo` instead" ), ObsoleteSyntax::Sized => ( - "`Sized? T` syntax for removing the `Sized` bound", + "`T: ?Sized` syntax for removing the `Sized` bound", "write `T: ?Sized` instead" ), }; diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 5f416a867e8bd..85eea2d9daf27 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -77,7 +77,7 @@ impl Interner { (*vect).len() } - pub fn find(&self, val: &Q) -> Option + pub fn find(&self, val: &Q) -> Option where Q: BorrowFrom + Eq + Hash { let map = self.map.borrow(); match (*map).get(val) { @@ -202,7 +202,7 @@ impl StrInterner { self.vect.borrow().len() } - pub fn find(&self, val: &Q) -> Option + pub fn find(&self, val: &Q) -> Option where Q: BorrowFrom + Eq + Hash { match (*self.map.borrow()).get(val) { Some(v) => Some(*v), diff --git a/src/test/compile-fail/associated-types-unsized.rs b/src/test/compile-fail/associated-types-unsized.rs index 47ab09d279f62..2ab3ec1aeadd7 100644 --- a/src/test/compile-fail/associated-types-unsized.rs +++ b/src/test/compile-fail/associated-types-unsized.rs @@ -11,7 +11,7 @@ #![feature(associated_types)] trait Get { - type Sized? Value; + type Value: ?Sized; fn get(&self) -> ::Value; } diff --git a/src/test/compile-fail/dst-bad-assign-2.rs b/src/test/compile-fail/dst-bad-assign-2.rs index fcc08cfcb1680..5e360b6ab9bad 100644 --- a/src/test/compile-fail/dst-bad-assign-2.rs +++ b/src/test/compile-fail/dst-bad-assign-2.rs @@ -10,7 +10,7 @@ // Forbid assignment into a dynamically sized type. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs index eb54f3f8e781f..cc709be99002e 100644 --- a/src/test/compile-fail/dst-bad-assign.rs +++ b/src/test/compile-fail/dst-bad-assign.rs @@ -10,7 +10,7 @@ // Forbid assignment into a dynamically sized type. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index c77ae25e0cf51..75bd94331b11d 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -10,7 +10,7 @@ // Attempt to change the type as well as unsizing. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 6eb650e978117..54c625221ba7d 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -10,7 +10,7 @@ // Attempt to change the mutability as well as unsizing. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index b0bd517637464..192d43e32fd27 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -10,7 +10,7 @@ // Attempt to extend the lifetime as well as unsizing. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 783a32d63028a..53ce18c73a088 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -10,7 +10,7 @@ // Attempt to coerce from unsized to sized. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index c3a814e3f44ff..b30eada162b84 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -14,7 +14,7 @@ struct S; trait T {} impl T for S {} -struct Foo { +struct Foo { f: T } diff --git a/src/test/compile-fail/dst-bad-deep.rs b/src/test/compile-fail/dst-bad-deep.rs index 0833a74f1daf9..b169824cb3aca 100644 --- a/src/test/compile-fail/dst-bad-deep.rs +++ b/src/test/compile-fail/dst-bad-deep.rs @@ -13,7 +13,7 @@ // because it would require stack allocation of an unsized temporary (*g in the // test). -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs index 99c63c3c6e95e..c331b02c7ccdc 100644 --- a/src/test/compile-fail/dst-object-from-unsized-type.rs +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -13,12 +13,12 @@ trait Foo for Sized? {} impl Foo for str {} -fn test1(t: &T) { +fn test1(t: &T) { let u: &Foo = t; //~^ ERROR `core::kinds::Sized` is not implemented for the type `T` } -fn test2(t: &T) { +fn test2(t: &T) { let v: &Foo = t as &Foo; //~^ ERROR `core::kinds::Sized` is not implemented for the type `T` } diff --git a/src/test/compile-fail/transmute-fat-pointers.rs b/src/test/compile-fail/transmute-fat-pointers.rs index 5e81a4cec2284..31456853e1c0f 100644 --- a/src/test/compile-fail/transmute-fat-pointers.rs +++ b/src/test/compile-fail/transmute-fat-pointers.rs @@ -14,11 +14,11 @@ use std::mem::transmute; -fn a(x: &[T]) -> &U { +fn a(x: &[T]) -> &U { unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes } -fn b(x: &T) -> &U { +fn b(x: &T) -> &U { unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes } @@ -30,11 +30,11 @@ fn d(x: &[T]) -> &[U] { unsafe { transmute(x) } } -fn e(x: &T) -> &U { +fn e(x: &T) -> &U { unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes } -fn f(x: &T) -> &U { +fn f(x: &T) -> &U { unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes } diff --git a/src/test/compile-fail/transmute-impl.rs b/src/test/compile-fail/transmute-impl.rs index 8b5a8c679b245..a68bba285df29 100644 --- a/src/test/compile-fail/transmute-impl.rs +++ b/src/test/compile-fail/transmute-impl.rs @@ -14,11 +14,11 @@ use std::mem::transmute; -struct Foo { +struct Foo { t: Box } -impl Foo { +impl Foo { fn m(x: &T) -> &int where T : Sized { // OK here, because T : Sized is in scope. unsafe { transmute(x) } diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 06a934063927a..81cfcf5cde918 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -18,9 +18,9 @@ trait Foo { fn dummy(&self, t: T, u: U, v: V); } -trait Eq for Sized? { } -impl Eq for X { } -fn eq() where A : Eq { } +trait Eq for Sized? { } +impl Eq for X { } +fn eq() where A : Eq { } fn test<'a,'b>() { // Parens are equivalent to omitting default in angle. diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 16d6b217872ae..368cb189907fe 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -20,9 +20,9 @@ trait Foo { fn dummy(&self, t: T, u: U); } -trait Eq for Sized? { } -impl Eq for X { } -fn eq>() { } +trait Eq for Sized? { } +impl Eq for X { } +fn eq>() { } fn test<'a,'b>() { // No errors expected: diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index e08d84944c02a..8c85382f45e0e 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -20,9 +20,9 @@ trait Foo { fn dummy(&self, t: T, u: U); } -trait Eq for Sized? { } -impl Eq for X { } -fn eq>() { } +trait Eq for Sized? { } +impl Eq for X { } +fn eq>() { } fn main() { eq::< for<'a> Foo<(&'a int,), &'a int>, diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index a938f126c1607..c99e7a116323f 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -21,9 +21,9 @@ trait Foo<'a,T,U> { fn dummy(&'a self) -> &'a (T,U); } -trait Eq for Sized? { } -impl Eq for X { } -fn eq>() { } +trait Eq for Sized? { } +impl Eq for X { } +fn eq>() { } fn same_type>(a: A, b: B) { } diff --git a/src/test/compile-fail/unsized-bare-typaram.rs b/src/test/compile-fail/unsized-bare-typaram.rs index 7b5d42954117c..2de490e018b44 100644 --- a/src/test/compile-fail/unsized-bare-typaram.rs +++ b/src/test/compile-fail/unsized-bare-typaram.rs @@ -9,5 +9,5 @@ // except according to those terms. fn bar() { } -fn foo() { bar::() } //~ ERROR the trait `core::kinds::Sized` is not implemented +fn foo() { bar::() } //~ ERROR the trait `core::kinds::Sized` is not implemented fn main() { } diff --git a/src/test/compile-fail/unsized-enum.rs b/src/test/compile-fail/unsized-enum.rs index 0462a2025d2ce..aea236c926815 100644 --- a/src/test/compile-fail/unsized-enum.rs +++ b/src/test/compile-fail/unsized-enum.rs @@ -10,18 +10,18 @@ fn is_sized() { } -fn not_sized() { } +fn not_sized() { } enum Foo { FooSome(U), FooNone } fn foo1() { not_sized::>() } // Hunky dory. -fn foo2() { not_sized::>() } +fn foo2() { not_sized::>() } //~^ ERROR the trait `core::kinds::Sized` is not implemented // // Not OK: `T` is not sized. -enum Bar { BarSome(U), BarNone } -fn bar1() { not_sized::>() } -fn bar2() { is_sized::>() } +enum Bar { BarSome(U), BarNone } +fn bar1() { not_sized::>() } +fn bar2() { is_sized::>() } //~^ ERROR the trait `core::kinds::Sized` is not implemented // // Not OK: `Bar` is not sized, but it should be. diff --git a/src/test/compile-fail/unsized-inherent-impl-self-type.rs b/src/test/compile-fail/unsized-inherent-impl-self-type.rs index 2c8a2b361d596..8740346a21750 100644 --- a/src/test/compile-fail/unsized-inherent-impl-self-type.rs +++ b/src/test/compile-fail/unsized-inherent-impl-self-type.rs @@ -14,7 +14,7 @@ struct S5; -impl S5 { //~ ERROR not implemented +impl S5 { //~ ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unsized-struct.rs b/src/test/compile-fail/unsized-struct.rs index db2e9cb932800..89c711036977a 100644 --- a/src/test/compile-fail/unsized-struct.rs +++ b/src/test/compile-fail/unsized-struct.rs @@ -10,18 +10,18 @@ fn is_sized() { } -fn not_sized() { } +fn not_sized() { } struct Foo { data: T } fn foo1() { not_sized::>() } // Hunky dory. -fn foo2() { not_sized::>() } +fn foo2() { not_sized::>() } //~^ ERROR the trait `core::kinds::Sized` is not implemented // // Not OK: `T` is not sized. -struct Bar { data: T } -fn bar1() { not_sized::>() } -fn bar2() { is_sized::>() } +struct Bar { data: T } +fn bar1() { not_sized::>() } +fn bar2() { is_sized::>() } //~^ ERROR the trait `core::kinds::Sized` is not implemented // // Not OK: `Bar` is not sized, but it should be. diff --git a/src/test/compile-fail/unsized-trait-impl-self-type.rs b/src/test/compile-fail/unsized-trait-impl-self-type.rs index 0f0a97fab4d75..3dd55b0ba7d23 100644 --- a/src/test/compile-fail/unsized-trait-impl-self-type.rs +++ b/src/test/compile-fail/unsized-trait-impl-self-type.rs @@ -11,12 +11,12 @@ // Test sized-ness checking in substitution in impls. // impl - struct -trait T3 { +trait T3 { } struct S5; -impl T3 for S5 { //~ ERROR not implemented +impl T3 for S5 { //~ ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs index bdb652b168a8c..7ae74fc2600c8 100644 --- a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs +++ b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs @@ -13,8 +13,8 @@ // impl - unbounded trait T2 { } -struct S4; -impl T2 for S4 { +struct S4; +impl T2 for S4 { //~^ ERROR `core::kinds::Sized` is not implemented for the type `X` } diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 0a75240f2d89d..02c0fd618927d 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -12,7 +12,7 @@ // Unbounded. -fn f1(x: &X) { +fn f1(x: &X) { f2::(x); //~^ ERROR the trait `core::kinds::Sized` is not implemented } @@ -21,7 +21,7 @@ fn f2(x: &X) { // Bounded. trait T for Sized? {} -fn f3(x: &X) { +fn f3(x: &X) { f4::(x); //~^ ERROR the trait `core::kinds::Sized` is not implemented } @@ -29,13 +29,13 @@ fn f4(x: &X) { } // Test with unsized enum. -enum E { +enum E { V(X), } fn f5(x: &Y) {} -fn f6(x: &X) {} -fn f7(x1: &E, x2: &E) { +fn f6(x: &X) {} +fn f7(x1: &E, x2: &E) { f5(x1); //~^ ERROR the trait `core::kinds::Sized` is not implemented f6(x2); // ok @@ -43,23 +43,23 @@ fn f7(x1: &E, x2: &E) { // Test with unsized struct. -struct S { +struct S { x: X, } -fn f8(x1: &S, x2: &S) { +fn f8(x1: &S, x2: &S) { f5(x1); //~^ ERROR the trait `core::kinds::Sized` is not implemented f6(x2); // ok } // Test some tuples. -fn f9(x1: Box>, x2: Box>) { +fn f9(x1: Box>, x2: Box>) { f5(&(*x1, 34i)); //~^ ERROR the trait `core::kinds::Sized` is not implemented } -fn f10(x1: Box>, x2: Box>) { +fn f10(x1: Box>, x2: Box>) { f5(&(32i, *x2)); //~^ ERROR the trait `core::kinds::Sized` is not implemented } diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs index f9ece8e6843db..f8b8ad2bf2efa 100644 --- a/src/test/compile-fail/unsized4.rs +++ b/src/test/compile-fail/unsized4.rs @@ -11,7 +11,7 @@ // Test that bounds are sized-compatible. trait T : Sized {} -fn f() { +fn f() { //~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type } diff --git a/src/test/compile-fail/unsized5.rs b/src/test/compile-fail/unsized5.rs index d9d7a86889f57..f7477d746fae4 100644 --- a/src/test/compile-fail/unsized5.rs +++ b/src/test/compile-fail/unsized5.rs @@ -10,11 +10,11 @@ // Test `Sized?` types not allowed in fields (except the last one). -struct S1 { +struct S1 { f1: X, //~ ERROR `core::kinds::Sized` is not implemented f2: int, } -struct S2 { +struct S2 { f: int, g: X, //~ ERROR `core::kinds::Sized` is not implemented h: int, @@ -27,10 +27,10 @@ struct S4 { f: str, //~ ERROR `core::kinds::Sized` is not implemented g: uint } -enum E { +enum E { V1(X, int), //~ERROR `core::kinds::Sized` is not implemented } -enum F { +enum F { V2{f1: X, f: int}, //~ERROR `core::kinds::Sized` is not implemented } diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 0efd178f75b8c..019d347550253 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -13,30 +13,30 @@ trait T for Sized? {} -fn f1(x: &X) { +fn f1(x: &X) { let _: X; // <-- this is OK, no bindings created, no initializer. let _: (int, (X, int)); // same let y: X; //~ERROR the trait `core::kinds::Sized` is not implemented let y: (int, (X, int)); //~ERROR the trait `core::kinds::Sized` is not implemented } -fn f2(x: &X) { +fn f2(x: &X) { let y: X; //~ERROR the trait `core::kinds::Sized` is not implemented let y: (int, (X, int)); //~ERROR the trait `core::kinds::Sized` is not implemented } -fn f3(x1: Box, x2: Box, x3: Box) { +fn f3(x1: Box, x2: Box, x3: Box) { let y: X = *x1; //~ERROR the trait `core::kinds::Sized` is not implemented let y = *x2; //~ERROR the trait `core::kinds::Sized` is not implemented let (y, z) = (*x3, 4i); //~ERROR the trait `core::kinds::Sized` is not implemented } -fn f4(x1: Box, x2: Box, x3: Box) { +fn f4(x1: Box, x2: Box, x3: Box) { let y: X = *x1; //~ERROR the trait `core::kinds::Sized` is not implemented let y = *x2; //~ERROR the trait `core::kinds::Sized` is not implemented let (y, z) = (*x3, 4i); //~ERROR the trait `core::kinds::Sized` is not implemented } -fn g1(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented -fn g2(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented +fn g1(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented +fn g2(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented pub fn main() { } diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index c0e6ae1db92c4..af64afb23b945 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -16,8 +16,8 @@ trait T for Sized? {} // impl - bounded trait T1 { } -struct S3; -impl T1 for S3 { +struct S3; +impl T1 for S3 { //~^ ERROR `core::kinds::Sized` is not implemented for the type `X` } diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 6e2ae117ce7ae..8b8b7f169c5a0 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -20,7 +20,7 @@ impl Drop for Foo { trait Trait {} impl Trait for Foo {} -struct Fat { +struct Fat { f: T } diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index deaf49228bc84..743293c23f6ad 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -17,7 +17,7 @@ impl Drop for Foo { } } -struct Fat { +struct Fat { f: T } diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index 3b53203d218e0..f7032da82a169 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -18,7 +18,7 @@ use std::ops::Deref; -pub trait MyEq for Sized? { +pub trait MyEq for Sized? { fn eq(&self, u: &U) -> bool; } diff --git a/src/test/run-pass/issue-18906.rs b/src/test/run-pass/issue-18906.rs index e82359bc168e6..11ffb4198dad8 100644 --- a/src/test/run-pass/issue-18906.rs +++ b/src/test/run-pass/issue-18906.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Borrow { +pub trait Borrow { fn borrow(&self) -> &Borrowed; } From 8f3a424322f5609f75aab2313dc93b0ad73e2670 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jan 2015 14:25:06 +1300 Subject: [PATCH 092/106] Fix the obsolete message --- src/libsyntax/parse/obsolete.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 299cf7e941b4e..d1b6034457d3a 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -95,7 +95,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { "write `extern crate bar as foo` instead" ), ObsoleteSyntax::Sized => ( - "`T: ?Sized` syntax for removing the `Sized` bound", + "`Sized? T` syntax for removing the `Sized` bound", "write `T: ?Sized` instead" ), }; From f314e2c4ea48c2027e627fdfca821bb6e0012e59 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 31 Dec 2014 19:48:39 -0800 Subject: [PATCH 093/106] creader: Load parts of plugin metadata on demand --- src/librustc/metadata/creader.rs | 148 ++++++++++++++++++++----------- src/librustc/plugin/load.rs | 59 ++++++------ 2 files changed, 125 insertions(+), 82 deletions(-) diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 3bf0e41ae9caa..34e7200806612 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -16,11 +16,10 @@ use back::svh::Svh; use session::{config, Session}; use session::search_paths::PathKind; use metadata::cstore; -use metadata::cstore::{CStore, CrateSource}; +use metadata::cstore::{CStore, CrateSource, MetadataBlob}; use metadata::decoder; use metadata::loader; use metadata::loader::CratePaths; -use plugin::load::PluginMetadata; use util::nodemap::FnvHashMap; use std::rc::Rc; @@ -154,6 +153,29 @@ fn register_native_lib(sess: &Session, sess.cstore.add_used_library(name, kind); } +pub struct PluginMetadata<'a> { + sess: &'a Session, + metadata: PMDSource, + dylib: Option, + info: CrateInfo, + vi_span: Span, + target_only: bool, +} + +enum PMDSource { + Registered(Rc), + Owned(MetadataBlob), +} + +impl PMDSource { + pub fn as_slice<'a>(&'a self) -> &'a [u8] { + match *self { + PMDSource::Registered(ref cmd) => cmd.data(), + PMDSource::Owned(ref mdb) => mdb.as_slice(), + } + } +} + impl<'a> CrateReader<'a> { pub fn new(sess: &'a Session) -> CrateReader<'a> { CrateReader { @@ -450,17 +472,20 @@ impl<'a> CrateReader<'a> { }).collect() } - pub fn read_plugin_metadata(&mut self, - krate: &ast::ViewItem) -> PluginMetadata { - let info = self.extract_crate_info(krate).unwrap(); + pub fn read_plugin_metadata<'b>(&'b mut self, + vi: &'b ast::ViewItem) -> PluginMetadata<'b> { + let info = self.extract_crate_info(vi).unwrap(); let target_triple = self.sess.opts.target_triple[]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; + let mut target_only = false; + let ident = info.ident.clone(); + let name = info.name.clone(); let mut load_ctxt = loader::Context { sess: self.sess, - span: krate.span, - ident: info.ident[], - crate_name: info.name[], + span: vi.span, + ident: ident[], + crate_name: name[], hash: None, filesearch: self.sess.host_filesearch(PathKind::Crate), triple: config::host_triple(), @@ -472,32 +497,49 @@ impl<'a> CrateReader<'a> { let library = match load_ctxt.maybe_load_library_crate() { Some(l) => l, None if is_cross => { - // try loading from target crates (only valid if there are - // no syntax extensions) + // Try loading from target crates. This will abort later if we try to + // load a plugin registrar function, + target_only = true; + should_link = info.should_link; + load_ctxt.triple = target_triple; load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); - let lib = load_ctxt.load_library_crate(); - if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() { - let message = format!("crate `{}` contains a plugin_registrar fn but \ - only a version for triple `{}` could be found (need {})", - info.ident, target_triple, config::host_triple()); - self.sess.span_err(krate.span, message[]); - // need to abort now because the syntax expansion - // code will shortly attempt to load and execute - // code from the found library. - self.sess.abort_if_errors(); - } - should_link = info.should_link; - lib + load_ctxt.load_library_crate() } None => { load_ctxt.report_load_errs(); unreachable!() }, }; - // Read exported macros - let imported_from = Some(token::intern(info.ident[]).ident()); - let source_name = format!("<{} macros>", info.ident[]); + let dylib = library.dylib.clone(); + let register = should_link && self.existing_match(info.name[], None).is_none(); + let metadata = if register { + // Register crate now to avoid double-reading metadata + let (_, cmd, _) = self.register_crate(&None, info.ident[], + info.name[], vi.span, library); + PMDSource::Registered(cmd) + } else { + // Not registering the crate; just hold on to the metadata + PMDSource::Owned(library.metadata) + }; + + PluginMetadata { + sess: self.sess, + metadata: metadata, + dylib: dylib, + info: info, + vi_span: vi.span, + target_only: target_only, + } + } +} + +impl<'a> PluginMetadata<'a> { + /// Read exported macros + pub fn exported_macros(&self) -> Vec { + let imported_from = Some(token::intern(self.info.ident[]).ident()); + let source_name = format!("<{} macros>", self.info.ident[]); let mut macros = vec![]; - decoder::each_exported_macro(library.metadata.as_slice(), &*self.sess.cstore.intr, + decoder::each_exported_macro(self.metadata.as_slice(), + &*self.sess.cstore.intr, |name, attrs, body| { // NB: Don't use parse::parse_tts_from_source_str because it parses with // quote_depth > 0. @@ -520,31 +562,37 @@ impl<'a> CrateReader<'a> { true } ); + macros + } - // Look for a plugin registrar - let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| { - decoder::get_symbol(library.metadata.as_slice(), id) - }); - if library.dylib.is_none() && registrar.is_some() { - let message = format!("plugin crate `{}` only found in rlib format, \ - but must be available in dylib format", - info.ident); - self.sess.span_err(krate.span, message[]); - // No need to abort because the loading code will just ignore this - // empty dylib. + /// Look for a plugin registrar. Returns library path and symbol name. + pub fn plugin_registrar(&self) -> Option<(Path, String)> { + if self.target_only { + // Need to abort before syntax expansion. + let message = format!("plugin crate `{}` is not available for triple `{}` \ + (only found {})", + self.info.ident, + config::host_triple(), + self.sess.opts.target_triple); + self.sess.span_err(self.vi_span, message[]); + self.sess.abort_if_errors(); } - let pc = PluginMetadata { - macros: macros, - registrar: match (library.dylib.as_ref(), registrar) { - (Some(dylib), Some(reg)) => Some((dylib.clone(), reg)), - _ => None, - }, - }; - if should_link && self.existing_match(info.name[], None).is_none() { - // register crate now to avoid double-reading metadata - self.register_crate(&None, info.ident[], - info.name[], krate.span, library); + + let registrar = decoder::get_plugin_registrar_fn(self.metadata.as_slice()) + .map(|id| decoder::get_symbol(self.metadata.as_slice(), id)); + + match (self.dylib.as_ref(), registrar) { + (Some(dylib), Some(reg)) => Some((dylib.clone(), reg)), + (None, Some(_)) => { + let message = format!("plugin crate `{}` only found in rlib format, \ + but must be available in dylib format", + self.info.ident); + self.sess.span_err(self.vi_span, message[]); + // No need to abort because the loading code will just ignore this + // empty dylib. + None + } + _ => None, } - pc } } diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 9aa7d8fe9906d..78730defc7fd6 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -23,14 +23,6 @@ use syntax::visit; use syntax::visit::Visitor; use syntax::attr::AttrMetaMethods; -/// Metadata for a single plugin crate. -pub struct PluginMetadata { - /// Macros exported by the crate. - pub macros: Vec, - /// Path to the shared library file, and registrar function symbol. - pub registrar: Option<(Path, String)>, -} - /// Pointer to a registrar function. pub type PluginRegistrarFun = fn(&mut Registry); @@ -86,37 +78,40 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, // note that macros aren't expanded yet, and therefore macros can't add plugins. impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { fn visit_view_item(&mut self, vi: &ast::ViewItem) { + // We're only interested in `extern crate`. match vi.node { - ast::ViewItemExternCrate(_, _, _) => { - let mut plugin_phase = false; - - for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) { - let phases = attr.meta_item_list().unwrap_or(&[]); - if attr::contains_name(phases, "plugin") { - plugin_phase = true; - } - if attr::contains_name(phases, "syntax") { - plugin_phase = true; - self.sess.span_warn(attr.span, - "phase(syntax) is a deprecated synonym for phase(plugin)"); - } - } + ast::ViewItemExternCrate(..) => (), + _ => return, + } - if !plugin_phase { return; } + let mut plugin_phase = false; + for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) { + let phases = attr.meta_item_list().unwrap_or(&[]); + if attr::contains_name(phases, "plugin") { + plugin_phase = true; + } + if attr::contains_name(phases, "syntax") { + plugin_phase = true; + self.sess.span_warn(attr.span, + "phase(syntax) is a deprecated synonym for phase(plugin)"); + } + } - let PluginMetadata { macros, registrar } = - self.reader.read_plugin_metadata(vi); + let mut macros = vec![]; + let mut registrar = None; - self.plugins.macros.extend(macros.into_iter()); + if plugin_phase { + let pmd = self.reader.read_plugin_metadata(vi); + macros = pmd.exported_macros(); + registrar = pmd.plugin_registrar(); + } - match registrar { - Some((lib, symbol)) => self.dylink_registrar(vi, lib, symbol), - _ => (), - } - } - _ => (), + self.plugins.macros.extend(macros.into_iter()); + if let Some((lib, symbol)) = registrar { + self.dylink_registrar(vi, lib, symbol); } } + fn visit_mac(&mut self, _: &ast::Mac) { // bummer... can't see plugins inside macros. // do nothing. From 60be2f52d2434dfbf2df7728454d572d76f58bf8 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 31 Dec 2014 20:43:46 -0800 Subject: [PATCH 094/106] Replace #[phase] with #[plugin] / #[macro_use] / #[no_link] --- src/compiletest/compiletest.rs | 9 ++++- src/grammar/verify.rs | 5 ++- src/liballoc/lib.rs | 23 +++++++++++-- src/libcollections/lib.rs | 25 ++++++++++++-- src/libflate/lib.rs | 4 +-- src/libgetopts/lib.rs | 4 +-- src/liblog/lib.rs | 3 +- src/liblog/macros.rs | 18 ++++------ src/librand/lib.rs | 22 ++++++++++-- src/librbml/lib.rs | 9 ++++- src/libregex/lib.rs | 2 +- src/librustc/lib.rs | 18 ++++++++-- src/librustc/metadata/creader.rs | 7 +--- src/librustc/plugin/load.rs | 34 ++++++++++++------- src/librustc/plugin/mod.rs | 8 ++--- src/librustc_back/lib.rs | 6 ++++ src/librustc_borrowck/lib.rs | 17 ++++++++-- src/librustc_driver/lib.rs | 18 ++++++++-- src/librustc_resolve/lib.rs | 17 ++++++++-- src/librustc_trans/lib.rs | 18 ++++++++-- src/librustc_typeck/lib.rs | 17 ++++++++-- src/librustdoc/lib.rs | 9 ++++- src/libserialize/lib.rs | 6 ++++ src/libstd/lib.rs | 20 ++++++++++- src/libsyntax/feature_gate.rs | 28 ++++----------- src/libsyntax/lib.rs | 9 ++++- src/libsyntax/std_inject.rs | 18 ++-------- src/libterm/lib.rs | 8 ++++- src/libtest/lib.rs | 2 +- src/test/auxiliary/issue-13560-3.rs | 5 ++- src/test/auxiliary/lint_group_plugin_test.rs | 4 +-- src/test/auxiliary/lint_plugin_test.rs | 4 +-- src/test/auxiliary/logging_right_crate.rs | 3 +- src/test/auxiliary/macro_reexport_2.rs | 3 +- src/test/auxiliary/weak-lang-items.rs | 3 +- src/test/bench/shootout-regex-dna.rs | 2 +- .../{gated-phase.rs => gated-plugin.rs} | 4 +-- .../lint-group-plugin-deny-cmdline.rs | 4 +-- .../lint-plugin-deny-attr.rs | 4 +-- .../lint-plugin-deny-cmdline.rs | 4 +-- .../lint-plugin-forbid-attrs.rs | 4 +-- .../lint-plugin-forbid-cmdline.rs | 4 +-- .../macro-crate-cannot-read-embedded-ident.rs | 4 +-- ...solve.rs => macro-crate-doesnt-resolve.rs} | 4 +-- .../compile-fail-fulldeps/macro-crate-rlib.rs | 4 +-- .../macro-crate-unexported-macro.rs | 4 +-- .../macro-crate-unknown-crate.rs | 4 +-- .../plugin-MacroRulesTT.rs | 4 +-- .../deprecated-phase.rs} | 9 ++--- .../compile-fail/fail-no-dead-code-core.rs | 3 +- src/test/compile-fail/lint-stability.rs | 4 +-- .../no-link.rs} | 14 ++++---- src/test/pretty/issue-4264.pp | 3 +- src/test/run-fail/rt-set-exit-status-panic.rs | 3 +- .../run-fail/rt-set-exit-status-panic2.rs | 3 +- src/test/run-fail/rt-set-exit-status.rs | 3 +- .../extern-diff-internal-name/test.rs | 4 +-- .../run-make/lto-syntax-extension/main.rs | 4 +-- .../issue_16723_multiple_items_syntax_ext.rs | 4 +-- .../run-pass-fulldeps/lint-group-plugin.rs | 4 +-- .../run-pass-fulldeps/lint-plugin-cmdline.rs | 4 +-- src/test/run-pass-fulldeps/lint-plugin.rs | 4 +-- .../macro-crate-does-hygiene-work.rs | 4 +-- .../macro-crate-outlive-expansion-phase.rs | 4 +-- src/test/run-pass-fulldeps/macro-crate.rs | 4 +-- ...resolve.rs => plugin-link-does-resolve.rs} | 4 +-- .../run-pass-fulldeps/roman-numerals-macro.rs | 4 +-- .../syntax-extension-with-dll-deps.rs | 4 +-- src/test/run-pass/capturing-logging.rs | 4 +-- .../run-pass/conditional-debug-macro-off.rs | 3 +- src/test/run-pass/issue-14330.rs | 4 +-- src/test/run-pass/logging-enabled-debug.rs | 3 +- src/test/run-pass/logging-enabled.rs | 3 +- src/test/run-pass/logging-separate-lines.rs | 4 +-- src/test/run-pass/macro-crate-def-only.rs | 4 +-- .../macro-crate-nonterminal-renamed.rs | 4 +-- src/test/run-pass/macro-crate-nonterminal.rs | 4 +-- .../run-pass/macro-export-inner-module.rs | 4 +-- src/test/run-pass/macro-reexport.rs | 4 +-- src/test/run-pass/rust-log-filter.rs | 3 +- src/test/run-pass/tcp-stress.rs | 3 +- src/test/run-pass/vec-macro-no-std.rs | 6 ++-- 82 files changed, 363 insertions(+), 236 deletions(-) rename src/test/compile-fail-fulldeps/{gated-phase.rs => gated-plugin.rs} (86%) rename src/test/compile-fail-fulldeps/{phase-syntax-doesnt-resolve.rs => macro-crate-doesnt-resolve.rs} (95%) rename src/test/{run-pass/phase-use-ignored.rs => compile-fail/deprecated-phase.rs} (87%) rename src/test/{run-pass/deprecated-phase-syntax.rs => compile-fail/no-link.rs} (62%) rename src/test/run-pass-fulldeps/{phase-syntax-link-does-resolve.rs => plugin-link-does-resolve.rs} (94%) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 350a10ce4832a..ee6bc0b4fa88b 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -15,7 +15,14 @@ extern crate test; extern crate getopts; -#[phase(plugin, link)] extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; extern crate regex; diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index db26ca6ffa5d5..ad271d230904e 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, phase, macro_rules)] +#![feature(globs, plugin, macro_rules)] extern crate syntax; extern crate rustc; -#[phase(link)] extern crate regex; -#[phase(link, plugin)] +#[macro_use] extern crate log; use std::collections::HashMap; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d040f8ff86390..001e02f9c0dd5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -68,14 +68,33 @@ #![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)] #![feature(associated_types)] +#[cfg(stage0)] #[phase(plugin, link)] extern crate core; + +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + extern crate libc; // Allow testing this library -#[cfg(test)] #[phase(plugin, link)] extern crate std; -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate std; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate std; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; // Heaps provided for low-level allocation strategies diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 142ac6f34e02f..7352c71e6797e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -29,15 +29,34 @@ #![feature(associated_types)] #![no_std] -#[phase(plugin, link)] extern crate core; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate core; + +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + extern crate unicode; extern crate alloc; #[cfg(test)] extern crate test; -#[cfg(test)] #[phase(plugin, link)] extern crate std; -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate std; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate std; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; pub use binary_heap::BinaryHeap; pub use bitv::Bitv; diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index aa1550ae5b874..744606d80553c 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -21,9 +21,9 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(phase, unboxed_closures)] +#![feature(unboxed_closures)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(test)] #[macro_use] extern crate log; extern crate libc; diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 2063654077f15..18077795e245f 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -85,11 +85,11 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(globs, phase, slicing_syntax)] +#![feature(globs, slicing_syntax)] #![feature(unboxed_closures)] #![deny(missing_docs)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(test)] #[macro_use] extern crate log; use self::Name::*; use self::HasArg::*; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index c210873563c5d..df85e89efd17c 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -13,8 +13,7 @@ //! # Examples //! //! ``` -//! #![feature(phase)] -//! #[phase(plugin, link)] extern crate log; +//! #[macro_use] extern crate log; //! //! fn main() { //! debug!("this is a debug {}", "message"); diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 66682dba7b6df..5249e971439cd 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -19,8 +19,7 @@ /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// fn main() { /// log!(log::WARN, "this is a warning {}", "message"); @@ -68,8 +67,7 @@ macro_rules! log { /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// fn main() { /// let error = 3u; @@ -94,8 +92,7 @@ macro_rules! error { /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// fn main() { /// let code = 3u; @@ -119,8 +116,7 @@ macro_rules! warn { /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// fn main() { /// let ret = 3i; @@ -146,8 +142,7 @@ macro_rules! info { /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// fn main() { /// debug!("x = {x}, y = {y}", x=10i, y=20i); @@ -170,8 +165,7 @@ macro_rules! debug { /// # Example /// /// ``` -/// #![feature(phase)] -/// #[phase(plugin, link)] extern crate log; +/// #[macro_use] extern crate log; /// /// struct Point { x: int, y: int } /// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0f8dbc78cde32..4017d8d57c075 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -29,11 +29,29 @@ #![no_std] #![experimental] +#[cfg(stage0)] #[phase(plugin, link)] extern crate core; -#[cfg(test)] #[phase(plugin, link)] extern crate std; -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate std; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate std; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; use core::prelude::*; diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 3acedac111d60..e57542a6d14de 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -30,7 +30,14 @@ extern crate serialize; -#[phase(plugin, link)] extern crate log; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + #[cfg(test)] extern crate test; pub use self::EbmlEncoderTag::*; diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs index b3807d313145d..0084be49b5619 100644 --- a/src/libregex/lib.rs +++ b/src/libregex/lib.rs @@ -24,7 +24,7 @@ html_playground_url = "http://play.rust-lang.org/")] #![allow(unknown_features)] -#![feature(macro_rules, phase, slicing_syntax, globs)] +#![feature(macro_rules, slicing_syntax, globs)] #![feature(unboxed_closures)] #![feature(associated_types)] #![deny(missing_docs)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 122171e469108..3ed712b15dfdc 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,8 +40,22 @@ extern crate rustc_back; extern crate serialize; extern crate rbml; extern crate collections; -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; extern crate "serialize" as rustc_serialize; // used by deriving diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 34e7200806612..c7a8457c6d24a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -89,12 +89,7 @@ fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) { } fn should_link(i: &ast::ViewItem) -> bool { - i.attrs.iter().all(|attr| { - attr.name().get() != "phase" || - attr.meta_item_list().map_or(false, |phases| { - attr::contains_name(phases[], "link") - }) - }) + !attr::contains_name(i.attrs[], "no_link") } struct CrateInfo { diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 78730defc7fd6..d17ef199aa1bd 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -84,26 +84,36 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { _ => return, } - let mut plugin_phase = false; - for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) { - let phases = attr.meta_item_list().unwrap_or(&[]); - if attr::contains_name(phases, "plugin") { - plugin_phase = true; + // Parse the attributes relating to macro / plugin loading. + let mut load_macros = false; + let mut load_registrar = false; + for attr in vi.attrs.iter() { + let mut used = true; + match attr.name().get() { + "phase" => { + self.sess.span_err(attr.span, "#[phase] is deprecated; use \ + #[macro_use], #[plugin], and/or #[no_link]"); + } + "plugin" => load_registrar = true, + "macro_use" => load_macros = true, + _ => used = false, } - if attr::contains_name(phases, "syntax") { - plugin_phase = true; - self.sess.span_warn(attr.span, - "phase(syntax) is a deprecated synonym for phase(plugin)"); + if used { + attr::mark_used(attr); } } let mut macros = vec![]; let mut registrar = None; - if plugin_phase { + if load_macros || load_registrar { let pmd = self.reader.read_plugin_metadata(vi); - macros = pmd.exported_macros(); - registrar = pmd.plugin_registrar(); + if load_macros { + macros = pmd.exported_macros(); + } + if load_registrar { + registrar = pmd.plugin_registrar(); + } } self.plugins.macros.extend(macros.into_iter()); diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs index 8dd60880cdd56..fd8873454b4d9 100644 --- a/src/librustc/plugin/mod.rs +++ b/src/librustc/plugin/mod.rs @@ -43,14 +43,14 @@ //! To use a plugin while compiling another crate: //! //! ```rust -//! #![feature(phase)] +//! #![feature(plugin)] //! -//! #[phase(plugin)] +//! #[plugin] //! extern crate myplugin; //! ``` //! -//! If you also need the plugin crate available at runtime, use -//! `phase(plugin, link)`. +//! If you don't need the plugin crate available at runtime, use +//! `#[no_link]` as well. //! //! See [the compiler plugin guide](../../guide-plugin.html) //! for more examples. diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 2bb99a7141f70..238c84e88a9e0 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -34,8 +34,14 @@ #![feature(unboxed_closures)] #![feature(old_orphan_check)] +#[cfg(stage0)] #[phase(plugin, link)] extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + extern crate syntax; extern crate serialize; diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index b886883c73ad2..0600ddba01897 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -24,8 +24,21 @@ #![feature(old_orphan_check)] #![allow(non_camel_case_types)] -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; // for "clarity", rename the graphviz crate to dot; graphviz within `borrowck` // refers to the borrowck-specific graphviz adapter traits. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 983188c709000..a43ee3e6d338d 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -39,11 +39,25 @@ extern crate rustc_borrowck; extern crate rustc_resolve; extern crate rustc_trans; extern crate rustc_typeck; -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; extern crate serialize; extern crate "rustc_llvm" as llvm; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; + pub use syntax::diagnostic; use rustc_trans::back::link; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2c2678c8dc68e..2237ec53ea177 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -20,8 +20,21 @@ #![feature(rustc_diagnostic_macros)] #![feature(associated_types)] -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; extern crate rustc; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 9dbff66aba286..705fecf4d198e 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -37,11 +37,25 @@ extern crate graphviz; extern crate libc; extern crate rustc; extern crate rustc_back; -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; extern crate serialize; extern crate "rustc_llvm" as llvm; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; + pub use rustc::session; pub use rustc::metadata; pub use rustc::middle; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 48f9b12971971..7206a71001be2 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -77,8 +77,21 @@ This API is completely unstable and subject to change. #![feature(unboxed_closures)] #![allow(non_camel_case_types)] -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; extern crate arena; extern crate rustc; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 319eee8731772..6e42c50f974c5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,7 +32,14 @@ extern crate rustc_driver; extern crate serialize; extern crate syntax; extern crate "test" as testing; -#[phase(plugin, link)] extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; extern crate "serialize" as rustc_serialize; // used by deriving diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 8ad2013f9368f..8fe15f00ded73 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -31,8 +31,14 @@ Core encoding and decoding interfaces. #[cfg(test)] extern crate test; +#[cfg(stage0)] #[phase(plugin, link)] extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + extern crate unicode; extern crate collections; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index abe968849c2b8..3eda6d3374ed9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -120,12 +120,30 @@ #![macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq, unreachable, unimplemented, write, writeln, vec)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; +#[cfg(stage0)] #[phase(plugin, link)] extern crate core; + +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + +#[cfg(stage0)] #[phase(plugin, link)] extern crate "collections" as core_collections; + +#[cfg(not(stage0))] +#[macro_use] +extern crate "collections" as core_collections; + extern crate "rand" as core_rand; extern crate alloc; extern crate unicode; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f8ac34cfe2920..e41fef4e77870 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -44,7 +44,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("non_ascii_idents", Active), ("thread_local", Active), ("link_args", Active), - ("phase", Active), + ("phase", Active), // NOTE(stage0): switch to Removed after next snapshot ("plugin_registrar", Active), ("log_syntax", Active), ("trace_macros", Active), @@ -74,6 +74,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("if_let", Accepted), ("while_let", Accepted), + ("plugin", Active), + // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. ("issue_5723_bootstrap", Accepted), @@ -163,22 +165,6 @@ struct MacroVisitor<'a> { } impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { - fn visit_view_item(&mut self, i: &ast::ViewItem) { - match i.node { - ast::ViewItemExternCrate(..) => { - for attr in i.attrs.iter() { - if attr.name().get() == "phase"{ - self.context.gate_feature("phase", attr.span, - "compile time crate loading is \ - experimental and possibly buggy"); - } - } - }, - _ => { } - } - visit::walk_view_item(self, i) - } - fn visit_mac(&mut self, macro: &ast::Mac) { let ast::MacInvocTT(ref path, _, _) = macro.node; let id = path.segments.last().unwrap().identifier; @@ -241,10 +227,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } ast::ViewItemExternCrate(..) => { for attr in i.attrs.iter() { - if attr.name().get() == "phase"{ - self.gate_feature("phase", attr.span, - "compile time crate loading is \ - experimental and possibly buggy"); + if attr.check_name("plugin") { + self.gate_feature("plugin", attr.span, + "compiler plugins are experimental \ + and possibly buggy"); } } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 0503d88cca201..774a9f61cf9af 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -31,11 +31,18 @@ extern crate arena; extern crate fmt_macros; -#[phase(plugin, link)] extern crate log; extern crate serialize; extern crate term; extern crate libc; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + extern crate "serialize" as rustc_serialize; // used by deriving pub mod util { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 5a4d0cc3bd896..4ef7eb97a2189 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -65,12 +65,8 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { Some((actual_crate_name, ast::CookedStr)), ast::DUMMY_NODE_ID), attrs: vec!( - attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item( - InternedString::new("phase"), - vec!( - attr::mk_word_item(InternedString::new("plugin")), - attr::mk_word_item(InternedString::new("link") - ))))), + attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item( + InternedString::new("macro_use")))), vis: ast::Inherited, span: DUMMY_SP }); @@ -82,16 +78,6 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { // don't add #![no_std] here, that will block the prelude injection later. // Add it during the prelude injection instead. - // Add #![feature(phase)] here, because we use #[phase] on extern crate std. - let feat_phase_attr = attr::mk_attr_inner(attr::mk_attr_id(), - attr::mk_list_item( - InternedString::new("feature"), - vec![attr::mk_word_item(InternedString::new("phase"))], - )); - // std_inject runs after feature checking so manually mark this attr - attr::mark_used(&feat_phase_attr); - krate.attrs.push(feat_phase_attr); - krate } } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 3a442080077f3..dd42bede13ac3 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -52,7 +52,13 @@ #![deny(missing_docs)] -#[phase(plugin, link)] extern crate log; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; pub use terminfo::TerminfoTerminal; #[cfg(windows)] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 3fb2211eff23a..18c253bcf01a8 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -32,7 +32,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![allow(unknown_features)] -#![feature(asm, macro_rules, phase, globs, slicing_syntax)] +#![feature(asm, macro_rules, globs, slicing_syntax)] #![feature(unboxed_closures, default_type_params)] #![feature(old_orphan_check)] diff --git a/src/test/auxiliary/issue-13560-3.rs b/src/test/auxiliary/issue-13560-3.rs index c80a7643e01ac..5510d3e2e0df1 100644 --- a/src/test/auxiliary/issue-13560-3.rs +++ b/src/test/auxiliary/issue-13560-3.rs @@ -11,8 +11,7 @@ // no-prefer-dynamic #![crate_type = "rlib"] -#![feature(phase)] -#[phase(plugin)] extern crate "issue-13560-1" as t1; -#[phase(plugin, link)] extern crate "issue-13560-2" as t2; +#[macro_use] #[no_link] extern crate "issue-13560-1" as t1; +#[macro_use] extern crate "issue-13560-2" as t2; diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index add54ed01e00e..097a5827fc4be 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -10,12 +10,12 @@ // force-host -#![feature(phase, plugin_registrar)] +#![feature(plugin_registrar)] extern crate syntax; // Load rustc as a plugin to get macros -#[phase(plugin, link)] +#[macro_use] extern crate rustc; use syntax::ast; diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index 6c78cdce28ac4..01ef08c475234 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -10,12 +10,12 @@ // force-host -#![feature(phase, plugin_registrar)] +#![feature(plugin_registrar)] extern crate syntax; // Load rustc as a plugin to get macros -#[phase(plugin, link)] +#[macro_use] extern crate rustc; use syntax::ast; diff --git a/src/test/auxiliary/logging_right_crate.rs b/src/test/auxiliary/logging_right_crate.rs index fad70a917980d..bf4ab975cedd8 100644 --- a/src/test/auxiliary/logging_right_crate.rs +++ b/src/test/auxiliary/logging_right_crate.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] -#[phase(plugin, link)] extern crate log; +#[macro_use] extern crate log; pub fn foo() { fn death() -> int { panic!() } diff --git a/src/test/auxiliary/macro_reexport_2.rs b/src/test/auxiliary/macro_reexport_2.rs index 3b68d47c55861..f54e5e5c4e122 100644 --- a/src/test/auxiliary/macro_reexport_2.rs +++ b/src/test/auxiliary/macro_reexport_2.rs @@ -9,9 +9,8 @@ // except according to those terms. #![crate_type = "dylib"] -#![feature(phase)] #![macro_reexport(reexported)] -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_reexport_1; diff --git a/src/test/auxiliary/weak-lang-items.rs b/src/test/auxiliary/weak-lang-items.rs index 6a1f8588b60d7..39462fdc1e528 100644 --- a/src/test/auxiliary/weak-lang-items.rs +++ b/src/test/auxiliary/weak-lang-items.rs @@ -14,10 +14,9 @@ // it hasn't been defined just yet. Make sure we don't explode. #![no_std] -#![feature(phase)] #![crate_type = "rlib"] -#[phase(plugin, link)] +#[macro_use] extern crate core; struct A; diff --git a/src/test/bench/shootout-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs index 4f87171f5d3fa..0a6c197f5ed31 100644 --- a/src/test/bench/shootout-regex-dna.rs +++ b/src/test/bench/shootout-regex-dna.rs @@ -41,7 +41,7 @@ // ignore-stage1 // ignore-cross-compile #12102 -#![feature(macro_rules, phase, slicing_syntax)] +#![feature(macro_rules, plugin, slicing_syntax)] extern crate regex; diff --git a/src/test/compile-fail-fulldeps/gated-phase.rs b/src/test/compile-fail-fulldeps/gated-plugin.rs similarity index 86% rename from src/test/compile-fail-fulldeps/gated-phase.rs rename to src/test/compile-fail-fulldeps/gated-plugin.rs index 1f384b856334c..89090d5f38abe 100644 --- a/src/test/compile-fail-fulldeps/gated-phase.rs +++ b/src/test/compile-fail-fulldeps/gated-plugin.rs @@ -11,8 +11,8 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -#[phase(plugin)] -//~^ ERROR compile time crate loading is experimental and possibly buggy +#[plugin] #[no_link] +//~^ ERROR compiler plugins are experimental and possibly buggy extern crate macro_crate_test; fn main() {} diff --git a/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs b/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs index 5edaa78eeea38..11ae556395962 100644 --- a/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs +++ b/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs @@ -12,9 +12,9 @@ // ignore-stage1 // compile-flags: -D lint-me -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_group_plugin_test; fn lintme() { } //~ ERROR item is named 'lintme' diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs b/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs index 9eb39a9178c02..62007d6575a8d 100644 --- a/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs +++ b/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs @@ -11,10 +11,10 @@ // aux-build:lint_plugin_test.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] #![deny(test_lint)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } //~ ERROR item is named 'lintme' diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs b/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs index 46aa4b6b5b741..da51c047f57e1 100644 --- a/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs +++ b/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs @@ -12,9 +12,9 @@ // ignore-stage1 // compile-flags: -D test-lint -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } //~ ERROR item is named 'lintme' diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs index 329d3e86c052e..cf51958b53d8b 100644 --- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs +++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs @@ -11,10 +11,10 @@ // aux-build:lint_plugin_test.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] #![forbid(test_lint)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } //~ ERROR item is named 'lintme' diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs index 601faa22d77a0..9a36143f65c6a 100644 --- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs +++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs @@ -12,9 +12,9 @@ // ignore-stage1 // compile-flags: -F test-lint -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } //~ ERROR item is named 'lintme' diff --git a/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs b/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs index fc7664c480fdb..46eb4d4b2eff1 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs @@ -20,9 +20,9 @@ // editors, so instead he made a macro that expands into the embedded // ident form. -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate macro_crate_test; fn main() { diff --git a/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs similarity index 95% rename from src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs rename to src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs index 00aeb1c1bae8f..adcdba04cc782 100644 --- a/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs @@ -12,9 +12,7 @@ // ignore-stage1 // ignore-android -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_crate_test; fn main() { diff --git a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs index d4f286f20e8f7..1f44ac7cf9cae 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs @@ -14,8 +14,8 @@ // ignore-android // ignore-cross-compile gives a different error message -#![feature(phase)] -#[phase(plugin)] extern crate rlib_crate_test; +#![feature(plugin)] +#[plugin] #[no_link] extern crate rlib_crate_test; //~^ ERROR: plugin crate `rlib_crate_test` only found in rlib format, but must be available in dylib format fn main() {} diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs index 6a3b0b91ffe29..b5ff8b7155632 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs @@ -12,9 +12,7 @@ // ignore-stage1 // ignore-android -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_crate_test; fn main() { diff --git a/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs b/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs index 7a7eac7b70925..65657eea1efb0 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-unknown-crate.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate doesnt_exist; //~ ERROR can't find crate fn main() {} diff --git a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs index 302a64c5ed34b..cff2e5eaf8786 100644 --- a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs +++ b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs @@ -13,9 +13,9 @@ // ignore-android // error-pattern: plugin tried to register a new MacroRulesTT -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate macro_crate_MacroRulesTT; fn main() { } diff --git a/src/test/run-pass/phase-use-ignored.rs b/src/test/compile-fail/deprecated-phase.rs similarity index 87% rename from src/test/run-pass/phase-use-ignored.rs rename to src/test/compile-fail/deprecated-phase.rs index 5015e43fa3f34..1401494d987a2 100644 --- a/src/test/run-pass/phase-use-ignored.rs +++ b/src/test/compile-fail/deprecated-phase.rs @@ -8,11 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(phase)] - -#[phase(plugin)] -use std::mem; +#[phase(blah)] +//~^ ERROR #[phase] is deprecated +extern crate foo; fn main() {} - diff --git a/src/test/compile-fail/fail-no-dead-code-core.rs b/src/test/compile-fail/fail-no-dead-code-core.rs index 49a927b9879e4..6f75181c31cbc 100644 --- a/src/test/compile-fail/fail-no-dead-code-core.rs +++ b/src/test/compile-fail/fail-no-dead-code-core.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] #![deny(dead_code)] #![allow(unreachable_code)] -#[phase(link, plugin)] extern crate core; +#[macro_use] extern crate core; fn foo() { //~ ERROR function is never used diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 8e1723ddab24c..87bdb15f6edf7 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -13,7 +13,7 @@ // aux-build:stability_cfg1.rs // aux-build:stability_cfg2.rs -#![feature(globs, phase)] +#![feature(globs)] #![deny(unstable)] #![deny(deprecated)] #![deny(experimental)] @@ -23,7 +23,7 @@ mod cross_crate { extern crate stability_cfg1; extern crate stability_cfg2; //~ ERROR: use of experimental item - #[phase(plugin, link)] + #[macro_use] extern crate lint_stability; //~ ERROR: use of unmarked item use self::lint_stability::*; diff --git a/src/test/run-pass/deprecated-phase-syntax.rs b/src/test/compile-fail/no-link.rs similarity index 62% rename from src/test/run-pass/deprecated-phase-syntax.rs rename to src/test/compile-fail/no-link.rs index df835dab4d4e0..a9c2b6a942c65 100644 --- a/src/test/run-pass/deprecated-phase-syntax.rs +++ b/src/test/compile-fail/no-link.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] - -//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin) -#[phase(syntax, link)] -extern crate log; +#[no_link] +extern crate libc; fn main() { - debug!("foo"); + unsafe { + libc::abs(0); //~ ERROR Use of undeclared type or module `libc` + //~^ ERROR unresolved name `libc::abs` + } } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 35bd22880cef7..500305f597075 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -1,7 +1,6 @@ -#![feature(phase)] #![no_std] #![feature(globs)] -#[phase(plugin, link)] +#[macro_use] extern crate "std" as std; #[prelude_import] use std::prelude::v1::*; diff --git a/src/test/run-fail/rt-set-exit-status-panic.rs b/src/test/run-fail/rt-set-exit-status-panic.rs index e524a2432ac4e..fd7c3f8cc0e4b 100644 --- a/src/test/run-fail/rt-set-exit-status-panic.rs +++ b/src/test/run-fail/rt-set-exit-status-panic.rs @@ -10,8 +10,7 @@ // error-pattern:whatever -#![feature(phase)] -#[phase(plugin, link)] extern crate log; +#[macro_use] extern crate log; use std::os; fn main() { diff --git a/src/test/run-fail/rt-set-exit-status-panic2.rs b/src/test/run-fail/rt-set-exit-status-panic2.rs index 972c85e376e51..446ef6f97e297 100644 --- a/src/test/run-fail/rt-set-exit-status-panic2.rs +++ b/src/test/run-fail/rt-set-exit-status-panic2.rs @@ -10,8 +10,7 @@ // error-pattern:whatever -#![feature(phase)] -#[phase(plugin, link)] extern crate log; +#[macro_use] extern crate log; use std::os; use std::thread::Thread; diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs index bddf9b5a7ea59..39ece8a464a6f 100644 --- a/src/test/run-fail/rt-set-exit-status.rs +++ b/src/test/run-fail/rt-set-exit-status.rs @@ -10,8 +10,7 @@ // error-pattern:whatever -#![feature(phase)] -#[phase(plugin, link)] extern crate log; +#[macro_use] extern crate log; use std::os; fn main() { diff --git a/src/test/run-make/extern-diff-internal-name/test.rs b/src/test/run-make/extern-diff-internal-name/test.rs index ab1cf96999dce..11e042c8c4a06 100644 --- a/src/test/run-make/extern-diff-internal-name/test.rs +++ b/src/test/run-make/extern-diff-internal-name/test.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] - -#[phase(plugin, link)] +#[macro_use] extern crate foo; fn main() { diff --git a/src/test/run-make/lto-syntax-extension/main.rs b/src/test/run-make/lto-syntax-extension/main.rs index 2028710cbd2bc..a38b2cfb96287 100644 --- a/src/test/run-make/lto-syntax-extension/main.rs +++ b/src/test/run-make/lto-syntax-extension/main.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] - extern crate lib; -#[phase(plugin, link)] extern crate log; +#[macro_use] extern crate log; fn main() {} diff --git a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs index 08c9f8b4aa7d5..11e7da770291a 100644 --- a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs +++ b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs @@ -11,9 +11,9 @@ // ignore-stage1 // ignore-android // aux-build:issue_16723_multiple_items_syntax_ext.rs -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] extern crate issue_16723_multiple_items_syntax_ext; +#[plugin] #[no_link] extern crate issue_16723_multiple_items_syntax_ext; multiple_items!(); diff --git a/src/test/run-pass-fulldeps/lint-group-plugin.rs b/src/test/run-pass-fulldeps/lint-group-plugin.rs index 726670b5d7f93..7615b25f9e40c 100644 --- a/src/test/run-pass-fulldeps/lint-group-plugin.rs +++ b/src/test/run-pass-fulldeps/lint-group-plugin.rs @@ -12,9 +12,9 @@ // ignore-stage1 // ignore-pretty -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_group_plugin_test; fn lintme() { } //~ WARNING item is named 'lintme' diff --git a/src/test/run-pass-fulldeps/lint-plugin-cmdline.rs b/src/test/run-pass-fulldeps/lint-plugin-cmdline.rs index d3d1f1ea565a3..7144d2b0f1e71 100644 --- a/src/test/run-pass-fulldeps/lint-plugin-cmdline.rs +++ b/src/test/run-pass-fulldeps/lint-plugin-cmdline.rs @@ -12,9 +12,9 @@ // ignore-stage1 // compile-flags: -A test-lint -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } diff --git a/src/test/run-pass-fulldeps/lint-plugin.rs b/src/test/run-pass-fulldeps/lint-plugin.rs index 8c5269e227410..d11242f4fe643 100644 --- a/src/test/run-pass-fulldeps/lint-plugin.rs +++ b/src/test/run-pass-fulldeps/lint-plugin.rs @@ -12,9 +12,9 @@ // ignore-stage1 // ignore-pretty -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate lint_plugin_test; fn lintme() { } //~ WARNING item is named 'lintme' diff --git a/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs b/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs index 0afd76e1659c4..a8762234ad996 100644 --- a/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs +++ b/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs @@ -14,9 +14,9 @@ // Issue #15750: a macro that internally parses its input and then // uses `quote_expr!` to rearrange it should be hygiene-preserving. -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate macro_crate_test; fn main() { diff --git a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs index dd585ea979408..d943cf0457b4f 100644 --- a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs +++ b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs @@ -11,9 +11,9 @@ // aux-build:plugin_crate_outlive_expansion_phase.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate plugin_crate_outlive_expansion_phase; pub fn main() {} diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index 0f5e2cb3b6b46..4ffb8a3f74d4f 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -11,9 +11,9 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[macro_use] #[plugin] #[no_link] extern crate macro_crate_test; #[into_foo] diff --git a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs b/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs similarity index 94% rename from src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs rename to src/test/run-pass-fulldeps/plugin-link-does-resolve.rs index 47ff7d31df5f3..518d02e3d75bb 100644 --- a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs +++ b/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs @@ -15,9 +15,9 @@ // macro_crate_test will not compile on a cross-compiled target because // libsyntax is not compiled for it. -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin, link)] +#[plugin] extern crate macro_crate_test; fn main() { diff --git a/src/test/run-pass-fulldeps/roman-numerals-macro.rs b/src/test/run-pass-fulldeps/roman-numerals-macro.rs index 73a4a51f31c4e..d76766094ed77 100644 --- a/src/test/run-pass-fulldeps/roman-numerals-macro.rs +++ b/src/test/run-pass-fulldeps/roman-numerals-macro.rs @@ -11,9 +11,9 @@ // aux-build:roman_numerals.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate roman_numerals; pub fn main() { diff --git a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs index b3fae671c5266..1c74c8ad08eec 100644 --- a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs +++ b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs @@ -12,9 +12,9 @@ // aux-build:syntax-extension-with-dll-deps-2.rs // ignore-stage1 -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] +#[plugin] #[no_link] extern crate "syntax-extension-with-dll-deps-2" as extension; fn main() { diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index 3f6d6a02c7926..e3e0041050762 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -11,9 +11,7 @@ // ignore-android (FIXME #11419) // exec-env:RUST_LOG=info -#![feature(phase)] - -#[phase(plugin, link)] +#[macro_use] extern crate log; use log::{set_logger, Logger, LogRecord}; diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs index f87d92dc16f7f..e3bdbeb169295 100644 --- a/src/test/run-pass/conditional-debug-macro-off.rs +++ b/src/test/run-pass/conditional-debug-macro-off.rs @@ -11,8 +11,7 @@ // compile-flags: --cfg ndebug // exec-env:RUST_LOG=conditional-debug-macro-off=4 -#![feature(phase)] -#[phase(plugin, link)] +#[macro_use] extern crate log; pub fn main() { diff --git a/src/test/run-pass/issue-14330.rs b/src/test/run-pass/issue-14330.rs index bac846dfa203b..f983f233ee356 100644 --- a/src/test/run-pass/issue-14330.rs +++ b/src/test/run-pass/issue-14330.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] - -#[phase(plugin, link)] extern crate "std" as std2; +#[macro_use] extern crate "std" as std2; fn main() {} diff --git a/src/test/run-pass/logging-enabled-debug.rs b/src/test/run-pass/logging-enabled-debug.rs index 4b97d274fbae4..262d9b21eb48b 100644 --- a/src/test/run-pass/logging-enabled-debug.rs +++ b/src/test/run-pass/logging-enabled-debug.rs @@ -11,8 +11,7 @@ // compile-flags:--cfg ndebug // exec-env:RUST_LOG=logging-enabled-debug=debug -#![feature(phase)] -#[phase(plugin, link)] +#[macro_use] extern crate log; pub fn main() { diff --git a/src/test/run-pass/logging-enabled.rs b/src/test/run-pass/logging-enabled.rs index c4f7b1492ab57..372cdc401b549 100644 --- a/src/test/run-pass/logging-enabled.rs +++ b/src/test/run-pass/logging-enabled.rs @@ -10,8 +10,7 @@ // exec-env:RUST_LOG=logging-enabled=info -#![feature(phase)] -#[phase(plugin, link)] +#[macro_use] extern crate log; pub fn main() { diff --git a/src/test/run-pass/logging-separate-lines.rs b/src/test/run-pass/logging-separate-lines.rs index ebbe7fa65cdf8..0f13df644a1f7 100644 --- a/src/test/run-pass/logging-separate-lines.rs +++ b/src/test/run-pass/logging-separate-lines.rs @@ -12,9 +12,7 @@ // ignore-windows // exec-env:RUST_LOG=debug -#![feature(phase)] - -#[phase(plugin, link)] +#[macro_use] extern crate log; use std::io::Command; diff --git a/src/test/run-pass/macro-crate-def-only.rs b/src/test/run-pass/macro-crate-def-only.rs index 70080fcc3c91d..7505fa6e6841a 100644 --- a/src/test/run-pass/macro-crate-def-only.rs +++ b/src/test/run-pass/macro-crate-def-only.rs @@ -10,9 +10,7 @@ // aux-build:macro_crate_def_only.rs -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_crate_def_only; pub fn main() { diff --git a/src/test/run-pass/macro-crate-nonterminal-renamed.rs b/src/test/run-pass/macro-crate-nonterminal-renamed.rs index cf9a53f27be5d..cb919297b0406 100644 --- a/src/test/run-pass/macro-crate-nonterminal-renamed.rs +++ b/src/test/run-pass/macro-crate-nonterminal-renamed.rs @@ -11,9 +11,7 @@ // aux-build:macro_crate_nonterminal.rs // ignore-stage1 -#![feature(phase)] - -#[phase(plugin, link)] +#[macro_use] extern crate "macro_crate_nonterminal" as new_name; pub fn main() { diff --git a/src/test/run-pass/macro-crate-nonterminal.rs b/src/test/run-pass/macro-crate-nonterminal.rs index 8abf534ab1249..9882f806a9eea 100644 --- a/src/test/run-pass/macro-crate-nonterminal.rs +++ b/src/test/run-pass/macro-crate-nonterminal.rs @@ -11,9 +11,7 @@ // aux-build:macro_crate_nonterminal.rs // ignore-stage1 -#![feature(phase)] - -#[phase(plugin, link)] +#[macro_use] extern crate macro_crate_nonterminal; pub fn main() { diff --git a/src/test/run-pass/macro-export-inner-module.rs b/src/test/run-pass/macro-export-inner-module.rs index 88ca466b4afdf..ef22410751c0c 100644 --- a/src/test/run-pass/macro-export-inner-module.rs +++ b/src/test/run-pass/macro-export-inner-module.rs @@ -11,9 +11,7 @@ //aux-build:macro_export_inner_module.rs //ignore-stage1 -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_export_inner_module; pub fn main() { diff --git a/src/test/run-pass/macro-reexport.rs b/src/test/run-pass/macro-reexport.rs index bc3632e76ba49..9701610cbd964 100644 --- a/src/test/run-pass/macro-reexport.rs +++ b/src/test/run-pass/macro-reexport.rs @@ -12,9 +12,7 @@ // aux-build:macro_reexport_2.rs // ignore-stage1 -#![feature(phase)] - -#[phase(plugin)] +#[macro_use] #[no_link] extern crate macro_reexport_2; fn main() { diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index 2612483ded486..95f90ebbf8edf 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -10,8 +10,7 @@ // exec-env:RUST_LOG=rust-log-filter/f.o -#![feature(phase)] -#[phase(plugin,link)] +#[macro_use] extern crate log; use std::sync::mpsc::{channel, Sender, Receiver}; diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index 62b61c153c707..7d226aa942032 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -12,8 +12,7 @@ // ignore-android needs extra network permissions // exec-env:RUST_LOG=debug -#![feature(phase)] -#[phase(plugin, link)] +#[macro_use] extern crate log; extern crate libc; diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index b01cad43603a9..c04afffb12037 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase, lang_items)] +#![feature(lang_items)] #![no_std] -#[phase(plugin, link)] +#[macro_use] extern crate core; extern crate libc; -#[phase(plugin, link)] +#[macro_use] extern crate collections; use core::option::Option::Some; From 0816255c80ee3f2a8870ee5e4379e3739d8ed72e Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Thu, 1 Jan 2015 16:37:47 -0800 Subject: [PATCH 095/106] Move #[macro_reexport] to extern crate --- src/librustc/metadata/creader.rs | 1 + src/librustc/plugin/load.rs | 28 ++++++++++++- src/librustc_driver/driver.rs | 2 - src/libstd/lib.rs | 6 +-- src/libsyntax/ast.rs | 1 + src/libsyntax/ext/base.rs | 10 +++++ src/libsyntax/ext/expand.rs | 22 ++-------- src/libsyntax/ext/tt/reexport.rs | 41 ------------------- src/libsyntax/lib.rs | 1 - src/test/auxiliary/macro_reexport_2.rs | 3 +- .../macro-reexport-malformed-1.rs | 3 +- .../macro-reexport-malformed-2.rs | 3 +- .../macro-reexport-malformed-3.rs | 3 +- 13 files changed, 53 insertions(+), 71 deletions(-) delete mode 100644 src/libsyntax/ext/tt/reexport.rs diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index c7a8457c6d24a..d83bd8b922395 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -552,6 +552,7 @@ impl<'a> PluginMetadata<'a> { id: ast::DUMMY_NODE_ID, span: span, imported_from: imported_from, + export: false, // overridden in plugin/load.rs body: body, }); true diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index d17ef199aa1bd..93c97f6caa66a 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -17,8 +17,10 @@ use plugin::registry::Registry; use std::mem; use std::os; use std::dynamic_lib::DynamicLibrary; +use std::collections::HashSet; use syntax::ast; use syntax::attr; +use syntax::parse::token; use syntax::visit; use syntax::visit::Visitor; use syntax::attr::AttrMetaMethods; @@ -87,6 +89,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { // Parse the attributes relating to macro / plugin loading. let mut load_macros = false; let mut load_registrar = false; + let mut reexport = HashSet::new(); for attr in vi.attrs.iter() { let mut used = true; match attr.name().get() { @@ -96,6 +99,23 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } "plugin" => load_registrar = true, "macro_use" => load_macros = true, + "macro_reexport" => { + let names = match attr.meta_item_list() { + Some(names) => names, + None => { + self.sess.span_err(attr.span, "bad macro reexport"); + continue; + } + }; + + for name in names.iter() { + if let ast::MetaWord(ref name) = name.node { + reexport.insert(name.clone()); + } else { + self.sess.span_err(name.span, "bad macro reexport"); + } + } + } _ => used = false, } if used { @@ -116,7 +136,13 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } - self.plugins.macros.extend(macros.into_iter()); + for mut def in macros.into_iter() { + if reexport.contains(&token::get_ident(def.ident)) { + def.export = true; + } + self.plugins.macros.push(def); + } + if let Some((lib, symbol)) = registrar { self.dylink_registrar(vi, lib, symbol); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f23cddf833cc9..261d73b5bf07a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -275,8 +275,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, deriving_hash_type_parameter: sess.features.borrow().default_type_params, enable_quotes: sess.features.borrow().quote, recursion_limit: sess.recursion_limit.get(), - reexported_macros: syntax::ext::tt::reexport::gather(sess.diagnostic(), - &krate), }; let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, cfg, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3eda6d3374ed9..65c36d813f478 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -117,9 +117,6 @@ #![reexport_test_harness_main = "test_main"] -#![macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq, - unreachable, unimplemented, write, writeln, vec)] - #[cfg(all(test, stage0))] #[phase(plugin, link)] extern crate log; @@ -134,6 +131,8 @@ extern crate core; #[cfg(not(stage0))] #[macro_use] +#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq, + unreachable, unimplemented, write, writeln)] extern crate core; #[cfg(stage0)] @@ -142,6 +141,7 @@ extern crate "collections" as core_collections; #[cfg(not(stage0))] #[macro_use] +#[macro_reexport(vec)] extern crate "collections" as core_collections; extern crate "rand" as core_rand; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 36fc8a691dc30..e34060a73c154 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1708,6 +1708,7 @@ pub struct MacroDef { pub id: NodeId, pub span: Span, pub imported_from: Option, + pub export: bool, pub body: Vec, } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a06745967f0d..815159e94c82a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -16,6 +16,7 @@ use codemap; use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION}; use ext; use ext::expand; +use ext::tt::macro_rules; use parse; use parse::parser; use parse::token; @@ -568,6 +569,15 @@ impl<'a> ExtCtxt<'a> { } } } + + pub fn insert_macro(&mut self, def: ast::MacroDef) { + if def.export { + self.exported_macros.push(def.clone()); + } + let ext = macro_rules::compile(self, &def); + self.syntax_env.insert(def.ident.name, ext); + } + /// Emit `msg` attached to `sp`, and stop compilation immediately. /// /// `span_err` should be strongly preferred where-ever possible: diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d56df2d7fb4e0..6c2b0610fa037 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -17,7 +17,6 @@ use ast; use ast_util::path_to_ident; use ext::mtwt; use ext::build::AstBuilder; -use ext::tt::macro_rules; use attr; use attr::AttrMetaMethods; use codemap; @@ -636,14 +635,10 @@ pub fn expand_item_mac(it: P, id: ast::DUMMY_NODE_ID, span: it.span, imported_from: None, + export: attr::contains_name(it.attrs.as_slice(), "macro_export"), body: tts, }; - let ext = macro_rules::compile(fld.cx, &def); - fld.cx.syntax_env.insert(def.ident.name, ext); - - if attr::contains_name(def.attrs.as_slice(), "macro_export") { - fld.cx.exported_macros.push(def); - } + fld.cx.insert_macro(def); // macro_rules! has a side effect but expands to nothing. fld.cx.bt_pop(); @@ -1178,7 +1173,6 @@ pub struct ExpansionConfig { pub deriving_hash_type_parameter: bool, pub enable_quotes: bool, pub recursion_limit: uint, - pub reexported_macros: Vec, } impl ExpansionConfig { @@ -1188,7 +1182,6 @@ impl ExpansionConfig { deriving_hash_type_parameter: false, enable_quotes: false, recursion_limit: 64, - reexported_macros: vec![], } } } @@ -1202,15 +1195,8 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander::new(&mut cx); - for def in imported_macros.iter() { - let ext = macro_rules::compile(expander.cx, def); - expander.cx.syntax_env.insert(def.ident.name, ext); - - if expander.cx.ecfg.reexported_macros.iter() - .any(|e| e[] == token::get_ident(def.ident).get()) { - - expander.cx.exported_macros.push(def.clone()); - } + for def in imported_macros.into_iter() { + expander.cx.insert_macro(def); } for (name, extension) in user_exts.into_iter() { diff --git a/src/libsyntax/ext/tt/reexport.rs b/src/libsyntax/ext/tt/reexport.rs deleted file mode 100644 index 104f37872535c..0000000000000 --- a/src/libsyntax/ext/tt/reexport.rs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -//! Defines the crate attribute syntax for macro re-export. - -use ast; -use attr::AttrMetaMethods; -use diagnostic::SpanHandler; - -/// Return a vector of the names of all macros re-exported from the crate. -pub fn gather(diag: &SpanHandler, krate: &ast::Crate) -> Vec { - let usage = "malformed macro_reexport attribute, expected \ - #![macro_reexport(ident, ident, ...)]"; - - let mut reexported: Vec = vec!(); - for attr in krate.attrs.iter() { - if !attr.check_name("macro_reexport") { - continue; - } - - match attr.meta_item_list() { - None => diag.span_err(attr.span, usage), - Some(list) => for mi in list.iter() { - match mi.node { - ast::MetaWord(ref word) - => reexported.push(word.to_string()), - _ => diag.span_err(mi.span, usage), - } - } - } - } - - reexported -} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 774a9f61cf9af..b7bfd346d506b 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -111,6 +111,5 @@ pub mod ext { pub mod transcribe; pub mod macro_parser; pub mod macro_rules; - pub mod reexport; } } diff --git a/src/test/auxiliary/macro_reexport_2.rs b/src/test/auxiliary/macro_reexport_2.rs index f54e5e5c4e122..15d9f9cc9146d 100644 --- a/src/test/auxiliary/macro_reexport_2.rs +++ b/src/test/auxiliary/macro_reexport_2.rs @@ -10,7 +10,6 @@ #![crate_type = "dylib"] -#![macro_reexport(reexported)] - +#[macro_reexport(reexported)] #[macro_use] #[no_link] extern crate macro_reexport_1; diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs index ea3074db124d6..b9f754b2778bc 100644 --- a/src/test/compile-fail/macro-reexport-malformed-1.rs +++ b/src/test/compile-fail/macro-reexport-malformed-1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_reexport] //~ ERROR malformed macro_reexport attribute +#[macro_reexport] //~ ERROR bad macro reexport +extern crate std; fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs index 3daa089d2c677..9ced5be8479ba 100644 --- a/src/test/compile-fail/macro-reexport-malformed-2.rs +++ b/src/test/compile-fail/macro-reexport-malformed-2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_reexport="foo"] //~ ERROR malformed macro_reexport attribute +#[macro_reexport="foo"] //~ ERROR bad macro reexport +extern crate std; fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs index b3c0bf95ce981..c8bd0a0509cdc 100644 --- a/src/test/compile-fail/macro-reexport-malformed-3.rs +++ b/src/test/compile-fail/macro-reexport-malformed-3.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_reexport(foo="bar")] //~ ERROR malformed macro_reexport attribute +#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport +extern crate std; fn main() { } From aa69cbde8279cd90457454c3b3f40a36e8a79dff Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 12:50:45 -0800 Subject: [PATCH 096/106] Allow selective macro import --- src/librustc/metadata/creader.rs | 5 ++- src/librustc/plugin/load.rs | 33 ++++++++++++++++--- src/libsyntax/ast.rs | 1 + src/libsyntax/ext/base.rs | 6 ++-- src/libsyntax/ext/expand.rs | 1 + src/test/auxiliary/macro_reexport_2_no_use.rs | 15 +++++++++ src/test/auxiliary/two_macros.rs | 19 +++++++++++ src/test/compile-fail/empty-macro-use.rs | 19 +++++++++++ .../macro-reexport-not-locally-visible.rs | 20 +++++++++++ src/test/compile-fail/macro-use-bad-args-1.rs | 15 +++++++++ src/test/compile-fail/macro-use-bad-args-2.rs | 15 +++++++++ src/test/compile-fail/macro-use-wrong-name.rs | 19 +++++++++++ src/test/compile-fail/missing-macro-use.rs | 18 ++++++++++ .../macro-reexport-no-intermediate-use.rs | 20 +++++++++++ src/test/run-pass/macro-use-all-and-none.rs | 21 ++++++++++++ src/test/run-pass/macro-use-all.rs | 20 +++++++++++ src/test/run-pass/macro-use-both.rs | 20 +++++++++++ src/test/run-pass/macro-use-one.rs | 19 +++++++++++ src/test/run-pass/two-macro-use.rs | 21 ++++++++++++ 19 files changed, 299 insertions(+), 8 deletions(-) create mode 100644 src/test/auxiliary/macro_reexport_2_no_use.rs create mode 100644 src/test/auxiliary/two_macros.rs create mode 100644 src/test/compile-fail/empty-macro-use.rs create mode 100644 src/test/compile-fail/macro-reexport-not-locally-visible.rs create mode 100644 src/test/compile-fail/macro-use-bad-args-1.rs create mode 100644 src/test/compile-fail/macro-use-bad-args-2.rs create mode 100644 src/test/compile-fail/macro-use-wrong-name.rs create mode 100644 src/test/compile-fail/missing-macro-use.rs create mode 100644 src/test/run-pass/macro-reexport-no-intermediate-use.rs create mode 100644 src/test/run-pass/macro-use-all-and-none.rs create mode 100644 src/test/run-pass/macro-use-all.rs create mode 100644 src/test/run-pass/macro-use-both.rs create mode 100644 src/test/run-pass/macro-use-one.rs create mode 100644 src/test/run-pass/two-macro-use.rs diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index d83bd8b922395..171bfd74a816b 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -552,7 +552,10 @@ impl<'a> PluginMetadata<'a> { id: ast::DUMMY_NODE_ID, span: span, imported_from: imported_from, - export: false, // overridden in plugin/load.rs + // overridden in plugin/load.rs + export: false, + use_locally: false, + body: body, }); true diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 93c97f6caa66a..3a9083828fc70 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -87,8 +87,8 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } // Parse the attributes relating to macro / plugin loading. - let mut load_macros = false; let mut load_registrar = false; + let mut macro_selection = Some(HashSet::new()); // None => load all let mut reexport = HashSet::new(); for attr in vi.attrs.iter() { let mut used = true; @@ -98,7 +98,22 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { #[macro_use], #[plugin], and/or #[no_link]"); } "plugin" => load_registrar = true, - "macro_use" => load_macros = true, + "macro_use" => { + let names = attr.meta_item_list(); + if names.is_none() { + // no names => load all + macro_selection = None; + } + if let (Some(sel), Some(names)) = (macro_selection.as_mut(), names) { + for name in names.iter() { + if let ast::MetaWord(ref name) = name.node { + sel.insert(name.clone()); + } else { + self.sess.span_err(name.span, "bad macro import"); + } + } + } + } "macro_reexport" => { let names = match attr.meta_item_list() { Some(names) => names, @@ -126,6 +141,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { let mut macros = vec![]; let mut registrar = None; + let load_macros = match macro_selection.as_ref() { + Some(sel) => sel.len() != 0 || reexport.len() != 0, + None => true, + }; + if load_macros || load_registrar { let pmd = self.reader.read_plugin_metadata(vi); if load_macros { @@ -137,9 +157,12 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } for mut def in macros.into_iter() { - if reexport.contains(&token::get_ident(def.ident)) { - def.export = true; - } + let name = token::get_ident(def.ident); + def.use_locally = match macro_selection.as_ref() { + None => true, + Some(sel) => sel.contains(&name), + }; + def.export = reexport.contains(&name); self.plugins.macros.push(def); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e34060a73c154..0f90e31c17eee 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1709,6 +1709,7 @@ pub struct MacroDef { pub span: Span, pub imported_from: Option, pub export: bool, + pub use_locally: bool, pub body: Vec, } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 815159e94c82a..91ae7396ea469 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -574,8 +574,10 @@ impl<'a> ExtCtxt<'a> { if def.export { self.exported_macros.push(def.clone()); } - let ext = macro_rules::compile(self, &def); - self.syntax_env.insert(def.ident.name, ext); + if def.use_locally { + let ext = macro_rules::compile(self, &def); + self.syntax_env.insert(def.ident.name, ext); + } } /// Emit `msg` attached to `sp`, and stop compilation immediately. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6c2b0610fa037..d3f2e0ea095b6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -636,6 +636,7 @@ pub fn expand_item_mac(it: P, span: it.span, imported_from: None, export: attr::contains_name(it.attrs.as_slice(), "macro_export"), + use_locally: true, body: tts, }; fld.cx.insert_macro(def); diff --git a/src/test/auxiliary/macro_reexport_2_no_use.rs b/src/test/auxiliary/macro_reexport_2_no_use.rs new file mode 100644 index 0000000000000..63142b0a69935 --- /dev/null +++ b/src/test/auxiliary/macro_reexport_2_no_use.rs @@ -0,0 +1,15 @@ +// Copyright 2015 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. + +#![crate_type = "dylib"] + +#[macro_reexport(reexported)] +#[no_link] +extern crate macro_reexport_1; diff --git a/src/test/auxiliary/two_macros.rs b/src/test/auxiliary/two_macros.rs new file mode 100644 index 0000000000000..39393b77f25f0 --- /dev/null +++ b/src/test/auxiliary/two_macros.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// force-host + +#![feature(macro_rules)] + +#[macro_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } diff --git a/src/test/compile-fail/empty-macro-use.rs b/src/test/compile-fail/empty-macro-use.rs new file mode 100644 index 0000000000000..fbf6287db9444 --- /dev/null +++ b/src/test/compile-fail/empty-macro-use.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use()] +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs new file mode 100644 index 0000000000000..c8e59f98d3cea --- /dev/null +++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:macro_reexport_1.rs +// ignore-stage1 + +#[macro_reexport(reexported)] +#[no_link] +extern crate macro_reexport_1; + +fn main() { + assert_eq!(reexported!(), 3u); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/macro-use-bad-args-1.rs b/src/test/compile-fail/macro-use-bad-args-1.rs new file mode 100644 index 0000000000000..a73c4adb71f9f --- /dev/null +++ b/src/test/compile-fail/macro-use-bad-args-1.rs @@ -0,0 +1,15 @@ +// Copyright 2015 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. + +#[macro_use(foo(bar))] //~ ERROR bad macro import +extern crate std; + +fn main() { +} diff --git a/src/test/compile-fail/macro-use-bad-args-2.rs b/src/test/compile-fail/macro-use-bad-args-2.rs new file mode 100644 index 0000000000000..31efe857605b4 --- /dev/null +++ b/src/test/compile-fail/macro-use-bad-args-2.rs @@ -0,0 +1,15 @@ +// Copyright 2015 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. + +#[macro_use(foo="bar")] //~ ERROR bad macro import +extern crate std; + +fn main() { +} diff --git a/src/test/compile-fail/macro-use-wrong-name.rs b/src/test/compile-fail/macro-use-wrong-name.rs new file mode 100644 index 0000000000000..4e0486f0db7e9 --- /dev/null +++ b/src/test/compile-fail/macro-use-wrong-name.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one)] +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/missing-macro-use.rs b/src/test/compile-fail/missing-macro-use.rs new file mode 100644 index 0000000000000..0153d71fb268f --- /dev/null +++ b/src/test/compile-fail/missing-macro-use.rs @@ -0,0 +1,18 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/run-pass/macro-reexport-no-intermediate-use.rs b/src/test/run-pass/macro-reexport-no-intermediate-use.rs new file mode 100644 index 0000000000000..77ef9421273ef --- /dev/null +++ b/src/test/run-pass/macro-reexport-no-intermediate-use.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:macro_reexport_1.rs +// aux-build:macro_reexport_2_no_use.rs +// ignore-stage1 + +#[macro_use] #[no_link] +extern crate macro_reexport_2_no_use; + +fn main() { + assert_eq!(reexported!(), 3u); +} diff --git a/src/test/run-pass/macro-use-all-and-none.rs b/src/test/run-pass/macro-use-all-and-none.rs new file mode 100644 index 0000000000000..b46910290a8a0 --- /dev/null +++ b/src/test/run-pass/macro-use-all-and-none.rs @@ -0,0 +1,21 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use] +#[macro_use()] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-all.rs b/src/test/run-pass/macro-use-all.rs new file mode 100644 index 0000000000000..cf72d2c623044 --- /dev/null +++ b/src/test/run-pass/macro-use-all.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-both.rs b/src/test/run-pass/macro-use-both.rs new file mode 100644 index 0000000000000..4b0814bef04b8 --- /dev/null +++ b/src/test/run-pass/macro-use-both.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one, macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-one.rs b/src/test/run-pass/macro-use-one.rs new file mode 100644 index 0000000000000..7911fec94da8b --- /dev/null +++ b/src/test/run-pass/macro-use-one.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_two!(); +} diff --git a/src/test/run-pass/two-macro-use.rs b/src/test/run-pass/two-macro-use.rs new file mode 100644 index 0000000000000..51c0b75e8fbe6 --- /dev/null +++ b/src/test/run-pass/two-macro-use.rs @@ -0,0 +1,21 @@ +// Copyright 2015 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one)] +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} From c9f0ff3813a662197e262e64edb8302d2b4a3e75 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 13:39:05 -0800 Subject: [PATCH 097/106] Reserve the keyword 'macro' --- src/doc/reference.md | 12 ++++++------ src/etc/vim/syntax/rust.vim | 2 +- src/librustc_back/svh.rs | 14 +++++++------- src/librustc_driver/pretty.rs | 4 ++-- src/libsyntax/ext/expand.rs | 12 ++++++------ src/libsyntax/feature_gate.rs | 4 ++-- src/libsyntax/fold.rs | 8 ++++---- src/libsyntax/parse/parser.rs | 6 +++--- src/libsyntax/parse/token.rs | 1 + src/libsyntax/show_span.rs | 4 ++-- src/libsyntax/visit.rs | 12 ++++++------ src/test/compile-fail/macro-keyword.rs | 15 +++++++++++++++ 12 files changed, 55 insertions(+), 39 deletions(-) create mode 100644 src/test/compile-fail/macro-keyword.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index d793028526052..e2134cdebef74 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -193,12 +193,12 @@ grammar as double-quoted strings. Other tokens have exact rules given. | break | const | continue | crate | do | | else | enum | extern | false | final | | fn | for | if | impl | in | -| let | loop | match | mod | move | -| mut | offsetof | override | priv | pub | -| pure | ref | return | sizeof | static | -| self | struct | super | true | trait | -| type | typeof | unsafe | unsized | use | -| virtual | where | while | yield | +| let | loop | macro | match | mod | +| move | mut | offsetof | override | priv | +| pub | pure | ref | return | sizeof | +| static | self | struct | super | true | +| trait | type | typeof | unsafe | unsized | +| use | virtual | where | while | yield | Each of these keywords has special meaning in its grammar, and all of them are diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 5588152a244c4..270459e8880f5 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -56,7 +56,7 @@ syn match rustMacroRepeatCount ".\?[*+]" contained syn match rustMacroVariable "$\w\+" " Reserved (but not yet used) keywords {{{2 -syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override +syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro " Built-in types {{{2 syn keyword rustType int uint float char bool u8 u16 u32 u64 f32 diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 2ae88aa4476f7..86bd74d3f85e5 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -327,11 +327,11 @@ mod svh_visitor { impl<'a, 'v> Visitor<'v> for StrictVersionHashVisitor<'a> { - fn visit_mac(&mut self, macro: &Mac) { + fn visit_mac(&mut self, mac: &Mac) { // macro invocations, namely macro_rules definitions, // *can* appear as items, even in the expanded crate AST. - if macro_name(macro).get() == "macro_rules" { + if macro_name(mac).get() == "macro_rules" { // Pretty-printing definition to a string strips out // surface artifacts (currently), such as the span // information, yielding a content-based hash. @@ -341,7 +341,7 @@ mod svh_visitor { // trees might be faster. Implementing this is far // easier in short term. let macro_defn_as_string = pprust::to_string(|pp_state| { - pp_state.print_mac(macro, token::Paren) + pp_state.print_mac(mac, token::Paren) }); macro_defn_as_string.hash(self.st); } else { @@ -349,14 +349,14 @@ mod svh_visitor { // invocation at this stage except `macro_rules!`. panic!("reached macro somehow: {}", pprust::to_string(|pp_state| { - pp_state.print_mac(macro, token::Paren) + pp_state.print_mac(mac, token::Paren) })); } - visit::walk_mac(self, macro); + visit::walk_mac(self, mac); - fn macro_name(macro: &Mac) -> token::InternedString { - match ¯o.node { + fn macro_name(mac: &Mac) -> token::InternedString { + match &mac.node { &MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => { let s = path.segments[]; assert_eq!(s.len(), 1); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d972229e7c75b..61fd7d16ab7dd 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -484,8 +484,8 @@ impl fold::Folder for ReplaceBodyWithLoop { // in general the pretty printer processes unexpanded code, so // we override the default `fold_mac` method which panics. - fn fold_mac(&mut self, _macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(_macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d3f2e0ea095b6..8decedf289af3 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -986,8 +986,8 @@ impl<'a> Folder for IdentRenamer<'a> { ctxt: mtwt::apply_renames(self.renames, id.ctxt), } } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } @@ -1023,8 +1023,8 @@ impl<'a> Folder for PatIdentRenamer<'a> { _ => unreachable!() }) } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } @@ -1286,8 +1286,8 @@ struct MacroExterminator<'a>{ } impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> { - fn visit_mac(&mut self, macro: &ast::Mac) { - self.sess.span_diagnostic.span_bug(macro.span, + fn visit_mac(&mut self, mac: &ast::Mac) { + self.sess.span_diagnostic.span_bug(mac.span, "macro exterminator: expected AST \ with no macro invocations"); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e41fef4e77870..28265b8e7c221 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -165,8 +165,8 @@ struct MacroVisitor<'a> { } impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { - fn visit_mac(&mut self, macro: &ast::Mac) { - let ast::MacInvocTT(ref path, _, _) = macro.node; + fn visit_mac(&mut self, mac: &ast::Mac) { + let ast::MacInvocTT(ref path, _, _) = mac.node; let id = path.segments.last().unwrap().identifier; if id == token::str_to_ident("macro_rules") { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6b5d333ef8fc1..aa4b04b28799a 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -194,13 +194,13 @@ pub trait Folder : Sized { noop_fold_local(l, self) } - fn fold_mac(&mut self, _macro: Mac) -> Mac { + fn fold_mac(&mut self, _mac: Mac) -> Mac { panic!("fold_mac disabled by default"); // NB: see note about macros above. // if you really want a folder that // works on macros, use this // definition in your trait impl: - // fold::noop_fold_mac(_macro, self) + // fold::noop_fold_mac(_mac, self) } fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf { @@ -1487,8 +1487,8 @@ mod test { fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident { token::str_to_ident("zz") } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5539abb16b461..24011df7acb9b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3881,13 +3881,13 @@ impl<'a> Parser<'a> { &mut stmts, &mut expr); } - StmtMac(macro, MacStmtWithoutBraces) => { + StmtMac(mac, MacStmtWithoutBraces) => { // statement macro without braces; might be an // expr depending on whether a semicolon follows match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(macro, + node: StmtMac(mac, MacStmtWithSemicolon), span: span, })); @@ -3896,7 +3896,7 @@ impl<'a> Parser<'a> { _ => { let e = self.mk_mac_expr(span.lo, span.hi, - macro.and_then(|m| m.node)); + mac.and_then(|m| m.node)); let e = self.parse_dot_or_call_expr_with(e); self.handle_expression_like_statement( diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index a653190cffdef..094aacf3207fc 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -574,6 +574,7 @@ declare_special_idents_and_keywords! { (56, Abstract, "abstract"); (57, Final, "final"); (58, Override, "override"); + (59, Macro, "macro"); } } diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 354ba854b101a..e7c9101ebc657 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -28,8 +28,8 @@ impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> { visit::walk_expr(self, e); } - fn visit_mac(&mut self, macro: &ast::Mac) { - visit::walk_mac(self, macro); + fn visit_mac(&mut self, mac: &ast::Mac) { + visit::walk_mac(self, mac); } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 054a288a69e6d..888c0251d7652 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -115,13 +115,13 @@ pub trait Visitor<'v> : Sized { fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { walk_explicit_self(self, es) } - fn visit_mac(&mut self, _macro: &'v Mac) { + fn visit_mac(&mut self, _mac: &'v Mac) { panic!("visit_mac disabled by default"); // NB: see note about macros above. // if you really want a visitor that // works on macros, use this // definition in your trait impl: - // visit::walk_mac(self, _macro) + // visit::walk_mac(self, _mac) } fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) @@ -334,7 +334,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_trait_item(method) } } - ItemMac(ref macro) => visitor.visit_mac(macro), + ItemMac(ref mac) => visitor.visit_mac(mac), } for attr in item.attrs.iter() { visitor.visit_attribute(attr); @@ -546,7 +546,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_pat(&**postpattern) } } - PatMac(ref macro) => visitor.visit_mac(macro), + PatMac(ref mac) => visitor.visit_mac(mac), } } @@ -746,7 +746,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => { visitor.visit_expr(&**expression) } - StmtMac(ref macro, _) => visitor.visit_mac(&**macro), + StmtMac(ref mac, _) => visitor.visit_mac(&**mac), } } @@ -893,7 +893,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) } - ExprMac(ref macro) => visitor.visit_mac(macro), + ExprMac(ref mac) => visitor.visit_mac(mac), ExprParen(ref subexpression) => { visitor.visit_expr(&**subexpression) } diff --git a/src/test/compile-fail/macro-keyword.rs b/src/test/compile-fail/macro-keyword.rs new file mode 100644 index 0000000000000..9d4ec9c176cce --- /dev/null +++ b/src/test/compile-fail/macro-keyword.rs @@ -0,0 +1,15 @@ +// Copyright 2015 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. + +fn macro() { //~ ERROR `macro` is a reserved keyword +} + +pub fn main() { +} From 416137eb3186c05b7a601e94cde354e9b3ec0a78 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 14:44:21 -0800 Subject: [PATCH 098/106] Modernize macro_rules! invocations macro_rules! is like an item that defines a macro. Other items don't have a trailing semicolon, or use a paren-delimited body. If there's an argument for matching the invocation syntax, e.g. parentheses for an expr macro, then I think that applies more strongly to the *inner* delimiters on the LHS, wrapping the individual argument patterns. --- src/grammar/verify.rs | 4 +- src/libcollections/slice.rs | 8 +- src/libcollections/str.rs | 8 +- src/libcollections/string.rs | 4 +- src/libcore/result.rs | 4 +- src/libcore/str/mod.rs | 9 +- src/libcoretest/num/int_macros.rs | 4 +- src/libcoretest/num/uint_macros.rs | 5 +- src/librand/distributions/mod.rs | 4 +- src/librand/distributions/range.rs | 8 +- src/librand/isaac.rs | 141 +++++++++--------- src/librustc/lint/context.rs | 36 +++-- src/librustc/middle/const_eval.rs | 4 +- src/librustc/middle/ty.rs | 4 +- src/librustc_back/sha2.rs | 8 +- src/librustc_back/target/mod.rs | 8 +- src/librustc_trans/trans/context.rs | 12 +- src/libstd/path/posix.rs | 68 ++++----- src/libstd/path/windows.rs | 76 +++++----- src/libsyntax/ext/deriving/cmp/eq.rs | 4 +- src/libsyntax/ext/deriving/cmp/ord.rs | 4 +- src/libsyntax/ext/deriving/mod.rs | 8 +- src/libsyntax/ext/tt/macro_rules.rs | 4 +- src/libterm/terminfo/parser/compiled.rs | 4 +- src/test/auxiliary/lint_stability.rs | 12 +- src/test/auxiliary/macro_crate_def_only.rs | 4 +- src/test/auxiliary/macro_crate_test.rs | 4 +- .../auxiliary/macro_export_inner_module.rs | 4 +- src/test/bench/core-std.rs | 5 +- src/test/compile-fail/gated-macro-rules.rs | 2 +- .../compile-fail/infinite-macro-expansion.rs | 8 +- src/test/compile-fail/issue-15167.rs | 2 +- src/test/compile-fail/issue-6596.rs | 4 +- .../liveness-return-last-stmt-semi.rs | 2 +- .../compile-fail/macro-inner-attributes.rs | 4 +- .../compile-fail/macro-match-nonterminal.rs | 2 +- .../compile-fail/macro-outer-attributes.rs | 4 +- .../compile-fail/macros-no-semicolon-items.rs | 1 - .../compile-fail/method-macro-backtrace.rs | 6 +- .../compile-fail/pattern-macro-hygiene.rs | 2 +- .../borrowck-macro-interaction-issue-6304.rs | 4 +- src/test/run-pass/cleanup-rvalue-scopes.rs | 8 +- src/test/run-pass/const-binops.rs | 4 +- src/test/run-pass/core-run-destroy.rs | 4 +- src/test/run-pass/deriving-in-macro.rs | 4 +- src/test/run-pass/exponential-notation.rs | 4 +- src/test/run-pass/html-literals.rs | 8 +- src/test/run-pass/ifmt.rs | 4 +- src/test/run-pass/intrinsics-math.rs | 4 +- src/test/run-pass/issue-15189.rs | 4 +- src/test/run-pass/issue-15221.rs | 10 +- src/test/run-pass/issue-5060.rs | 4 +- src/test/run-pass/issue-7911.rs | 4 +- src/test/run-pass/issue-8709.rs | 8 +- src/test/run-pass/issue-8851.rs | 4 +- src/test/run-pass/issue-9110.rs | 4 +- src/test/run-pass/issue-9129.rs | 4 +- src/test/run-pass/issue-9737.rs | 4 +- src/test/run-pass/lambda-var-hygiene.rs | 4 +- src/test/run-pass/let-var-hygiene.rs | 5 +- src/test/run-pass/macro-2.rs | 4 +- src/test/run-pass/macro-interpolation.rs | 4 +- ...vocation-in-count-expr-fixed-array-type.rs | 4 +- src/test/run-pass/macro-multiple-items.rs | 4 +- src/test/run-pass/macro-nt-list.rs | 8 +- src/test/run-pass/macro-of-higher-order.rs | 6 +- src/test/run-pass/macro-pat.rs | 20 +-- src/test/run-pass/macro-stmt.rs | 12 +- src/test/run-pass/macro-with-attrs1.rs | 4 +- src/test/run-pass/macro-with-attrs2.rs | 4 +- .../macro-with-braces-in-expr-position.rs | 2 +- src/test/run-pass/match-in-macro.rs | 4 +- src/test/run-pass/match-var-hygiene.rs | 4 +- src/test/run-pass/non-built-in-quote.rs | 2 +- .../run-pass/syntax-extension-source-utils.rs | 2 +- .../typeck-macro-interaction-issue-8852.rs | 4 +- 76 files changed, 361 insertions(+), 331 deletions(-) diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index ad271d230904e..2e8bce3f5064b 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -268,7 +268,7 @@ fn main() { assert!(rustc_tok.sp == antlr_tok.sp, "{} and {} have different spans", rustc_tok, antlr_tok); - macro_rules! matches ( + macro_rules! matches { ( $($x:pat),+ ) => ( match rustc_tok.tok { $($x => match antlr_tok.tok { @@ -284,7 +284,7 @@ fn main() { ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok) } ) - ); + } matches!( token::Literal(token::Byte(..), _), diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..6a9abfbd22ee5 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -2460,13 +2460,13 @@ mod tests { #[test] fn test_show() { - macro_rules! test_show_vec( + macro_rules! test_show_vec { ($x:expr, $x_str:expr) => ({ let (x, x_str) = ($x, $x_str); assert_eq!(format!("{}", x), x_str); assert_eq!(format!("{}", x.as_slice()), x_str); }) - ); + } let empty: Vec = vec![]; test_show_vec!(empty, "[]"); test_show_vec!(vec![1i], "[1]"); @@ -2486,12 +2486,12 @@ mod tests { #[test] fn test_vec_default() { - macro_rules! t ( + macro_rules! t { ($ty:ty) => {{ let v: $ty = Default::default(); assert!(v.is_empty()); }} - ); + } t!(&[int]); t!(Vec); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ecf17820d2d8f..69403ccd88be8 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1838,7 +1838,9 @@ mod tests { #[test] fn test_is_utf16() { use unicode::str::is_utf16; - macro_rules! pos ( ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } }); + macro_rules! pos { + ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } + } // non-surrogates pos!(&[0x0000], @@ -1858,7 +1860,9 @@ mod tests { &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); // negative tests - macro_rules! neg ( ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } }); + macro_rules! neg { + ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } + } neg!( // surrogate + regular unit diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index e7451331908ae..8fe636f8cd392 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -182,7 +182,7 @@ impl String { let byte = unsafe_get(v, i); i += 1; - macro_rules! error(() => ({ + macro_rules! error { () => ({ unsafe { if subseqidx != i_ { res.as_mut_vec().push_all(v[subseqidx..i_]); @@ -190,7 +190,7 @@ impl String { subseqidx = i; res.as_mut_vec().push_all(REPLACEMENT); } - })); + })} if byte < 128u8 { // subseqidx handles this diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 7135faaa76516..3ed0116c28911 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -220,9 +220,9 @@ //! //! ``` //! # #![feature(macro_rules)] -//! macro_rules! try( +//! macro_rules! try { //! ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) -//! ); +//! } //! # fn main() { } //! ``` //! diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d069744f8da54..02887024d00cb 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -948,17 +948,18 @@ fn run_utf8_validation_iterator(iter: &mut slice::Iter) let old = *iter; // restore the iterator we had at the start of this codepoint. - macro_rules! err (() => { { + macro_rules! err { () => {{ *iter = old; return Err(Utf8Error::InvalidByte(whole.len() - iter.as_slice().len())) - } }); - macro_rules! next ( () => { + }}} + + macro_rules! next { () => { match iter.next() { Some(a) => *a, // we needed data, but there was none: error! None => return Err(Utf8Error::TooShort), } - }); + }} let first = match iter.next() { Some(&b) => b, diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 965ffde70970b..b98432e26b215 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! int_module (($T:ty, $T_i:ident) => ( +macro_rules! int_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; @@ -203,4 +203,4 @@ mod tests { } } -)); +)} diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index eff238c816eee..04d8fb15cf5aa 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! uint_module (($T:ty, $T_i:ident) => ( +macro_rules! uint_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; @@ -123,4 +123,5 @@ mod tests { assert!(5u.checked_div(0) == None); } } -)); + +)} diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index e684fcf40f7b3..2fdba8a6c4f96 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -297,7 +297,7 @@ mod tests { // it doesn't do weird things to the RNG (so 0 maps to 0, 1 to // 1, internally; modulo a modulo operation). - macro_rules! t ( + macro_rules! t { ($items:expr, $expected:expr) => {{ let mut items = $items; let wc = WeightedChoice::new(items.as_mut_slice()); @@ -309,7 +309,7 @@ mod tests { assert_eq!(wc.ind_sample(&mut rng), val) } }} - ); + } t!(vec!(Weighted { weight: 1, item: 10i}), [10]); diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index 558fa20125675..1038009522d67 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -182,7 +182,7 @@ mod tests { #[test] fn test_integers() { let mut rng = ::test::rng(); - macro_rules! t ( + macro_rules! t { ($($ty:ty),*) => {{ $( let v: &[($ty, $ty)] = &[(0, 10), @@ -199,7 +199,7 @@ mod tests { } )* }} - ); + } t!(i8, i16, i32, i64, int, u8, u16, u32, u64, uint) } @@ -207,7 +207,7 @@ mod tests { #[test] fn test_floats() { let mut rng = ::test::rng(); - macro_rules! t ( + macro_rules! t { ($($ty:ty),*) => {{ $( let v: &[($ty, $ty)] = &[(0.0, 100.0), @@ -225,7 +225,7 @@ mod tests { } )* }} - ); + } t!(f32, f64) } diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 53ae242c5e245..698730302b9ca 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -69,7 +69,7 @@ impl IsaacRng { let mut g = a; let mut h = a; - macro_rules! mix( + macro_rules! mix { () => {{ a^=b<<11; d+=a; b+=c; b^=c>>2; e+=b; c+=d; @@ -80,14 +80,14 @@ impl IsaacRng { g^=h<<8; b+=g; h+=a; h^=a>>9; c+=h; a+=b; }} - ); + } for _ in range(0u, 4) { mix!(); } if use_rsl { - macro_rules! memloop ( + macro_rules! memloop { ($arr:expr) => {{ for i in range_step(0, RAND_SIZE as uint, 8) { a+=$arr[i ]; b+=$arr[i+1]; @@ -101,7 +101,7 @@ impl IsaacRng { self.mem[i+6]=g; self.mem[i+7]=h; } }} - ); + } memloop!(self.rsl); memloop!(self.mem); @@ -129,41 +129,42 @@ impl IsaacRng { static MIDPOINT: uint = (RAND_SIZE / 2) as uint; - macro_rules! ind (($x:expr) => { - self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] - }); + macro_rules! ind { + ($x:expr) => ( self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] ) + } let r = [(0, MIDPOINT), (MIDPOINT, 0)]; for &(mr_offset, m2_offset) in r.iter() { - macro_rules! rngstepp( + macro_rules! rngstepp { ($j:expr, $shift:expr) => {{ - let base = $j; - let mix = a << $shift as uint; + let base = $j; + let mix = a << $shift as uint; - let x = self.mem[base + mr_offset]; - a = (a ^ mix) + self.mem[base + m2_offset]; - let y = ind!(x) + a + b; - self.mem[base + mr_offset] = y; + let x = self.mem[base + mr_offset]; + a = (a ^ mix) + self.mem[base + m2_offset]; + let y = ind!(x) + a + b; + self.mem[base + mr_offset] = y; - b = ind!(y >> RAND_SIZE_LEN as uint) + x; - self.rsl[base + mr_offset] = b; - }} - ); - macro_rules! rngstepn( + b = ind!(y >> RAND_SIZE_LEN as uint) + x; + self.rsl[base + mr_offset] = b; + }} + } + + macro_rules! rngstepn { ($j:expr, $shift:expr) => {{ - let base = $j; - let mix = a >> $shift as uint; + let base = $j; + let mix = a >> $shift as uint; - let x = self.mem[base + mr_offset]; - a = (a ^ mix) + self.mem[base + m2_offset]; - let y = ind!(x) + a + b; - self.mem[base + mr_offset] = y; + let x = self.mem[base + mr_offset]; + a = (a ^ mix) + self.mem[base + m2_offset]; + let y = ind!(x) + a + b; + self.mem[base + mr_offset] = y; - b = ind!(y >> RAND_SIZE_LEN as uint) + x; - self.rsl[base + mr_offset] = b; - }} - ); + b = ind!(y >> RAND_SIZE_LEN as uint) + x; + self.rsl[base + mr_offset] = b; + }} + } for i in range_step(0u, MIDPOINT, 4) { rngstepp!(i + 0, 13); @@ -294,15 +295,15 @@ impl Isaac64Rng { /// of `rsl` as a seed, otherwise construct one algorithmically (not /// randomly). fn init(&mut self, use_rsl: bool) { - macro_rules! init ( + macro_rules! init { ($var:ident) => ( let mut $var = 0x9e3779b97f4a7c13; ) - ); + } init!(a); init!(b); init!(c); init!(d); init!(e); init!(f); init!(g); init!(h); - macro_rules! mix( + macro_rules! mix { () => {{ a-=e; f^=h>>9; h+=a; b-=f; g^=a<<9; a+=b; @@ -313,14 +314,14 @@ impl Isaac64Rng { g-=c; d^=f>>17; f+=g; h-=d; e^=g<<14; g+=h; }} - ); + } for _ in range(0u, 4) { mix!(); } if use_rsl { - macro_rules! memloop ( + macro_rules! memloop { ($arr:expr) => {{ for i in range(0, RAND_SIZE_64 / 8).map(|i| i * 8) { a+=$arr[i ]; b+=$arr[i+1]; @@ -334,7 +335,7 @@ impl Isaac64Rng { self.mem[i+6]=g; self.mem[i+7]=h; } }} - ); + } memloop!(self.rsl); memloop!(self.mem); @@ -359,49 +360,51 @@ impl Isaac64Rng { let mut b = self.b + self.c; const MIDPOINT: uint = RAND_SIZE_64 / 2; const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; - macro_rules! ind ( + macro_rules! ind { ($x:expr) => { *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1)) } - ); + } for &(mr_offset, m2_offset) in MP_VEC.iter() { for base in range(0, MIDPOINT / 4).map(|i| i * 4) { - macro_rules! rngstepp( + macro_rules! rngstepp { ($j:expr, $shift:expr) => {{ - let base = base + $j; - let mix = a ^ (a << $shift as uint); - let mix = if $j == 0 {!mix} else {mix}; - - unsafe { - let x = *self.mem.get_unchecked(base + mr_offset); - a = mix + *self.mem.get_unchecked(base + m2_offset); - let y = ind!(x) + a + b; - *self.mem.get_unchecked_mut(base + mr_offset) = y; - - b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.get_unchecked_mut(base + mr_offset) = b; - } - }} - ); - macro_rules! rngstepn( + let base = base + $j; + let mix = a ^ (a << $shift as uint); + let mix = if $j == 0 {!mix} else {mix}; + + unsafe { + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); + let y = ind!(x) + a + b; + *self.mem.get_unchecked_mut(base + mr_offset) = y; + + b = ind!(y >> RAND_SIZE_64_LEN) + x; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; + } + }} + } + + macro_rules! rngstepn { ($j:expr, $shift:expr) => {{ - let base = base + $j; - let mix = a ^ (a >> $shift as uint); - let mix = if $j == 0 {!mix} else {mix}; - - unsafe { - let x = *self.mem.get_unchecked(base + mr_offset); - a = mix + *self.mem.get_unchecked(base + m2_offset); - let y = ind!(x) + a + b; - *self.mem.get_unchecked_mut(base + mr_offset) = y; - - b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.get_unchecked_mut(base + mr_offset) = b; - } - }} - ); + let base = base + $j; + let mix = a ^ (a >> $shift as uint); + let mix = if $j == 0 {!mix} else {mix}; + + unsafe { + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); + let y = ind!(x) + a + b; + *self.mem.get_unchecked_mut(base + mr_offset) = y; + + b = ind!(y >> RAND_SIZE_64_LEN) + x; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; + } + }} + } + rngstepp!(0u, 21); rngstepn!(1u, 5); rngstepp!(2u, 12); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 69e5b4889c288..c070bed2be23d 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -167,21 +167,27 @@ impl LintStore { } pub fn register_builtin(&mut self, sess: Option<&Session>) { - macro_rules! add_builtin ( ( $sess:ident, $($name:ident),*, ) => ( - {$( - self.register_pass($sess, false, box builtin::$name as LintPassObject); - )*} - )); - - macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => ( - {$( - self.register_pass($sess, false, box builtin::$name::new() as LintPassObject); - )*} - )); - - macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => ( - self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); - )); + macro_rules! add_builtin { + ($sess:ident, $($name:ident),*,) => ( + {$( + self.register_pass($sess, false, box builtin::$name as LintPassObject); + )*} + ) + } + + macro_rules! add_builtin_with_new { + ($sess:ident, $($name:ident),*,) => ( + {$( + self.register_pass($sess, false, box builtin::$name::new() as LintPassObject); + )*} + ) + } + + macro_rules! add_lint_group { + ($sess:ident, $name:expr, $($lint:ident),*) => ( + self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); + ) + } add_builtin!(sess, HardwiredLints, diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 6671f0f72f674..f50d629dae789 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -503,7 +503,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result ( $intermediate_ty:ty, @@ -524,7 +524,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result Err("can't cast this type".to_string()) }) - ); + } eval_const_expr_partial(tcx, &**base) .and_then(|val| define_casts!(val, { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5834844382207..b1098c5d9f7a1 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6237,8 +6237,8 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - return state.result(); fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, state: &mut sip::SipState) { - macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } ); - macro_rules! hash( ($e:expr) => { $e.hash(state) } ); + macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } } + macro_rules! hash { ($e:expr) => { $e.hash(state) } } let region = |&: state: &mut sip::SipState, r: Region| { match r { diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 1e55f442fb9ac..d606c5158d0f7 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -346,12 +346,12 @@ impl Engine256State { // Sha-512 and Sha-256 use basically the same calculations which are implemented // by these macros. Inlining the calculations seems to result in better generated code. - macro_rules! schedule_round( ($t:expr) => ( + macro_rules! schedule_round { ($t:expr) => ( w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16]; ) - ); + } - macro_rules! sha2_round( + macro_rules! sha2_round { ($A:ident, $B:ident, $C:ident, $D:ident, $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => ( { @@ -360,7 +360,7 @@ impl Engine256State { $H += sum0($A) + maj($A, $B, $C); } ) - ); + } read_u32v_be(w.slice_mut(0, 16), data); diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index d53f97c3a0423..f14583bb9aa81 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -239,7 +239,7 @@ impl Target { options: Default::default(), }; - macro_rules! key ( + macro_rules! key { ($key_name:ident) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(name[]).map(|o| o.as_string() @@ -257,7 +257,7 @@ impl Target { ) ); } ); - ); + } key!(cpu); key!(linker); @@ -305,7 +305,7 @@ impl Target { } // this would use a match if stringify! were allowed in pattern position - macro_rules! load_specific ( + macro_rules! load_specific { ( $($name:ident),+ ) => ( { let target = target.replace("-", "_"); @@ -326,7 +326,7 @@ impl Target { } } ) - ); + } load_specific!( x86_64_unknown_linux_gnu, diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index e5a0e2e9234d5..b121dbec011c9 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -741,7 +741,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option { - macro_rules! ifn ( + macro_rules! ifn { ($name:expr fn() -> $ret:expr) => ( if *key == $name { let f = base::decl_cdecl_fn( @@ -759,10 +759,10 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option (Type::struct_(ccx, &[$($field_ty),*], false)) - ); + } let i8p = Type::i8p(ccx); let void = Type::void(ccx); @@ -883,7 +883,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option $ret:expr) => ( if unsafe { llvm::LLVMVersionMinor() >= 4 } { // The `if key == $name` is already in ifn! @@ -896,7 +896,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option t_f32); compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64); diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index ae82e201cb855..a78dfe3edceda 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -558,7 +558,7 @@ mod tests { t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar"); t!(b"/", filename_display, ""); - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -573,7 +573,7 @@ mod tests { assert!(mo.as_slice() == $exp); } ) - ); + } t!("foo", "foo"); t!(b"foo\x80", "foo\u{FFFD}"); @@ -585,7 +585,7 @@ mod tests { #[test] fn test_display() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr, $expf:expr) => ( { let path = Path::new($path); @@ -595,7 +595,7 @@ mod tests { assert!(f == $expf); } ) - ); + } t!(b"foo", "foo", "foo"); t!(b"foo/bar", "foo/bar", "bar"); @@ -608,7 +608,7 @@ mod tests { #[test] fn test_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $exp:expr) => ( { let path = Path::new($path); @@ -629,7 +629,7 @@ mod tests { assert!(path.$op() == $exp); } ); - ); + } t!(v: b"a/b/c", filename, Some(b"c")); t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF")); @@ -692,7 +692,7 @@ mod tests { #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -703,7 +703,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a/b/c", ".."); t!(s: "/a/b/c", "d"); @@ -713,7 +713,7 @@ mod tests { #[test] fn test_push_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -722,7 +722,7 @@ mod tests { assert!(p.as_str() == Some($exp)); } ) - ); + } t!(s: "a/b/c", "d", "a/b/c/d"); t!(s: "/a/b/c", "d", "/a/b/c/d"); @@ -734,7 +734,7 @@ mod tests { #[test] fn test_push_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -749,7 +749,7 @@ mod tests { assert!(p.as_vec() == $exp); } ) - ); + } t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e"); t!(s: "a/b/c", ["d", "/e"], "/e"); @@ -762,7 +762,7 @@ mod tests { #[test] fn test_pop() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $left:expr, $right:expr) => ( { let mut p = Path::new($path); @@ -779,7 +779,7 @@ mod tests { assert!(result == $right); } ) - ); + } t!(b: b"a/b/c", b"a/b", true); t!(b: b"a", b".", true); @@ -818,7 +818,7 @@ mod tests { #[test] fn test_join_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -827,7 +827,7 @@ mod tests { assert!(res.as_str() == Some($exp)); } ) - ); + } t!(s: "a/b/c", "..", "a/b"); t!(s: "/a/b/c", "d", "/a/b/c/d"); @@ -839,7 +839,7 @@ mod tests { #[test] fn test_join_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -854,7 +854,7 @@ mod tests { assert!(res.as_vec() == $exp); } ) - ); + } t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e"); t!(s: "a/b/c", ["..", "d"], "a/b/d"); @@ -917,7 +917,7 @@ mod tests { #[test] fn test_setters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; @@ -938,7 +938,7 @@ mod tests { assert!(p1 == p2.$with(arg)); } ) - ); + } t!(v: b"a/b/c", set_filename, with_filename, b"d"); t!(v: b"/", set_filename, with_filename, b"foo"); @@ -961,7 +961,7 @@ mod tests { #[test] fn test_getters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; @@ -992,7 +992,7 @@ mod tests { assert!(path.extension() == $ext); } ) - ); + } t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None); t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None); @@ -1031,7 +1031,7 @@ mod tests { #[test] fn test_is_absolute() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $abs:expr, $rel:expr) => ( { let path = Path::new($path); @@ -1039,7 +1039,7 @@ mod tests { assert_eq!(path.is_relative(), $rel); } ) - ); + } t!(s: "a/b/c", false, true); t!(s: "/a/b/c", true, false); t!(s: "a", false, true); @@ -1052,7 +1052,7 @@ mod tests { #[test] fn test_is_ancestor_of() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $dest:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1060,7 +1060,7 @@ mod tests { assert_eq!(path.is_ancestor_of(&dest), $exp); } ) - ); + } t!(s: "a/b/c", "a/b/c/d", true); t!(s: "a/b/c", "a/b/c", true); @@ -1086,7 +1086,7 @@ mod tests { #[test] fn test_ends_with_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $child:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1101,7 +1101,7 @@ mod tests { assert_eq!(path.ends_with_path(&child), $exp); } ) - ); + } t!(s: "a/b/c", "c", true); t!(s: "a/b/c", "d", false); @@ -1125,7 +1125,7 @@ mod tests { #[test] fn test_path_relative_from() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $other:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1134,7 +1134,7 @@ mod tests { assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp); } ) - ); + } t!(s: "a/b/c", "a/b", Some("c")); t!(s: "a/b/c", "a/b/d", Some("../c")); @@ -1170,7 +1170,7 @@ mod tests { #[test] fn test_components_iter() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1196,7 +1196,7 @@ mod tests { assert_eq!(comps, exp) } ) - ); + } t!(b: b"a/b/c", [b"a", b"b", b"c"]); t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]); @@ -1216,7 +1216,7 @@ mod tests { #[test] fn test_str_components() { - macro_rules! t( + macro_rules! t { (b: $arg:expr, $exp:expr) => ( { let path = Path::new($arg); @@ -1228,7 +1228,7 @@ mod tests { assert_eq!(comps, exp); } ) - ); + } t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]); t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]); diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index cf8bc0e6242b3..30ed07446a400 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1149,7 +1149,7 @@ mod tests { #[test] fn test_parse_prefix() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = $path; @@ -1159,7 +1159,7 @@ mod tests { "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res); } ) - ); + } t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5))); t!("\\\\", None); @@ -1348,7 +1348,7 @@ mod tests { #[test] fn test_display() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr, $expf:expr) => ( { let path = Path::new($path); @@ -1358,7 +1358,7 @@ mod tests { assert_eq!(f, $expf); } ) - ); + } t!("foo", "foo", "foo"); t!("foo\\bar", "foo\\bar", "bar"); @@ -1367,7 +1367,7 @@ mod tests { #[test] fn test_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $exp:expr) => ( { let path = $path; @@ -1390,7 +1390,7 @@ mod tests { assert!(path.$op() == $exp); } ) - ); + } t!(v: b"a\\b\\c", filename, Some(b"c")); t!(s: "a\\b\\c", filename_str, "c"); @@ -1490,7 +1490,7 @@ mod tests { #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -1501,7 +1501,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a\\b\\c", ".."); t!(s: "\\a\\b\\c", "d"); @@ -1525,7 +1525,7 @@ mod tests { #[test] fn test_push_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -1534,7 +1534,7 @@ mod tests { assert_eq!(p.as_str(), Some($exp)); } ) - ); + } t!(s: "a\\b\\c", "d", "a\\b\\c\\d"); t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d"); @@ -1577,7 +1577,7 @@ mod tests { #[test] fn test_push_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -1592,7 +1592,7 @@ mod tests { assert_eq!(p.as_vec(), $exp); } ) - ); + } t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e"); t!(s: "a\\b\\c", ["d", "\\e"], "\\e"); @@ -1606,7 +1606,7 @@ mod tests { #[test] fn test_pop() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $left:expr, $right:expr) => ( { let pstr = $path; @@ -1627,7 +1627,7 @@ mod tests { assert!(result == $right); } ) - ); + } t!(s: "a\\b\\c", "a\\b", true); t!(s: "a", ".", true); @@ -1695,7 +1695,7 @@ mod tests { #[test] fn test_join_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1704,7 +1704,7 @@ mod tests { assert_eq!(res.as_str(), Some($exp)); } ) - ); + } t!(s: "a\\b\\c", "..", "a\\b"); t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d"); @@ -1718,7 +1718,7 @@ mod tests { #[test] fn test_join_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1733,7 +1733,7 @@ mod tests { assert_eq!(res.as_vec(), $exp); } ) - ); + } t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e"); t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d"); @@ -1746,7 +1746,7 @@ mod tests { #[test] fn test_with_helpers() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $arg:expr, $res:expr) => ( { let pstr = $path; @@ -1759,7 +1759,7 @@ mod tests { pstr, stringify!($op), arg, exp, res.as_str().unwrap()); } ) - ); + } t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d"); t!(s: ".", with_filename, "foo", "foo"); @@ -1831,7 +1831,7 @@ mod tests { #[test] fn test_setters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; @@ -1852,7 +1852,7 @@ mod tests { assert!(p1 == p2.$with(arg)); } ) - ); + } t!(v: b"a\\b\\c", set_filename, with_filename, b"d"); t!(v: b"\\", set_filename, with_filename, b"foo"); @@ -1876,7 +1876,7 @@ mod tests { #[test] fn test_getters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; @@ -1907,7 +1907,7 @@ mod tests { assert!(path.extension() == $ext); } ) - ); + } t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None); t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None); @@ -1942,7 +1942,7 @@ mod tests { #[test] fn test_is_absolute() { - macro_rules! t( + macro_rules! t { ($path:expr, $abs:expr, $vol:expr, $cwd:expr, $rel:expr) => ( { let path = Path::new($path); @@ -1961,7 +1961,7 @@ mod tests { path.as_str().unwrap(), rel, b); } ) - ); + } t!("a\\b\\c", false, false, false, true); t!("\\a\\b\\c", false, true, false, false); t!("a", false, false, false, true); @@ -1982,7 +1982,7 @@ mod tests { #[test] fn test_is_ancestor_of() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $dest:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1994,7 +1994,7 @@ mod tests { path.as_str().unwrap(), dest.as_str().unwrap(), exp, res); } ) - ); + } t!(s: "a\\b\\c", "a\\b\\c\\d", true); t!(s: "a\\b\\c", "a\\b\\c", true); @@ -2085,7 +2085,7 @@ mod tests { #[test] fn test_ends_with_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $child:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2093,7 +2093,7 @@ mod tests { assert_eq!(path.ends_with_path(&child), $exp); } ); - ); + } t!(s: "a\\b\\c", "c", true); t!(s: "a\\b\\c", "d", false); @@ -2117,7 +2117,7 @@ mod tests { #[test] fn test_path_relative_from() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $other:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2130,7 +2130,7 @@ mod tests { res.as_ref().and_then(|x| x.as_str())); } ) - ); + } t!(s: "a\\b\\c", "a\\b", Some("c")); t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c")); @@ -2251,7 +2251,7 @@ mod tests { #[test] fn test_str_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2265,7 +2265,7 @@ mod tests { assert_eq!(comps, exp); } ); - ); + } t!(s: b"a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\c", ["a", "b", "c"]); @@ -2309,7 +2309,7 @@ mod tests { #[test] fn test_components_iter() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2321,7 +2321,7 @@ mod tests { assert_eq!(comps, exp); } ) - ); + } t!(s: "a\\b\\c", [b"a", b"b", b"c"]); t!(s: ".", [b"."]); @@ -2330,7 +2330,7 @@ mod tests { #[test] fn test_make_non_verbatim() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2339,7 +2339,7 @@ mod tests { assert!(make_non_verbatim(&path) == exp); } ) - ); + } t!(r"\a\b\c", Some(r"\a\b\c")); t!(r"a\b\c", Some(r"a\b\c")); diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 7a67fab820de5..1b1bc6d281a2f 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -61,7 +61,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, cx, span, substr) } - macro_rules! md ( + macro_rules! md { ($name:expr, $f:ident) => { { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); @@ -77,7 +77,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, }) } } } - ); + } let trait_def = TraitDef { span: span, diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index c02416bfbea3a..7353ddc172015 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -27,7 +27,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, push: F) where F: FnOnce(P), { - macro_rules! md ( + macro_rules! md { ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); @@ -43,7 +43,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, }) } } } - ); + } let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"])); let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"], diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 14b19fee3df5e..e72c83b67c89b 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -71,9 +71,11 @@ pub fn expand_meta_derive(cx: &mut ExtCtxt, MetaNameValue(ref tname, _) | MetaList(ref tname, _) | MetaWord(ref tname) => { - macro_rules! expand(($func:path) => ($func(cx, titem.span, - &**titem, item, - |i| push.call_mut((i,))))); + macro_rules! expand { + ($func:path) => ($func(cx, titem.span, &**titem, item, + |i| push.call_mut((i,)))) + } + match tname.get() { "Clone" => expand!(clone::expand_deriving_clone), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index cf0d2c6474b2c..9837c8088fa45 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -38,8 +38,8 @@ impl<'a> ParserAnyMacro<'a> { /// Make sure we don't have any tokens left to parse, so we don't /// silently drop anything. `allow_semi` is so that "optional" /// semicolons at the end of normal expressions aren't complained - /// about e.g. the semicolon in `macro_rules! kapow( () => { - /// panic!(); } )` doesn't get picked up by .parse_expr(), but it's + /// about e.g. the semicolon in `macro_rules! kapow { () => { + /// panic!(); } }` doesn't get picked up by .parse_expr(), but it's /// allowed to be there. fn ensure_complete_parse(&self, allow_semi: bool) { let mut parser = self.parser.borrow_mut(); diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index fe96d7b8b7d01..5f0111c7d7a84 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -160,12 +160,12 @@ pub static stringnames: &'static[&'static str] = &[ "cbt", "_", "cr", "csr", "tb /// Parse a compiled terminfo entry, using long capability names if `longnames` is true pub fn parse(file: &mut io::Reader, longnames: bool) -> Result, String> { - macro_rules! try( ($e:expr) => ( + macro_rules! try { ($e:expr) => ( match $e { Ok(e) => e, Err(e) => return Err(format!("{}", e)) } - ) ); + ) } let bnames; let snames; diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 5ef1acae6c7ed..5eb6b0de3de94 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -180,16 +180,16 @@ pub struct FrozenTupleStruct(pub int); pub struct LockedTupleStruct(pub int); #[macro_export] -macro_rules! macro_test( +macro_rules! macro_test { () => (deprecated()); -); +} #[macro_export] -macro_rules! macro_test_arg( +macro_rules! macro_test_arg { ($func:expr) => ($func); -); +} #[macro_export] -macro_rules! macro_test_arg_nested( +macro_rules! macro_test_arg_nested { ($func:ident) => (macro_test_arg!($func())); -); +} diff --git a/src/test/auxiliary/macro_crate_def_only.rs b/src/test/auxiliary/macro_crate_def_only.rs index ad3e72f5fa221..c323eb0c44624 100644 --- a/src/test/auxiliary/macro_crate_def_only.rs +++ b/src/test/auxiliary/macro_crate_def_only.rs @@ -11,6 +11,6 @@ #![feature(macro_rules)] #[macro_export] -macro_rules! make_a_5( +macro_rules! make_a_5 { () => (5) -); +} diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index b82cfcbc8fcb2..418a7c6e538ed 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -24,9 +24,9 @@ use syntax::ptr::P; use rustc::plugin::Registry; #[macro_export] -macro_rules! exported_macro (() => (2i)); +macro_rules! exported_macro { () => (2i) } -macro_rules! unexported_macro (() => (3i)); +macro_rules! unexported_macro { () => (3i) } #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/test/auxiliary/macro_export_inner_module.rs b/src/test/auxiliary/macro_export_inner_module.rs index 9b4b1ceb5c1e7..fb98637811d72 100644 --- a/src/test/auxiliary/macro_export_inner_module.rs +++ b/src/test/auxiliary/macro_export_inner_module.rs @@ -12,7 +12,7 @@ pub mod inner { #[macro_export] - macro_rules! foo( + macro_rules! foo { () => (1) - ); + } } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index ee7c442da195c..21e55384f46bf 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -28,11 +28,12 @@ fn main() { let argv = os::args(); let _tests = argv.slice(1, argv.len()); - macro_rules! bench ( + macro_rules! bench { ($id:ident) => (maybe_run_test(argv.as_slice(), stringify!($id).to_string(), - $id))); + $id)) + } bench!(shift_push); bench!(read_line); diff --git a/src/test/compile-fail/gated-macro-rules.rs b/src/test/compile-fail/gated-macro-rules.rs index ae2f03fd5f798..dea0c60d91b7f 100644 --- a/src/test/compile-fail/gated-macro-rules.rs +++ b/src/test/compile-fail/gated-macro-rules.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! foo(() => ()); +macro_rules! foo { () => () } //~^ ERROR: macro definitions are not stable enough for use fn main() {} diff --git a/src/test/compile-fail/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 22ac2eb1f7d5d..22011f192356b 100644 --- a/src/test/compile-fail/infinite-macro-expansion.rs +++ b/src/test/compile-fail/infinite-macro-expansion.rs @@ -10,11 +10,9 @@ #![feature(macro_rules)] -macro_rules! recursive( - () => ( - recursive!() //~ ERROR recursion limit reached while expanding the macro `recursive` - ) - ); +macro_rules! recursive { + () => (recursive!()) //~ ERROR recursion limit reached while expanding the macro `recursive` +} fn main() { recursive!() diff --git a/src/test/compile-fail/issue-15167.rs b/src/test/compile-fail/issue-15167.rs index 300831b100773..cb10791973340 100644 --- a/src/test/compile-fail/issue-15167.rs +++ b/src/test/compile-fail/issue-15167.rs @@ -17,7 +17,7 @@ #![feature(macro_rules)] -macro_rules! f(() => (n)) +macro_rules! f { () => (n) } fn main() -> (){ for n in range(0i, 1) { diff --git a/src/test/compile-fail/issue-6596.rs b/src/test/compile-fail/issue-6596.rs index 3222b2cd53719..b237b4259184f 100644 --- a/src/test/compile-fail/issue-6596.rs +++ b/src/test/compile-fail/issue-6596.rs @@ -12,11 +12,11 @@ // error-pattern: unexpected token -macro_rules! e( +macro_rules! e { ($inp:ident) => ( $nonexistent ); -); +} fn main() { e!(foo); diff --git a/src/test/compile-fail/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index e92faa6bdaf6e..cdcb0859ed950 100644 --- a/src/test/compile-fail/liveness-return-last-stmt-semi.rs +++ b/src/test/compile-fail/liveness-return-last-stmt-semi.rs @@ -12,7 +12,7 @@ #![feature(macro_rules)] -macro_rules! test ( () => { fn foo() -> int { 1i; } } ); +macro_rules! test { () => { fn foo() -> int { 1i; } } } //~^ ERROR not all control paths return a value //~^^ HELP consider removing this semicolon diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index f64b7be50e307..8d2f49ecc7f53 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -10,9 +10,9 @@ #![feature(macro_rules)] -macro_rules! test ( ($nm:ident, +macro_rules! test { ($nm:ident, #[$a:meta], - $i:item) => (mod $nm { #![$a] $i }); ); + $i:item) => (mod $nm { #![$a] $i }); } test!(a, #[cfg(qux)], diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 150187aa07d3c..8bfaac1770d96 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! test ( ($a, $b) => (()); ); //~ ERROR Cannot transcribe +macro_rules! test { ($a, $b) => (()); } //~ ERROR Cannot transcribe fn main() { test!() diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs index 6d59c203d14bd..4f2c097eca94f 100644 --- a/src/test/compile-fail/macro-outer-attributes.rs +++ b/src/test/compile-fail/macro-outer-attributes.rs @@ -10,9 +10,9 @@ #![feature(macro_rules)] -macro_rules! test ( ($nm:ident, +macro_rules! test { ($nm:ident, #[$a:meta], - $i:item) => (mod $nm { #[$a] $i }); ); + $i:item) => (mod $nm { #[$a] $i }); } test!(a, #[cfg(qux)], diff --git a/src/test/compile-fail/macros-no-semicolon-items.rs b/src/test/compile-fail/macros-no-semicolon-items.rs index f1f31a99e970a..314292085dfe6 100644 --- a/src/test/compile-fail/macros-no-semicolon-items.rs +++ b/src/test/compile-fail/macros-no-semicolon-items.rs @@ -12,4 +12,3 @@ macro_rules! foo() //~ ERROR semicolon fn main() { } - diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index 747b4815ac2ae..56087c79799f6 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -12,9 +12,9 @@ #![feature(macro_rules)] -macro_rules! make_method ( ($name:ident) => ( - fn $name(&self) { } -)); +macro_rules! make_method { + ($name:ident) => ( fn $name(&self) { } ) +} struct S; diff --git a/src/test/compile-fail/pattern-macro-hygiene.rs b/src/test/compile-fail/pattern-macro-hygiene.rs index 3322fecf950c1..64f810c1c95e7 100644 --- a/src/test/compile-fail/pattern-macro-hygiene.rs +++ b/src/test/compile-fail/pattern-macro-hygiene.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! foo ( () => ( x ) ); +macro_rules! foo { () => ( x ) } fn main() { let foo!() = 2; diff --git a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs index 822db63971e21..bd42cc94a3393 100644 --- a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs +++ b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs @@ -24,12 +24,12 @@ pub enum Bar { impl Foo { fn elaborate_stm(&mut self, s: Box) -> Box { - macro_rules! declare( + macro_rules! declare { ($id:expr, $rest:expr) => ({ self.check_id($id); box Bar::Bar2($id, $rest) }) - ); + } match s { box Bar::Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)), _ => panic!() diff --git a/src/test/run-pass/cleanup-rvalue-scopes.rs b/src/test/run-pass/cleanup-rvalue-scopes.rs index 42f6914e081a3..fe74956fd1e40 100644 --- a/src/test/run-pass/cleanup-rvalue-scopes.rs +++ b/src/test/run-pass/cleanup-rvalue-scopes.rs @@ -61,7 +61,7 @@ impl Drop for AddFlags { } } -macro_rules! end_of_block( +macro_rules! end_of_block { ($pat:pat, $expr:expr) => ( { println!("end_of_block({})", stringify!({let $pat = $expr;})); @@ -74,9 +74,9 @@ macro_rules! end_of_block( check_flags(1); } ) -); +} -macro_rules! end_of_stmt( +macro_rules! end_of_stmt { ($pat:pat, $expr:expr) => ( { println!("end_of_stmt({})", stringify!($expr)); @@ -91,7 +91,7 @@ macro_rules! end_of_stmt( check_flags(0); } ) -); +} pub fn main() { diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index cac805189b82e..51647aebcf85d 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -10,14 +10,14 @@ #![feature(macro_rules)] -macro_rules! assert_approx_eq( +macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) -); +} static A: int = -4 + 3; static A2: uint = 3 + 3; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index c1db8a6eb13f4..33564af2d7d20 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -26,9 +26,9 @@ use std::str; use std::sync::mpsc::channel; use std::thread::Thread; -macro_rules! succeed( ($e:expr) => ( +macro_rules! succeed { ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } -) ); +) } fn test_destroy_once() { let mut p = sleeper(); diff --git a/src/test/run-pass/deriving-in-macro.rs b/src/test/run-pass/deriving-in-macro.rs index 97f6ee341a71f..162de18f581ab 100644 --- a/src/test/run-pass/deriving-in-macro.rs +++ b/src/test/run-pass/deriving-in-macro.rs @@ -10,14 +10,14 @@ #![feature(macro_rules)] -macro_rules! define_vec ( +macro_rules! define_vec { () => ( mod foo { #[derive(PartialEq)] pub struct bar; } ) -); +} define_vec!(); diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index 38d1093762432..6addbf693548f 100644 --- a/src/test/run-pass/exponential-notation.rs +++ b/src/test/run-pass/exponential-notation.rs @@ -15,7 +15,9 @@ use std::num::strconv::SignificantDigits::DigMax; use std::num::strconv::SignFormat::{SignAll, SignNeg}; use std::num::strconv::float_to_str_common as to_string; -macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } }); +macro_rules! t { + ($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } } +} pub fn main() { // Basic usage diff --git a/src/test/run-pass/html-literals.rs b/src/test/run-pass/html-literals.rs index 0d56f28e8fae7..6f6a429db172e 100644 --- a/src/test/run-pass/html-literals.rs +++ b/src/test/run-pass/html-literals.rs @@ -27,13 +27,13 @@ left. */ use HTMLFragment::{tag, text}; -macro_rules! html ( +macro_rules! html { ( $($body:tt)* ) => ( parse_node!( []; []; $($body)* ) ) -); +} -macro_rules! parse_node ( +macro_rules! parse_node { ( [:$head:ident ($(:$head_nodes:expr),*) $(:$tags:ident ($(:$tag_nodes:expr),*))*]; @@ -85,7 +85,7 @@ macro_rules! parse_node ( ); ( []; [:$e:expr]; ) => ( $e ); -); +} pub fn main() { let _page = html! ( diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 1efae89f66563..6f050e7db05f4 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -37,7 +37,9 @@ impl fmt::Show for C { } } -macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) }); +macro_rules! t { + ($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) } +} pub fn main() { // Various edge cases without formats diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 9f2fe155cdf95..4c86cb0049af6 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -11,14 +11,14 @@ #![feature(globs, macro_rules, intrinsics)] -macro_rules! assert_approx_eq( +macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use std::num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); }) -); +} mod rusti { extern "rust-intrinsic" { diff --git a/src/test/run-pass/issue-15189.rs b/src/test/run-pass/issue-15189.rs index 01c96b7563a75..60083c254805d 100644 --- a/src/test/run-pass/issue-15189.rs +++ b/src/test/run-pass/issue-15189.rs @@ -12,7 +12,9 @@ #![feature(macro_rules)] -macro_rules! third(($e:expr)=>({let x = 2; $e[x]})); +macro_rules! third { + ($e:expr) => ({let x = 2; $e[x]}) +} fn main() { let x = vec!(10u,11u,12u,13u); diff --git a/src/test/run-pass/issue-15221.rs b/src/test/run-pass/issue-15221.rs index a11b34e476275..f778af7ebcf51 100644 --- a/src/test/run-pass/issue-15221.rs +++ b/src/test/run-pass/issue-15221.rs @@ -10,11 +10,13 @@ #![feature(macro_rules)] -macro_rules! inner ( - ($e:pat ) => ($e)); +macro_rules! inner { + ($e:pat ) => ($e) +} -macro_rules! outer ( - ($e:pat ) => (inner!($e))); +macro_rules! outer { + ($e:pat ) => (inner!($e)) +} fn main() { let outer!(g1) = 13i; diff --git a/src/test/run-pass/issue-5060.rs b/src/test/run-pass/issue-5060.rs index 0cd25bc2c719b..18ebe35dcdf7d 100644 --- a/src/test/run-pass/issue-5060.rs +++ b/src/test/run-pass/issue-5060.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! print_hd_tl ( +macro_rules! print_hd_tl { ($field_hd:ident, $($field_tl:ident),+) => ({ print!("{}", stringify!($field_hd)); print!("::["); @@ -21,7 +21,7 @@ macro_rules! print_hd_tl ( // FIXME: #9970 print!("{}", "]\n"); }) -); +} pub fn main() { print_hd_tl!(x, y, z, w) diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index c69b66f4dbd76..8cc507d88558a 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -27,7 +27,7 @@ trait Test { fn get_mut(&mut self) -> &mut FooBar; } -macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => ( +macro_rules! generate_test { ($type_:path, $slf:ident, $field:expr) => ( impl Test for $type_ { fn get_immut(&$slf) -> &FooBar { &$field as &FooBar @@ -37,7 +37,7 @@ macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => ( &mut $field as &mut FooBar } } -)); +)} generate_test!(Foo, self, self.bar); diff --git a/src/test/run-pass/issue-8709.rs b/src/test/run-pass/issue-8709.rs index d4ea05004a064..4e7d42f6b0bd7 100644 --- a/src/test/run-pass/issue-8709.rs +++ b/src/test/run-pass/issue-8709.rs @@ -10,13 +10,13 @@ #![feature(macro_rules)] -macro_rules! sty( +macro_rules! sty { ($t:ty) => (stringify!($t)) -); +} -macro_rules! spath( +macro_rules! spath { ($t:path) => (stringify!($t)) -); +} fn main() { assert_eq!(sty!(int), "int"); diff --git a/src/test/run-pass/issue-8851.rs b/src/test/run-pass/issue-8851.rs index 5826a5f9919f4..765e696cd55fd 100644 --- a/src/test/run-pass/issue-8851.rs +++ b/src/test/run-pass/issue-8851.rs @@ -20,7 +20,7 @@ enum T { B(uint) } -macro_rules! test( +macro_rules! test { ($id:ident, $e:expr) => ( fn foo(t: T) -> int { match t { @@ -29,7 +29,7 @@ macro_rules! test( } } ) -); +} test!(y, 10 + (y as int)); diff --git a/src/test/run-pass/issue-9110.rs b/src/test/run-pass/issue-9110.rs index 60011281d425e..26390d8da7d57 100644 --- a/src/test/run-pass/issue-9110.rs +++ b/src/test/run-pass/issue-9110.rs @@ -10,14 +10,14 @@ #![feature(macro_rules)] -macro_rules! silly_macro( +macro_rules! silly_macro { () => ( pub mod Qux { pub struct Foo { x : u8 } pub fn bar(_foo : Foo) {} } ); -); +} silly_macro!(); diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index a6746f452065d..2ac1a42a24629 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -19,8 +19,8 @@ impl bomb for S { fn boom(&self, _: Ident) { } } pub struct Ident { name: uint } -// macro_rules! int3( () => ( unsafe { asm!( "int3" ); } ) ) -macro_rules! int3( () => ( { } ) ); +// macro_rules! int3 { () => ( unsafe { asm!( "int3" ); } ) } +macro_rules! int3 { () => ( { } ) } fn Ident_new() -> Ident { int3!(); diff --git a/src/test/run-pass/issue-9737.rs b/src/test/run-pass/issue-9737.rs index 1f385b2fb1589..2bd251ca58750 100644 --- a/src/test/run-pass/issue-9737.rs +++ b/src/test/run-pass/issue-9737.rs @@ -12,7 +12,9 @@ #![feature(macro_rules)] -macro_rules! f((v: $x:expr) => ( println!("{}", $x) )) +macro_rules! f { + (v: $x:expr) => ( println!("{}", $x) ) +} fn main () { let v = 5; diff --git a/src/test/run-pass/lambda-var-hygiene.rs b/src/test/run-pass/lambda-var-hygiene.rs index 5dfc4208554b1..ebd3e3c6641ea 100644 --- a/src/test/run-pass/lambda-var-hygiene.rs +++ b/src/test/run-pass/lambda-var-hygiene.rs @@ -13,7 +13,9 @@ #![feature(macro_rules)] // shouldn't affect evaluation of $ex: -macro_rules! bad_macro (($ex:expr) => ({(|_x| { $ex }) (9) })) +macro_rules! bad_macro { + ($ex:expr) => ({(|_x| { $ex }) (9) }) +} fn takes_x(_x : int) { assert_eq!(bad_macro!(_x),8); diff --git a/src/test/run-pass/let-var-hygiene.rs b/src/test/run-pass/let-var-hygiene.rs index 5eed791e0582d..e0388407571f9 100644 --- a/src/test/run-pass/let-var-hygiene.rs +++ b/src/test/run-pass/let-var-hygiene.rs @@ -11,7 +11,10 @@ #![feature(macro_rules)] // shouldn't affect evaluation of $ex: -macro_rules! bad_macro (($ex:expr) => ({let _x = 9i; $ex})); +macro_rules! bad_macro { + ($ex:expr) => ({let _x = 9i; $ex}) +} + pub fn main() { let _x = 8i; assert_eq!(bad_macro!(_x),8i) diff --git a/src/test/run-pass/macro-2.rs b/src/test/run-pass/macro-2.rs index 7b4d376993aa9..07667de4716f5 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -14,12 +14,12 @@ pub fn main() { - macro_rules! mylambda_tt( + macro_rules! mylambda_tt { ($x:ident, $body:expr) => ({ fn f($x: int) -> int { return $body; }; f }) - ); + } assert!(mylambda_tt!(y, y * 2)(8) == 16); } diff --git a/src/test/run-pass/macro-interpolation.rs b/src/test/run-pass/macro-interpolation.rs index 45712f5c62a6e..e531eb9dbc445 100644 --- a/src/test/run-pass/macro-interpolation.rs +++ b/src/test/run-pass/macro-interpolation.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! overly_complicated ( +macro_rules! overly_complicated { ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => ({ fn $fnname($arg: $ty) -> Option<$ty> $body @@ -22,7 +22,7 @@ macro_rules! overly_complicated ( } }) -); +} pub fn main() { assert!(overly_complicated!(f, x, Option, { return Some(x); }, diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs index ecd7c0458f701..5103c50f5cf57 100644 --- a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -10,9 +10,9 @@ #![feature(macro_rules)] -macro_rules! four ( +macro_rules! four { () => (4) -); +} fn main() { let _x: [u16; four!()]; diff --git a/src/test/run-pass/macro-multiple-items.rs b/src/test/run-pass/macro-multiple-items.rs index 4fb130f0e1314..40f41447aa85a 100644 --- a/src/test/run-pass/macro-multiple-items.rs +++ b/src/test/run-pass/macro-multiple-items.rs @@ -12,7 +12,7 @@ #![feature(macro_rules)] -macro_rules! make_foo( +macro_rules! make_foo { () => ( struct Foo; @@ -20,7 +20,7 @@ macro_rules! make_foo( fn bar(&self) {} } ) -); +} make_foo!(); diff --git a/src/test/run-pass/macro-nt-list.rs b/src/test/run-pass/macro-nt-list.rs index 9367a231d4f65..91f0a3b607c3e 100644 --- a/src/test/run-pass/macro-nt-list.rs +++ b/src/test/run-pass/macro-nt-list.rs @@ -10,15 +10,15 @@ #![feature(macro_rules)] -macro_rules! list ( +macro_rules! list { ( ($($id:ident),*) ) => (()); ( [$($id:ident),*] ) => (()); ( {$($id:ident),*} ) => (()); -); +} -macro_rules! tt_list ( +macro_rules! tt_list { ( ($($tt:tt),*) ) => (()); -); +} pub fn main() { list!( () ); diff --git a/src/test/run-pass/macro-of-higher-order.rs b/src/test/run-pass/macro-of-higher-order.rs index c47b5e1108901..a7c0ca56d60c8 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -10,12 +10,12 @@ #![feature(macro_rules)] -macro_rules! higher_order ( +macro_rules! higher_order { (subst $lhs:tt => $rhs:tt) => ({ - macro_rules! anon ( $lhs => $rhs ); + macro_rules! anon { $lhs => $rhs } anon!(1u, 2u, "foo") }); -); +} fn main() { let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo))); diff --git a/src/test/run-pass/macro-pat.rs b/src/test/run-pass/macro-pat.rs index 496cef9d644e2..d3e3292307586 100644 --- a/src/test/run-pass/macro-pat.rs +++ b/src/test/run-pass/macro-pat.rs @@ -10,35 +10,35 @@ #![feature(macro_rules)] -macro_rules! mypat( +macro_rules! mypat { () => ( Some('y') ) -); +} -macro_rules! char_x( +macro_rules! char_x { () => ( 'x' ) -); +} -macro_rules! some( +macro_rules! some { ($x:pat) => ( Some($x) ) -); +} -macro_rules! indirect( +macro_rules! indirect { () => ( some!(char_x!()) ) -); +} -macro_rules! ident_pat( +macro_rules! ident_pat { ($x:ident) => ( $x ) -); +} fn f(c: Option) -> uint { match c { diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 7be49e1acd844..77d6b59f8bf44 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -12,21 +12,21 @@ #![feature(macro_rules)] -macro_rules! myfn( +macro_rules! myfn { ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( fn $f( $( $x : int),* ) -> int $body ) -); +} myfn!(add, (a,b), { return a+b; } ); pub fn main() { - macro_rules! mylet( + macro_rules! mylet { ($x:ident, $val:expr) => ( let $x = $val; ) - ); + } mylet!(y, 8i*2); assert_eq!(y, 16i); @@ -35,9 +35,9 @@ pub fn main() { assert_eq!(mult(2, add(4,4)), 16); - macro_rules! actually_an_expr_macro ( + macro_rules! actually_an_expr_macro { () => ( 16i ) - ); + } assert_eq!({ actually_an_expr_macro!() }, 16i); diff --git a/src/test/run-pass/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs index 631fc8666713d..23a3a0374973d 100644 --- a/src/test/run-pass/macro-with-attrs1.rs +++ b/src/test/run-pass/macro-with-attrs1.rs @@ -13,10 +13,10 @@ #![feature(macro_rules)] #[cfg(foo)] -macro_rules! foo( () => (1i) ); +macro_rules! foo { () => (1i) } #[cfg(not(foo))] -macro_rules! foo( () => (2i) ); +macro_rules! foo { () => (2i) } pub fn main() { assert_eq!(foo!(), 1i); diff --git a/src/test/run-pass/macro-with-attrs2.rs b/src/test/run-pass/macro-with-attrs2.rs index 3ac0d47e61a63..038931551a88c 100644 --- a/src/test/run-pass/macro-with-attrs2.rs +++ b/src/test/run-pass/macro-with-attrs2.rs @@ -11,10 +11,10 @@ #![feature(macro_rules)] #[cfg(foo)] -macro_rules! foo( () => (1i) ); +macro_rules! foo { () => (1i) } #[cfg(not(foo))] -macro_rules! foo( () => (2i) ); +macro_rules! foo { () => (2i) } pub fn main() { assert_eq!(foo!(), 2i); diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index a6e579ddff304..b4170c27ec288 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -12,7 +12,7 @@ use std::thread::Thread; -macro_rules! expr (($e: expr) => { $e }); +macro_rules! expr { ($e: expr) => { $e } } macro_rules! spawn { ($($code: tt)*) => { diff --git a/src/test/run-pass/match-in-macro.rs b/src/test/run-pass/match-in-macro.rs index a776999ec8a00..7dde322ead620 100644 --- a/src/test/run-pass/match-in-macro.rs +++ b/src/test/run-pass/match-in-macro.rs @@ -14,13 +14,13 @@ enum Foo { B { b1: int, bb1: int}, } -macro_rules! match_inside_expansion( +macro_rules! match_inside_expansion { () => ( match (Foo::B { b1:29 , bb1: 100}) { Foo::B { b1:b2 , bb1:bb2 } => b2+bb2 } ) -); +} pub fn main() { assert_eq!(match_inside_expansion!(),129); diff --git a/src/test/run-pass/match-var-hygiene.rs b/src/test/run-pass/match-var-hygiene.rs index 482fdf5b1d040..da15f911e8b52 100644 --- a/src/test/run-pass/match-var-hygiene.rs +++ b/src/test/run-pass/match-var-hygiene.rs @@ -13,9 +13,9 @@ #![feature(macro_rules)] // shouldn't affect evaluation of $ex. -macro_rules! bad_macro (($ex:expr) => ( +macro_rules! bad_macro { ($ex:expr) => ( {match 9 {_x => $ex}} -)) +)} fn main() { match 8 { diff --git a/src/test/run-pass/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index 9151564b3407b..e4a3ac8cd9101 100644 --- a/src/test/run-pass/non-built-in-quote.rs +++ b/src/test/run-pass/non-built-in-quote.rs @@ -10,7 +10,7 @@ #![feature(macro_rules)] -macro_rules! quote_tokens ( () => (()) ); +macro_rules! quote_tokens { () => (()) } pub fn main() { quote_tokens!(); diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index f6708536a9d99..939d20ddc27fd 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -21,7 +21,7 @@ pub mod m1 { } } -macro_rules! indirect_line( () => ( line!() ) ); +macro_rules! indirect_line { () => ( line!() ) } pub fn main() { assert_eq!(line!(), 27); diff --git a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs index 4dec227d52020..ce6122aad00e0 100644 --- a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs +++ b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs @@ -20,7 +20,7 @@ enum T { // doesn't cause capture. Making this macro hygienic (as I've done) // could very well make this test case completely pointless.... -macro_rules! test( +macro_rules! test { ($id1:ident, $id2:ident, $e:expr) => ( fn foo(a:T, b:T) -> T { match (a, b) { @@ -30,7 +30,7 @@ macro_rules! test( } } ) -); +} test!(x,y,x + y); From d0163d3311f0afe7b8dc3b70dba8aa32f318225c Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 18:26:00 -0800 Subject: [PATCH 099/106] Pass the #[plugin(...)] meta item to the registrar --- src/librustc/plugin/load.rs | 32 +++++++++++--- src/librustc/plugin/registry.rs | 13 ++++++ src/librustc_driver/driver.rs | 7 +-- src/test/auxiliary/plugin_args.rs | 50 ++++++++++++++++++++++ src/test/compile-fail/multi-plugin-attr.rs | 15 +++++++ src/test/run-pass/plugin-args-1.rs | 22 ++++++++++ src/test/run-pass/plugin-args-2.rs | 22 ++++++++++ src/test/run-pass/plugin-args-3.rs | 22 ++++++++++ src/test/run-pass/plugin-args-4.rs | 22 ++++++++++ 9 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 src/test/auxiliary/plugin_args.rs create mode 100644 src/test/compile-fail/multi-plugin-attr.rs create mode 100644 src/test/run-pass/plugin-args-1.rs create mode 100644 src/test/run-pass/plugin-args-2.rs create mode 100644 src/test/run-pass/plugin-args-3.rs create mode 100644 src/test/run-pass/plugin-args-4.rs diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 3a9083828fc70..64a5a02b34b47 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -21,6 +21,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::attr; use syntax::parse::token; +use syntax::ptr::P; use syntax::visit; use syntax::visit::Visitor; use syntax::attr::AttrMetaMethods; @@ -29,12 +30,17 @@ use syntax::attr::AttrMetaMethods; pub type PluginRegistrarFun = fn(&mut Registry); +pub struct PluginRegistrar { + pub fun: PluginRegistrarFun, + pub args: P, +} + /// Information about loaded plugins. pub struct Plugins { /// Imported macros. pub macros: Vec, /// Registrars, as function pointers. - pub registrars: Vec, + pub registrars: Vec, } struct PluginLoader<'a> { @@ -87,7 +93,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } // Parse the attributes relating to macro / plugin loading. - let mut load_registrar = false; + let mut plugin_attr = None; let mut macro_selection = Some(HashSet::new()); // None => load all let mut reexport = HashSet::new(); for attr in vi.attrs.iter() { @@ -97,7 +103,12 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { self.sess.span_err(attr.span, "#[phase] is deprecated; use \ #[macro_use], #[plugin], and/or #[no_link]"); } - "plugin" => load_registrar = true, + "plugin" => { + if plugin_attr.is_some() { + self.sess.span_err(attr.span, "#[plugin] specified multiple times"); + } + plugin_attr = Some(attr.node.value.clone()); + } "macro_use" => { let names = attr.meta_item_list(); if names.is_none() { @@ -145,6 +156,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { Some(sel) => sel.len() != 0 || reexport.len() != 0, None => true, }; + let load_registrar = plugin_attr.is_some(); if load_macros || load_registrar { let pmd = self.reader.read_plugin_metadata(vi); @@ -167,7 +179,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } if let Some((lib, symbol)) = registrar { - self.dylink_registrar(vi, lib, symbol); + let fun = self.dylink_registrar(vi, lib, symbol); + self.plugins.registrars.push(PluginRegistrar { + fun: fun, + args: plugin_attr.unwrap(), + }); } } @@ -179,7 +195,10 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { impl<'a> PluginLoader<'a> { // Dynamically link a registrar function into the compiler process. - fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) { + fn dylink_registrar(&mut self, + vi: &ast::ViewItem, + path: Path, + symbol: String) -> PluginRegistrarFun { // Make sure the path contains a / or the linker will search for it. let path = os::make_absolute(&path).unwrap(); @@ -201,13 +220,12 @@ impl<'a> PluginLoader<'a> { Err(err) => self.sess.span_fatal(vi.span, err[]) }; - self.plugins.registrars.push(registrar); - // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long // (e.g. an @-box cycle or a task). mem::forget(lib); + registrar } } } diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index c5550902f1989..feec97f02da55 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -18,6 +18,7 @@ use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT}; use syntax::ext::base::{MacroExpanderFn}; use syntax::codemap::Span; use syntax::parse::token; +use syntax::ptr::P; use syntax::ast; use std::collections::HashMap; @@ -35,6 +36,9 @@ pub struct Registry<'a> { /// from the plugin registrar. pub sess: &'a Session, + #[doc(hidden)] + pub args_hidden: Option>, + #[doc(hidden)] pub krate_span: Span, @@ -53,6 +57,7 @@ impl<'a> Registry<'a> { pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> { Registry { sess: sess, + args_hidden: None, krate_span: krate.span, syntax_exts: vec!(), lint_passes: vec!(), @@ -60,6 +65,14 @@ impl<'a> Registry<'a> { } } + /// Get the `#[plugin]` attribute used to load this plugin. + /// + /// This gives access to arguments passed via `#[plugin=...]` or + /// `#[plugin(...)]`. + pub fn args<'b>(&'b self) -> &'b P { + self.args_hidden.as_ref().expect("args not set") + } + /// Register a syntax extension of any kind. /// /// This is the most general hook into `libsyntax`'s expansion behavior. diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 261d73b5bf07a..c88ffffecc32d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -218,7 +218,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, let mut registry = Registry::new(sess, &krate); - time(time_passes, "plugin registration", (), |_| { + time(time_passes, "plugin registration", registrars, |registrars| { if sess.features.borrow().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", diagnostics::plugin::expand_diagnostic_used); @@ -228,8 +228,9 @@ pub fn phase_2_configure_and_expand(sess: &Session, diagnostics::plugin::expand_build_diagnostic_array); } - for ®istrar in registrars.iter() { - registrar(&mut registry); + for registrar in registrars.into_iter() { + registry.args_hidden = Some(registrar.args); + (registrar.fun)(&mut registry); } }); diff --git a/src/test/auxiliary/plugin_args.rs b/src/test/auxiliary/plugin_args.rs new file mode 100644 index 0000000000000..b90c3f1d727bf --- /dev/null +++ b/src/test/auxiliary/plugin_args.rs @@ -0,0 +1,50 @@ +// Copyright 2015 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. + +// force-host + +#![feature(plugin_registrar)] + +extern crate syntax; +extern crate rustc; + +use std::borrow::ToOwned; +use syntax::ast; +use syntax::codemap::Span; +use syntax::ext::build::AstBuilder; +use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacExpr, NormalTT}; +use syntax::parse::token; +use syntax::print::pprust; +use syntax::ptr::P; +use rustc::plugin::Registry; + +struct Expander { + args: P, +} + +impl TTMacroExpander for Expander { + fn expand<'cx>(&self, + ecx: &'cx mut ExtCtxt, + sp: Span, + _: &[ast::TokenTree]) -> Box { + + let attr = ecx.attribute(sp, self.args.clone()); + let src = pprust::attribute_to_string(&attr); + let interned = token::intern_and_get_ident(src.as_slice()); + MacExpr::new(ecx.expr_str(sp, interned)) + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + let args = reg.args().clone(); + reg.register_syntax_extension(token::intern("plugin_args"), + NormalTT(box Expander { args: args, }, None)); +} diff --git a/src/test/compile-fail/multi-plugin-attr.rs b/src/test/compile-fail/multi-plugin-attr.rs new file mode 100644 index 0000000000000..1d98cd26a38f5 --- /dev/null +++ b/src/test/compile-fail/multi-plugin-attr.rs @@ -0,0 +1,15 @@ +// Copyright 2015 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. + +#[plugin] +#[plugin] //~ ERROR #[plugin] specified multiple times +extern crate std; + +fn main() {} diff --git a/src/test/run-pass/plugin-args-1.rs b/src/test/run-pass/plugin-args-1.rs new file mode 100644 index 0000000000000..5a91f603f9681 --- /dev/null +++ b/src/test/run-pass/plugin-args-1.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +// aux-build:plugin_args.rs +// ignore-stage1 + +#![feature(plugin)] + +#[no_link] +#[plugin] +extern crate plugin_args; + +fn main() { + assert_eq!(plugin_args!(), "#[plugin]"); +} diff --git a/src/test/run-pass/plugin-args-2.rs b/src/test/run-pass/plugin-args-2.rs new file mode 100644 index 0000000000000..d0ac22a529021 --- /dev/null +++ b/src/test/run-pass/plugin-args-2.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +// aux-build:plugin_args.rs +// ignore-stage1 + +#![feature(plugin)] + +#[no_link] +#[plugin()] +extern crate plugin_args; + +fn main() { + assert_eq!(plugin_args!(), "#[plugin()]"); +} diff --git a/src/test/run-pass/plugin-args-3.rs b/src/test/run-pass/plugin-args-3.rs new file mode 100644 index 0000000000000..7cac8ac57e55c --- /dev/null +++ b/src/test/run-pass/plugin-args-3.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +// aux-build:plugin_args.rs +// ignore-stage1 + +#![feature(plugin)] + +#[no_link] +#[plugin(hello(there), how(are="you"))] +extern crate plugin_args; + +fn main() { + assert_eq!(plugin_args!(), "#[plugin(hello(there), how(are = \"you\"))]"); +} diff --git a/src/test/run-pass/plugin-args-4.rs b/src/test/run-pass/plugin-args-4.rs new file mode 100644 index 0000000000000..8563c8c178ff8 --- /dev/null +++ b/src/test/run-pass/plugin-args-4.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +// aux-build:plugin_args.rs +// ignore-stage1 + +#![feature(plugin)] + +#[no_link] +#[plugin="foobar"] +extern crate plugin_args; + +fn main() { + assert_eq!(plugin_args!(), "#[plugin = \"foobar\"]"); +} From c2e26972e307a2e82b9ff7a5345a5bff47a99501 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 19:41:40 -0800 Subject: [PATCH 100/106] Un-gate macro_rules --- src/grammar/verify.rs | 2 +- src/libcoretest/lib.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/libsyntax/feature_gate.rs | 9 ++------- src/libtest/lib.rs | 2 +- src/test/auxiliary/lint_stability.rs | 2 -- src/test/auxiliary/macro_crate_def_only.rs | 2 -- src/test/auxiliary/macro_crate_nonterminal.rs | 2 -- src/test/auxiliary/macro_crate_test.rs | 2 +- src/test/auxiliary/macro_export_inner_module.rs | 2 -- src/test/auxiliary/macro_reexport_1.rs | 2 -- src/test/auxiliary/svh-a-base.rs | 2 -- src/test/auxiliary/svh-a-change-lit.rs | 2 -- src/test/auxiliary/svh-a-change-significant-cfg.rs | 2 -- src/test/auxiliary/svh-a-change-trait-bound.rs | 2 -- src/test/auxiliary/svh-a-change-type-arg.rs | 2 -- src/test/auxiliary/svh-a-change-type-ret.rs | 2 -- src/test/auxiliary/svh-a-change-type-static.rs | 2 -- src/test/auxiliary/svh-a-comment.rs | 2 -- src/test/auxiliary/svh-a-doc.rs | 2 -- src/test/auxiliary/svh-a-macro.rs | 2 -- src/test/auxiliary/svh-a-no-change.rs | 2 -- src/test/auxiliary/svh-a-redundant-cfg.rs | 2 -- src/test/auxiliary/svh-a-whitespace.rs | 2 -- src/test/auxiliary/two_macros.rs | 2 -- src/test/bench/core-std.rs | 1 - src/test/bench/shootout-mandelbrot.rs | 1 - src/test/bench/shootout-regex-dna.rs | 2 +- src/test/compile-fail/cleanup-rvalue-scopes-cf.rs | 2 -- .../compile-fail/const-block-non-item-statement.rs | 2 -- src/test/compile-fail/gated-macro-rules.rs | 14 -------------- src/test/compile-fail/hygienic-label-1.rs | 2 -- src/test/compile-fail/hygienic-label-2.rs | 2 -- src/test/compile-fail/hygienic-label-3.rs | 2 -- src/test/compile-fail/hygienic-label-4.rs | 2 -- src/test/compile-fail/if-let.rs | 2 -- src/test/compile-fail/infinite-macro-expansion.rs | 2 -- src/test/compile-fail/issue-10536.rs | 2 -- src/test/compile-fail/issue-15167.rs | 2 -- src/test/compile-fail/issue-16098.rs | 2 -- src/test/compile-fail/issue-6596.rs | 2 -- src/test/compile-fail/lint-unsafe-block.rs | 2 -- .../compile-fail/liveness-return-last-stmt-semi.rs | 2 -- src/test/compile-fail/macro-incomplete-parse.rs | 2 -- src/test/compile-fail/macro-inner-attributes.rs | 2 -- src/test/compile-fail/macro-match-nonterminal.rs | 2 -- src/test/compile-fail/macro-outer-attributes.rs | 2 -- src/test/compile-fail/method-macro-backtrace.rs | 2 -- src/test/compile-fail/pattern-macro-hygiene.rs | 2 -- src/test/compile-fail/recursion_limit.rs | 1 - src/test/compile-fail/svh-change-lit.rs | 2 -- .../compile-fail/svh-change-significant-cfg.rs | 2 -- src/test/compile-fail/svh-change-trait-bound.rs | 2 -- src/test/compile-fail/svh-change-type-arg.rs | 2 -- src/test/compile-fail/svh-change-type-ret.rs | 2 -- src/test/compile-fail/svh-change-type-static.rs | 2 -- src/test/compile-fail/trace_macros-format.rs | 2 +- src/test/compile-fail/while-let.rs | 2 -- src/test/debuginfo/lexical-scope-with-macro.rs | 1 - .../run-make/pretty-expanded-hygiene/input.pp.rs | 1 - src/test/run-make/pretty-expanded-hygiene/input.rs | 1 - .../borrowck-macro-interaction-issue-6304.rs | 2 -- src/test/run-pass/cfg-macros-foo.rs | 2 -- src/test/run-pass/cfg-macros-notfoo.rs | 2 -- src/test/run-pass/cleanup-rvalue-for-scope.rs | 2 -- src/test/run-pass/cleanup-rvalue-scopes.rs | 2 -- src/test/run-pass/colorful-write-macros.rs | 2 -- src/test/run-pass/const-binops.rs | 2 -- .../run-pass/const-block-item-macro-codegen.rs | 2 -- src/test/run-pass/const-block-item.rs | 2 -- src/test/run-pass/core-run-destroy.rs | 1 - src/test/run-pass/deriving-in-macro.rs | 2 -- src/test/run-pass/deriving-show.rs | 2 -- src/test/run-pass/enum-discrim-width-stuff.rs | 2 -- src/test/run-pass/exponential-notation.rs | 2 -- src/test/run-pass/html-literals.rs | 2 -- src/test/run-pass/hygienic-labels-in-let.rs | 2 -- src/test/run-pass/hygienic-labels.rs | 2 -- src/test/run-pass/ifmt.rs | 1 - src/test/run-pass/intrinsics-math.rs | 2 +- src/test/run-pass/issue-14936.rs | 2 +- src/test/run-pass/issue-15189.rs | 2 -- src/test/run-pass/issue-15221.rs | 2 -- src/test/run-pass/issue-5060.rs | 2 -- src/test/run-pass/issue-5554.rs | 2 -- src/test/run-pass/issue-5718.rs | 2 -- src/test/run-pass/issue-7911.rs | 2 -- src/test/run-pass/issue-8709.rs | 2 -- src/test/run-pass/issue-8851.rs | 2 -- src/test/run-pass/issue-9110.rs | 2 -- src/test/run-pass/issue-9129.rs | 2 -- src/test/run-pass/issue-9737.rs | 2 -- src/test/run-pass/lambda-var-hygiene.rs | 2 -- src/test/run-pass/let-var-hygiene.rs | 2 -- src/test/run-pass/macro-2.rs | 2 -- src/test/run-pass/macro-attribute-expansion.rs | 2 -- src/test/run-pass/macro-attributes.rs | 2 -- src/test/run-pass/macro-block-nonterminal.rs | 2 -- src/test/run-pass/macro-crate-use.rs | 2 -- src/test/run-pass/macro-deep_expansion.rs | 2 -- src/test/run-pass/macro-interpolation.rs | 2 -- ...ro-invocation-in-count-expr-fixed-array-type.rs | 2 -- src/test/run-pass/macro-meta-items.rs | 2 -- src/test/run-pass/macro-method-issue-4621.rs | 2 -- src/test/run-pass/macro-multiple-items.rs | 2 -- src/test/run-pass/macro-nt-list.rs | 2 -- src/test/run-pass/macro-of-higher-order.rs | 2 -- src/test/run-pass/macro-pat.rs | 2 -- src/test/run-pass/macro-path.rs | 2 -- src/test/run-pass/macro-stmt.rs | 2 -- src/test/run-pass/macro-with-attrs1.rs | 2 -- src/test/run-pass/macro-with-attrs2.rs | 2 -- .../run-pass/macro-with-braces-in-expr-position.rs | 2 -- src/test/run-pass/match-in-macro.rs | 2 -- src/test/run-pass/match-var-hygiene.rs | 2 -- src/test/run-pass/non-built-in-quote.rs | 2 -- .../run-pass/nullable-pointer-iotareduction.rs | 2 -- src/test/run-pass/nullable-pointer-size.rs | 2 -- src/test/run-pass/small-enums-with-fields.rs | 2 -- src/test/run-pass/svh-add-comment.rs | 2 -- src/test/run-pass/svh-add-doc.rs | 2 -- src/test/run-pass/svh-add-macro.rs | 2 -- src/test/run-pass/svh-add-nothing.rs | 2 -- src/test/run-pass/svh-add-redundant-cfg.rs | 2 -- src/test/run-pass/svh-add-whitespace.rs | 2 -- src/test/run-pass/syntax-extension-source-utils.rs | 8 +++----- src/test/run-pass/tcp-connect-timeouts.rs | 2 +- .../typeck-macro-interaction-issue-8852.rs | 2 -- src/test/run-pass/vec-macro-with-brackets.rs | 2 -- 129 files changed, 15 insertions(+), 260 deletions(-) delete mode 100644 src/test/compile-fail/gated-macro-rules.rs diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index 2e8bce3f5064b..9194c7a47663d 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, plugin, macro_rules)] +#![feature(globs, plugin)] extern crate syntax; extern crate rustc; diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index e6608eee3ddfa..04c0a2e5580f3 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -7,7 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, unsafe_destructor, macro_rules, slicing_syntax, default_type_params)] +#![feature(globs, unsafe_destructor, slicing_syntax, default_type_params)] #![feature(unboxed_closures)] extern crate core; diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index a4d89bf301ec6..917c6e99992f2 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,7 +23,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(macro_rules, globs, slicing_syntax)] +#![feature(globs, slicing_syntax)] #![feature(associated_types)] pub use self::Piece::*; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 28265b8e7c221..fe6e28f23a355 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -37,7 +37,7 @@ use std::ascii::AsciiExt; // if you change this list without updating src/doc/reference.md, @cmr will be sad static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("globs", Active), - ("macro_rules", Active), + ("macro_rules", Accepted), ("struct_variant", Accepted), ("asm", Active), ("managed_boxes", Removed), @@ -169,12 +169,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { let ast::MacInvocTT(ref path, _, _) = mac.node; let id = path.segments.last().unwrap().identifier; - if id == token::str_to_ident("macro_rules") { - self.context.gate_feature("macro_rules", path.span, "macro definitions are \ - not stable enough for use and are subject to change"); - } - - else if id == token::str_to_ident("asm") { + if id == token::str_to_ident("asm") { self.context.gate_feature("asm", path.span, "inline assembly is not \ stable enough for use and is subject to change"); } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 18c253bcf01a8..0419d85d3914e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -32,7 +32,7 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![allow(unknown_features)] -#![feature(asm, macro_rules, globs, slicing_syntax)] +#![feature(asm, globs, slicing_syntax)] #![feature(unboxed_closures, default_type_params)] #![feature(old_orphan_check)] diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 5eb6b0de3de94..708830d025986 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -10,8 +10,6 @@ #![crate_name="lint_stability"] #![crate_type = "lib"] -#![feature(macro_rules)] - #[deprecated] pub fn deprecated() {} #[deprecated="text"] diff --git a/src/test/auxiliary/macro_crate_def_only.rs b/src/test/auxiliary/macro_crate_def_only.rs index c323eb0c44624..4f55ac4f65fd4 100644 --- a/src/test/auxiliary/macro_crate_def_only.rs +++ b/src/test/auxiliary/macro_crate_def_only.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - #[macro_export] macro_rules! make_a_5 { () => (5) diff --git a/src/test/auxiliary/macro_crate_nonterminal.rs b/src/test/auxiliary/macro_crate_nonterminal.rs index 20df664c3c6ad..922efc1aec38f 100644 --- a/src/test/auxiliary/macro_crate_nonterminal.rs +++ b/src/test/auxiliary/macro_crate_nonterminal.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - pub fn increment(x: uint) -> uint { x + 1 } diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 418a7c6e538ed..ce66cad213d0e 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -10,7 +10,7 @@ // force-host -#![feature(globs, plugin_registrar, macro_rules, quote)] +#![feature(globs, plugin_registrar, quote)] extern crate syntax; extern crate rustc; diff --git a/src/test/auxiliary/macro_export_inner_module.rs b/src/test/auxiliary/macro_export_inner_module.rs index fb98637811d72..84e944f69b98e 100644 --- a/src/test/auxiliary/macro_export_inner_module.rs +++ b/src/test/auxiliary/macro_export_inner_module.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - pub mod inner { #[macro_export] macro_rules! foo { diff --git a/src/test/auxiliary/macro_reexport_1.rs b/src/test/auxiliary/macro_reexport_1.rs index bd00b33f28012..a913749bc66a9 100644 --- a/src/test/auxiliary/macro_reexport_1.rs +++ b/src/test/auxiliary/macro_reexport_1.rs @@ -9,8 +9,6 @@ // except according to those terms. #![crate_type = "dylib"] -#![feature(macro_rules)] - #[macro_export] macro_rules! reexported { () => ( 3u ) diff --git a/src/test/auxiliary/svh-a-base.rs b/src/test/auxiliary/svh-a-base.rs index c035f1203f8e3..12833daf60458 100644 --- a/src/test/auxiliary/svh-a-base.rs +++ b/src/test/auxiliary/svh-a-base.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-lit.rs b/src/test/auxiliary/svh-a-change-lit.rs index 614487c981713..9e74bf281358f 100644 --- a/src/test/auxiliary/svh-a-change-lit.rs +++ b/src/test/auxiliary/svh-a-change-lit.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-significant-cfg.rs b/src/test/auxiliary/svh-a-change-significant-cfg.rs index 99506309a592e..c900550041b5c 100644 --- a/src/test/auxiliary/svh-a-change-significant-cfg.rs +++ b/src/test/auxiliary/svh-a-change-significant-cfg.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-trait-bound.rs b/src/test/auxiliary/svh-a-change-trait-bound.rs index 8ec4eaebbe8df..04f8eb3cf9bc0 100644 --- a/src/test/auxiliary/svh-a-change-trait-bound.rs +++ b/src/test/auxiliary/svh-a-change-trait-bound.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-type-arg.rs b/src/test/auxiliary/svh-a-change-type-arg.rs index ad120e12f86fb..c7e0a18768a3d 100644 --- a/src/test/auxiliary/svh-a-change-type-arg.rs +++ b/src/test/auxiliary/svh-a-change-type-arg.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-type-ret.rs b/src/test/auxiliary/svh-a-change-type-ret.rs index c68c13c0991f2..5100af323183b 100644 --- a/src/test/auxiliary/svh-a-change-type-ret.rs +++ b/src/test/auxiliary/svh-a-change-type-ret.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-change-type-static.rs b/src/test/auxiliary/svh-a-change-type-static.rs index 6c13e84a7febe..077c33cb90d75 100644 --- a/src/test/auxiliary/svh-a-change-type-static.rs +++ b/src/test/auxiliary/svh-a-change-type-static.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-comment.rs b/src/test/auxiliary/svh-a-comment.rs index 3d0973cb7ba13..d481fa5a1fa3b 100644 --- a/src/test/auxiliary/svh-a-comment.rs +++ b/src/test/auxiliary/svh-a-comment.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-doc.rs b/src/test/auxiliary/svh-a-doc.rs index 1ad9e5e1c0e3a..9e99a355ac1ee 100644 --- a/src/test/auxiliary/svh-a-doc.rs +++ b/src/test/auxiliary/svh-a-doc.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-macro.rs b/src/test/auxiliary/svh-a-macro.rs index 6bd36b5a9b1c4..b8dd497ac99c8 100644 --- a/src/test/auxiliary/svh-a-macro.rs +++ b/src/test/auxiliary/svh-a-macro.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-no-change.rs b/src/test/auxiliary/svh-a-no-change.rs index c035f1203f8e3..12833daf60458 100644 --- a/src/test/auxiliary/svh-a-no-change.rs +++ b/src/test/auxiliary/svh-a-no-change.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-redundant-cfg.rs b/src/test/auxiliary/svh-a-redundant-cfg.rs index d67c8f4c18179..690ddc670f5fa 100644 --- a/src/test/auxiliary/svh-a-redundant-cfg.rs +++ b/src/test/auxiliary/svh-a-redundant-cfg.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/svh-a-whitespace.rs b/src/test/auxiliary/svh-a-whitespace.rs index 73798f3787558..216e8e997f22d 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/two_macros.rs b/src/test/auxiliary/two_macros.rs index 39393b77f25f0..11b6108b99ed9 100644 --- a/src/test/auxiliary/two_macros.rs +++ b/src/test/auxiliary/two_macros.rs @@ -10,8 +10,6 @@ // force-host -#![feature(macro_rules)] - #[macro_export] macro_rules! macro_one { () => ("one") } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 21e55384f46bf..9007b4fd64c43 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -11,7 +11,6 @@ // ignore-lexer-test FIXME #15679 // Microbenchmarks for various functions in std and extra -#![feature(macro_rules)] #![feature(unboxed_closures)] use std::io::File; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 4e8e0d64d52ce..16d6036d4c40f 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -38,7 +38,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(macro_rules)] #![feature(simd)] #![allow(experimental)] diff --git a/src/test/bench/shootout-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs index 0a6c197f5ed31..ef538eb699189 100644 --- a/src/test/bench/shootout-regex-dna.rs +++ b/src/test/bench/shootout-regex-dna.rs @@ -41,7 +41,7 @@ // ignore-stage1 // ignore-cross-compile #12102 -#![feature(macro_rules, plugin, slicing_syntax)] +#![feature(plugin, slicing_syntax)] extern crate regex; diff --git a/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs b/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs index b79f4507d4673..dcbb25ba5a95f 100644 --- a/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs +++ b/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs @@ -11,8 +11,6 @@ // Test that the borrow checker prevents pointers to temporaries // with statement lifetimes from escaping. -#![feature(macro_rules)] - use std::ops::Drop; static mut FLAGS: u64 = 0; diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs index 0a004c101ee4f..1814b1cd544ef 100644 --- a/src/test/compile-fail/const-block-non-item-statement.rs +++ b/src/test/compile-fail/const-block-non-item-statement.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - static A: uint = { 1u; 2 }; //~^ ERROR: blocks in constants are limited to items and tail expressions diff --git a/src/test/compile-fail/gated-macro-rules.rs b/src/test/compile-fail/gated-macro-rules.rs deleted file mode 100644 index dea0c60d91b7f..0000000000000 --- a/src/test/compile-fail/gated-macro-rules.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 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. - -macro_rules! foo { () => () } -//~^ ERROR: macro definitions are not stable enough for use - -fn main() {} diff --git a/src/test/compile-fail/hygienic-label-1.rs b/src/test/compile-fail/hygienic-label-1.rs index 0e87dc97c2631..dd6682a6f4282 100644 --- a/src/test/compile-fail/hygienic-label-1.rs +++ b/src/test/compile-fail/hygienic-label-1.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo { () => { break 'x; } } diff --git a/src/test/compile-fail/hygienic-label-2.rs b/src/test/compile-fail/hygienic-label-2.rs index fe87e32459bb1..24194d7bbe970 100644 --- a/src/test/compile-fail/hygienic-label-2.rs +++ b/src/test/compile-fail/hygienic-label-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo { ($e: expr) => { 'x: loop { $e } } } diff --git a/src/test/compile-fail/hygienic-label-3.rs b/src/test/compile-fail/hygienic-label-3.rs index b5954ac99303b..4ff3bec3c6459 100644 --- a/src/test/compile-fail/hygienic-label-3.rs +++ b/src/test/compile-fail/hygienic-label-3.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo { () => { break 'x; } } diff --git a/src/test/compile-fail/hygienic-label-4.rs b/src/test/compile-fail/hygienic-label-4.rs index 67fa56b130677..174e8a2834f4b 100644 --- a/src/test/compile-fail/hygienic-label-4.rs +++ b/src/test/compile-fail/hygienic-label-4.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo { ($e: expr) => { 'x: for _ in range(0,1) { $e } } } diff --git a/src/test/compile-fail/if-let.rs b/src/test/compile-fail/if-let.rs index 88b6854bb1d2c..971f643c0fe91 100644 --- a/src/test/compile-fail/if-let.rs +++ b/src/test/compile-fail/if-let.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - fn macros() { macro_rules! foo{ ($p:pat, $e:expr, $b:block) => {{ diff --git a/src/test/compile-fail/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 22011f192356b..74835f4bf22ca 100644 --- a/src/test/compile-fail/infinite-macro-expansion.rs +++ b/src/test/compile-fail/infinite-macro-expansion.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! recursive { () => (recursive!()) //~ ERROR recursion limit reached while expanding the macro `recursive` } diff --git a/src/test/compile-fail/issue-10536.rs b/src/test/compile-fail/issue-10536.rs index 36afc729de959..370a6228db6ac 100644 --- a/src/test/compile-fail/issue-10536.rs +++ b/src/test/compile-fail/issue-10536.rs @@ -13,8 +13,6 @@ // error-pattern: -#![feature(macro_rules)] - macro_rules! foo{ () => {{ macro_rules! bar{() => (())} diff --git a/src/test/compile-fail/issue-15167.rs b/src/test/compile-fail/issue-15167.rs index cb10791973340..d4de4e177f026 100644 --- a/src/test/compile-fail/issue-15167.rs +++ b/src/test/compile-fail/issue-15167.rs @@ -15,8 +15,6 @@ // ignore-test -#![feature(macro_rules)] - macro_rules! f { () => (n) } fn main() -> (){ diff --git a/src/test/compile-fail/issue-16098.rs b/src/test/compile-fail/issue-16098.rs index 5adcd7c2bb6d7..68ac19b383f5a 100644 --- a/src/test/compile-fail/issue-16098.rs +++ b/src/test/compile-fail/issue-16098.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! prob1 { (0) => { 0 diff --git a/src/test/compile-fail/issue-6596.rs b/src/test/compile-fail/issue-6596.rs index b237b4259184f..c5be0da5f4b2a 100644 --- a/src/test/compile-fail/issue-6596.rs +++ b/src/test/compile-fail/issue-6596.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - // error-pattern: unexpected token macro_rules! e { diff --git a/src/test/compile-fail/lint-unsafe-block.rs b/src/test/compile-fail/lint-unsafe-block.rs index 8899d06804f1e..56d2b2cd6c084 100644 --- a/src/test/compile-fail/lint-unsafe-block.rs +++ b/src/test/compile-fail/lint-unsafe-block.rs @@ -11,8 +11,6 @@ #![allow(unused_unsafe)] #![allow(dead_code)] #![deny(unsafe_blocks)] -#![feature(macro_rules)] - unsafe fn allowed() {} #[allow(unsafe_blocks)] fn also_allowed() { unsafe {} } diff --git a/src/test/compile-fail/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index cdcb0859ed950..9cfffb5fa6b62 100644 --- a/src/test/compile-fail/liveness-return-last-stmt-semi.rs +++ b/src/test/compile-fail/liveness-return-last-stmt-semi.rs @@ -10,8 +10,6 @@ // // regression test for #8005 -#![feature(macro_rules)] - macro_rules! test { () => { fn foo() -> int { 1i; } } } //~^ ERROR not all control paths return a value //~^^ HELP consider removing this semicolon diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index 71b656d0bbb57..53b29ccb0c0c7 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! ignored_item { () => { fn foo() {} diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index 8d2f49ecc7f53..e4fc5bb462700 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! test { ($nm:ident, #[$a:meta], $i:item) => (mod $nm { #![$a] $i }); } diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 8bfaac1770d96..a66b638701436 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! test { ($a, $b) => (()); } //~ ERROR Cannot transcribe fn main() { diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs index 4f2c097eca94f..a0f23c72bc41e 100644 --- a/src/test/compile-fail/macro-outer-attributes.rs +++ b/src/test/compile-fail/macro-outer-attributes.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! test { ($nm:ident, #[$a:meta], $i:item) => (mod $nm { #[$a] $i }); } diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index 56087c79799f6..f4740492651ae 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -10,8 +10,6 @@ // forbid-output: in expansion of -#![feature(macro_rules)] - macro_rules! make_method { ($name:ident) => ( fn $name(&self) { } ) } diff --git a/src/test/compile-fail/pattern-macro-hygiene.rs b/src/test/compile-fail/pattern-macro-hygiene.rs index 64f810c1c95e7..1c79c9a2293a0 100644 --- a/src/test/compile-fail/pattern-macro-hygiene.rs +++ b/src/test/compile-fail/pattern-macro-hygiene.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo { () => ( x ) } fn main() { diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index de0d5c90fdd4b..6e1ecb10e3a2a 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -12,7 +12,6 @@ // deeply nested types that will fail the `Send` check by overflow // when the recursion limit is set very low. -#![feature(macro_rules)] #![allow(dead_code)] #![recursion_limit="10"] diff --git a/src/test/compile-fail/svh-change-lit.rs b/src/test/compile-fail/svh-change-lit.rs index 179fb11d5fe5b..c839ade75cf29 100644 --- a/src/test/compile-fail/svh-change-lit.rs +++ b/src/test/compile-fail/svh-change-lit.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-lit.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/svh-change-significant-cfg.rs b/src/test/compile-fail/svh-change-significant-cfg.rs index 1f65f3873a94d..df0adf36ce2e6 100644 --- a/src/test/compile-fail/svh-change-significant-cfg.rs +++ b/src/test/compile-fail/svh-change-significant-cfg.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-significant-cfg.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/svh-change-trait-bound.rs b/src/test/compile-fail/svh-change-trait-bound.rs index 4e4f7b232f469..4774384fecd49 100644 --- a/src/test/compile-fail/svh-change-trait-bound.rs +++ b/src/test/compile-fail/svh-change-trait-bound.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-trait-bound.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/svh-change-type-arg.rs b/src/test/compile-fail/svh-change-type-arg.rs index 77b0a9211cafd..51d3fd0a73a12 100644 --- a/src/test/compile-fail/svh-change-type-arg.rs +++ b/src/test/compile-fail/svh-change-type-arg.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-type-arg.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/svh-change-type-ret.rs b/src/test/compile-fail/svh-change-type-ret.rs index 13dcfa3b5da58..609e0f3689e5d 100644 --- a/src/test/compile-fail/svh-change-type-ret.rs +++ b/src/test/compile-fail/svh-change-type-ret.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-type-ret.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/svh-change-type-static.rs b/src/test/compile-fail/svh-change-type-static.rs index 7d26bdd15fb28..c42714609b6f8 100644 --- a/src/test/compile-fail/svh-change-type-static.rs +++ b/src/test/compile-fail/svh-change-type-static.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-change-type-static.rs -#![feature(macro_rules)] - extern crate a; extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on //~^ NOTE: perhaps this crate needs to be recompiled diff --git a/src/test/compile-fail/trace_macros-format.rs b/src/test/compile-fail/trace_macros-format.rs index 8e0000246757d..95cb17c215b7b 100644 --- a/src/test/compile-fail/trace_macros-format.rs +++ b/src/test/compile-fail/trace_macros-format.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules, trace_macros)] +#![feature(trace_macros)] fn main() { trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false` diff --git a/src/test/compile-fail/while-let.rs b/src/test/compile-fail/while-let.rs index ccf3d2dd75076..adb8ee6940d3b 100644 --- a/src/test/compile-fail/while-let.rs +++ b/src/test/compile-fail/while-let.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - fn macros() { macro_rules! foo{ ($p:pat, $e:expr, $b:block) => {{ diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index be52ffff1b45e..2aa31969a46ad 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -111,7 +111,6 @@ // lldb-command:continue -#![feature(macro_rules)] #![omit_gdb_pretty_printer_section] macro_rules! trivial { diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs index bf60784ab58b9..6febe2ff7c1d3 100755 --- a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] // minimal junk #![no_std] diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs index c9d603c2e1cfb..c31b67b8043ae 100755 --- a/src/test/run-make/pretty-expanded-hygiene/input.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] // minimal junk #![no_std] diff --git a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs index bd42cc94a3393..28db3953a0021 100644 --- a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs +++ b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs @@ -11,8 +11,6 @@ // Check that we do not ICE when compiling this // macro, which reuses the expression `$id` -#![feature(macro_rules)] - struct Foo { a: int diff --git a/src/test/run-pass/cfg-macros-foo.rs b/src/test/run-pass/cfg-macros-foo.rs index 548057e9e6050..aeb6fcbbc0f01 100644 --- a/src/test/run-pass/cfg-macros-foo.rs +++ b/src/test/run-pass/cfg-macros-foo.rs @@ -13,8 +13,6 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-notfoo.rs) -#![feature(macro_rules)] - #[cfg(foo)] #[macro_use] mod foo { diff --git a/src/test/run-pass/cfg-macros-notfoo.rs b/src/test/run-pass/cfg-macros-notfoo.rs index bf4f7e6bc403b..adc27d556227e 100644 --- a/src/test/run-pass/cfg-macros-notfoo.rs +++ b/src/test/run-pass/cfg-macros-notfoo.rs @@ -13,8 +13,6 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-foo.rs) -#![feature(macro_rules)] - #[cfg(foo)] #[macro_use] mod foo { diff --git a/src/test/run-pass/cleanup-rvalue-for-scope.rs b/src/test/run-pass/cleanup-rvalue-for-scope.rs index 932a5a044ad3e..8969cca2610ea 100644 --- a/src/test/run-pass/cleanup-rvalue-for-scope.rs +++ b/src/test/run-pass/cleanup-rvalue-for-scope.rs @@ -11,8 +11,6 @@ // Test that the lifetime of rvalues in for loops is extended // to the for loop itself. -#![feature(macro_rules)] - use std::ops::Drop; static mut FLAGS: u64 = 0; diff --git a/src/test/run-pass/cleanup-rvalue-scopes.rs b/src/test/run-pass/cleanup-rvalue-scopes.rs index fe74956fd1e40..59763e417a258 100644 --- a/src/test/run-pass/cleanup-rvalue-scopes.rs +++ b/src/test/run-pass/cleanup-rvalue-scopes.rs @@ -12,8 +12,6 @@ // statement or end of block, as appropriate given the temporary // lifetime rules. -#![feature(macro_rules)] - use std::ops::Drop; static mut FLAGS: u64 = 0; diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs index d2caecdf05be2..ca7f761b80d31 100644 --- a/src/test/run-pass/colorful-write-macros.rs +++ b/src/test/run-pass/colorful-write-macros.rs @@ -11,8 +11,6 @@ // no-pretty-expanded #![allow(unused_must_use, dead_code, deprecated)] -#![feature(macro_rules)] - use std::io::MemWriter; use std::fmt; diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index 51647aebcf85d..11590ceb19d48 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use std::num::Float; diff --git a/src/test/run-pass/const-block-item-macro-codegen.rs b/src/test/run-pass/const-block-item-macro-codegen.rs index 09f26b15734ff..03afe798954d5 100644 --- a/src/test/run-pass/const-block-item-macro-codegen.rs +++ b/src/test/run-pass/const-block-item-macro-codegen.rs @@ -11,8 +11,6 @@ // General test that function items in static blocks // can be generated with a macro. -#![feature(macro_rules)] - struct MyType { desc: &'static str, data: uint, diff --git a/src/test/run-pass/const-block-item.rs b/src/test/run-pass/const-block-item.rs index 3365f09cd80ab..d55b420db083e 100644 --- a/src/test/run-pass/const-block-item.rs +++ b/src/test/run-pass/const-block-item.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - mod foo { pub trait Value { fn value(&self) -> uint; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 33564af2d7d20..3298976de6ce3 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -15,7 +15,6 @@ // memory, which makes for some *confusing* logs. That's why these are here // instead of in std. -#![feature(macro_rules)] #![reexport_test_harness_main = "test_main"] extern crate libc; diff --git a/src/test/run-pass/deriving-in-macro.rs b/src/test/run-pass/deriving-in-macro.rs index 162de18f581ab..c9b60d22ecb7b 100644 --- a/src/test/run-pass/deriving-in-macro.rs +++ b/src/test/run-pass/deriving-in-macro.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! define_vec { () => ( mod foo { diff --git a/src/test/run-pass/deriving-show.rs b/src/test/run-pass/deriving-show.rs index f619c824d5e68..e8086b8b7c6b2 100644 --- a/src/test/run-pass/deriving-show.rs +++ b/src/test/run-pass/deriving-show.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - #[derive(Show)] struct Unit; diff --git a/src/test/run-pass/enum-discrim-width-stuff.rs b/src/test/run-pass/enum-discrim-width-stuff.rs index 73abec89a2df9..07941eca2243e 100644 --- a/src/test/run-pass/enum-discrim-width-stuff.rs +++ b/src/test/run-pass/enum-discrim-width-stuff.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! check { ($m:ident, $t:ty, $v:expr) => {{ mod $m { diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index 6addbf693548f..1fb434f7d7619 100644 --- a/src/test/run-pass/exponential-notation.rs +++ b/src/test/run-pass/exponential-notation.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::num::strconv::ExponentFormat::{ExpBin, ExpDec}; use std::num::strconv::SignificantDigits::DigMax; use std::num::strconv::SignFormat::{SignAll, SignNeg}; diff --git a/src/test/run-pass/html-literals.rs b/src/test/run-pass/html-literals.rs index 6f6a429db172e..fbaeb1753f41d 100644 --- a/src/test/run-pass/html-literals.rs +++ b/src/test/run-pass/html-literals.rs @@ -10,8 +10,6 @@ // A test of the macro system. Can we do HTML literals? -#![feature(macro_rules)] - /* diff --git a/src/test/run-pass/hygienic-labels-in-let.rs b/src/test/run-pass/hygienic-labels-in-let.rs index 397ce75b6b93e..17c0299cf4dd7 100644 --- a/src/test/run-pass/hygienic-labels-in-let.rs +++ b/src/test/run-pass/hygienic-labels-in-let.rs @@ -10,8 +10,6 @@ // ignore-pretty: pprust doesn't print hygiene output -#![feature(macro_rules)] - macro_rules! loop_x { ($e: expr) => { // $e shouldn't be able to interact with this 'x diff --git a/src/test/run-pass/hygienic-labels.rs b/src/test/run-pass/hygienic-labels.rs index 53c081ff83e0e..e899a1adb794f 100644 --- a/src/test/run-pass/hygienic-labels.rs +++ b/src/test/run-pass/hygienic-labels.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! loop_x { ($e: expr) => { // $e shouldn't be able to interact with this 'x diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 6f050e7db05f4..d38b0ea274765 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -11,7 +11,6 @@ // no-pretty-expanded unnecessary unsafe block generated // ignore-lexer-test FIXME #15679 -#![feature(macro_rules)] #![deny(warnings)] #![allow(unused_must_use)] diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 4c86cb0049af6..efb2ecfe875df 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -9,7 +9,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, macro_rules, intrinsics)] +#![feature(globs, intrinsics)] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ diff --git a/src/test/run-pass/issue-14936.rs b/src/test/run-pass/issue-14936.rs index 960dae8b7043c..a441729e2d0ba 100644 --- a/src/test/run-pass/issue-14936.rs +++ b/src/test/run-pass/issue-14936.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(asm, macro_rules)] +#![feature(asm)] type History = Vec<&'static str>; diff --git a/src/test/run-pass/issue-15189.rs b/src/test/run-pass/issue-15189.rs index 60083c254805d..6d1813f8aa437 100644 --- a/src/test/run-pass/issue-15189.rs +++ b/src/test/run-pass/issue-15189.rs @@ -10,8 +10,6 @@ // ignore-pretty -#![feature(macro_rules)] - macro_rules! third { ($e:expr) => ({let x = 2; $e[x]}) } diff --git a/src/test/run-pass/issue-15221.rs b/src/test/run-pass/issue-15221.rs index f778af7ebcf51..e3c102e01ec5e 100644 --- a/src/test/run-pass/issue-15221.rs +++ b/src/test/run-pass/issue-15221.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! inner { ($e:pat ) => ($e) } diff --git a/src/test/run-pass/issue-5060.rs b/src/test/run-pass/issue-5060.rs index 18ebe35dcdf7d..7c3b0a5f1f014 100644 --- a/src/test/run-pass/issue-5060.rs +++ b/src/test/run-pass/issue-5060.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! print_hd_tl { ($field_hd:ident, $($field_tl:ident),+) => ({ print!("{}", stringify!($field_hd)); diff --git a/src/test/run-pass/issue-5554.rs b/src/test/run-pass/issue-5554.rs index 24dcc3838c5fc..32fca7a182c1b 100644 --- a/src/test/run-pass/issue-5554.rs +++ b/src/test/run-pass/issue-5554.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::default::Default; pub struct X { diff --git a/src/test/run-pass/issue-5718.rs b/src/test/run-pass/issue-5718.rs index f2167da31fc2b..589ccefd9ea28 100644 --- a/src/test/run-pass/issue-5718.rs +++ b/src/test/run-pass/issue-5718.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - struct Element; macro_rules! foo { diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index 8cc507d88558a..86948ebcb91e0 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -14,8 +14,6 @@ // with different mutability in macro in two methods #![allow(unused_variable)] // unused foobar_immut + foobar_mut -#![feature(macro_rules)] - trait FooBar {} struct Bar(i32); struct Foo { bar: Bar } diff --git a/src/test/run-pass/issue-8709.rs b/src/test/run-pass/issue-8709.rs index 4e7d42f6b0bd7..865905bf50441 100644 --- a/src/test/run-pass/issue-8709.rs +++ b/src/test/run-pass/issue-8709.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! sty { ($t:ty) => (stringify!($t)) } diff --git a/src/test/run-pass/issue-8851.rs b/src/test/run-pass/issue-8851.rs index 765e696cd55fd..b70711f9f39e2 100644 --- a/src/test/run-pass/issue-8851.rs +++ b/src/test/run-pass/issue-8851.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - // after fixing #9384 and implementing hygiene for match bindings, // this now fails because the insertion of the 'y' into the match // doesn't cause capture. Making this macro hygienic (as I've done) diff --git a/src/test/run-pass/issue-9110.rs b/src/test/run-pass/issue-9110.rs index 26390d8da7d57..09d0f20c96d6c 100644 --- a/src/test/run-pass/issue-9110.rs +++ b/src/test/run-pass/issue-9110.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! silly_macro { () => ( pub mod Qux { diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index 2ac1a42a24629..2e089d30bab02 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -10,8 +10,6 @@ // ignore-pretty -#![feature(macro_rules)] - pub trait bomb { fn boom(&self, Ident); } pub struct S; diff --git a/src/test/run-pass/issue-9737.rs b/src/test/run-pass/issue-9737.rs index 2bd251ca58750..e5a287d014919 100644 --- a/src/test/run-pass/issue-9737.rs +++ b/src/test/run-pass/issue-9737.rs @@ -10,8 +10,6 @@ // ignore-test #9737 -#![feature(macro_rules)] - macro_rules! f { (v: $x:expr) => ( println!("{}", $x) ) } diff --git a/src/test/run-pass/lambda-var-hygiene.rs b/src/test/run-pass/lambda-var-hygiene.rs index ebd3e3c6641ea..a6060bebbc5cd 100644 --- a/src/test/run-pass/lambda-var-hygiene.rs +++ b/src/test/run-pass/lambda-var-hygiene.rs @@ -10,8 +10,6 @@ // ignore-test #9383 -#![feature(macro_rules)] - // shouldn't affect evaluation of $ex: macro_rules! bad_macro { ($ex:expr) => ({(|_x| { $ex }) (9) }) diff --git a/src/test/run-pass/let-var-hygiene.rs b/src/test/run-pass/let-var-hygiene.rs index e0388407571f9..2287cc48b66ce 100644 --- a/src/test/run-pass/let-var-hygiene.rs +++ b/src/test/run-pass/let-var-hygiene.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - // shouldn't affect evaluation of $ex: macro_rules! bad_macro { ($ex:expr) => ({let _x = 9i; $ex}) diff --git a/src/test/run-pass/macro-2.rs b/src/test/run-pass/macro-2.rs index 07667de4716f5..80b2f408c1915 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -10,8 +10,6 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - pub fn main() { macro_rules! mylambda_tt { diff --git a/src/test/run-pass/macro-attribute-expansion.rs b/src/test/run-pass/macro-attribute-expansion.rs index 3c170634c2231..60217139cd778 100644 --- a/src/test/run-pass/macro-attribute-expansion.rs +++ b/src/test/run-pass/macro-attribute-expansion.rs @@ -10,8 +10,6 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - macro_rules! descriptions { ($name:ident is $desc:expr) => { // Check that we will correctly expand attributes diff --git a/src/test/run-pass/macro-attributes.rs b/src/test/run-pass/macro-attributes.rs index 4df3b94c1c9d1..521aef4b5ba5b 100644 --- a/src/test/run-pass/macro-attributes.rs +++ b/src/test/run-pass/macro-attributes.rs @@ -10,8 +10,6 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - macro_rules! compiles_fine { (#[$at:meta]) => { // test that the different types of attributes work diff --git a/src/test/run-pass/macro-block-nonterminal.rs b/src/test/run-pass/macro-block-nonterminal.rs index 8a9fbbe284864..6c568d6d493ca 100644 --- a/src/test/run-pass/macro-block-nonterminal.rs +++ b/src/test/run-pass/macro-block-nonterminal.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! do_block{ ($val:block) => {$val} } diff --git a/src/test/run-pass/macro-crate-use.rs b/src/test/run-pass/macro-crate-use.rs index 1cea4fba2aa2e..fbbe0105cf4fe 100644 --- a/src/test/run-pass/macro-crate-use.rs +++ b/src/test/run-pass/macro-crate-use.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - pub fn increment(x: uint) -> uint { x + 1 } diff --git a/src/test/run-pass/macro-deep_expansion.rs b/src/test/run-pass/macro-deep_expansion.rs index f85c6f1fc9349..c4012e2cf3c7e 100644 --- a/src/test/run-pass/macro-deep_expansion.rs +++ b/src/test/run-pass/macro-deep_expansion.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! foo2 { () => { "foo" diff --git a/src/test/run-pass/macro-interpolation.rs b/src/test/run-pass/macro-interpolation.rs index e531eb9dbc445..ff5b29d6ac88b 100644 --- a/src/test/run-pass/macro-interpolation.rs +++ b/src/test/run-pass/macro-interpolation.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! overly_complicated { ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => ({ diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs index 5103c50f5cf57..ce74896749838 100644 --- a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! four { () => (4) } diff --git a/src/test/run-pass/macro-meta-items.rs b/src/test/run-pass/macro-meta-items.rs index 4b01fdf816216..47e3a0723993e 100644 --- a/src/test/run-pass/macro-meta-items.rs +++ b/src/test/run-pass/macro-meta-items.rs @@ -11,8 +11,6 @@ // ignore-pretty - token trees can't pretty print // compile-flags: --cfg foo -#![feature(macro_rules)] - macro_rules! compiles_fine { ($at:meta) => { #[cfg($at)] diff --git a/src/test/run-pass/macro-method-issue-4621.rs b/src/test/run-pass/macro-method-issue-4621.rs index aa6de9acf6b88..fd16958d8964b 100644 --- a/src/test/run-pass/macro-method-issue-4621.rs +++ b/src/test/run-pass/macro-method-issue-4621.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - struct A; macro_rules! make_thirteen_method {() => (fn thirteen(&self)->int {13})} diff --git a/src/test/run-pass/macro-multiple-items.rs b/src/test/run-pass/macro-multiple-items.rs index 40f41447aa85a..f78f93e84810c 100644 --- a/src/test/run-pass/macro-multiple-items.rs +++ b/src/test/run-pass/macro-multiple-items.rs @@ -10,8 +10,6 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - macro_rules! make_foo { () => ( struct Foo; diff --git a/src/test/run-pass/macro-nt-list.rs b/src/test/run-pass/macro-nt-list.rs index 91f0a3b607c3e..c6efc2f2bc83b 100644 --- a/src/test/run-pass/macro-nt-list.rs +++ b/src/test/run-pass/macro-nt-list.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! list { ( ($($id:ident),*) ) => (()); ( [$($id:ident),*] ) => (()); diff --git a/src/test/run-pass/macro-of-higher-order.rs b/src/test/run-pass/macro-of-higher-order.rs index a7c0ca56d60c8..3276aa0265f70 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! higher_order { (subst $lhs:tt => $rhs:tt) => ({ macro_rules! anon { $lhs => $rhs } diff --git a/src/test/run-pass/macro-pat.rs b/src/test/run-pass/macro-pat.rs index d3e3292307586..07b75389cf4ff 100644 --- a/src/test/run-pass/macro-pat.rs +++ b/src/test/run-pass/macro-pat.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! mypat { () => ( Some('y') diff --git a/src/test/run-pass/macro-path.rs b/src/test/run-pass/macro-path.rs index 97f6e2b50d7c8..4aa1587943413 100644 --- a/src/test/run-pass/macro-path.rs +++ b/src/test/run-pass/macro-path.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - mod m { pub type t = int; } diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 77d6b59f8bf44..cb5370c8bcba1 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -10,8 +10,6 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - macro_rules! myfn { ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( fn $f( $( $x : int),* ) -> int $body diff --git a/src/test/run-pass/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs index 23a3a0374973d..3f9d07466cc81 100644 --- a/src/test/run-pass/macro-with-attrs1.rs +++ b/src/test/run-pass/macro-with-attrs1.rs @@ -10,8 +10,6 @@ // compile-flags: --cfg foo -#![feature(macro_rules)] - #[cfg(foo)] macro_rules! foo { () => (1i) } diff --git a/src/test/run-pass/macro-with-attrs2.rs b/src/test/run-pass/macro-with-attrs2.rs index 038931551a88c..f90a0dfa6b31e 100644 --- a/src/test/run-pass/macro-with-attrs2.rs +++ b/src/test/run-pass/macro-with-attrs2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - #[cfg(foo)] macro_rules! foo { () => (1i) } diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index b4170c27ec288..93bb9557604c4 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::thread::Thread; macro_rules! expr { ($e: expr) => { $e } } diff --git a/src/test/run-pass/match-in-macro.rs b/src/test/run-pass/match-in-macro.rs index 7dde322ead620..e4886ddaa0ed3 100644 --- a/src/test/run-pass/match-in-macro.rs +++ b/src/test/run-pass/match-in-macro.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - enum Foo { B { b1: int, bb1: int}, } diff --git a/src/test/run-pass/match-var-hygiene.rs b/src/test/run-pass/match-var-hygiene.rs index da15f911e8b52..984f675b4dc7d 100644 --- a/src/test/run-pass/match-var-hygiene.rs +++ b/src/test/run-pass/match-var-hygiene.rs @@ -10,8 +10,6 @@ // ignore-test #9384 -#![feature(macro_rules)] - // shouldn't affect evaluation of $ex. macro_rules! bad_macro { ($ex:expr) => ( {match 9 {_x => $ex}} diff --git a/src/test/run-pass/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index e4a3ac8cd9101..8b41670734f95 100644 --- a/src/test/run-pass/non-built-in-quote.rs +++ b/src/test/run-pass/non-built-in-quote.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! quote_tokens { () => (()) } pub fn main() { diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs index 2660de619e9c7..9b9a7f68995f7 100644 --- a/src/test/run-pass/nullable-pointer-iotareduction.rs +++ b/src/test/run-pass/nullable-pointer-iotareduction.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::{option, mem}; // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs index afc22be38b8a4..02fc0cf0291d4 100644 --- a/src/test/run-pass/nullable-pointer-size.rs +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::mem; enum E { Thing(int, T), Nothing((), ((), ()), [i8; 0]) } diff --git a/src/test/run-pass/small-enums-with-fields.rs b/src/test/run-pass/small-enums-with-fields.rs index 247fa6453b831..46daa6594303c 100644 --- a/src/test/run-pass/small-enums-with-fields.rs +++ b/src/test/run-pass/small-enums-with-fields.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - use std::mem::size_of; #[derive(PartialEq, Show)] diff --git a/src/test/run-pass/svh-add-comment.rs b/src/test/run-pass/svh-add-comment.rs index bc9a371edf7ce..235c4e74d0857 100644 --- a/src/test/run-pass/svh-add-comment.rs +++ b/src/test/run-pass/svh-add-comment.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-comment.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-doc.rs b/src/test/run-pass/svh-add-doc.rs index 6599e493d25a1..365960b96e4e9 100644 --- a/src/test/run-pass/svh-add-doc.rs +++ b/src/test/run-pass/svh-add-doc.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-doc.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-macro.rs b/src/test/run-pass/svh-add-macro.rs index f4bfe3d8c7c98..a0dbc96cdb02a 100644 --- a/src/test/run-pass/svh-add-macro.rs +++ b/src/test/run-pass/svh-add-macro.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-macro.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-nothing.rs b/src/test/run-pass/svh-add-nothing.rs index 7f702bd7ab553..98b7663c58ebb 100644 --- a/src/test/run-pass/svh-add-nothing.rs +++ b/src/test/run-pass/svh-add-nothing.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-no-change.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-redundant-cfg.rs b/src/test/run-pass/svh-add-redundant-cfg.rs index b5a84843a545b..650f76d729a54 100644 --- a/src/test/run-pass/svh-add-redundant-cfg.rs +++ b/src/test/run-pass/svh-add-redundant-cfg.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-redundant-cfg.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-whitespace.rs b/src/test/run-pass/svh-add-whitespace.rs index 4a8058c96643e..6612c93e90bc5 100644 --- a/src/test/run-pass/svh-add-whitespace.rs +++ b/src/test/run-pass/svh-add-whitespace.rs @@ -13,8 +13,6 @@ // aux-build:svh-b.rs // aux-build:svh-a-whitespace.rs -#![feature(macro_rules)] - extern crate a; extern crate b; diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index 939d20ddc27fd..f85305cf31926 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -11,8 +11,6 @@ // This test is brittle! // ignore-pretty - the pretty tests lose path information, breaking include! -#![feature(macro_rules)] - pub mod m1 { pub mod m2 { pub fn where_am_i() -> String { @@ -24,9 +22,9 @@ pub mod m1 { macro_rules! indirect_line { () => ( line!() ) } pub fn main() { - assert_eq!(line!(), 27); + assert_eq!(line!(), 25); //assert!((column!() == 11)); - assert_eq!(indirect_line!(), 29); + assert_eq!(indirect_line!(), 27); assert!((file!().ends_with("syntax-extension-source-utils.rs"))); assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string()); assert!(include!("syntax-extension-source-utils-files/includeme.\ @@ -44,7 +42,7 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().as_slice().ends_with("m1::m2"))); - assert!(match (47, "( 2 * 3 ) + 5") { + assert!(match (45, "( 2 * 3 ) + 5") { (line!(), stringify!((2*3) + 5)) => true, _ => false }) diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index 6812255d82ca0..adbc16f5c2918 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -16,7 +16,7 @@ // one test task to ensure that errors are timeouts, not file descriptor // exhaustion. -#![feature(macro_rules, globs)] +#![feature(globs)] #![allow(experimental)] #![reexport_test_harness_main = "test_main"] diff --git a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs index ce6122aad00e0..673e852356266 100644 --- a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs +++ b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - enum T { A(int), B(f64) diff --git a/src/test/run-pass/vec-macro-with-brackets.rs b/src/test/run-pass/vec-macro-with-brackets.rs index 2c784dade5711..a263501f8fe71 100644 --- a/src/test/run-pass/vec-macro-with-brackets.rs +++ b/src/test/run-pass/vec-macro-with-brackets.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! vec [ ($($e:expr),*) => ({ let mut _temp = ::std::vec::Vec::new(); From bbbb85a4ec029e961c01fa95725ee065621c07dc Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 22:21:28 -0800 Subject: [PATCH 101/106] Forbid '#[macro_use] extern crate' outside the crate root --- src/librustc/plugin/load.rs | 16 +++++++++++++++ src/test/compile-fail/lint-stability.rs | 7 ++++--- .../macro-crate-nonterminal-non-root.rs | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/macro-crate-nonterminal-non-root.rs diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 64a5a02b34b47..44a223954858a 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -20,6 +20,7 @@ use std::dynamic_lib::DynamicLibrary; use std::collections::HashSet; use syntax::ast; use syntax::attr; +use syntax::codemap::Span; use syntax::parse::token; use syntax::ptr::P; use syntax::visit; @@ -45,6 +46,7 @@ pub struct Plugins { struct PluginLoader<'a> { sess: &'a Session, + span_whitelist: HashSet, reader: CrateReader<'a>, plugins: Plugins, } @@ -54,6 +56,7 @@ impl<'a> PluginLoader<'a> { PluginLoader { sess: sess, reader: CrateReader::new(sess), + span_whitelist: HashSet::new(), plugins: Plugins { macros: vec!(), registrars: vec!(), @@ -66,6 +69,14 @@ impl<'a> PluginLoader<'a> { pub fn load_plugins(sess: &Session, krate: &ast::Crate, addl_plugins: Option) -> Plugins { let mut loader = PluginLoader::new(sess); + + // We need to error on `#[macro_use] extern crate` when it isn't at the + // crate root, because `$crate` won't work properly. Identify these by + // spans, because the crate map isn't set up yet. + for vi in krate.module.view_items.iter() { + loader.span_whitelist.insert(vi.span); + } + visit::walk_crate(&mut loader, krate); let mut plugins = loader.plugins; @@ -158,6 +169,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { }; let load_registrar = plugin_attr.is_some(); + if load_macros && !self.span_whitelist.contains(&vi.span) { + self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \ + the crate root"); + } + if load_macros || load_registrar { let pmd = self.reader.read_plugin_metadata(vi); if load_macros { diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 87bdb15f6edf7..63dc8d692bacd 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -19,13 +19,14 @@ #![deny(experimental)] #![allow(dead_code)] +#[macro_use] +extern crate lint_stability; //~ ERROR: use of unmarked item + mod cross_crate { extern crate stability_cfg1; extern crate stability_cfg2; //~ ERROR: use of experimental item - #[macro_use] - extern crate lint_stability; //~ ERROR: use of unmarked item - use self::lint_stability::*; + use lint_stability::*; fn test() { let foo = MethodTester; diff --git a/src/test/compile-fail/macro-crate-nonterminal-non-root.rs b/src/test/compile-fail/macro-crate-nonterminal-non-root.rs new file mode 100644 index 0000000000000..67aaf05c3101b --- /dev/null +++ b/src/test/compile-fail/macro-crate-nonterminal-non-root.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:macro_crate_nonterminal.rs +// ignore-stage1 + +mod foo { + #[macro_use] + extern crate macro_crate_nonterminal; //~ ERROR must be at the crate root +} + +fn main() { +} From 34b995d9e2f46e10124ac67a6249d9ef022972a9 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 3 Jan 2015 11:04:46 -0800 Subject: [PATCH 102/106] Add a test case for accidental macro re-export --- src/test/auxiliary/macro_non_reexport_2.rs | 19 ++++++++++++++++++ .../macro-no-implicit-reexport.rs | 20 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/auxiliary/macro_non_reexport_2.rs create mode 100644 src/test/compile-fail/macro-no-implicit-reexport.rs diff --git a/src/test/auxiliary/macro_non_reexport_2.rs b/src/test/auxiliary/macro_non_reexport_2.rs new file mode 100644 index 0000000000000..910fcd2e3671d --- /dev/null +++ b/src/test/auxiliary/macro_non_reexport_2.rs @@ -0,0 +1,19 @@ +// Copyright 2015 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. + +#![crate_type = "dylib"] + +// Since we load a serialized macro with all its attributes, accidentally +// re-exporting a `#[macro_export] macro_rules!` is something of a concern! +// +// We avoid it at the moment only because of the order in which we do things. + +#[macro_use] #[no_link] +extern crate macro_reexport_1; diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs new file mode 100644 index 0000000000000..4a427f121fcab --- /dev/null +++ b/src/test/compile-fail/macro-no-implicit-reexport.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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. + +// aux-build:macro_reexport_1.rs +// aux-build:macro_non_reexport_2.rs +// ignore-stage1 + +#[macro_use] #[no_link] +extern crate macro_non_reexport_2; + +fn main() { + assert_eq!(reexported!(), 3u); //~ ERROR macro undefined +} From 78e841d8b10e05b5bbad4b02a9d5f0e9611100c7 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 2 Jan 2015 20:05:30 -0800 Subject: [PATCH 103/106] Update docs --- src/doc/guide-macros.md | 155 +++++++++++++++++++++++++--------------- src/doc/guide-plugin.md | 14 ++-- src/doc/reference.md | 64 +++++++++-------- 3 files changed, 140 insertions(+), 93 deletions(-) diff --git a/src/doc/guide-macros.md b/src/doc/guide-macros.md index 58af591740709..dc6d281307a7a 100644 --- a/src/doc/guide-macros.md +++ b/src/doc/guide-macros.md @@ -1,14 +1,5 @@ % The Rust Macros Guide -

- # Introduction Functions are the primary tool that programmers can use to build abstractions. @@ -46,19 +37,18 @@ lightweight custom syntax extensions, themselves defined using the the pattern in the above code: ~~~~ -# #![feature(macro_rules)] # enum T { SpecialA(uint), SpecialB(uint) } # fn f() -> uint { # let input_1 = T::SpecialA(0); # let input_2 = T::SpecialA(0); -macro_rules! early_return( +macro_rules! early_return { ($inp:expr $sp:path) => ( // invoke it like `(input_5 SpecialE)` match $inp { $sp(x) => { return x; } _ => {} } ); -); +} // ... early_return!(input_1 T::SpecialA); // ... @@ -109,10 +99,10 @@ that could be invoked like: `my_macro!(i->(( 2+2 )))`. ## Invocation location -A macro invocation may take the place of (and therefore expand to) -an expression, an item, or a statement. -The Rust parser will parse the macro invocation as a "placeholder" -for whichever of those three nonterminals is appropriate for the location. +A macro invocation may take the place of (and therefore expand to) an +expression, item, statement, or pattern. The Rust parser will parse the macro +invocation as a "placeholder" for whichever syntactic form is appropriate for +the location. At expansion time, the output of the macro will be parsed as whichever of the three nonterminals it stands in for. This means that a single macro might, @@ -166,12 +156,11 @@ separator token (a comma-separated list could be written `$(...),*`), and `+` instead of `*` to mean "at least one". ~~~~ -# #![feature(macro_rules)] # enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)} # fn f() -> uint { # let input_1 = T::SpecialA(0); # let input_2 = T::SpecialA(0); -macro_rules! early_return( +macro_rules! early_return { ($inp:expr, [ $($sp:path)|+ ]) => ( match $inp { $( @@ -180,7 +169,7 @@ macro_rules! early_return( _ => {} } ) -); +} // ... early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]); // ... @@ -228,7 +217,6 @@ solves the problem. Now consider code like the following: ~~~~ -# #![feature(macro_rules)] # enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } # enum T3 { Good2(uint), Bad2} @@ -255,8 +243,7 @@ a match, but with a syntax that suits the problem better. The following macro can solve the problem: ~~~~ -# #![feature(macro_rules)] -macro_rules! biased_match ( +macro_rules! biased_match { // special case: `let (x) = ...` is illegal, so use `let x = ...` instead ( ($e:expr) ~ ($p:pat) else $err:stmt ; binds $bind_res:ident @@ -275,7 +262,7 @@ macro_rules! biased_match ( _ => { $err } }; ) -); +} # enum T1 { Good1(T2, uint), Bad1} # struct T2 { body: T3 } @@ -297,13 +284,12 @@ like this, we might prefer to write a single macro invocation. The input pattern we want is clear: ~~~~ -# #![feature(macro_rules)] # fn main() {} -# macro_rules! b( +# macro_rules! b { ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )* binds $( $bind_res:ident ),* ) -# => (0)); +# => (0) } ~~~~ However, it's not possible to directly expand to nested match statements. But @@ -320,24 +306,22 @@ process the semicolon-terminated lines, one-by-one. So, we want the following input patterns: ~~~~ -# #![feature(macro_rules)] -# macro_rules! b( +# macro_rules! b { ( binds $( $bind_res:ident ),* ) -# => (0)); +# => (0) } # fn main() {} ~~~~ ...and: ~~~~ -# #![feature(macro_rules)] # fn main() {} -# macro_rules! b( +# macro_rules! b { ( ($e :expr) ~ ($p :pat) else $err :stmt ; $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )* binds $( $bind_res:ident ),* ) -# => (0)); +# => (0) } ~~~~ The resulting macro looks like this. Note that the separation into @@ -345,10 +329,9 @@ The resulting macro looks like this. Note that the separation into piece of syntax (the `let`) which we only want to transcribe once. ~~~~ -# #![feature(macro_rules)] # fn main() { -macro_rules! biased_match_rec ( +macro_rules! biased_match_rec { // Handle the first layer ( ($e :expr) ~ ($p :pat) else $err :stmt ; $( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )* @@ -366,10 +349,10 @@ macro_rules! biased_match_rec ( ); // Produce the requested values ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) ) -); +} // Wrap the whole thing in a `let`. -macro_rules! biased_match ( +macro_rules! biased_match { // special case: `let (x) = ...` is illegal, so use `let x = ...` instead ( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )* binds $bind_res:ident @@ -388,7 +371,7 @@ macro_rules! biased_match ( binds $( $bind_res ),* ); ) -); +} # enum T1 { Good1(T2, uint), Bad1} @@ -434,9 +417,7 @@ As an example, `loop` and `for-loop` labels (discussed in the lifetimes guide) will not clash. The following code will print "Hello!" only once: ~~~ -#![feature(macro_rules)] - -macro_rules! loop_x ( +macro_rules! loop_x { ($e: expr) => ( // $e will not interact with this 'x 'x: loop { @@ -444,7 +425,7 @@ macro_rules! loop_x ( $e } ); -); +} fn main() { 'x: loop { @@ -467,22 +448,30 @@ lexical-order traversal of a crate's source. So a macro defined at module scope is visible to any subsequent code in the same module, which includes the body of any subsequent child `mod` items. -If a module has the `macro_escape` attribute, its macros are also visible in -its parent module after the child's `mod` item. If the parent also has -`macro_escape` then the macros will be visible in the grandparent after the -parent's `mod` item, and so forth. +If a module has the `macro_use` attribute, its macros are also visible in its +parent module after the child's `mod` item. If the parent also has `macro_use` +then the macros will be visible in the grandparent after the parent's `mod` +item, and so forth. -Independent of `macro_escape`, the `macro_export` attribute controls visibility -between crates. Any `macro_rules!` definition with the `macro_export` -attribute will be visible to other crates that have loaded this crate with -`phase(plugin)`. There is currently no way for the importing crate to control -which macros are imported. +The `macro_use` attribute can also appear on `extern crate`. In this context +it controls which macros are loaded from the external crate, e.g. + +```rust,ignore +#[macro_use(foo, bar)] +extern crate baz; +``` + +If the attribute is given simply as `#[macro_use]`, all macros are loaded. If +there is no `#[macro_use]` attribute then no macros are loaded. Only macros +defined with the `#[macro_export]` attribute may be loaded. + +To load a crate's macros *without* linking it into the output, use `#[no_link]` +as well. An example: ```rust -# #![feature(macro_rules)] -macro_rules! m1 (() => (())); +macro_rules! m1 { () => (()) } // visible here: m1 @@ -490,22 +479,22 @@ mod foo { // visible here: m1 #[macro_export] - macro_rules! m2 (() => (())); + macro_rules! m2 { () => (()) } // visible here: m1, m2 } // visible here: m1 -macro_rules! m3 (() => (())); +macro_rules! m3 { () => (()) } // visible here: m1, m3 -#[macro_escape] +#[macro_use] mod bar { // visible here: m1, m3 - macro_rules! m4 (() => (())); + macro_rules! m4 { () => (()) } // visible here: m1, m3, m4 } @@ -514,8 +503,58 @@ mod bar { # fn main() { } ``` -When this library is loaded with `#[phase(plugin)] extern crate`, only `m2` -will be imported. +When this library is loaded with `#[use_macros] extern crate`, only `m2` will +be imported. + +The Rust Reference has a [listing of macro-related +attributes](reference.html#macro--and-plugin-related-attributes). + +# The variable `$crate` + +A further difficulty occurs when a macro is used in multiple crates. Say that +`mylib` defines + +```rust +pub fn increment(x: uint) -> uint { + x + 1 +} + +#[macro_export] +macro_rules! inc_a { + ($x:expr) => ( ::increment($x) ) +} + +#[macro_export] +macro_rules! inc_b { + ($x:expr) => ( ::mylib::increment($x) ) +} +# fn main() { } +``` + +`inc_a` only works within `mylib`, while `inc_b` only works outside the +library. Furthermore, `inc_b` will break if the user imports `mylib` under +another name. + +Rust does not (yet) have a hygiene system for crate references, but it does +provide a simple workaround for this problem. Within a macro imported from a +crate named `foo`, the special macro variable `$crate` will expand to `::foo`. +By contrast, when a macro is defined and then used in the same crate, `$crate` +will expand to nothing. This means we can write + +```rust +#[macro_export] +macro_rules! inc { + ($x:expr) => ( $crate::increment($x) ) +} +# fn main() { } +``` + +to define a single macro that works both inside and outside our library. The +function name will expand to either `::increment` or `::mylib::increment`. + +To keep this system simple and correct, `#[macro_use] extern crate ...` may +only appear at the root of your crate, not inside `mod`. This ensures that +`$crate` is a single identifier. # A final note diff --git a/src/doc/guide-plugin.md b/src/doc/guide-plugin.md index eb3e4ce75c470..025f0cced63a6 100644 --- a/src/doc/guide-plugin.md +++ b/src/doc/guide-plugin.md @@ -31,10 +31,14 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc. A plugin is a dynamic library crate with a designated "registrar" function that registers extensions with `rustc`. Other crates can use these extensions by -loading the plugin crate with `#[phase(plugin)] extern crate`. See the +loading the plugin crate with `#[plugin] extern crate`. See the [`rustc::plugin`](rustc/plugin/index.html) documentation for more about the mechanics of defining and loading a plugin. +Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by +rustc itself. They are provided to the plugin through the `Registry`'s [`args` +method](rustc/plugin/registry/struct.Registry.html#method.args). + # Syntax extensions Plugins can extend Rust's syntax in various ways. One kind of syntax extension @@ -105,10 +109,9 @@ pub fn plugin_registrar(reg: &mut Registry) { Then we can use `rn!()` like any other macro: ```ignore -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] -extern crate roman_numerals; +#[plugin] extern crate roman_numerals; fn main() { assert_eq!(rn!(MMXV), 2015); @@ -217,8 +220,7 @@ pub fn plugin_registrar(reg: &mut Registry) { Then code like ```ignore -#[phase(plugin)] -extern crate lint_plugin_test; +#[plugin] extern crate lint_plugin_test; fn lintme() { } ``` diff --git a/src/doc/reference.md b/src/doc/reference.md index e2134cdebef74..829c0e675146a 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -668,9 +668,11 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']' | non_special_token ; ``` -User-defined syntax extensions are called "macros", and the `macro_rules` -syntax extension defines them. Currently, user-defined macros can expand to -expressions, statements, items, or patterns. +`macro_rules` allows users to define syntax extension in a declarative way. We +call such extensions "macros by example" or simply "macros" — to be distinguished +from the "procedural macros" defined in [compiler plugins][plugin]. + +Currently, macros can expand to expressions, statements, items, or patterns. (A `sep_token` is any token other than `*` and `+`. A `non_special_token` is any token other than a delimiter or `$`.) @@ -2002,8 +2004,6 @@ type int8_t = i8; ### Module-only attributes -- `macro_escape` - macros defined in this module will be visible in the - module's parent, after this module has been included. - `no_implicit_prelude` - disable injecting `use std::prelude::*` in this module. - `path` - specifies the file to load the module from. `#[path="foo.rs"] mod @@ -2066,23 +2066,43 @@ On `struct`s: remove any padding between fields (note that this is very fragile and may break platforms which require aligned access). +### Macro- and plugin-related attributes + +- `macro_use` on a `mod` — macros defined in this module will be visible in the + module's parent, after this module has been included. + +- `macro_use` on an `extern crate` — load macros from this crate. An optional + list of names `#[macro_use(foo, bar)]` restricts the import to just those + macros named. The `extern crate` must appear at the crate root, not inside + `mod`, which ensures proper function of the [`$crate` macro + variable](guide-macros.html#the-variable-$crate). + +- `macro_reexport` on an `extern crate` — re-export the named macros. + +- `macro_export` - export a macro for cross-crate usage. + +- `plugin` on an `extern crate` — load this crate as a [compiler + plugin][plugin]. The `plugin` feature gate is required. Any arguments to + the attribute, e.g. `#[plugin=...]` or `#[plugin(...)]`, are provided to the + plugin. + +- `no_link` on an `extern crate` — even if we load this crate for macros or + compiler plugins, don't link it into the output. + +See the [macros guide](guide-macros.html#scoping-and-macro-import/export) for +more information on macro scope. + + ### Miscellaneous attributes - `export_name` - on statics and functions, this determines the name of the exported symbol. - `link_section` - on statics and functions, this specifies the section of the object file that this item's contents will be placed into. -- `macro_export` - export a macro for cross-crate usage. - `no_mangle` - on any item, do not apply the standard name mangling. Set the symbol for this item to its identifier. - `packed` - on structs or enums, eliminate any padding that would be used to align fields. -- `phase` - on `extern crate` statements, allows specifying which "phase" of - compilation the crate should be loaded for. Currently, there are two - choices: `link` and `plugin`. `link` is the default. `plugin` will [load the - crate at compile-time][plugin] and use any syntax extensions or lints that the crate - defines. They can both be specified, `#[phase(link, plugin)]` to use a crate - both at runtime and compiletime. - `simd` - on certain tuple structs, derive the arithmetic operators, which lower to the target's SIMD instructions, if any; the `simd` feature gate is necessary to use this attribute. @@ -2569,15 +2589,6 @@ The currently implemented features of the reference compiler are: * `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a nasty hack that will certainly be removed. -* `macro_rules` - The definition of new macros. This does not encompass - macro-invocation, that is always enabled by default, this - only covers the definition of new macros. There are currently - various problems with invoking macros, how they interact with - their environment, and possibly how they are used outside of - location in which they are defined. Macro definitions are - likely to change slightly in the future, so they are - currently hidden behind this feature. - * `non_ascii_idents` - The compiler supports the use of non-ascii identifiers, but the implementation is a little rough around the edges, so this can be seen as an experimental feature @@ -2588,15 +2599,10 @@ The currently implemented features of the reference compiler are: closure as `once` is unlikely to be supported going forward. So they are hidden behind this feature until they are to be removed. -* `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins - for custom lints or syntax extensions. The implementation is - considered unwholesome and in need of overhaul, and it is not clear - what they will look like moving forward. +* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions. + These depend on compiler internals and are subject to change. -* `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it - wants to load. As with `phase`, the implementation is - in need of an overhaul, and it is not clear that plugins - defined using this will continue to work. +* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin]. * `quote` - Allows use of the `quote_*!` family of macros, which are implemented very poorly and will likely change significantly From f331c568698db2361598a7ae017bfdb1fed9543d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Jan 2015 19:07:07 -0800 Subject: [PATCH 104/106] Test fixes --- src/libcore/iter.rs | 53 --------------------------------------------- 1 file changed, 53 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index b262054992c9f..79c268c844167 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -580,44 +580,6 @@ pub trait IteratorExt: Iterator + Sized { (left, right) } - /// Loops through `n` iterations, returning the `n`th element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.nth(2).unwrap() == &3); - /// assert!(it.nth(2) == None); - /// ``` - #[inline] - #[stable] - fn nth(&mut self, mut n: uint) -> Option< ::Item> { - for x in *self { - if n == 0 { return Some(x) } - n -= 1; - } - None - } - - /// Loops through the entire iterator, returning the last element of the - /// iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().last().unwrap() == &5); - /// ``` - #[inline] - #[unstable = "just changed to take self by value"] - fn last(mut self) -> Option< ::Item> { - let mut last = None; - for x in self { last = Some(x); } - last - } - /// Performs a fold operation over the entire iterator, returning the /// eventual state at the end of the iteration. /// @@ -639,21 +601,6 @@ pub trait IteratorExt: Iterator + Sized { accum } - /// Counts the number of elements in this iterator. - /// - /// # Example - /// - /// ```rust - /// let a = [1, 2, 3, 4, 5]; - /// let mut it = a.iter(); - /// assert!(it.count() == 5); - /// ``` - #[inline] - #[unstable = "just changed to take self by value"] - fn count(self) -> uint { - self.fold(0, |cnt, _x| cnt + 1) - } - /// Tests whether the predicate holds true for all elements in the iterator. /// /// # Example From ee9921aaedb26de3cac4c1c174888528f68bbd3f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Jan 2015 19:08:37 -0800 Subject: [PATCH 105/106] Revert "Remove i suffix in docs" This reverts commit f031671c6ea79391eeb3e1ad8f06fe0e436103fb. Conflicts: src/libcollections/slice.rs src/libcore/iter.rs src/libstd/sync/mpsc/mod.rs src/libstd/sync/rwlock.rs --- src/liballoc/arc.rs | 52 +- src/liballoc/rc.rs | 54 +- src/libcollections/binary_heap.rs | 22 +- src/libcollections/btree/set.rs | 20 +- src/libcollections/dlist.rs | 10 +- src/libcollections/ring_buf.rs | 72 +- src/libcollections/slice.rs | 790 +++++++--------- src/libcollections/vec.rs | 58 +- src/libcore/atomic.rs | 18 +- src/libcore/fmt/num.rs | 2 +- src/libcore/iter.rs | 215 ++++- src/libcore/mem.rs | 8 +- src/libcore/num/mod.rs | 2 +- src/libcore/option.rs | 12 +- src/liblog/macros.rs | 4 +- src/librand/lib.rs | 4 +- src/libstd/collections/hash/set.rs | 28 +- src/libstd/macros.rs | 20 +- src/libstd/sync/mpsc/mod.rs | 1413 ++++++++++++++-------------- src/libstd/sync/rwlock.rs | 2 +- 20 files changed, 1429 insertions(+), 1377 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 1d679f18feb3e..25f80ad11bd11 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -35,7 +35,7 @@ //! use std::sync::Arc; //! use std::thread::Thread; //! -//! let five = Arc::new(5); +//! let five = Arc::new(5i); //! //! for i in range(0u, 10) { //! let five = five.clone(); @@ -52,7 +52,7 @@ //! use std::sync::{Arc, Mutex}; //! use std::thread::Thread; //! -//! let five = Arc::new(Mutex::new(5)); +//! let five = Arc::new(Mutex::new(5i)); //! //! for _ in range(0u, 10) { //! let five = five.clone(); @@ -154,7 +154,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// ``` #[inline] #[stable] @@ -176,7 +176,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// /// let weak_five = five.downgrade(); /// ``` @@ -220,7 +220,7 @@ impl Clone for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// /// five.clone(); /// ``` @@ -267,7 +267,7 @@ impl Arc { /// ``` /// use std::sync::Arc; /// - /// let mut five = Arc::new(5); + /// let mut five = Arc::new(5i); /// /// let mut_five = five.make_unique(); /// ``` @@ -303,14 +303,14 @@ impl Drop for Arc { /// use std::sync::Arc; /// /// { - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// /// // stuff /// /// drop(five); // explict drop /// } /// { - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// /// // stuff /// @@ -369,7 +369,7 @@ impl Weak { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// /// let weak_five = five.downgrade(); /// @@ -405,7 +405,7 @@ impl Clone for Weak { /// ``` /// use std::sync::Arc; /// - /// let weak_five = Arc::new(5).downgrade(); + /// let weak_five = Arc::new(5i).downgrade(); /// /// weak_five.clone(); /// ``` @@ -430,7 +430,7 @@ impl Drop for Weak { /// use std::sync::Arc; /// /// { - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// let weak_five = five.downgrade(); /// /// // stuff @@ -438,7 +438,7 @@ impl Drop for Weak { /// drop(weak_five); // explict drop /// } /// { - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// let weak_five = five.downgrade(); /// /// // stuff @@ -472,9 +472,9 @@ impl PartialEq for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five == Arc::new(5); + /// five == Arc::new(5i); /// ``` fn eq(&self, other: &Arc) -> bool { *(*self) == *(*other) } @@ -487,9 +487,9 @@ impl PartialEq for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five != Arc::new(5); + /// five != Arc::new(5i); /// ``` fn ne(&self, other: &Arc) -> bool { *(*self) != *(*other) } } @@ -504,9 +504,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five.partial_cmp(&Arc::new(5)); + /// five.partial_cmp(&Arc::new(5i)); /// ``` fn partial_cmp(&self, other: &Arc) -> Option { (**self).partial_cmp(&**other) @@ -521,9 +521,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five < Arc::new(5); + /// five < Arc::new(5i); /// ``` fn lt(&self, other: &Arc) -> bool { *(*self) < *(*other) } @@ -536,9 +536,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five <= Arc::new(5); + /// five <= Arc::new(5i); /// ``` fn le(&self, other: &Arc) -> bool { *(*self) <= *(*other) } @@ -551,9 +551,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five > Arc::new(5); + /// five > Arc::new(5i); /// ``` fn gt(&self, other: &Arc) -> bool { *(*self) > *(*other) } @@ -566,9 +566,9 @@ impl PartialOrd for Arc { /// ``` /// use std::sync::Arc; /// - /// let five = Arc::new(5); + /// let five = Arc::new(5i); /// - /// five >= Arc::new(5); + /// five >= Arc::new(5i); /// ``` fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1621e1934faec..175bba4e71dc4 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -187,7 +187,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// ``` #[stable] pub fn new(value: T) -> Rc { @@ -214,7 +214,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// /// let weak_five = five.downgrade(); /// ``` @@ -247,7 +247,7 @@ pub fn strong_count(this: &Rc) -> uint { this.strong() } /// use std::rc; /// use std::rc::Rc; /// -/// let five = Rc::new(5); +/// let five = Rc::new(5i); /// /// rc::is_unique(&five); /// ``` @@ -329,7 +329,7 @@ impl Rc { /// ``` /// use std::rc::Rc; /// - /// let mut five = Rc::new(5); + /// let mut five = Rc::new(5i); /// /// let mut_five = five.make_unique(); /// ``` @@ -378,14 +378,14 @@ impl Drop for Rc { /// use std::rc::Rc; /// /// { - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// /// // stuff /// /// drop(five); // explict drop /// } /// { - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// /// // stuff /// @@ -424,7 +424,7 @@ impl Clone for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// /// five.clone(); /// ``` @@ -465,9 +465,9 @@ impl PartialEq for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five == Rc::new(5); + /// five == Rc::new(5i); /// ``` #[inline(always)] fn eq(&self, other: &Rc) -> bool { **self == **other } @@ -481,9 +481,9 @@ impl PartialEq for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five != Rc::new(5); + /// five != Rc::new(5i); /// ``` #[inline(always)] fn ne(&self, other: &Rc) -> bool { **self != **other } @@ -503,9 +503,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five.partial_cmp(&Rc::new(5)); + /// five.partial_cmp(&Rc::new(5i)); /// ``` #[inline(always)] fn partial_cmp(&self, other: &Rc) -> Option { @@ -521,9 +521,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five < Rc::new(5); + /// five < Rc::new(5i); /// ``` #[inline(always)] fn lt(&self, other: &Rc) -> bool { **self < **other } @@ -537,9 +537,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five <= Rc::new(5); + /// five <= Rc::new(5i); /// ``` #[inline(always)] fn le(&self, other: &Rc) -> bool { **self <= **other } @@ -553,9 +553,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five > Rc::new(5); + /// five > Rc::new(5i); /// ``` #[inline(always)] fn gt(&self, other: &Rc) -> bool { **self > **other } @@ -569,9 +569,9 @@ impl PartialOrd for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five >= Rc::new(5); + /// five >= Rc::new(5i); /// ``` #[inline(always)] fn ge(&self, other: &Rc) -> bool { **self >= **other } @@ -588,9 +588,9 @@ impl Ord for Rc { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// - /// five.partial_cmp(&Rc::new(5)); + /// five.partial_cmp(&Rc::new(5i)); /// ``` #[inline] fn cmp(&self, other: &Rc) -> Ordering { (**self).cmp(&**other) } @@ -639,7 +639,7 @@ impl Weak { /// ``` /// use std::rc::Rc; /// - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// /// let weak_five = five.downgrade(); /// @@ -668,7 +668,7 @@ impl Drop for Weak { /// use std::rc::Rc; /// /// { - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// let weak_five = five.downgrade(); /// /// // stuff @@ -676,7 +676,7 @@ impl Drop for Weak { /// drop(weak_five); // explict drop /// } /// { - /// let five = Rc::new(5); + /// let five = Rc::new(5i); /// let weak_five = five.downgrade(); /// /// // stuff @@ -710,7 +710,7 @@ impl Clone for Weak { /// ``` /// use std::rc::Rc; /// - /// let weak_five = Rc::new(5).downgrade(); + /// let weak_five = Rc::new(5i).downgrade(); /// /// weak_five.clone(); /// ``` diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index d95c666b5860c..01693391abed5 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -212,7 +212,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]); + /// let heap = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]); /// ``` pub fn from_vec(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; @@ -231,7 +231,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); + /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order /// for x in heap.iter() { @@ -251,7 +251,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); + /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order /// for x in heap.into_iter() { @@ -273,7 +273,7 @@ impl BinaryHeap { /// let mut heap = BinaryHeap::new(); /// assert_eq!(heap.peek(), None); /// - /// heap.push(1); + /// heap.push(1i); /// heap.push(5); /// heap.push(2); /// assert_eq!(heap.peek(), Some(&5)); @@ -356,7 +356,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let mut heap = BinaryHeap::from_vec(vec![1, 3]); + /// let mut heap = BinaryHeap::from_vec(vec![1i, 3]); /// /// assert_eq!(heap.pop(), Some(3)); /// assert_eq!(heap.pop(), Some(1)); @@ -380,7 +380,7 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); - /// heap.push(3); + /// heap.push(3i); /// heap.push(5); /// heap.push(1); /// @@ -402,7 +402,7 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); - /// heap.push(1); + /// heap.push(1i); /// heap.push(5); /// /// assert_eq!(heap.push_pop(3), 5); @@ -434,7 +434,7 @@ impl BinaryHeap { /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// - /// assert_eq!(heap.replace(1), None); + /// assert_eq!(heap.replace(1i), None); /// assert_eq!(heap.replace(3), Some(1)); /// assert_eq!(heap.len(), 1); /// assert_eq!(heap.peek(), Some(&3)); @@ -457,7 +457,7 @@ impl BinaryHeap { /// /// ``` /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4, 5, 6, 7]); + /// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); /// let vec = heap.into_vec(); /// /// // Will print in some order @@ -475,12 +475,12 @@ impl BinaryHeap { /// ``` /// use std::collections::BinaryHeap; /// - /// let mut heap = BinaryHeap::from_vec(vec![1, 2, 4, 5, 7]); + /// let mut heap = BinaryHeap::from_vec(vec![1i, 2, 4, 5, 7]); /// heap.push(6); /// heap.push(3); /// /// let vec = heap.into_sorted_vec(); - /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]); + /// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]); /// ``` pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 82cef9b3549de..98f1633217060 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -245,7 +245,7 @@ impl BTreeSet { /// /// let mut v = BTreeSet::new(); /// assert_eq!(v.len(), 0); - /// v.insert(1); + /// v.insert(1i); /// assert_eq!(v.len(), 1); /// ``` #[stable] @@ -260,7 +260,7 @@ impl BTreeSet { /// /// let mut v = BTreeSet::new(); /// assert!(v.is_empty()); - /// v.insert(1); + /// v.insert(1i); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -274,7 +274,7 @@ impl BTreeSet { /// use std::collections::BTreeSet; /// /// let mut v = BTreeSet::new(); - /// v.insert(1); + /// v.insert(1i); /// v.clear(); /// assert!(v.is_empty()); /// ``` @@ -294,7 +294,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let set: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` @@ -311,7 +311,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let a: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); /// let mut b: BTreeSet = BTreeSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); @@ -332,7 +332,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let sup: BTreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let sup: BTreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); /// let mut set: BTreeSet = BTreeSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); @@ -374,7 +374,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let sub: BTreeSet = [1, 2].iter().map(|&x| x).collect(); + /// let sub: BTreeSet = [1i, 2].iter().map(|&x| x).collect(); /// let mut set: BTreeSet = BTreeSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); @@ -401,8 +401,8 @@ impl BTreeSet { /// /// let mut set = BTreeSet::new(); /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.insert(2i), true); + /// assert_eq!(set.insert(2i), false); /// assert_eq!(set.len(), 1); /// ``` #[stable] @@ -424,7 +424,7 @@ impl BTreeSet { /// /// let mut set = BTreeSet::new(); /// - /// set.insert(2); + /// set.insert(2i); /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index b3c1486eaf363..14d61edca0438 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -232,9 +232,9 @@ impl DList { /// /// let mut a = DList::new(); /// let mut b = DList::new(); - /// a.push_back(1); + /// a.push_back(1i); /// a.push_back(2); - /// b.push_back(3); + /// b.push_back(3i); /// b.push_back(4); /// /// a.append(b); @@ -377,7 +377,7 @@ impl DList { /// use std::collections::DList; /// /// let mut d = DList::new(); - /// d.push_back(1); + /// d.push_back(1i); /// d.push_back(3); /// assert_eq!(3, *d.back().unwrap()); /// ``` @@ -396,7 +396,7 @@ impl DList { /// /// let mut d = DList::new(); /// assert_eq!(d.pop_back(), None); - /// d.push_back(1); + /// d.push_back(1i); /// d.push_back(3); /// assert_eq!(d.pop_back(), Some(3)); /// ``` @@ -553,7 +553,7 @@ impl<'a, A> IterMut<'a, A> { /// } /// { /// let vec: Vec = list.into_iter().collect(); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// assert_eq!(vec, vec![1i, 2, 3, 4]); /// } /// ``` #[inline] diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 0ffede776eade..11775f62b1c54 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -186,7 +186,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3); + /// buf.push_back(3i); /// buf.push_back(4); /// buf.push_back(5); /// assert_eq!(buf.get(1).unwrap(), &4); @@ -209,7 +209,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3); + /// buf.push_back(3i); /// buf.push_back(4); /// buf.push_back(5); /// match buf.get_mut(1) { @@ -243,7 +243,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(3); + /// buf.push_back(3i); /// buf.push_back(4); /// buf.push_back(5); /// buf.swap(0, 2); @@ -495,7 +495,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5); + /// buf.push_back(5i); /// buf.push_back(3); /// buf.push_back(4); /// let b: &[_] = &[&5, &3, &4]; @@ -518,7 +518,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5); + /// buf.push_back(5i); /// buf.push_back(3); /// buf.push_back(4); /// for num in buf.iter_mut() { @@ -597,7 +597,7 @@ impl RingBuf { /// /// let mut v = RingBuf::new(); /// assert_eq!(v.len(), 0); - /// v.push_back(1); + /// v.push_back(1i); /// assert_eq!(v.len(), 1); /// ``` #[stable] @@ -612,7 +612,7 @@ impl RingBuf { /// /// let mut v = RingBuf::new(); /// assert!(v.is_empty()); - /// v.push_front(1); + /// v.push_front(1i); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -627,7 +627,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut v = RingBuf::new(); - /// v.push_back(1); + /// v.push_back(1i); /// assert_eq!(v.drain().next(), Some(1)); /// assert!(v.is_empty()); /// ``` @@ -647,7 +647,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut v = RingBuf::new(); - /// v.push_back(1); + /// v.push_back(1i); /// v.clear(); /// assert!(v.is_empty()); /// ``` @@ -668,9 +668,9 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.front(), None); /// - /// d.push_back(1); - /// d.push_back(2); - /// assert_eq!(d.front(), Some(&1)); + /// d.push_back(1i); + /// d.push_back(2i); + /// assert_eq!(d.front(), Some(&1i)); /// ``` #[stable] pub fn front(&self) -> Option<&T> { @@ -688,13 +688,13 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.front_mut(), None); /// - /// d.push_back(1); - /// d.push_back(2); + /// d.push_back(1i); + /// d.push_back(2i); /// match d.front_mut() { - /// Some(x) => *x = 9, + /// Some(x) => *x = 9i, /// None => (), /// } - /// assert_eq!(d.front(), Some(&9)); + /// assert_eq!(d.front(), Some(&9i)); /// ``` #[stable] pub fn front_mut(&mut self) -> Option<&mut T> { @@ -712,9 +712,9 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.back(), None); /// - /// d.push_back(1); - /// d.push_back(2); - /// assert_eq!(d.back(), Some(&2)); + /// d.push_back(1i); + /// d.push_back(2i); + /// assert_eq!(d.back(), Some(&2i)); /// ``` #[stable] pub fn back(&self) -> Option<&T> { @@ -732,13 +732,13 @@ impl RingBuf { /// let mut d = RingBuf::new(); /// assert_eq!(d.back(), None); /// - /// d.push_back(1); - /// d.push_back(2); + /// d.push_back(1i); + /// d.push_back(2i); /// match d.back_mut() { - /// Some(x) => *x = 9, + /// Some(x) => *x = 9i, /// None => (), /// } - /// assert_eq!(d.back(), Some(&9)); + /// assert_eq!(d.back(), Some(&9i)); /// ``` #[stable] pub fn back_mut(&mut self) -> Option<&mut T> { @@ -755,11 +755,11 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut d = RingBuf::new(); - /// d.push_back(1); - /// d.push_back(2); + /// d.push_back(1i); + /// d.push_back(2i); /// - /// assert_eq!(d.pop_front(), Some(1)); - /// assert_eq!(d.pop_front(), Some(2)); + /// assert_eq!(d.pop_front(), Some(1i)); + /// assert_eq!(d.pop_front(), Some(2i)); /// assert_eq!(d.pop_front(), None); /// ``` #[stable] @@ -781,9 +781,9 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut d = RingBuf::new(); - /// d.push_front(1); - /// d.push_front(2); - /// assert_eq!(d.front(), Some(&2)); + /// d.push_front(1i); + /// d.push_front(2i); + /// assert_eq!(d.front(), Some(&2i)); /// ``` #[stable] pub fn push_front(&mut self, t: T) { @@ -805,7 +805,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(1); + /// buf.push_back(1i); /// buf.push_back(3); /// assert_eq!(3, *buf.back().unwrap()); /// ``` @@ -831,7 +831,7 @@ impl RingBuf { /// /// let mut buf = RingBuf::new(); /// assert_eq!(buf.pop_back(), None); - /// buf.push_back(1); + /// buf.push_back(1i); /// buf.push_back(3); /// assert_eq!(buf.pop_back(), Some(3)); /// ``` @@ -928,7 +928,7 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(10); + /// buf.push_back(10i); /// buf.push_back(12); /// buf.insert(1,11); /// assert_eq!(Some(&11), buf.get(1)); @@ -1130,9 +1130,9 @@ impl RingBuf { /// use std::collections::RingBuf; /// /// let mut buf = RingBuf::new(); - /// buf.push_back(5); - /// buf.push_back(10); - /// buf.push_back(12); + /// buf.push_back(5i); + /// buf.push_back(10i); + /// buf.push_back(12i); /// buf.push_back(15); /// buf.remove(2); /// assert_eq!(Some(&15), buf.get(2)); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 1cb9e9009db62..9e5aa7d645ba0 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -15,7 +15,7 @@ //! //! ```rust //! // slicing a Vec -//! let vec = vec!(1, 2, 3); +//! let vec = vec!(1i, 2, 3); //! let int_slice = vec.as_slice(); //! // coercing an array to a slice //! let str_slice: &[&str] = &["one", "two", "three"]; @@ -26,7 +26,7 @@ //! block of memory that a mutable slice points to: //! //! ```rust -//! let x: &mut[int] = &mut [1, 2, 3]; +//! let x: &mut[int] = &mut [1i, 2, 3]; //! x[1] = 7; //! assert_eq!(x[0], 1); //! assert_eq!(x[1], 7); @@ -54,9 +54,9 @@ //! ```rust //! #![feature(slicing_syntax)] //! fn main() { -//! let numbers = [0, 1, 2]; +//! let numbers = [0i, 1i, 2i]; //! let last_numbers = numbers[1..3]; -//! // last_numbers is now &[1, 2] +//! // last_numbers is now &[1i, 2i] //! } //! ``` //! @@ -76,7 +76,7 @@ //! type of the slice is `int`, the element type of the iterator is `&int`. //! //! ```rust -//! let numbers = [0, 1, 2]; +//! let numbers = [0i, 1i, 2i]; //! for &x in numbers.iter() { //! println!("{} is a number!", x); //! } @@ -90,40 +90,38 @@ use alloc::boxed::Box; use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; -use core::cmp; -use core::iter::{range_step, MultiplicativeIterator}; +use core::clone::Clone; +use core::cmp::Ordering::{self, Greater, Less}; +use core::cmp::{self, Ord, PartialEq}; +use core::iter::{Iterator, IteratorExt}; +use core::iter::{range, range_step, MultiplicativeIterator}; use core::kinds::Sized; use core::mem::size_of; use core::mem; -use core::ops::{FnMut,SliceMut}; -use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option}; -use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result}; +use core::ops::{FnMut, SliceMut}; +use core::option::Option::{self, Some, None}; +use core::ptr::PtrExt; use core::ptr; +use core::result::Result; use core::slice as core_slice; use self::Direction::*; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; -pub use core::slice::{Iter, IterMut, PartialEqSliceExt}; +pub use core::slice::{Iter, IterMut}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; pub use core::slice::{from_raw_buf, from_raw_mut_buf}; -#[deprecated = "use Iter instead"] -pub type Items<'a, T:'a> = Iter<'a, T>; - -#[deprecated = "use IterMut instead"] -pub type MutItems<'a, T:'a> = IterMut<'a, T>; - //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// /// Allocating extension methods for slices. #[stable] -pub trait SliceExt for Sized? { +pub trait SliceExt { #[stable] type Item; @@ -136,7 +134,7 @@ pub trait SliceExt for Sized? { /// # Examples /// /// ```rust - /// let mut v = [5, 4, 1, 3, 2]; + /// let mut v = [5i, 4, 1, 3, 2]; /// v.sort_by(|a, b| a.cmp(b)); /// assert!(v == [1, 2, 3, 4, 5]); /// @@ -145,7 +143,7 @@ pub trait SliceExt for Sized? { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[stable] - fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering; + fn sort_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; /// Consumes `src` and moves as many elements as it can into `self` /// from the range [start,end). @@ -162,14 +160,14 @@ pub trait SliceExt for Sized? { /// # Examples /// /// ```rust - /// let mut a = [1, 2, 3, 4, 5]; - /// let b = vec![6, 7, 8]; + /// let mut a = [1i, 2, 3, 4, 5]; + /// let b = vec![6i, 7, 8]; /// let num_moved = a.move_from(b, 0, 3); /// assert_eq!(num_moved, 3); - /// assert!(a == [6, 7, 8, 4, 5]); + /// assert!(a == [6i, 7, 8, 4, 5]); /// ``` #[experimental = "uncertain about this API approach"] - fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; + fn move_from(&mut self, src: Vec, start: uint, end: uint) -> uint; /// Returns a subslice spanning the interval [`start`, `end`). /// @@ -178,7 +176,7 @@ pub trait SliceExt for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice(&self, start: uint, end: uint) -> &[T]; + fn slice(&self, start: uint, end: uint) -> &[Self::Item]; /// Returns a subslice from `start` to the end of the slice. /// @@ -186,7 +184,7 @@ pub trait SliceExt for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from(&self, start: uint) -> &[T]; + fn slice_from(&self, start: uint) -> &[Self::Item]; /// Returns a subslice from the start of the slice to `end`. /// @@ -194,7 +192,7 @@ pub trait SliceExt for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to(&self, end: uint) -> &[T]; + fn slice_to(&self, end: uint) -> &[Self::Item]; /// Divides one slice into two at an index. /// @@ -204,32 +202,32 @@ pub trait SliceExt for Sized? { /// /// Panics if `mid > len`. #[stable] - fn split_at(&self, mid: uint) -> (&[T], &[T]); + fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]); /// Returns an iterator over the slice #[stable] - fn iter(&self) -> Iter; + fn iter(&self) -> Iter; /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. #[stable] - fn split(&self, pred: F) -> Split - where F: FnMut(&T) -> bool; + fn split(&self, pred: F) -> Split + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn(&self, n: uint, pred: F) -> SplitN - where F: FnMut(&T) -> bool; + fn splitn(&self, n: uint, pred: F) -> SplitN + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn(&self, n: uint, pred: F) -> RSplitN - where F: FnMut(&T) -> bool; + fn rsplitn(&self, n: uint, pred: F) -> RSplitN + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over all contiguous windows of length /// `size`. The windows overlap. If the slice is shorter than @@ -245,13 +243,13 @@ pub trait SliceExt for Sized? { /// `[3,4]`): /// /// ```rust - /// let v = &[1, 2, 3, 4]; + /// let v = &[1i, 2, 3, 4]; /// for win in v.windows(2) { /// println!("{}", win); /// } /// ``` #[stable] - fn windows(&self, size: uint) -> Windows; + fn windows(&self, size: uint) -> Windows; /// Returns an iterator over `size` elements of the slice at a /// time. The chunks do not overlap. If `size` does not divide the @@ -268,49 +266,39 @@ pub trait SliceExt for Sized? { /// `[3,4]`, `[5]`): /// /// ```rust - /// let v = &[1, 2, 3, 4, 5]; + /// let v = &[1i, 2, 3, 4, 5]; /// for win in v.chunks(2) { /// println!("{}", win); /// } /// ``` #[stable] - fn chunks(&self, size: uint) -> Chunks; + fn chunks(&self, size: uint) -> Chunks; /// Returns the element of a slice at the given index, or `None` if the /// index is out of bounds. #[stable] - fn get(&self, index: uint) -> Option<&T>; + fn get(&self, index: uint) -> Option<&Self::Item>; /// Returns the first element of a slice, or `None` if it is empty. #[stable] - fn first(&self) -> Option<&T>; - - /// Deprecated: renamed to `first`. - #[deprecated = "renamed to `first`"] - fn head(&self) -> Option<&T> { self.first() } + fn first(&self) -> Option<&Self::Item>; /// Returns all but the first element of a slice. #[experimental = "likely to be renamed"] - fn tail(&self) -> &[T]; + fn tail(&self) -> &[Self::Item]; /// Returns all but the last element of a slice. #[experimental = "likely to be renamed"] - fn init(&self) -> &[T]; + fn init(&self) -> &[Self::Item]; /// Returns the last element of a slice, or `None` if it is empty. #[stable] - fn last(&self) -> Option<&T>; + fn last(&self) -> Option<&Self::Item>; /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable] - unsafe fn get_unchecked(&self, index: uint) -> &T; - - /// Deprecated: renamed to `get_unchecked`. - #[deprecated = "renamed to get_unchecked"] - unsafe fn unsafe_get(&self, index: uint) -> &T { - self.get_unchecked(index) - } + unsafe fn get_unchecked(&self, index: uint) -> &Self::Item; /// Returns an unsafe pointer to the slice's buffer /// @@ -320,7 +308,7 @@ pub trait SliceExt for Sized? { /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[stable] - fn as_ptr(&self) -> *const T; + fn as_ptr(&self) -> *const Self::Item; /// Binary search a sorted slice with a comparator function. /// @@ -341,7 +329,7 @@ pub trait SliceExt for Sized? { /// found; the fourth could match any position in `[1,4]`. /// /// ```rust - /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// let s = s.as_slice(); /// /// let seek = 13; @@ -356,14 +344,14 @@ pub trait SliceExt for Sized? { /// ``` #[stable] fn binary_search_by(&self, f: F) -> Result where - F: FnMut(&T) -> Ordering; + F: FnMut(&Self::Item) -> Ordering; /// Return the number of elements in the slice /// /// # Example /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [1i, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` #[stable] @@ -374,7 +362,7 @@ pub trait SliceExt for Sized? { /// # Example /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [1i, 2, 3]; /// assert!(!a.is_empty()); /// ``` #[inline] @@ -383,12 +371,12 @@ pub trait SliceExt for Sized? { /// Returns a mutable reference to the element at the given index, /// or `None` if the index is out of bounds #[stable] - fn get_mut(&mut self, index: uint) -> Option<&mut T>; + fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>; /// Work with `self` as a mut slice. /// Primarily intended for getting a &mut [T] from a [T; N]. #[stable] - fn as_mut_slice(&mut self) -> &mut [T]; + fn as_mut_slice(&mut self) -> &mut [Self::Item]; /// Returns a mutable subslice spanning the interval [`start`, `end`). /// @@ -397,7 +385,7 @@ pub trait SliceExt for Sized? { /// /// Slicing with `start` equal to `end` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T]; + fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from `start` to the end of the slice. /// @@ -405,7 +393,7 @@ pub trait SliceExt for Sized? { /// /// Slicing from `self.len()` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_from_mut(&mut self, start: uint) -> &mut [T]; + fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item]; /// Returns a mutable subslice from the start of the slice to `end`. /// @@ -413,54 +401,48 @@ pub trait SliceExt for Sized? { /// /// Slicing to `0` yields an empty slice. #[experimental = "will be replaced by slice syntax"] - fn slice_to_mut(&mut self, end: uint) -> &mut [T]; + fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item]; /// Returns an iterator that allows modifying each value #[stable] - fn iter_mut(&mut self) -> IterMut; + fn iter_mut(&mut self) -> IterMut; /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty #[stable] - fn first_mut(&mut self) -> Option<&mut T>; - - /// Depreated: renamed to `first_mut`. - #[deprecated = "renamed to first_mut"] - fn head_mut(&mut self) -> Option<&mut T> { - self.first_mut() - } + fn first_mut(&mut self) -> Option<&mut Self::Item>; /// Returns all but the first element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn tail_mut(&mut self) -> &mut [T]; + fn tail_mut(&mut self) -> &mut [Self::Item]; /// Returns all but the last element of a mutable slice #[experimental = "likely to be renamed or removed"] - fn init_mut(&mut self) -> &mut [T]; + fn init_mut(&mut self) -> &mut [Self::Item]; /// Returns a mutable pointer to the last item in the slice. #[stable] - fn last_mut(&mut self) -> Option<&mut T>; + fn last_mut(&mut self) -> Option<&mut Self::Item>; /// Returns an iterator over mutable subslices separated by elements that /// match `pred`. The matched element is not contained in the subslices. #[stable] - fn split_mut(&mut self, pred: F) -> SplitMut - where F: FnMut(&T) -> bool; + fn split_mut(&mut self, pred: F) -> SplitMut + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to splitting at most `n` times. The matched element is /// not contained in the subslices. #[stable] - fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut - where F: FnMut(&T) -> bool; + fn splitn_mut(&mut self, n: uint, pred: F) -> SplitNMut + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over subslices separated by elements that match /// `pred` limited to splitting at most `n` times. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. #[stable] - fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut - where F: FnMut(&T) -> bool; + fn rsplitn_mut(&mut self, n: uint, pred: F) -> RSplitNMut + where F: FnMut(&Self::Item) -> bool; /// Returns an iterator over `chunk_size` elements of the slice at a time. /// The chunks are mutable and do not overlap. If `chunk_size` does @@ -471,7 +453,7 @@ pub trait SliceExt for Sized? { /// /// Panics if `chunk_size` is 0. #[stable] - fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut; + fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut; /// Swaps two elements in a slice. /// @@ -507,51 +489,45 @@ pub trait SliceExt for Sized? { /// # Example /// /// ```rust - /// let mut v = [1, 2, 3, 4, 5, 6]; + /// let mut v = [1i, 2, 3, 4, 5, 6]; /// /// // scoped to restrict the lifetime of the borrows /// { /// let (left, right) = v.split_at_mut(0); /// assert!(left == []); - /// assert!(right == [1, 2, 3, 4, 5, 6]); + /// assert!(right == [1i, 2, 3, 4, 5, 6]); /// } /// /// { /// let (left, right) = v.split_at_mut(2); - /// assert!(left == [1, 2]); - /// assert!(right == [3, 4, 5, 6]); + /// assert!(left == [1i, 2]); + /// assert!(right == [3i, 4, 5, 6]); /// } /// /// { /// let (left, right) = v.split_at_mut(6); - /// assert!(left == [1, 2, 3, 4, 5, 6]); + /// assert!(left == [1i, 2, 3, 4, 5, 6]); /// assert!(right == []); /// } /// ``` #[stable] - fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]); + fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]); /// Reverse the order of elements in a slice, in place. /// /// # Example /// /// ```rust - /// let mut v = [1, 2, 3]; + /// let mut v = [1i, 2, 3]; /// v.reverse(); - /// assert!(v == [3, 2, 1]); + /// assert!(v == [3i, 2, 1]); /// ``` #[stable] fn reverse(&mut self); /// Returns an unsafe mutable pointer to the element in index #[stable] - unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T; - - /// Deprecated: renamed to `get_unchecked_mut`. - #[deprecated = "renamed to get_unchecked_mut"] - unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T { - self.get_unchecked_mut(index) - } + unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item; /// Return an unsafe mutable pointer to the slice's buffer. /// @@ -562,7 +538,167 @@ pub trait SliceExt for Sized? { /// would also make any pointers to it invalid. #[inline] #[stable] - fn as_mut_ptr(&mut self) -> *mut T; + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + /// Copies `self` into a new `Vec`. + #[stable] + fn to_vec(&self) -> Vec where Self::Item: Clone; + + /// Creates an iterator that yields every possible permutation of the + /// vector in succession. + /// + /// # Examples + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// for p in perms { + /// println!("{}", p); + /// } + /// ``` + /// + /// Iterating through permutations one by one. + /// + /// ```rust + /// let v = [1i, 2, 3]; + /// let mut perms = v.permutations(); + /// + /// assert_eq!(Some(vec![1i, 2, 3]), perms.next()); + /// assert_eq!(Some(vec![1i, 3, 2]), perms.next()); + /// assert_eq!(Some(vec![3i, 1, 2]), perms.next()); + /// ``` + #[unstable] + fn permutations(&self) -> Permutations where Self::Item: Clone; + + /// Copies as many elements from `src` as it can into `self` (the + /// shorter of `self.len()` and `src.len()`). Returns the number + /// of elements copied. + /// + /// # Example + /// + /// ```rust + /// let mut dst = [0i, 0, 0]; + /// let src = [1i, 2]; + /// + /// assert!(dst.clone_from_slice(&src) == 2); + /// assert!(dst == [1, 2, 0]); + /// + /// let src2 = [3i, 4, 5, 6]; + /// assert!(dst.clone_from_slice(&src2) == 3); + /// assert!(dst == [3i, 4, 5]); + /// ``` + #[experimental] + fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone; + + /// Sorts the slice, in place. + /// + /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. + /// + /// # Examples + /// + /// ```rust + /// let mut v = [-5i, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5i, -3, 1, 2, 4]); + /// ``` + #[stable] + fn sort(&mut self) where Self::Item: Ord; + + /// Binary search a sorted slice for a given element. + /// + /// If the value is found then `Ok` is returned, containing the + /// index of the matching element; if the value is not found then + /// `Err` is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// # Example + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1,4]`. + /// + /// ```rust + /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let s = s.as_slice(); + /// + /// assert_eq!(s.binary_search(&13), Ok(9)); + /// assert_eq!(s.binary_search(&4), Err(7)); + /// assert_eq!(s.binary_search(&100), Err(13)); + /// let r = s.binary_search(&1); + /// assert!(match r { Ok(1...4) => true, _ => false, }); + /// ``` + #[stable] + fn binary_search(&self, x: &Self::Item) -> Result where Self::Item: Ord; + + /// Deprecated: use `binary_search` instead. + #[deprecated = "use binary_search instead"] + fn binary_search_elem(&self, x: &Self::Item) -> Result where Self::Item: Ord { + self.binary_search(x) + } + + /// Mutates the slice to the next lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// last-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [0i, 1, 2]; + /// v.next_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.next_permutation(); + /// let b: &mut [_] = &mut [1i, 0, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn next_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Mutates the slice to the previous lexicographic permutation. + /// + /// Returns `true` if successful and `false` if the slice is at the + /// first-ordered permutation. + /// + /// # Example + /// + /// ```rust + /// let v: &mut [_] = &mut [1i, 0, 2]; + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 2, 1]; + /// assert!(v == b); + /// v.prev_permutation(); + /// let b: &mut [_] = &mut [0i, 1, 2]; + /// assert!(v == b); + /// ``` + #[unstable = "uncertain if this merits inclusion in std"] + fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + + /// Find the first index containing a matching value. + #[experimental] + fn position_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; + + /// Find the last index containing a matching value. + #[experimental] + fn rposition_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; + + /// Return true if the slice contains an element with the given value. + #[stable] + fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a prefix of the slice. + #[stable] + fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Returns true if `needle` is a suffix of the slice. + #[stable] + fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + + /// Convert `self` into a vector without clones or allocation. + #[experimental] + fn into_vec(self: Box) -> Vec; } #[stable] @@ -783,229 +919,76 @@ impl SliceExt for [T] { fn as_mut_ptr(&mut self) -> *mut T { core_slice::SliceExt::as_mut_ptr(self) } -} - -//////////////////////////////////////////////////////////////////////////////// -// Extension traits for slices over specifc kinds of data -//////////////////////////////////////////////////////////////////////////////// - -/// Extension methods for boxed slices. -#[experimental = "likely to merge into SliceExt if it survives"] -pub trait BoxedSliceExt { - /// Convert `self` into a vector without clones or allocation. - #[experimental] - fn into_vec(self) -> Vec; -} - -#[experimental = "trait is experimental"] -impl BoxedSliceExt for Box<[T]> { - fn into_vec(mut self) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } - } -} - -/// Allocating extension methods for slices containing `Clone` elements. -#[unstable = "likely to be merged into SliceExt"] -pub trait CloneSliceExt for Sized? { - /// Copies `self` into a new `Vec`. - #[stable] - fn to_vec(&self) -> Vec; - - /// Deprecated: use `iter().cloned().partition(f)` instead. - #[deprecated = "use iter().cloned().partition(f) instead"] - fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool; - - /// Creates an iterator that yields every possible permutation of the - /// vector in succession. - /// - /// # Examples - /// - /// ```rust - /// let v = [1, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// for p in perms { - /// println!("{}", p); - /// } - /// ``` - /// - /// Iterating through permutations one by one. - /// - /// ```rust - /// let v = [1, 2, 3]; - /// let mut perms = v.permutations(); - /// - /// assert_eq!(Some(vec![1, 2, 3]), perms.next()); - /// assert_eq!(Some(vec![1, 3, 2]), perms.next()); - /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); - /// ``` - #[unstable] - fn permutations(&self) -> Permutations; - - /// Copies as many elements from `src` as it can into `self` (the - /// shorter of `self.len()` and `src.len()`). Returns the number - /// of elements copied. - /// - /// # Example - /// - /// ```rust - /// let mut dst = [0, 0, 0]; - /// let src = [1, 2]; - /// - /// assert!(dst.clone_from_slice(&src) == 2); - /// assert!(dst == [1, 2, 0]); - /// - /// let src2 = [3, 4, 5, 6]; - /// assert!(dst.clone_from_slice(&src2) == 3); - /// assert!(dst == [3, 4, 5]); - /// ``` - #[experimental] - fn clone_from_slice(&mut self, &[T]) -> uint; -} - -#[unstable = "trait is unstable"] -impl CloneSliceExt for [T] { /// Returns a copy of `v`. #[inline] - fn to_vec(&self) -> Vec { + fn to_vec(&self) -> Vec where T: Clone { let mut vector = Vec::with_capacity(self.len()); vector.push_all(self); vector } - - #[inline] - fn partitioned(&self, f: F) -> (Vec, Vec) where F: FnMut(&T) -> bool { - self.iter().cloned().partition(f) - } - /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations { + fn permutations(&self) -> Permutations where T: Clone { Permutations{ swaps: ElementSwaps::new(self.len()), v: self.to_vec(), } } - fn clone_from_slice(&mut self, src: &[T]) -> uint { - core_slice::CloneSliceExt::clone_from_slice(self, src) + fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) } -} -/// Allocating extension methods for slices on Ord values. -#[unstable = "likely to merge with SliceExt"] -pub trait OrdSliceExt for Sized? { - /// Sorts the slice, in place. - /// - /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`. - /// - /// # Examples - /// - /// ```rust - /// let mut v = [-5, 4, 1, -3, 2]; - /// - /// v.sort(); - /// assert!(v == [-5, -3, 1, 2, 4]); - /// ``` - #[stable] - fn sort(&mut self); + #[inline] + fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } - /// Binary search a sorted slice for a given element. - /// - /// If the value is found then `Ok` is returned, containing the - /// index of the matching element; if the value is not found then - /// `Err` is returned, containing the index where a matching - /// element could be inserted while maintaining sorted order. - /// - /// # Example - /// - /// Looks up a series of four elements. The first is found, with a - /// uniquely determined position; the second and third are not - /// found; the fourth could match any position in `[1,4]`. - /// - /// ```rust - /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); - /// - /// assert_eq!(s.binary_search(&13), Ok(9)); - /// assert_eq!(s.binary_search(&4), Err(7)); - /// assert_eq!(s.binary_search(&100), Err(13)); - /// let r = s.binary_search(&1); - /// assert!(match r { Ok(1...4) => true, _ => false, }); - /// ``` - #[stable] - fn binary_search(&self, x: &T) -> Result; + fn binary_search(&self, x: &T) -> Result where T: Ord { + core_slice::SliceExt::binary_search(self, x) + } - /// Deprecated: use `binary_search` instead. - #[deprecated = "use binary_search instead"] - fn binary_search_elem(&self, x: &T) -> Result { - self.binary_search(x) + fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) } - /// Mutates the slice to the next lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// last-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [0, 1, 2]; - /// v.next_permutation(); - /// let b: &mut [_] = &mut [0, 2, 1]; - /// assert!(v == b); - /// v.next_permutation(); - /// let b: &mut [_] = &mut [1, 0, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn next_permutation(&mut self) -> bool; + fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } - /// Mutates the slice to the previous lexicographic permutation. - /// - /// Returns `true` if successful and `false` if the slice is at the - /// first-ordered permutation. - /// - /// # Example - /// - /// ```rust - /// let v: &mut [_] = &mut [1, 0, 2]; - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0, 2, 1]; - /// assert!(v == b); - /// v.prev_permutation(); - /// let b: &mut [_] = &mut [0, 1, 2]; - /// assert!(v == b); - /// ``` - #[unstable = "uncertain if this merits inclusion in std"] - fn prev_permutation(&mut self) -> bool; -} + fn position_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } -#[unstable = "trait is unstable"] -impl OrdSliceExt for [T] { - #[inline] - fn sort(&mut self) { - self.sort_by(|a, b| a.cmp(b)) + fn rposition_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) } - fn binary_search(&self, x: &T) -> Result { - core_slice::OrdSliceExt::binary_search(self, x) + fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) } - fn next_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::next_permutation(self) + fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) } - fn prev_permutation(&mut self) -> bool { - core_slice::OrdSliceExt::prev_permutation(self) + fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) + } + + fn into_vec(mut self: Box) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); + mem::forget(self); + xs + } } } +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specifc kinds of data +//////////////////////////////////////////////////////////////////////////////// #[unstable = "U should be an associated type"] /// An extension trait for concatenating slices pub trait SliceConcatExt { @@ -1013,20 +996,10 @@ pub trait SliceConcatExt { #[stable] fn concat(&self) -> U; - #[deprecated = "renamed to concat"] - fn concat_vec(&self) -> U { - self.concat() - } - /// Flattens a slice of `T` into a single value `U`, placing a /// given seperator between each. #[stable] fn connect(&self, sep: &T) -> U; - - #[deprecated = "renamed to connect"] - fn connect_vec(&self, sep: &T) -> U { - self.connect(sep) - } } impl> SliceConcatExt> for [V] { @@ -1062,7 +1035,7 @@ impl> SliceConcatExt> for [V] { /// The last generated swap is always (0, 1), and it returns the /// sequence to its initial order. #[experimental] -#[deriving(Clone)] +#[derive(Clone)] pub struct ElementSwaps { sdir: Vec, /// If `true`, emit the last swap that returns the sequence to initial @@ -1109,11 +1082,11 @@ impl ToOwned> for [T] { // Iterators //////////////////////////////////////////////////////////////////////////////// -#[deriving(Copy, Clone)] +#[derive(Copy, Clone)] enum Direction { Pos, Neg } /// An `Index` and `Direction` together. -#[deriving(Copy, Clone)] +#[derive(Copy, Clone)] struct SizeDirection { size: uint, dir: Direction, @@ -1189,7 +1162,9 @@ pub struct Permutations { } #[unstable = "trait is unstable"] -impl Iterator> for Permutations { +impl Iterator for Permutations { + type Item = Vec; + #[inline] fn next(&mut self) -> Option> { match self.swaps.next() { @@ -1416,21 +1391,12 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order } } -/// Deprecated, unsafe operations -#[deprecated] -pub mod raw { - pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice}; - pub use core::slice::raw::{shift_ptr, pop_ptr}; -} - #[cfg(test)] mod tests { - use std::boxed::Box; use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal}; - use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt}; - use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice}; + use prelude::{SliceExt, Iterator, IteratorExt}; + use prelude::AsSlice; use prelude::{RandomAccessIterator, Ord, SliceConcatExt}; - use core::cell::Cell; use core::default::Default; use core::mem; use std::rand::{Rng, thread_rng}; @@ -1444,7 +1410,7 @@ mod tests { #[test] fn test_from_fn() { // Test on-stack from_fn. - let mut v = Vec::from_fn(3u, square); + let mut v = range(0, 3).map(square).collect::>(); { let v = v.as_slice(); assert_eq!(v.len(), 3u); @@ -1454,7 +1420,7 @@ mod tests { } // Test on-heap from_fn. - v = Vec::from_fn(5u, square); + v = range(0, 5).map(square).collect::>(); { let v = v.as_slice(); assert_eq!(v.len(), 5u); @@ -1469,7 +1435,7 @@ mod tests { #[test] fn test_from_elem() { // Test on-stack from_elem. - let mut v = Vec::from_elem(2u, 10u); + let mut v = vec![10u, 10u]; { let v = v.as_slice(); assert_eq!(v.len(), 2u); @@ -1478,7 +1444,7 @@ mod tests { } // Test on-heap from_elem. - v = Vec::from_elem(6u, 20u); + v = vec![20u, 20u, 20u, 20u, 20u, 20u]; { let v = v.as_slice(); assert_eq!(v[0], 20u); @@ -1520,23 +1486,23 @@ mod tests { } #[test] - fn test_head() { + fn test_first() { let mut a = vec![]; - assert_eq!(a.as_slice().head(), None); + assert_eq!(a.as_slice().first(), None); a = vec![11i]; - assert_eq!(a.as_slice().head().unwrap(), &11); + assert_eq!(a.as_slice().first().unwrap(), &11); a = vec![11i, 12]; - assert_eq!(a.as_slice().head().unwrap(), &11); + assert_eq!(a.as_slice().first().unwrap(), &11); } #[test] - fn test_head_mut() { + fn test_first_mut() { let mut a = vec![]; - assert_eq!(a.head_mut(), None); + assert_eq!(a.first_mut(), None); a = vec![11i]; - assert_eq!(*a.head_mut().unwrap(), 11); + assert_eq!(*a.first_mut().unwrap(), 11); a = vec![11i, 12]; - assert_eq!(*a.head_mut().unwrap(), 11); + assert_eq!(*a.first_mut().unwrap(), 11); } #[test] @@ -1740,42 +1706,6 @@ mod tests { assert_eq!(v.as_slice()[1], 2); } - #[test] - fn test_grow() { - // Test on-stack grow(). - let mut v = vec![]; - v.grow(2u, 1i); - { - let v = v.as_slice(); - assert_eq!(v.len(), 2u); - assert_eq!(v[0], 1); - assert_eq!(v[1], 1); - } - - // Test on-heap grow(). - v.grow(3u, 2i); - { - let v = v.as_slice(); - assert_eq!(v.len(), 5u); - assert_eq!(v[0], 1); - assert_eq!(v[1], 1); - assert_eq!(v[2], 2); - assert_eq!(v[3], 2); - assert_eq!(v[4], 2); - } - } - - #[test] - fn test_grow_fn() { - let mut v = vec![]; - v.grow_fn(3u, square); - let v = v.as_slice(); - assert_eq!(v.len(), 3u); - assert_eq!(v[0], 0u); - assert_eq!(v[1], 1u); - assert_eq!(v[2], 4u); - } - #[test] fn test_truncate() { let mut v = vec![box 6i,box 5,box 4]; @@ -2108,22 +2038,6 @@ mod tests { } } - #[test] - fn test_partition() { - assert_eq!((vec![]).partition(|x: &int| *x < 3), (vec![], vec![])); - assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 2), (vec![1], vec![2, 3])); - assert_eq!((vec![1i, 2, 3]).partition(|x: &int| *x < 0), (vec![], vec![1, 2, 3])); - } - - #[test] - fn test_partitioned() { - assert_eq!(([]).partitioned(|x: &int| *x < 3), (vec![], vec![])); - assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 2), (vec![1], vec![2, 3])); - assert_eq!(([1i, 2, 3]).partitioned(|x: &int| *x < 0), (vec![], vec![1, 2, 3])); - } - #[test] fn test_concat() { let v: [Vec; 0] = []; @@ -2141,14 +2055,14 @@ mod tests { #[test] fn test_connect() { let v: [Vec; 0] = []; - assert_eq!(v.connect_vec(&0), vec![]); - assert_eq!([vec![1i], vec![2i, 3]].connect_vec(&0), vec![1, 0, 2, 3]); - assert_eq!([vec![1i], vec![2i], vec![3i]].connect_vec(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), vec![]); + assert_eq!([vec![1i], vec![2i, 3]].connect(&0), vec![1, 0, 2, 3]); + assert_eq!([vec![1i], vec![2i], vec![3i]].connect(&0), vec![1, 0, 2, 0, 3]); let v: [&[int]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]); + assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); let v: [&[int]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]); + assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); } #[test] @@ -2221,55 +2135,6 @@ mod tests { assert_eq!(v[1], 3); } - - #[test] - #[should_fail] - fn test_from_fn_fail() { - Vec::from_fn(100, |v| { - if v == 50 { panic!() } - box 0i - }); - } - - #[test] - #[should_fail] - fn test_from_elem_fail() { - - struct S { - f: Cell, - boxes: (Box, Rc) - } - - impl Clone for S { - fn clone(&self) -> S { - self.f.set(self.f.get() + 1); - if self.f.get() == 10 { panic!() } - S { - f: self.f.clone(), - boxes: self.boxes.clone(), - } - } - } - - let s = S { - f: Cell::new(0), - boxes: (box 0, Rc::new(0)), - }; - let _ = Vec::from_elem(100, s); - } - - #[test] - #[should_fail] - fn test_grow_fn_fail() { - let mut v = vec![]; - v.grow_fn(100, |i| { - if i == 50 { - panic!() - } - (box 0i, Rc::new(0i)) - }) - } - #[test] #[should_fail] fn test_permute_fail() { @@ -2687,7 +2552,7 @@ mod tests { assert!(values == [2, 3, 5, 6, 7]); } - #[deriving(Clone, PartialEq)] + #[derive(Clone, PartialEq)] struct Foo; #[test] @@ -2858,6 +2723,7 @@ mod bench { use prelude::*; use core::mem; use core::ptr; + use core::iter::repeat; use std::rand::{weak_rng, Rng}; use test::{Bencher, black_box}; @@ -2865,7 +2731,7 @@ mod bench { fn iterator(b: &mut Bencher) { // peculiar numbers to stop LLVM from optimising the summation // out. - let v = Vec::from_fn(100, |i| i ^ (i << 1) ^ (i >> 1)); + let v = range(0u, 100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect::>(); b.iter(|| { let mut sum = 0; @@ -2879,7 +2745,7 @@ mod bench { #[bench] fn mut_iterator(b: &mut Bencher) { - let mut v = Vec::from_elem(100, 0i); + let mut v = repeat(0i).take(100).collect::>(); b.iter(|| { let mut i = 0i; @@ -2893,7 +2759,7 @@ mod bench { #[bench] fn concat(b: &mut Bencher) { let xss: Vec> = - Vec::from_fn(100, |i| range(0u, i).collect()); + range(0, 100u).map(|i| range(0, i).collect()).collect(); b.iter(|| { xss.as_slice().concat(); }); @@ -2902,9 +2768,9 @@ mod bench { #[bench] fn connect(b: &mut Bencher) { let xss: Vec> = - Vec::from_fn(100, |i| range(0u, i).collect()); + range(0, 100u).map(|i| range(0, i).collect()).collect(); b.iter(|| { - xss.as_slice().connect_vec(&0) + xss.as_slice().connect(&0) }); } @@ -2919,7 +2785,7 @@ mod bench { #[bench] fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec = Vec::from_fn(100, |i| i); + let vec: Vec = range(0, 100).collect(); b.iter(|| { vec.as_slice().starts_with(vec.as_slice()) }) @@ -2935,8 +2801,8 @@ mod bench { #[bench] fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec = Vec::from_fn(100, |i| i); - let mut match_vec: Vec = Vec::from_fn(99, |i| i); + let vec: Vec = range(0, 100).collect(); + let mut match_vec: Vec = range(0, 99).collect(); match_vec.push(0); b.iter(|| { vec.as_slice().starts_with(match_vec.as_slice()) @@ -2945,7 +2811,7 @@ mod bench { #[bench] fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec = Vec::from_fn(100, |i| i); + let vec: Vec = range(0, 100).collect(); b.iter(|| { vec.as_slice().ends_with(vec.as_slice()) }) @@ -2961,8 +2827,8 @@ mod bench { #[bench] fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec = Vec::from_fn(100, |i| i); - let mut match_vec: Vec = Vec::from_fn(100, |i| i); + let vec: Vec = range(0, 100).collect(); + let mut match_vec: Vec = range(0, 100).collect(); match_vec.as_mut_slice()[0] = 200; b.iter(|| { vec.as_slice().starts_with(match_vec.as_slice()) @@ -2971,7 +2837,7 @@ mod bench { #[bench] fn contains_last_element(b: &mut Bencher) { - let vec: Vec = Vec::from_fn(100, |i| i); + let vec: Vec = range(0, 100).collect(); b.iter(|| { vec.contains(&99u) }) @@ -2980,7 +2846,7 @@ mod bench { #[bench] fn zero_1kb_from_elem(b: &mut Bencher) { b.iter(|| { - Vec::from_elem(1024, 0u8) + repeat(0u8).take(1024).collect::>() }); } @@ -3028,24 +2894,24 @@ mod bench { fn random_inserts(b: &mut Bencher) { let mut rng = weak_rng(); b.iter(|| { - let mut v = Vec::from_elem(30, (0u, 0u)); - for _ in range(0u, 100) { - let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); - } - }) + let mut v = repeat((0u, 0u)).take(30).collect::>(); + for _ in range(0u, 100) { + let l = v.len(); + v.insert(rng.gen::() % (l + 1), + (1, 1)); + } + }) } #[bench] fn random_removes(b: &mut Bencher) { let mut rng = weak_rng(); b.iter(|| { - let mut v = Vec::from_elem(130, (0u, 0u)); - for _ in range(0u, 100) { - let l = v.len(); - v.remove(rng.gen::() % l); - } - }) + let mut v = repeat((0u, 0u)).take(130).collect::>(); + for _ in range(0u, 100) { + let l = v.len(); + v.remove(rng.gen::() % l); + } + }) } #[bench] @@ -3080,7 +2946,7 @@ mod bench { #[bench] fn sort_sorted(b: &mut Bencher) { - let mut v = Vec::from_fn(10000, |i| i); + let mut v = range(0u, 10000).collect::>(); b.iter(|| { v.sort(); }); @@ -3124,7 +2990,7 @@ mod bench { #[bench] fn sort_big_sorted(b: &mut Bencher) { - let mut v = Vec::from_fn(10000u, |i| (i, i, i, i)); + let mut v = range(0, 10000u).map(|i| (i, i, i, i)).collect::>(); b.iter(|| { v.sort(); }); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 86f5f61b2105e..99231e7253c3c 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -25,13 +25,13 @@ //! ``` //! let ys: Vec = vec![]; //! -//! let zs = vec![1, 2, 3, 4, 5]; +//! let zs = vec![1i32, 2, 3, 4, 5]; //! ``` //! //! Push: //! //! ``` -//! let mut xs = vec![1, 2]; +//! let mut xs = vec![1i32, 2]; //! //! xs.push(3); //! ``` @@ -39,7 +39,7 @@ //! And pop: //! //! ``` -//! let mut xs = vec![1, 2]; +//! let mut xs = vec![1i32, 2]; //! //! let two = xs.pop(); //! ``` @@ -71,8 +71,8 @@ use core::uint; /// /// ``` /// let mut vec = Vec::new(); -/// vec.push(1); -/// vec.push(2); +/// vec.push(1i); +/// vec.push(2i); /// /// assert_eq!(vec.len(), 2); /// assert_eq!(vec[0], 1); @@ -80,7 +80,7 @@ use core::uint; /// assert_eq!(vec.pop(), Some(2)); /// assert_eq!(vec.len(), 1); /// -/// vec[0] = 7; +/// vec[0] = 7i; /// assert_eq!(vec[0], 7); /// /// vec.push_all(&[1, 2, 3]); @@ -88,13 +88,13 @@ use core::uint; /// for x in vec.iter() { /// println!("{}", x); /// } -/// assert_eq!(vec, vec![7, 1, 2, 3]); +/// assert_eq!(vec, vec![7i, 1, 2, 3]); /// ``` /// /// The `vec!` macro is provided to make initialization more convenient: /// /// ``` -/// let mut vec = vec![1, 2, 3]; +/// let mut vec = vec![1i, 2i, 3i]; /// vec.push(4); /// assert_eq!(vec, vec![1, 2, 3, 4]); /// ``` @@ -104,9 +104,9 @@ use core::uint; /// ``` /// let mut stack = Vec::new(); /// -/// stack.push(1); -/// stack.push(2); -/// stack.push(3); +/// stack.push(1i); +/// stack.push(2i); +/// stack.push(3i); /// /// loop { /// let top = match stack.pop() { @@ -218,7 +218,7 @@ impl Vec { /// use std::mem; /// /// fn main() { - /// let mut v = vec![1, 2, 3]; + /// let mut v = vec![1i, 2, 3]; /// /// // Pull out the various important pieces of information about `v` /// let p = v.as_mut_ptr(); @@ -237,7 +237,7 @@ impl Vec { /// /// // Put everything back together into a Vec /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, vec![4, 5, 6]); + /// assert_eq!(rebuilt, vec![4i, 5i, 6i]); /// } /// } /// ``` @@ -392,7 +392,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1, 2, 3, 4]; + /// let mut vec = vec![1i, 2, 3, 4]; /// vec.truncate(2); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -416,7 +416,7 @@ impl Vec { /// ``` /// fn foo(slice: &mut [int]) {} /// - /// let mut vec = vec![1, 2]; + /// let mut vec = vec![1i, 2]; /// foo(vec.as_mut_slice()); /// ``` #[inline] @@ -519,7 +519,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1, 2, 3]; + /// let mut vec = vec![1i, 2, 3]; /// vec.insert(1, 4); /// assert_eq!(vec, vec![1, 4, 2, 3]); /// vec.insert(4, 5); @@ -557,7 +557,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut v = vec![1, 2, 3]; + /// let mut v = vec![1i, 2, 3]; /// assert_eq!(v.remove(1), 2); /// assert_eq!(v, vec![1, 3]); /// ``` @@ -591,7 +591,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1, 2, 3, 4]; + /// let mut vec = vec![1i, 2, 3, 4]; /// vec.retain(|&x| x%2 == 0); /// assert_eq!(vec, vec![2, 4]); /// ``` @@ -624,7 +624,7 @@ impl Vec { /// # Examples /// /// ```rust - /// let mut vec = vec!(1, 2); + /// let mut vec = vec!(1i, 2); /// vec.push(3); /// assert_eq!(vec, vec!(1, 2, 3)); /// ``` @@ -662,7 +662,7 @@ impl Vec { /// # Examples /// /// ```rust - /// let mut vec = vec![1, 2, 3]; + /// let mut vec = vec![1i, 2, 3]; /// assert_eq!(vec.pop(), Some(3)); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -716,7 +716,7 @@ impl Vec { /// # Examples /// /// ``` - /// let mut v = vec![1, 2, 3]; + /// let mut v = vec![1i, 2, 3]; /// /// v.clear(); /// @@ -733,7 +733,7 @@ impl Vec { /// # Examples /// /// ``` - /// let a = vec![1, 2, 3]; + /// let a = vec![1i, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` #[inline] @@ -748,7 +748,7 @@ impl Vec { /// let mut v = Vec::new(); /// assert!(v.is_empty()); /// - /// v.push(1); + /// v.push(1i); /// assert!(!v.is_empty()); /// ``` #[stable] @@ -965,7 +965,7 @@ impl Vec { /// vec.resize(3, "world"); /// assert_eq!(vec, vec!["hello", "world", "world"]); /// - /// let mut vec = vec![1, 2, 3, 4]; + /// let mut vec = vec![1i, 2, 3, 4]; /// vec.resize(2, 0); /// assert_eq!(vec, vec![1, 2]); /// ``` @@ -988,8 +988,8 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1]; - /// vec.push_all(&[2, 3, 4]); + /// let mut vec = vec![1i]; + /// vec.push_all(&[2i, 3, 4]); /// assert_eq!(vec, vec![1, 2, 3, 4]); /// ``` #[inline] @@ -1021,11 +1021,11 @@ impl Vec { /// # Examples /// /// ``` - /// let mut vec = vec![1, 2, 2, 3, 2]; + /// let mut vec = vec![1i, 2, 2, 3, 2]; /// /// vec.dedup(); /// - /// assert_eq!(vec, vec![1, 2, 3, 2]); + /// assert_eq!(vec, vec![1i, 2, 3, 2]); /// ``` #[stable] pub fn dedup(&mut self) { @@ -1378,7 +1378,7 @@ impl AsSlice for Vec { /// ``` /// fn foo(slice: &[int]) {} /// - /// let vec = vec![1, 2]; + /// let vec = vec![1i, 2]; /// foo(vec.as_slice()); /// ``` #[inline] diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 0f326aac052e3..15c20253c8bc7 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -765,7 +765,7 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::AtomicPtr; /// - /// let ptr = &mut 5; + /// let ptr = &mut 5i; /// let atomic_ptr = AtomicPtr::new(ptr); /// ``` #[inline] @@ -787,7 +787,7 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5; + /// let ptr = &mut 5i; /// let some_ptr = AtomicPtr::new(ptr); /// /// let value = some_ptr.load(Ordering::Relaxed); @@ -809,10 +809,10 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5; + /// let ptr = &mut 5i; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10; + /// let other_ptr = &mut 10i; /// /// some_ptr.store(other_ptr, Ordering::Relaxed); /// ``` @@ -835,10 +835,10 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5; + /// let ptr = &mut 5i; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10; + /// let other_ptr = &mut 10i; /// /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed); /// ``` @@ -860,11 +860,11 @@ impl AtomicPtr { /// ``` /// use std::sync::atomic::{AtomicPtr, Ordering}; /// - /// let ptr = &mut 5; + /// let ptr = &mut 5i; /// let some_ptr = AtomicPtr::new(ptr); /// - /// let other_ptr = &mut 10; - /// let another_ptr = &mut 10; + /// let other_ptr = &mut 10i; + /// let another_ptr = &mut 10i; /// /// let value = some_ptr.compare_and_swap(other_ptr, another_ptr, Ordering::Relaxed); /// ``` diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index c9646bb3d3506..e0724fc2da5f5 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -145,7 +145,7 @@ pub struct RadixFmt(T, R); /// /// ``` /// use std::fmt::radix; -/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string()); +/// assert_eq!(format!("{}", radix(55i, 36)), "1j".to_string()); /// ``` #[unstable = "may be renamed or move to a different module"] pub fn radix(x: T, base: u8) -> RadixFmt { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 79c268c844167..9a2245501a814 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -33,7 +33,7 @@ //! translated to the `loop` below. //! //! ```rust -//! let values = vec![1, 2, 3]; +//! let values = vec![1i, 2, 3]; //! //! // "Syntactical sugar" taking advantage of an iterator //! for &x in values.iter() { @@ -176,8 +176,8 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [0]; - /// let b = [1]; + /// let a = [0i]; + /// let b = [1i]; /// let mut it = a.iter().chain(b.iter()); /// assert_eq!(it.next().unwrap(), &0); /// assert_eq!(it.next().unwrap(), &1); @@ -199,10 +199,10 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [0]; - /// let b = [1]; + /// let a = [0i]; + /// let b = [1i]; /// let mut it = a.iter().zip(b.iter()); - /// let (x0, x1) = (0, 1); + /// let (x0, x1) = (0i, 1i); /// assert_eq!(it.next().unwrap(), (&x0, &x1)); /// assert!(it.next().is_none()); /// ``` @@ -220,7 +220,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2]; + /// let a = [1i, 2]; /// let mut it = a.iter().map(|&x| 2 * x); /// assert_eq!(it.next().unwrap(), 2); /// assert_eq!(it.next().unwrap(), 4); @@ -241,7 +241,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2]; + /// let a = [1i, 2]; /// let mut it = a.iter().filter(|&x| *x > 1); /// assert_eq!(it.next().unwrap(), &2); /// assert!(it.next().is_none()); @@ -261,7 +261,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2]; + /// let a = [1i, 2]; /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); /// assert_eq!(it.next().unwrap(), 4); /// assert!(it.next().is_none()); @@ -280,9 +280,9 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [100, 200]; + /// let a = [100i, 200]; /// let mut it = a.iter().enumerate(); - /// let (x100, x200) = (100, 200); + /// let (x100, x200) = (100i, 200i); /// assert_eq!(it.next().unwrap(), (0, &x100)); /// assert_eq!(it.next().unwrap(), (1, &x200)); /// assert!(it.next().is_none()); @@ -299,7 +299,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let xs = [100, 200, 300]; + /// let xs = [100i, 200, 300]; /// let mut it = xs.iter().map(|x| *x).peekable(); /// assert_eq!(*it.peek().unwrap(), 100); /// assert_eq!(it.next().unwrap(), 100); @@ -323,7 +323,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 2, 1]; + /// let a = [1i, 2, 3, 2, 1]; /// let mut it = a.iter().skip_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &3); /// assert_eq!(it.next().unwrap(), &2); @@ -345,7 +345,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 2, 1]; + /// let a = [1i, 2, 3, 2, 1]; /// let mut it = a.iter().take_while(|&a| *a < 3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -365,7 +365,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let mut it = a.iter().skip(3); /// assert_eq!(it.next().unwrap(), &4); /// assert_eq!(it.next().unwrap(), &5); @@ -383,7 +383,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let mut it = a.iter().take(3); /// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next().unwrap(), &2); @@ -404,7 +404,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let mut it = a.iter().scan(1, |fac, &x| { /// *fac = *fac * x; /// Some(*fac) @@ -477,9 +477,9 @@ pub trait IteratorExt: Iterator + Sized { /// } /// sum /// } - /// let x = vec![1,2,3,7,8,9]; + /// let x = vec![1i,2,3,7,8,9]; /// assert_eq!(process(x.into_iter()), 6); - /// let x = vec![1,2,3]; + /// let x = vec![1i,2,3]; /// assert_eq!(process(x.into_iter()), 1006); /// ``` #[inline] @@ -540,7 +540,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let b: Vec = a.iter().map(|&x| x).collect(); /// assert!(a.as_slice() == b.as_slice()); /// ``` @@ -556,7 +556,7 @@ pub trait IteratorExt: Iterator + Sized { /// do not. /// /// ``` - /// let vec = vec![1, 2, 3, 4]; + /// let vec = vec![1i, 2i, 3i, 4i]; /// let (even, odd): (Vec, Vec) = vec.into_iter().partition(|&n| n % 2 == 0); /// assert_eq!(even, vec![2, 4]); /// assert_eq!(odd, vec![1, 3]); @@ -586,7 +586,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); /// ``` #[inline] @@ -606,7 +606,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// assert!(a.iter().all(|x| *x > 0)); /// assert!(!a.iter().all(|x| *x > 2)); /// ``` @@ -623,7 +623,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Example /// /// ```rust - /// let a = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.any(|x| *x == 3)); /// assert!(!it.any(|x| *x == 3)); @@ -812,7 +812,7 @@ pub trait IteratorExt: Iterator + Sized { /// ```rust /// use core::num::SignedInt; /// - /// let xs = [-3, 0, 1, 5, -10]; + /// let xs = [-3i, 0, 1, 5, -10]; /// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); /// ``` #[inline] @@ -841,7 +841,7 @@ pub trait IteratorExt: Iterator + Sized { /// ```rust /// use core::num::SignedInt; /// - /// let xs = [-3, 0, 1, 5, -10]; + /// let xs = [-3i, 0, 1, 5, -10]; /// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); /// ``` #[inline] @@ -1096,7 +1096,7 @@ pub trait AdditiveIterator { /// ```rust /// use std::iter::AdditiveIterator; /// - /// let a: [i32] = [1, 2, 3, 4, 5]; + /// let a = [1i, 2, 3, 4, 5]; /// let mut it = a.iter().map(|&x| x); /// assert!(it.sum() == 15); /// ``` @@ -1171,6 +1171,134 @@ impl_multiplicative! { uint, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } +<<<<<<< HEAD +======= +/// A trait for iterators over elements which can be compared to one another. +#[unstable = "recently renamed for new extension trait conventions"] +pub trait IteratorOrdExt { + /// Consumes the entire iterator to return the maximum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// assert!(a.iter().max().unwrap() == &5); + /// ``` + fn max(self) -> Option; + + /// Consumes the entire iterator to return the minimum element. + /// + /// # Example + /// + /// ```rust + /// let a = [1i, 2, 3, 4, 5]; + /// assert!(a.iter().min().unwrap() == &1); + /// ``` + fn min(self) -> Option; + + /// `min_max` finds the minimum and maximum elements in the iterator. + /// + /// The return type `MinMaxResult` is an enum of three variants: + /// + /// - `NoElements` if the iterator is empty. + /// - `OneElement(x)` if the iterator has exactly one element. + /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two + /// values are equal if and only if there is more than one + /// element in the iterator and all elements are equal. + /// + /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, + /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. + /// + /// # Example + /// + /// ```rust + /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let v: [int; 0] = []; + /// assert_eq!(v.iter().min_max(), NoElements); + /// + /// let v = [1i]; + /// assert!(v.iter().min_max() == OneElement(&1)); + /// + /// let v = [1i, 2, 3, 4, 5]; + /// assert!(v.iter().min_max() == MinMax(&1, &5)); + /// + /// let v = [1i, 2, 3, 4, 5, 6]; + /// assert!(v.iter().min_max() == MinMax(&1, &6)); + /// + /// let v = [1i, 1, 1, 1]; + /// assert!(v.iter().min_max() == MinMax(&1, &1)); + /// ``` + fn min_max(self) -> MinMaxResult; +} + +#[unstable = "trait is unstable"] +impl IteratorOrdExt for I where I: Iterator, T: Ord { + #[inline] + fn max(self) -> Option { + self.fold(None, |max, x| { + match max { + None => Some(x), + Some(y) => Some(cmp::max(x, y)) + } + }) + } + + #[inline] + fn min(self) -> Option { + self.fold(None, |min, x| { + match min { + None => Some(x), + Some(y) => Some(cmp::min(x, y)) + } + }) + } + + fn min_max(mut self) -> MinMaxResult { + let (mut min, mut max) = match self.next() { + None => return NoElements, + Some(x) => { + match self.next() { + None => return OneElement(x), + Some(y) => if x < y {(x, y)} else {(y,x)} + } + } + }; + + loop { + // `first` and `second` are the two next elements we want to look at. + // We first compare `first` and `second` (#1). The smaller one is then compared to + // current minimum (#2). The larger one is compared to current maximum (#3). This + // way we do 3 comparisons for 2 elements. + let first = match self.next() { + None => break, + Some(x) => x + }; + let second = match self.next() { + None => { + if first < min { + min = first; + } else if first > max { + max = first; + } + break; + } + Some(x) => x + }; + if first < second { + if first < min {min = first;} + if max < second {max = second;} + } else { + if second < min {min = second;} + if max < first {max = first;} + } + } + + MinMax(min, max) + } +} + +>>>>>>> parent of f031671... Remove i suffix in docs /// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail. #[derive(Clone, PartialEq, Show)] #[unstable = "unclear whether such a fine-grained result is widely useful"] @@ -1199,10 +1327,10 @@ impl MinMaxResult { /// let r: MinMaxResult = NoElements; /// assert_eq!(r.into_option(), None); /// - /// let r = OneElement(1); + /// let r = OneElement(1i); /// assert_eq!(r.into_option(), Some((1,1))); /// - /// let r = MinMax(1, 2); + /// let r = MinMax(1i,2i); /// assert_eq!(r.into_option(), Some((1,2))); /// ``` #[unstable = "type is unstable"] @@ -1258,6 +1386,35 @@ impl ExactSizeIterator for Cloned where I: ExactSizeIterator + Iterator, {} +<<<<<<< HEAD +======= +#[unstable = "recently renamed for extension trait conventions"] +/// An extension trait for cloneable iterators. +pub trait CloneIteratorExt { + /// Repeats an iterator endlessly + /// + /// # Example + /// + /// ```rust + /// use std::iter::{CloneIteratorExt, count}; + /// + /// let a = count(1i,1i).take(1); + /// let mut cy = a.cycle(); + /// assert_eq!(cy.next(), Some(1)); + /// assert_eq!(cy.next(), Some(1)); + /// ``` + #[stable] + fn cycle(self) -> Cycle; +} + +impl CloneIteratorExt for I where I: Iterator + Clone { + #[inline] + fn cycle(self) -> Cycle { + Cycle{orig: self.clone(), iter: self} + } +} + +>>>>>>> parent of f031671... Remove i suffix in docs /// An iterator that repeats endlessly #[derive(Clone, Copy)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a8f8802de5982..c60569161213f 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -187,13 +187,13 @@ pub unsafe fn uninitialized() -> T { /// ``` /// use std::mem; /// -/// let x = &mut 5; -/// let y = &mut 42; +/// let x = &mut 5i; +/// let y = &mut 42i; /// /// mem::swap(x, y); /// -/// assert_eq!(42, *x); -/// assert_eq!(5, *y); +/// assert_eq!(42i, *x); +/// assert_eq!(5i, *y); /// ``` #[inline] #[stable] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 485d320cf5cc8..426c858d408ad 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -336,7 +336,7 @@ pub trait Int /// ```rust /// use std::num::Int; /// - /// assert_eq!(2.pow(4), 16); + /// assert_eq!(2i.pow(4), 16); /// ``` #[inline] fn pow(self, mut exp: uint) -> Self { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 3c96011867cef..39d0f024d4d41 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -470,10 +470,10 @@ impl Option { /// /// ``` /// let x = Some("foo"); - /// assert_eq!(x.ok_or(0), Ok("foo")); + /// assert_eq!(x.ok_or(0i), Ok("foo")); /// /// let x: Option<&str> = None; - /// assert_eq!(x.ok_or(0), Err(0)); + /// assert_eq!(x.ok_or(0i), Err(0i)); /// ``` #[inline] #[experimental] @@ -491,10 +491,10 @@ impl Option { /// /// ``` /// let x = Some("foo"); - /// assert_eq!(x.ok_or_else(|| 0), Ok("foo")); + /// assert_eq!(x.ok_or_else(|| 0i), Ok("foo")); /// /// let x: Option<&str> = None; - /// assert_eq!(x.ok_or_else(|| 0), Err(0)); + /// assert_eq!(x.ok_or_else(|| 0i), Err(0i)); /// ``` #[inline] #[experimental] @@ -728,8 +728,8 @@ impl Option { /// let good_year = good_year_from_input.parse().unwrap_or_default(); /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); + /// assert_eq!(1909i, good_year); + /// assert_eq!(0i, bad_year); /// ``` #[inline] #[stable] diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 5c7085b7b6c5f..5249e971439cd 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -119,7 +119,7 @@ macro_rules! warn { /// #[macro_use] extern crate log; /// /// fn main() { -/// let ret = 3; +/// let ret = 3i; /// info!("this function is about to return: {}", ret); /// } /// ``` @@ -145,7 +145,7 @@ macro_rules! info { /// #[macro_use] extern crate log; /// /// fn main() { -/// debug!("x = {x}, y = {y}", x=10, y=20); +/// debug!("x = {x}, y = {y}", x=10i, y=20i); /// } /// ``` /// diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 99dd505a9ef39..8eae769737614 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -287,7 +287,7 @@ pub trait Rng : Sized { /// ``` /// use std::rand::{thread_rng, Rng}; /// - /// let choices = [1, 2, 4, 8, 16, 32]; + /// let choices = [1i, 2, 4, 8, 16, 32]; /// let mut rng = thread_rng(); /// println!("{}", rng.choose(&choices)); /// # // replace with slicing syntax when it's stable! @@ -309,7 +309,7 @@ pub trait Rng : Sized { /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); - /// let mut y = [1, 2, 3]; + /// let mut y = [1i, 2, 3]; /// rng.shuffle(&mut y); /// println!("{}", y.as_slice()); /// rng.shuffle(&mut y); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 38ea4dad027a0..211bfe2c10e8f 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -166,7 +166,7 @@ impl, S, H: Hasher> HashSet { /// /// let h = SipHasher::new(); /// let mut set = HashSet::with_capacity_and_hasher(10u, h); - /// set.insert(1); + /// set.insert(1i); /// ``` #[inline] #[unstable = "hasher stuff is unclear"] @@ -285,8 +285,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { @@ -294,12 +294,12 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.difference(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [1i].iter().map(|&x| x).collect()); /// /// // Note that difference is not symmetric, /// // and `b - a` means something else: /// let diff: HashSet = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn difference<'a>(&'a self, other: &'a HashSet) -> Difference<'a, T, H> { @@ -315,8 +315,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 4 in arbitrary order. /// for x in a.symmetric_difference(&b) { @@ -327,7 +327,7 @@ impl, S, H: Hasher> HashSet { /// let diff2: HashSet = b.symmetric_difference(&a).map(|&x| x).collect(); /// /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect()); + /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet) @@ -341,8 +341,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 2, 3 in arbitrary order. /// for x in a.intersection(&b) { @@ -350,7 +350,7 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn intersection<'a>(&'a self, other: &'a HashSet) -> Intersection<'a, T, H> { @@ -366,8 +366,8 @@ impl, S, H: Hasher> HashSet { /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); /// /// // Print 1, 2, 3, 4 in arbitrary order. /// for x in a.union(&b) { @@ -375,7 +375,7 @@ impl, S, H: Hasher> HashSet { /// } /// /// let diff: HashSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect()); + /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); /// ``` #[stable] pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, H> { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 22cbf16e2b0b9..d96441e09a813 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -32,7 +32,7 @@ /// # #![allow(unreachable_code)] /// panic!(); /// panic!("this is a terrible mistake!"); -/// panic!(4); // panic with the value of 4 to be collected elsewhere +/// panic!(4i); // panic with the value of 4 to be collected elsewhere /// panic!("this is a {} {message}", "fancy", message = "message"); /// ``` #[macro_export] @@ -73,7 +73,7 @@ macro_rules! panic { /// // assert with a custom message /// # let x = true; /// assert!(x, "x wasn't true!"); -/// # let a = 3; let b = 27; +/// # let a = 3i; let b = 27i; /// assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] @@ -98,8 +98,8 @@ macro_rules! assert { /// # Example /// /// ``` -/// let a = 3; -/// let b = 1 + 2; +/// let a = 3i; +/// let b = 1i + 2i; /// assert_eq!(a, b); /// ``` #[macro_export] @@ -140,7 +140,7 @@ macro_rules! assert_eq { /// // assert with a custom message /// # let x = true; /// debug_assert!(x, "x wasn't true!"); -/// # let a = 3; let b = 27; +/// # let a = 3i; let b = 27i; /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b); /// ``` #[macro_export] @@ -161,8 +161,8 @@ macro_rules! debug_assert { /// # Example /// /// ``` -/// let a = 3; -/// let b = 1 + 2; +/// let a = 3i; +/// let b = 1i + 2i; /// debug_assert_eq!(a, b); /// ``` #[macro_export] @@ -237,7 +237,7 @@ macro_rules! unimplemented { /// ``` /// format!("test"); /// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10, y = 30); +/// format!("x = {}, y = {y}", 10i, y = 30i); /// ``` #[macro_export] #[stable] @@ -301,7 +301,7 @@ macro_rules! try { /// let (tx1, rx1) = channel(); /// let (tx2, rx2) = channel(); /// # fn long_running_task() {} -/// # fn calculate_the_answer() -> int { 42 } +/// # fn calculate_the_answer() -> int { 42i } /// /// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach(); /// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach(); @@ -470,7 +470,7 @@ pub mod builtin { /// # Example /// /// ``` - /// let s = concat!("test", 10, 'b', true); + /// let s = concat!("test", 10i, 'b', true); /// assert_eq!(s, "test10btrue"); /// ``` #[macro_export] diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index bcfd61582a31d..7c18b8a43faad 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -8,12 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Communication primitives for concurrent tasks -//! -//! Rust makes it very difficult to share data among tasks to prevent race -//! conditions and to improve parallelism, but there is often a need for -//! communication between concurrent tasks. The primitives defined in this -//! module are the building blocks for synchronization in rust. +//! Multi-producer, single-consumer communication primitives threads //! //! This module provides message-based communication over channels, concretely //! defined among three types: @@ -23,12 +18,10 @@ //! * `Receiver` //! //! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both -//! senders are clone-able such that many tasks can send simultaneously to one -//! receiver. These channels are *task blocking*, not *thread blocking*. This -//! means that if one task is blocked on a channel, other tasks can continue to -//! make progress. +//! senders are clone-able (multi-producer) such that many threads can send +//! simultaneously to one receiver (single-consumer). //! -//! Rust channels come in one of two flavors: +//! These channels come in two flavors: //! //! 1. An asynchronous, infinitely buffered channel. The `channel()` function //! will return a `(Sender, Receiver)` tuple where all sends will be @@ -43,36 +36,39 @@ //! "rendezvous" channel where each sender atomically hands off a message to //! a receiver. //! -//! ## Panic Propagation +//! ## Disconnection //! -//! In addition to being a core primitive for communicating in rust, channels -//! are the points at which panics are propagated among tasks. Whenever the one -//! half of channel is closed, the other half will have its next operation -//! `panic!`. The purpose of this is to allow propagation of panics among tasks -//! that are linked to one another via channels. +//! The send and receive operations on channels will all return a `Result` +//! indicating whether the operation succeeded or not. An unsuccessful operation +//! is normally indicative of the other half of a channel having "hung up" by +//! being dropped in its corresponding thread. //! -//! There are methods on both of senders and receivers to perform their -//! respective operations without panicking, however. +//! Once half of a channel has been deallocated, most operations can no longer +//! continue to make progress, so `Err` will be returned. Many applications will +//! continue to `unwrap()` the results returned from this module, instigating a +//! propagation of failure among threads if one unexpectedly dies. //! -//! # Example +//! # Examples //! //! Simple usage: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::channel; //! //! // Create a simple streaming channel //! let (tx, rx) = channel(); //! Thread::spawn(move|| { -//! tx.send(10); +//! tx.send(10i).unwrap(); //! }).detach(); -//! assert_eq!(rx.recv(), 10); +//! assert_eq!(rx.recv().unwrap(), 10i); //! ``` //! //! Shared usage: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::channel; //! //! // Create a shared channel that can be sent along from many threads //! // where tx is the sending half (tx for transmission), and rx is the receiving @@ -81,37 +77,40 @@ //! for i in range(0i, 10i) { //! let tx = tx.clone(); //! Thread::spawn(move|| { -//! tx.send(i); +//! tx.send(i).unwrap(); //! }).detach() //! } //! //! for _ in range(0i, 10i) { -//! let j = rx.recv(); +//! let j = rx.recv().unwrap(); //! assert!(0 <= j && j < 10); //! } //! ``` //! //! Propagating panics: //! -//! ```should_fail -//! // The call to recv() will panic!() because the channel has already hung -//! // up (or been deallocated) +//! ``` +//! use std::sync::mpsc::channel; +//! +//! // The call to recv() will return an error because the channel has already +//! // hung up (or been deallocated) //! let (tx, rx) = channel::(); //! drop(tx); -//! rx.recv(); +//! assert!(rx.recv().is_err()); //! ``` //! //! Synchronous channels: //! //! ``` //! use std::thread::Thread; +//! use std::sync::mpsc::sync_channel; //! //! let (tx, rx) = sync_channel::(0); //! Thread::spawn(move|| { //! // This will wait for the parent task to start receiving -//! tx.send(53); +//! tx.send(53).unwrap(); //! }).detach(); -//! rx.recv(); +//! rx.recv().unwrap(); //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together @@ -120,6 +119,7 @@ //! after 10 seconds no matter what: //! //! ```no_run +//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -129,8 +129,8 @@ //! //! loop { //! select! { -//! val = rx.recv() => println!("Received {}", val), -//! () = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val.unwrap()), +//! _ = timeout.recv() => { //! println!("timed out, total time was more than 10 seconds"); //! break; //! } @@ -143,6 +143,7 @@ //! has been inactive for 5 seconds: //! //! ```no_run +//! use std::sync::mpsc::channel; //! use std::io::timer::Timer; //! use std::time::Duration; //! @@ -153,8 +154,8 @@ //! let timeout = timer.oneshot(Duration::seconds(5)); //! //! select! { -//! val = rx.recv() => println!("Received {}", val), -//! () = timeout.recv() => { +//! val = rx.recv() => println!("Received {}", val.unwrap()), +//! _ = timeout.recv() => { //! println!("timed out, no message received in 5 seconds"); //! break; //! } @@ -314,38 +315,19 @@ // And now that you've seen all the races that I found and attempted to fix, // here's the code for you to find some more! -use core::prelude::*; +use prelude::v1::*; -pub use self::TryRecvError::*; -pub use self::TrySendError::*; - -use alloc::arc::Arc; -use core::kinds; -use core::kinds::marker; -use core::mem; -use core::cell::UnsafeCell; +use sync::Arc; +use fmt; +use kinds::marker; +use mem; +use cell::UnsafeCell; pub use self::select::{Select, Handle}; use self::select::StartResult; use self::select::StartResult::*; use self::blocking::SignalToken; -macro_rules! test { - { fn $name:ident() $b:block $(#[$a:meta])*} => ( - mod $name { - #![allow(unused_imports)] - - use super::*; - use comm::*; - use thread::Thread; - use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option}; - use prelude::{Vec, Buffer, from_str, Clone}; - - $(#[$a])* #[test] fn f() { $b } - } - ) -} - mod blocking; mod oneshot; mod select; @@ -357,7 +339,7 @@ mod spsc_queue; /// The receiving-half of Rust's channel type. This half can only be owned by /// one task -#[unstable] +#[stable] pub struct Receiver { inner: UnsafeCell>, } @@ -369,14 +351,14 @@ unsafe impl Send for Receiver { } /// An iterator over messages on a receiver, this iterator will block /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. -#[unstable] -pub struct Messages<'a, T:'a> { +#[stable] +pub struct Iter<'a, T:'a> { rx: &'a Receiver } /// The sending-half of Rust's asynchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[unstable] +#[stable] pub struct Sender { inner: UnsafeCell>, } @@ -387,30 +369,50 @@ unsafe impl Send for Sender { } /// The sending-half of Rust's synchronous channel type. This half can only be /// owned by one task, but it can be cloned to send to other tasks. -#[unstable = "this type may be renamed, but it will always exist"] +#[stable] pub struct SyncSender { inner: Arc>>, // can't share in an arc _marker: marker::NoSync, } +/// An error returned from the `send` function on channels. +/// +/// A `send` operation can only fail if the receiving end of a channel is +/// disconnected, implying that the data could never be received. The error +/// contains the data being sent as a payload so it can be recovered. +#[derive(PartialEq, Eq)] +#[stable] +pub struct SendError(pub T); + +/// An error returned from the `recv` function on a `Receiver`. +/// +/// The `recv` operation can only fail if the sending half of a channel is +/// disconnected, implying that no further messages will ever be received. +#[derive(PartialEq, Eq, Clone, Copy)] +#[stable] +pub struct RecvError; + /// This enumeration is the list of the possible reasons that try_recv could not /// return data when called. -#[deriving(PartialEq, Clone, Copy, Show)] -#[experimental = "this is likely to be removed in changing try_recv()"] +#[derive(PartialEq, Clone, Copy)] +#[stable] pub enum TryRecvError { /// This channel is currently empty, but the sender(s) have not yet /// disconnected, so data may yet become available. + #[stable] Empty, + /// This channel's sending half has become disconnected, and there will /// never be any more data received on this channel + #[stable] Disconnected, } /// This enumeration is the list of the possible error outcomes for the /// `SyncSender::try_send` method. -#[deriving(PartialEq, Clone, Show)] -#[experimental = "this is likely to be removed in changing try_send()"] +#[derive(PartialEq, Clone)] +#[stable] pub enum TrySendError { /// The data could not be sent on the channel because it would require that /// the callee block to send the data. @@ -418,10 +420,13 @@ pub enum TrySendError { /// If this is a buffered channel, then the buffer is full at this time. If /// this is not a buffered channel, then there is no receiver available to /// acquire the data. + #[stable] Full(T), + /// This channel's receiving half has disconnected, so the data could not be /// sent. The data is returned back to the callee in this case. - RecvDisconnected(T), + #[stable] + Disconnected(T), } enum Flavor { @@ -460,6 +465,7 @@ impl UnsafeFlavor for Receiver { /// # Example /// /// ``` +/// use std::sync::mpsc::channel; /// use std::thread::Thread; /// /// // tx is is the sending half (tx for transmission), and rx is the receiving @@ -469,15 +475,15 @@ impl UnsafeFlavor for Receiver { /// // Spawn off an expensive computation /// Thread::spawn(move|| { /// # fn expensive_computation() {} -/// tx.send(expensive_computation()); +/// tx.send(expensive_computation()).unwrap(); /// }).detach(); /// /// // Do some useful work for awhile /// /// // Let's see what that answer was -/// println!("{}", rx.recv()); +/// println!("{}", rx.recv().unwrap()); /// ``` -#[unstable] +#[stable] pub fn channel() -> (Sender, Receiver) { let a = Arc::new(RacyCell::new(oneshot::Packet::new())); (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) @@ -501,23 +507,23 @@ pub fn channel() -> (Sender, Receiver) { /// # Example /// /// ``` +/// use std::sync::mpsc::sync_channel; /// use std::thread::Thread; /// /// let (tx, rx) = sync_channel(1); /// /// // this returns immediately -/// tx.send(1); +/// tx.send(1i).unwrap(); /// /// Thread::spawn(move|| { /// // this will block until the previous message has been received -/// tx.send(2); +/// tx.send(2i).unwrap(); /// }).detach(); /// -/// assert_eq!(rx.recv(), 1); -/// assert_eq!(rx.recv(), 2); +/// assert_eq!(rx.recv().unwrap(), 1i); +/// assert_eq!(rx.recv().unwrap(), 2i); /// ``` -#[unstable = "this function may be renamed to more accurately reflect the type \ - of channel that is is creating"] +#[stable] pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { let a = Arc::new(RacyCell::new(sync::Packet::new(bound))); (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) @@ -534,33 +540,6 @@ impl Sender { } } - /// Sends a value along this channel to be received by the corresponding - /// receiver. - /// - /// Rust channels are infinitely buffered so this method will never block. - /// - /// # Panics - /// - /// This function will panic if the other end of the channel has hung up. - /// This means that if the corresponding receiver has fallen out of scope, - /// this function will trigger a panic message saying that a message is - /// being sent on a closed channel. - /// - /// Note that if this function does *not* panic, it does not mean that the - /// data will be successfully received. All sends are placed into a queue, - /// so it is possible for a send to succeed (the other end is alive), but - /// then the other end could immediately disconnect. - /// - /// The purpose of this functionality is to propagate panics among tasks. - /// If a panic is not desired, then consider using the `send_opt` method - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn send(&self, t: T) { - if self.send_opt(t).is_err() { - panic!("sending on a closed channel"); - } - } - /// Attempts to send a value on this channel, returning it back if it could /// not be sent. /// @@ -572,24 +551,21 @@ impl Sender { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns `Ok`. /// - /// Like `send`, this method will never block. - /// - /// # Panics - /// - /// This method will never panic, it will return the message back to the - /// caller if the other end is disconnected + /// This method will never block the current thread. /// /// # Example /// /// ``` + /// use std::sync::mpsc::channel; + /// /// let (tx, rx) = channel(); /// /// // This send is always successful - /// assert_eq!(tx.send_opt(1), Ok(())); + /// tx.send(1i).unwrap(); /// /// // This send will fail because the receiver is gone /// drop(rx); - /// assert_eq!(tx.send_opt(1), Err(1)); + /// assert_eq!(tx.send(1i).err().unwrap().0, 1); /// ``` #[stable] pub fn send(&self, t: T) -> Result<(), SendError> { @@ -598,11 +574,12 @@ impl Sender { unsafe { let p = p.get(); if !(*p).sent() { - return (*p).send(t); + return (*p).send(t).map_err(SendError); } else { let a = Arc::new(RacyCell::new(stream::Packet::new())); - match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) { + let rx = Receiver::new(Flavor::Stream(a.clone())); + match (*p).upgrade(rx) { oneshot::UpSuccess => { let ret = (*a.get()).send(t); (a, ret) @@ -613,15 +590,19 @@ impl Sender { // asleep (we're looking at it), so the receiver // can't go away. (*a.get()).send(t).ok().unwrap(); - token.signal(); + token.signal(); (a, Ok(())) } } } } } - Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) }, - Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) }, + Flavor::Stream(ref p) => return unsafe { + (*p.get()).send(t).map_err(SendError) + }, + Flavor::Shared(ref p) => return unsafe { + (*p.get()).send(t).map_err(SendError) + }, Flavor::Sync(..) => unreachable!(), }; @@ -629,7 +610,7 @@ impl Sender { let tmp = Sender::new(Flavor::Stream(new_inner)); mem::swap(self.inner_mut(), tmp.inner_mut()); } - return ret; + ret.map_err(SendError) } } @@ -641,7 +622,8 @@ impl Clone for Sender { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { + let rx = Receiver::new(Flavor::Shared(a.clone())); + match (*p.get()).upgrade(rx) { oneshot::UpSuccess | oneshot::UpDisconnected => (a, None, guard), oneshot::UpWoke(task) => (a, Some(task), guard) @@ -652,7 +634,8 @@ impl Clone for Sender { let a = Arc::new(RacyCell::new(shared::Packet::new())); unsafe { let guard = (*a.get()).postinit_lock(); - match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) { + let rx = Receiver::new(Flavor::Shared(a.clone())); + match (*p.get()).upgrade(rx) { stream::UpSuccess | stream::UpDisconnected => (a, None, guard), stream::UpWoke(task) => (a, Some(task), guard), @@ -704,59 +687,29 @@ impl SyncSender { /// available or a receiver is available to hand off the message to. /// /// Note that a successful send does *not* guarantee that the receiver will - /// ever see the data if there is a buffer on this channel. Messages may be + /// ever see the data if there is a buffer on this channel. Items may be /// enqueued in the internal buffer for the receiver to receive at a later /// time. If the buffer size is 0, however, it can be guaranteed that the /// receiver has indeed received the data if this function returns success. /// - /// # Panics - /// - /// Similarly to `Sender::send`, this function will panic if the - /// corresponding `Receiver` for this channel has disconnected. This - /// behavior is used to propagate panics among tasks. - /// - /// If a panic is not desired, you can achieve the same semantics with the - /// `SyncSender::send_opt` method which will not panic if the receiver - /// disconnects. - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn send(&self, t: T) { - if self.send_opt(t).is_err() { - panic!("sending on a closed channel"); - } - } - - /// Send a value on a channel, returning it back if the receiver - /// disconnected - /// - /// This method will *block* to send the value `t` on the channel, but if - /// the value could not be sent due to the receiver disconnecting, the value - /// is returned back to the callee. This function is similar to `try_send`, - /// except that it will block if the channel is currently full. - /// - /// # Panics - /// - /// This function cannot panic. - #[unstable = "this function may be renamed to send() in the future"] - pub fn send_opt(&self, t: T) -> Result<(), T> { - unsafe { (*self.inner.get()).send(t) } + /// This function will never panic, but it may return `Err` if the + /// `Receiver` has disconnected and is no longer able to receive + /// information. + #[stable] + pub fn send(&self, t: T) -> Result<(), SendError> { + unsafe { (*self.inner.get()).send(t).map_err(SendError) } } /// Attempts to send a value on this channel without blocking. /// - /// This method differs from `send_opt` by returning immediately if the + /// This method differs from `send` by returning immediately if the /// channel's buffer is full or no receiver is waiting to acquire some - /// data. Compared with `send_opt`, this function has two failure cases + /// data. Compared with `send`, this function has two failure cases /// instead of one (one for disconnection, one for a full buffer). /// /// See `SyncSender::send` for notes about guarantees of whether the /// receiver has received the data or not if this function is successful. - /// - /// # Panics - /// - /// This function cannot panic - #[unstable = "the return type of this function is candidate for \ - modification"] + #[stable] pub fn try_send(&self, t: T) -> Result<(), TrySendError> { unsafe { (*self.inner.get()).try_send(t) } } @@ -787,34 +740,6 @@ impl Receiver { Receiver { inner: UnsafeCell::new(inner) } } - /// Blocks waiting for a value on this receiver - /// - /// This function will block if necessary to wait for a corresponding send - /// on the channel from its paired `Sender` structure. This receiver will - /// be woken up when data is ready, and the data will be returned. - /// - /// # Panics - /// - /// Similar to channels, this method will trigger a task panic if the - /// other end of the channel has hung up (been deallocated). The purpose of - /// this is to propagate panics among tasks. - /// - /// If a panic is not desired, then there are two options: - /// - /// * If blocking is still desired, the `recv_opt` method will return `None` - /// when the other end hangs up - /// - /// * If blocking is not desired, then the `try_recv` method will attempt to - /// peek at a value on this receiver. - #[experimental = "this function is being considered candidate for removal \ - to adhere to the general guidelines of rust"] - pub fn recv(&self) -> T { - match self.recv_opt() { - Ok(t) => t, - Err(()) => panic!("receiving on a closed channel"), - } - } - /// Attempts to return a pending value on this receiver without blocking /// /// This method will never block the caller in order to wait for data to @@ -823,42 +748,46 @@ impl Receiver { /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. - /// - /// # Panics - /// - /// This function cannot panic. - #[unstable = "the return type of this function may be altered"] + #[stable] pub fn try_recv(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(oneshot::Empty) => return Err(Empty), - Err(oneshot::Disconnected) => return Err(Disconnected), + Err(oneshot::Empty) => return Err(TryRecvError::Empty), + Err(oneshot::Disconnected) => { + return Err(TryRecvError::Disconnected) + } Err(oneshot::Upgraded(rx)) => rx, } } Flavor::Stream(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(stream::Empty) => return Err(Empty), - Err(stream::Disconnected) => return Err(Disconnected), + Err(stream::Empty) => return Err(TryRecvError::Empty), + Err(stream::Disconnected) => { + return Err(TryRecvError::Disconnected) + } Err(stream::Upgraded(rx)) => rx, } } Flavor::Shared(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(shared::Empty) => return Err(Empty), - Err(shared::Disconnected) => return Err(Disconnected), + Err(shared::Empty) => return Err(TryRecvError::Empty), + Err(shared::Disconnected) => { + return Err(TryRecvError::Disconnected) + } } } Flavor::Sync(ref p) => { match unsafe { (*p.get()).try_recv() } { Ok(t) => return Ok(t), - Err(sync::Empty) => return Err(Empty), - Err(sync::Disconnected) => return Err(Disconnected), + Err(sync::Empty) => return Err(TryRecvError::Empty), + Err(sync::Disconnected) => { + return Err(TryRecvError::Disconnected) + } } } }; @@ -869,27 +798,26 @@ impl Receiver { } } - /// Attempt to wait for a value on this receiver, but does not panic if the + /// Attempt to wait for a value on this receiver, returning an error if the /// corresponding channel has hung up. /// - /// This implementation of iterators for ports will always block if there is - /// not data available on the receiver, but it will not panic in the case - /// that the channel has been deallocated. + /// This function will always block the current thread if there is no data + /// available and it's possible for more data to be sent. Once a message is + /// sent to the corresponding `Sender`, then this receiver will wake up and + /// return that message. /// - /// In other words, this function has the same semantics as the `recv` - /// method except for the panic aspect. - /// - /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of - /// the value found on the receiver is returned. - #[unstable = "this function may be renamed to recv()"] - pub fn recv_opt(&self) -> Result { + /// If the corresponding `Sender` has disconnected, or it disconnects while + /// this call is blocking, this call will wake up and return `Err` to + /// indicate that no more messages can ever be received on this channel. + #[stable] + pub fn recv(&self) -> Result { loop { let new_port = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(oneshot::Empty) => return unreachable!(), - Err(oneshot::Disconnected) => return Err(()), + Err(oneshot::Disconnected) => return Err(RecvError), Err(oneshot::Upgraded(rx)) => rx, } } @@ -897,7 +825,7 @@ impl Receiver { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(stream::Empty) => return unreachable!(), - Err(stream::Disconnected) => return Err(()), + Err(stream::Disconnected) => return Err(RecvError), Err(stream::Upgraded(rx)) => rx, } } @@ -905,10 +833,12 @@ impl Receiver { match unsafe { (*p.get()).recv() } { Ok(t) => return Ok(t), Err(shared::Empty) => return unreachable!(), - Err(shared::Disconnected) => return Err(()), + Err(shared::Disconnected) => return Err(RecvError), } } - Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() } + Flavor::Sync(ref p) => return unsafe { + (*p.get()).recv().map_err(|()| RecvError) + } }; unsafe { mem::swap(self.inner_mut(), new_port.inner_mut()); @@ -918,9 +848,9 @@ impl Receiver { /// Returns an iterator that will block waiting for messages, but never /// `panic!`. It will return `None` when the channel has hung up. - #[unstable] - pub fn iter<'a>(&'a self) -> Messages<'a, T> { - Messages { rx: self } + #[stable] + pub fn iter(&self) -> Iter { + Iter { rx: self } } } @@ -1048,368 +978,425 @@ impl RacyCell { unsafe impl Send for RacyCell { } -unsafe impl kinds::Sync for RacyCell { } // Oh dear +unsafe impl Sync for RacyCell { } // Oh dear + +impl fmt::Show for SendError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "sending on a closed channel".fmt(f) + } +} + +impl fmt::Show for TrySendError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + TrySendError::Full(..) => { + "sending on a full channel".fmt(f) + } + TrySendError::Disconnected(..) => { + "sending on a closed channel".fmt(f) + } + } + } +} + +impl fmt::Show for RecvError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "receiving on a closed channel".fmt(f) + } +} +impl fmt::Show for TryRecvError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + TryRecvError::Empty => { + "receiving on an empty channel".fmt(f) + } + TryRecvError::Disconnected => { + "receiving on a closed channel".fmt(f) + } + } + } +} #[cfg(test)] mod test { - use super::*; - use prelude::{spawn, range, Some, None, from_str, Clone, Str}; + use prelude::v1::*; + use os; + use super::*; + use thread::Thread; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => from_str::(val.as_slice()).unwrap(), + Some(val) => val.parse().unwrap(), None => 1, } } - test! { fn smoke() { + #[test] + fn smoke() { let (tx, rx) = channel::(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn drop_full() { + #[test] + fn drop_full() { let (tx, _rx) = channel(); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn drop_full_shared() { + #[test] + fn drop_full_shared() { let (tx, _rx) = channel(); drop(tx.clone()); drop(tx.clone()); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn smoke_shared() { + #[test] + fn smoke_shared() { let (tx, rx) = channel::(); - tx.send(1); - assert_eq!(rx.recv(), 1); + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_threads() { + #[test] + fn smoke_threads() { let (tx, rx) = channel::(); - spawn(move|| { - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); }); - assert_eq!(rx.recv(), 1); - } } + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_port_gone() { + #[test] + fn smoke_port_gone() { let (tx, rx) = channel::(); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()); + } - test! { fn smoke_shared_port_gone() { + #[test] + fn smoke_shared_port_gone() { let (tx, rx) = channel::(); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()) + } - test! { fn smoke_shared_port_gone2() { + #[test] + fn smoke_shared_port_gone2() { let (tx, rx) = channel::(); drop(rx); let tx2 = tx.clone(); drop(tx); - tx2.send(1); - } #[should_fail] } + assert!(tx2.send(1).is_err()); + } - test! { fn port_gone_concurrent() { + #[test] + fn port_gone_concurrent() { let (tx, rx) = channel::(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { tx.send(1) } - } #[should_fail] } + while tx.send(1).is_ok() {} + } - test! { fn port_gone_concurrent_shared() { + #[test] + fn port_gone_concurrent_shared() { let (tx, rx) = channel::(); let tx2 = tx.clone(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { - tx.send(1); - tx2.send(1); - } - } #[should_fail] } + while tx.send(1).is_ok() && tx2.send(1).is_ok() {} + } - test! { fn smoke_chan_gone() { + #[test] + fn smoke_chan_gone() { let (tx, rx) = channel::(); drop(tx); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn smoke_chan_gone_shared() { + #[test] + fn smoke_chan_gone_shared() { let (tx, rx) = channel::<()>(); let tx2 = tx.clone(); drop(tx); drop(tx2); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn chan_gone_concurrent() { + #[test] + fn chan_gone_concurrent() { let (tx, rx) = channel::(); - spawn(move|| { - tx.send(1); - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); + tx.send(1).unwrap(); }); - loop { rx.recv(); } - } #[should_fail] } + while rx.recv().is_ok() {} + } - test! { fn stress() { + #[test] + fn stress() { let (tx, rx) = channel::(); - spawn(move|| { - for _ in range(0u, 10000) { tx.send(1i); } + let t = Thread::spawn(move|| { + for _ in range(0u, 10000) { tx.send(1i).unwrap(); } }); for _ in range(0u, 10000) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - } } + t.join().ok().unwrap(); + } - test! { fn stress_shared() { + #[test] + fn stress_shared() { static AMT: uint = 10000; static NTHREADS: uint = 8; let (tx, rx) = channel::(); - let (dtx, drx) = channel::<()>(); - spawn(move|| { + let t = Thread::spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } - dtx.send(()); }); for _ in range(0, NTHREADS) { let tx = tx.clone(); - spawn(move|| { - for _ in range(0, AMT) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0, AMT) { tx.send(1).unwrap(); } + }).detach(); } drop(tx); - drx.recv(); - } } + t.join().ok().unwrap(); + } #[test] fn send_from_outside_runtime() { let (tx1, rx1) = channel::<()>(); let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - let tx4 = tx3.clone(); - spawn(move|| { - tx1.send(()); + let t1 = Thread::spawn(move|| { + tx1.send(()).unwrap(); for _ in range(0i, 40) { - assert_eq!(rx2.recv(), 1); + assert_eq!(rx2.recv().unwrap(), 1); } - tx3.send(()); }); - rx1.recv(); - spawn(move|| { + rx1.recv().unwrap(); + let t2 = Thread::spawn(move|| { for _ in range(0i, 40) { - tx2.send(1); + tx2.send(1).unwrap(); } - tx4.send(()); }); - rx3.recv(); - rx3.recv(); + t1.join().ok().unwrap(); + t2.join().ok().unwrap(); } #[test] fn recv_from_outside_runtime() { let (tx, rx) = channel::(); - let (dtx, drx) = channel(); - spawn(move|| { + let t = Thread::spawn(move|| { for _ in range(0i, 40) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - dtx.send(()); }); for _ in range(0u, 40) { - tx.send(1); + tx.send(1).unwrap(); } - drx.recv(); + t.join().ok().unwrap(); } #[test] fn no_runtime() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - let tx4 = tx3.clone(); - spawn(move|| { - assert_eq!(rx1.recv(), 1); - tx2.send(2); - tx4.send(()); + let t1 = Thread::spawn(move|| { + assert_eq!(rx1.recv().unwrap(), 1); + tx2.send(2).unwrap(); }); - spawn(move|| { - tx1.send(1); - assert_eq!(rx2.recv(), 2); - tx3.send(()); + let t2 = Thread::spawn(move|| { + tx1.send(1).unwrap(); + assert_eq!(rx2.recv().unwrap(), 2); }); - rx3.recv(); - rx3.recv(); + t1.join().ok().unwrap(); + t2.join().ok().unwrap(); } - test! { fn oneshot_single_thread_close_port_first() { + #[test] + fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = channel::(); drop(rx); - } } + } - test! { fn oneshot_single_thread_close_chan_first() { + #[test] + fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = channel::(); drop(tx); - } } + } - test! { fn oneshot_single_thread_send_port_close() { + #[test] + fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = channel::>(); drop(rx); - tx.send(box 0); - } #[should_fail] } + assert!(tx.send(box 0).is_err()); + } - test! { fn oneshot_single_thread_recv_chan_close() { + #[test] + fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = channel::(); drop(tx); - rx.recv(); + rx.recv().unwrap(); }).join(); // What is our res? assert!(res.is_err()); - } } + } - test! { fn oneshot_single_thread_send_then_recv() { + #[test] + fn oneshot_single_thread_send_then_recv() { let (tx, rx) = channel::>(); - tx.send(box 10); - assert!(rx.recv() == box 10); - } } + tx.send(box 10).unwrap(); + assert!(rx.recv().unwrap() == box 10); + } - test! { fn oneshot_single_thread_try_send_open() { + #[test] + fn oneshot_single_thread_try_send_open() { let (tx, rx) = channel::(); - assert!(tx.send_opt(10).is_ok()); - assert!(rx.recv() == 10); - } } + assert!(tx.send(10).is_ok()); + assert!(rx.recv().unwrap() == 10); + } - test! { fn oneshot_single_thread_try_send_closed() { + #[test] + fn oneshot_single_thread_try_send_closed() { let (tx, rx) = channel::(); drop(rx); - assert!(tx.send_opt(10).is_err()); - } } + assert!(tx.send(10).is_err()); + } - test! { fn oneshot_single_thread_try_recv_open() { + #[test] + fn oneshot_single_thread_try_recv_open() { let (tx, rx) = channel::(); - tx.send(10); - assert!(rx.recv_opt() == Ok(10)); - } } + tx.send(10).unwrap(); + assert!(rx.recv() == Ok(10)); + } - test! { fn oneshot_single_thread_try_recv_closed() { + #[test] + fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = channel::(); drop(tx); - assert!(rx.recv_opt() == Err(())); - } } + assert!(rx.recv().is_err()); + } - test! { fn oneshot_single_thread_peek_data() { + #[test] + fn oneshot_single_thread_peek_data() { let (tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(Empty)); - tx.send(10); + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); - } } + } - test! { fn oneshot_single_thread_peek_close() { + #[test] + fn oneshot_single_thread_peek_close() { let (tx, rx) = channel::(); drop(tx); - assert_eq!(rx.try_recv(), Err(Disconnected)); - assert_eq!(rx.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + } - test! { fn oneshot_single_thread_peek_open() { + #[test] + fn oneshot_single_thread_peek_open() { let (_tx, rx) = channel::(); - assert_eq!(rx.try_recv(), Err(Empty)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + } - test! { fn oneshot_multi_task_recv_then_send() { + #[test] + fn oneshot_multi_task_recv_then_send() { let (tx, rx) = channel::>(); - spawn(move|| { - assert!(rx.recv() == box 10); + let _t = Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box 10); }); - tx.send(box 10); - } } + tx.send(box 10).unwrap(); + } - test! { fn oneshot_multi_task_recv_then_close() { + #[test] + fn oneshot_multi_task_recv_then_close() { let (tx, rx) = channel::>(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv() == box 10); + assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); - } } + } - test! { fn oneshot_multi_thread_close_stress() { + #[test] + fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); drop(tx); } - } } + } - test! { fn oneshot_multi_thread_send_close_stress() { + #[test] + fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); let _ = Thread::spawn(move|| { - tx.send(1); + tx.send(1).unwrap(); }).join(); } - } } + } - test! { fn oneshot_multi_thread_recv_close_stress() { + #[test] + fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel::(); - spawn(move|| { + Thread::spawn(move|| { let res = Thread::spawn(move|| { - rx.recv(); + rx.recv().unwrap(); }).join(); assert!(res.is_err()); - }); - spawn(move|| { - spawn(move|| { + }).detach(); + let _t = Thread::spawn(move|| { + Thread::spawn(move|| { drop(tx); - }); + }).detach(); }); } - } } + } - test! { fn oneshot_multi_thread_send_recv_stress() { + #[test] + fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); - spawn(move|| { - tx.send(box 10i); - }); - spawn(move|| { - assert!(rx.recv() == box 10i); + let _t = Thread::spawn(move|| { + tx.send(box 10i).unwrap(); }); + assert!(rx.recv().unwrap() == box 10i); } - } } + } - test! { fn stream_send_recv_stress() { + #[test] + fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = channel(); @@ -1419,69 +1406,73 @@ mod test { fn send(tx: Sender>, i: int) { if i == 10 { return } - spawn(move|| { - tx.send(box i); + Thread::spawn(move|| { + tx.send(box i).unwrap(); send(tx, i + 1); - }); + }).detach(); } fn recv(rx: Receiver>, i: int) { if i == 10 { return } - spawn(move|| { - assert!(rx.recv() == box i); + Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }); + }).detach(); } } - } } + } - test! { fn recv_a_lot() { + #[test] + fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = channel(); - for _ in range(0i, 10000) { tx.send(()); } - for _ in range(0i, 10000) { rx.recv(); } - } } + for _ in range(0i, 10000) { tx.send(()).unwrap(); } + for _ in range(0i, 10000) { rx.recv().unwrap(); } + } - test! { fn shared_chan_stress() { + #[test] + fn shared_chan_stress() { let (tx, rx) = channel(); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - spawn(move|| { - tx.send(()); - }); + Thread::spawn(move|| { + tx.send(()).unwrap(); + }).detach(); } for _ in range(0, total) { - rx.recv(); + rx.recv().unwrap(); } - } } + } - test! { fn test_nested_recv_iter() { + #[test] + fn test_nested_recv_iter() { let (tx, rx) = channel::(); let (total_tx, total_rx) = channel::(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc); + total_tx.send(acc).unwrap(); }); - tx.send(3); - tx.send(1); - tx.send(2); + tx.send(3).unwrap(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); drop(tx); - assert_eq!(total_rx.recv(), 6); - } } + assert_eq!(total_rx.recv().unwrap(), 6); + } - test! { fn test_recv_iter_break() { + #[test] + fn test_recv_iter_break() { let (tx, rx) = channel::(); let (count_tx, count_rx) = channel(); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1490,49 +1481,51 @@ mod test { count += x; } } - count_tx.send(count); + count_tx.send(count).unwrap(); }); - tx.send(2); - tx.send(2); - tx.send(2); - let _ = tx.send_opt(2); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + let _ = tx.send(2); drop(tx); - assert_eq!(count_rx.recv(), 4); - } } + assert_eq!(count_rx.recv().unwrap(), 4); + } - test! { fn try_recv_states() { + #[test] + fn try_recv_states() { let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); - spawn(move|| { - rx2.recv(); - tx1.send(1); - tx3.send(()); - rx2.recv(); + let _t = Thread::spawn(move|| { + rx2.recv().unwrap(); + tx1.send(1).unwrap(); + tx3.send(()).unwrap(); + rx2.recv().unwrap(); drop(tx1); - tx3.send(()); + tx3.send(()).unwrap(); }); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); - assert_eq!(rx1.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); + } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test! { fn destroy_upgraded_shared_port_when_sender_still_active() { + #[test] + fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = channel(); let (tx2, rx2) = channel(); - spawn(move|| { - rx.recv(); // wait on a oneshot + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()); + tx2.send(()).unwrap(); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1540,303 +1533,334 @@ mod test { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()); + t.send(()).unwrap(); // wait for the child task to exit before we exit - rx2.recv(); - }} + rx2.recv().unwrap(); + } } #[cfg(test)] mod sync_tests { - use prelude::*; + use prelude::v1::*; + use os; + use thread::Thread; + use super::*; pub fn stress_factor() -> uint { match os::getenv("RUST_TEST_STRESS") { - Some(val) => from_str::(val.as_slice()).unwrap(), + Some(val) => val.parse().unwrap(), None => 1, } } - test! { fn smoke() { + #[test] + fn smoke() { let (tx, rx) = sync_channel::(1); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn drop_full() { + #[test] + fn drop_full() { let (tx, _rx) = sync_channel(1); - tx.send(box 1i); - } } + tx.send(box 1i).unwrap(); + } - test! { fn smoke_shared() { + #[test] + fn smoke_shared() { let (tx, rx) = sync_channel::(1); - tx.send(1); - assert_eq!(rx.recv(), 1); + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); - tx.send(1); - assert_eq!(rx.recv(), 1); - } } + tx.send(1).unwrap(); + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_threads() { + #[test] + fn smoke_threads() { let (tx, rx) = sync_channel::(0); - spawn(move|| { - tx.send(1); + let _t = Thread::spawn(move|| { + tx.send(1).unwrap(); }); - assert_eq!(rx.recv(), 1); - } } + assert_eq!(rx.recv().unwrap(), 1); + } - test! { fn smoke_port_gone() { + #[test] + fn smoke_port_gone() { let (tx, rx) = sync_channel::(0); drop(rx); - tx.send(1); - } #[should_fail] } + assert!(tx.send(1).is_err()); + } - test! { fn smoke_shared_port_gone2() { + #[test] + fn smoke_shared_port_gone2() { let (tx, rx) = sync_channel::(0); drop(rx); let tx2 = tx.clone(); drop(tx); - tx2.send(1); - } #[should_fail] } + assert!(tx2.send(1).is_err()); + } - test! { fn port_gone_concurrent() { + #[test] + fn port_gone_concurrent() { let (tx, rx) = sync_channel::(0); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { tx.send(1) } - } #[should_fail] } + while tx.send(1).is_ok() {} + } - test! { fn port_gone_concurrent_shared() { + #[test] + fn port_gone_concurrent_shared() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); - spawn(move|| { - rx.recv(); + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); }); - loop { - tx.send(1); - tx2.send(1); - } - } #[should_fail] } + while tx.send(1).is_ok() && tx2.send(1).is_ok() {} + } - test! { fn smoke_chan_gone() { + #[test] + fn smoke_chan_gone() { let (tx, rx) = sync_channel::(0); drop(tx); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn smoke_chan_gone_shared() { + #[test] + fn smoke_chan_gone_shared() { let (tx, rx) = sync_channel::<()>(0); let tx2 = tx.clone(); drop(tx); drop(tx2); - rx.recv(); - } #[should_fail] } + assert!(rx.recv().is_err()); + } - test! { fn chan_gone_concurrent() { + #[test] + fn chan_gone_concurrent() { let (tx, rx) = sync_channel::(0); - spawn(move|| { - tx.send(1); - tx.send(1); - }); - loop { rx.recv(); } - } #[should_fail] } + Thread::spawn(move|| { + tx.send(1).unwrap(); + tx.send(1).unwrap(); + }).detach(); + while rx.recv().is_ok() {} + } - test! { fn stress() { + #[test] + fn stress() { let (tx, rx) = sync_channel::(0); - spawn(move|| { - for _ in range(0u, 10000) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0u, 10000) { tx.send(1).unwrap(); } + }).detach(); for _ in range(0u, 10000) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } - } } + } - test! { fn stress_shared() { + #[test] + fn stress_shared() { static AMT: uint = 1000; static NTHREADS: uint = 8; let (tx, rx) = sync_channel::(0); let (dtx, drx) = sync_channel::<()>(0); - spawn(move|| { + Thread::spawn(move|| { for _ in range(0, AMT * NTHREADS) { - assert_eq!(rx.recv(), 1); + assert_eq!(rx.recv().unwrap(), 1); } match rx.try_recv() { Ok(..) => panic!(), _ => {} } - dtx.send(()); - }); + dtx.send(()).unwrap(); + }).detach(); for _ in range(0, NTHREADS) { let tx = tx.clone(); - spawn(move|| { - for _ in range(0, AMT) { tx.send(1); } - }); + Thread::spawn(move|| { + for _ in range(0, AMT) { tx.send(1).unwrap(); } + }).detach(); } drop(tx); - drx.recv(); - } } + drx.recv().unwrap(); + } - test! { fn oneshot_single_thread_close_port_first() { + #[test] + fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending let (_tx, rx) = sync_channel::(0); drop(rx); - } } + } - test! { fn oneshot_single_thread_close_chan_first() { + #[test] + fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending let (tx, _rx) = sync_channel::(0); drop(tx); - } } + } - test! { fn oneshot_single_thread_send_port_close() { + #[test] + fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed let (tx, rx) = sync_channel::>(0); drop(rx); - tx.send(box 0); - } #[should_fail] } + assert!(tx.send(box 0).is_err()); + } - test! { fn oneshot_single_thread_recv_chan_close() { + #[test] + fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = Thread::spawn(move|| { let (tx, rx) = sync_channel::(0); drop(tx); - rx.recv(); + rx.recv().unwrap(); }).join(); // What is our res? assert!(res.is_err()); - } } + } - test! { fn oneshot_single_thread_send_then_recv() { + #[test] + fn oneshot_single_thread_send_then_recv() { let (tx, rx) = sync_channel::>(1); - tx.send(box 10); - assert!(rx.recv() == box 10); - } } + tx.send(box 10).unwrap(); + assert!(rx.recv().unwrap() == box 10); + } - test! { fn oneshot_single_thread_try_send_open() { + #[test] + fn oneshot_single_thread_try_send_open() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(10), Ok(())); - assert!(rx.recv() == 10); - } } + assert!(rx.recv().unwrap() == 10); + } - test! { fn oneshot_single_thread_try_send_closed() { + #[test] + fn oneshot_single_thread_try_send_closed() { let (tx, rx) = sync_channel::(0); drop(rx); - assert_eq!(tx.try_send(10), Err(RecvDisconnected(10))); - } } + assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10))); + } - test! { fn oneshot_single_thread_try_send_closed2() { + #[test] + fn oneshot_single_thread_try_send_closed2() { let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(10), Err(Full(10))); - } } + assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); + } - test! { fn oneshot_single_thread_try_recv_open() { + #[test] + fn oneshot_single_thread_try_recv_open() { let (tx, rx) = sync_channel::(1); - tx.send(10); - assert!(rx.recv_opt() == Ok(10)); - } } + tx.send(10).unwrap(); + assert!(rx.recv() == Ok(10)); + } - test! { fn oneshot_single_thread_try_recv_closed() { + #[test] + fn oneshot_single_thread_try_recv_closed() { let (tx, rx) = sync_channel::(0); drop(tx); - assert!(rx.recv_opt() == Err(())); - } } + assert!(rx.recv().is_err()); + } - test! { fn oneshot_single_thread_peek_data() { + #[test] + fn oneshot_single_thread_peek_data() { let (tx, rx) = sync_channel::(1); - assert_eq!(rx.try_recv(), Err(Empty)); - tx.send(10); + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); - } } + } - test! { fn oneshot_single_thread_peek_close() { + #[test] + fn oneshot_single_thread_peek_close() { let (tx, rx) = sync_channel::(0); drop(tx); - assert_eq!(rx.try_recv(), Err(Disconnected)); - assert_eq!(rx.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); + } - test! { fn oneshot_single_thread_peek_open() { + #[test] + fn oneshot_single_thread_peek_open() { let (_tx, rx) = sync_channel::(0); - assert_eq!(rx.try_recv(), Err(Empty)); - } } + assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); + } - test! { fn oneshot_multi_task_recv_then_send() { + #[test] + fn oneshot_multi_task_recv_then_send() { let (tx, rx) = sync_channel::>(0); - spawn(move|| { - assert!(rx.recv() == box 10); + let _t = Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box 10); }); - tx.send(box 10); - } } + tx.send(box 10).unwrap(); + } - test! { fn oneshot_multi_task_recv_then_close() { + #[test] + fn oneshot_multi_task_recv_then_close() { let (tx, rx) = sync_channel::>(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(tx); }); let res = Thread::spawn(move|| { - assert!(rx.recv() == box 10); + assert!(rx.recv().unwrap() == box 10); }).join(); assert!(res.is_err()); - } } + } - test! { fn oneshot_multi_thread_close_stress() { + #[test] + fn oneshot_multi_thread_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); drop(tx); } - } } + } - test! { fn oneshot_multi_thread_send_close_stress() { + #[test] + fn oneshot_multi_thread_send_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - spawn(move|| { + let _t = Thread::spawn(move|| { drop(rx); }); let _ = Thread::spawn(move || { - tx.send(1); + tx.send(1).unwrap(); }).join(); } - } } + } - test! { fn oneshot_multi_thread_recv_close_stress() { + #[test] + fn oneshot_multi_thread_recv_close_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let res = Thread::spawn(move|| { - rx.recv(); + rx.recv().unwrap(); }).join(); assert!(res.is_err()); }); - spawn(move|| { - spawn(move|| { + let _t = Thread::spawn(move|| { + Thread::spawn(move|| { drop(tx); - }); + }).detach(); }); } - } } + } - test! { fn oneshot_multi_thread_send_recv_stress() { + #[test] + fn oneshot_multi_thread_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); - spawn(move|| { - tx.send(box 10i); - }); - spawn(move|| { - assert!(rx.recv() == box 10i); + let _t = Thread::spawn(move|| { + tx.send(box 10i).unwrap(); }); + assert!(rx.recv().unwrap() == box 10i); } - } } + } - test! { fn stream_send_recv_stress() { + #[test] + fn stream_send_recv_stress() { for _ in range(0, stress_factor()) { let (tx, rx) = sync_channel::>(0); @@ -1846,69 +1870,73 @@ mod sync_tests { fn send(tx: SyncSender>, i: int) { if i == 10 { return } - spawn(move|| { - tx.send(box i); + Thread::spawn(move|| { + tx.send(box i).unwrap(); send(tx, i + 1); - }); + }).detach(); } fn recv(rx: Receiver>, i: int) { if i == 10 { return } - spawn(move|| { - assert!(rx.recv() == box i); + Thread::spawn(move|| { + assert!(rx.recv().unwrap() == box i); recv(rx, i + 1); - }); + }).detach(); } } - } } + } - test! { fn recv_a_lot() { + #[test] + fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = sync_channel(10000); - for _ in range(0u, 10000) { tx.send(()); } - for _ in range(0u, 10000) { rx.recv(); } - } } + for _ in range(0u, 10000) { tx.send(()).unwrap(); } + for _ in range(0u, 10000) { rx.recv().unwrap(); } + } - test! { fn shared_chan_stress() { + #[test] + fn shared_chan_stress() { let (tx, rx) = sync_channel(0); let total = stress_factor() + 100; for _ in range(0, total) { let tx = tx.clone(); - spawn(move|| { - tx.send(()); - }); + Thread::spawn(move|| { + tx.send(()).unwrap(); + }).detach(); } for _ in range(0, total) { - rx.recv(); + rx.recv().unwrap(); } - } } + } - test! { fn test_nested_recv_iter() { + #[test] + fn test_nested_recv_iter() { let (tx, rx) = sync_channel::(0); let (total_tx, total_rx) = sync_channel::(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut acc = 0; for x in rx.iter() { acc += x; } - total_tx.send(acc); + total_tx.send(acc).unwrap(); }); - tx.send(3); - tx.send(1); - tx.send(2); + tx.send(3).unwrap(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); drop(tx); - assert_eq!(total_rx.recv(), 6); - } } + assert_eq!(total_rx.recv().unwrap(), 6); + } - test! { fn test_recv_iter_break() { + #[test] + fn test_recv_iter_break() { let (tx, rx) = sync_channel::(0); let (count_tx, count_rx) = sync_channel(0); - spawn(move|| { + let _t = Thread::spawn(move|| { let mut count = 0; for x in rx.iter() { if count >= 3 { @@ -1917,49 +1945,51 @@ mod sync_tests { count += x; } } - count_tx.send(count); + count_tx.send(count).unwrap(); }); - tx.send(2); - tx.send(2); - tx.send(2); + tx.send(2).unwrap(); + tx.send(2).unwrap(); + tx.send(2).unwrap(); let _ = tx.try_send(2); drop(tx); - assert_eq!(count_rx.recv(), 4); - } } + assert_eq!(count_rx.recv().unwrap(), 4); + } - test! { fn try_recv_states() { + #[test] + fn try_recv_states() { let (tx1, rx1) = sync_channel::(1); let (tx2, rx2) = sync_channel::<()>(1); let (tx3, rx3) = sync_channel::<()>(1); - spawn(move|| { - rx2.recv(); - tx1.send(1); - tx3.send(()); - rx2.recv(); + let _t = Thread::spawn(move|| { + rx2.recv().unwrap(); + tx1.send(1).unwrap(); + tx3.send(()).unwrap(); + rx2.recv().unwrap(); drop(tx1); - tx3.send(()); + tx3.send(()).unwrap(); }); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); assert_eq!(rx1.try_recv(), Ok(1)); - assert_eq!(rx1.try_recv(), Err(Empty)); - tx2.send(()); - rx3.recv(); - assert_eq!(rx1.try_recv(), Err(Disconnected)); - } } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); + assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected)); + } // This bug used to end up in a livelock inside of the Receiver destructor // because the internal state of the Shared packet was corrupted - test! { fn destroy_upgraded_shared_port_when_sender_still_active() { + #[test] + fn destroy_upgraded_shared_port_when_sender_still_active() { let (tx, rx) = sync_channel::<()>(0); let (tx2, rx2) = sync_channel::<()>(0); - spawn(move|| { - rx.recv(); // wait on a oneshot + let _t = Thread::spawn(move|| { + rx.recv().unwrap(); // wait on a oneshot drop(rx); // destroy a shared - tx2.send(()); + tx2.send(()).unwrap(); }); // make sure the other task has gone to sleep for _ in range(0u, 5000) { Thread::yield_now(); } @@ -1967,92 +1997,91 @@ mod sync_tests { // upgrade to a shared chan and send a message let t = tx.clone(); drop(tx); - t.send(()); + t.send(()).unwrap(); // wait for the child task to exit before we exit - rx2.recv(); - } } + rx2.recv().unwrap(); + } - test! { fn send_opt1() { + #[test] + fn send1() { let (tx, rx) = sync_channel::(0); - spawn(move|| { rx.recv(); }); - assert_eq!(tx.send_opt(1), Ok(())); - } } + let _t = Thread::spawn(move|| { rx.recv().unwrap(); }); + assert_eq!(tx.send(1), Ok(())); + } - test! { fn send_opt2() { + #[test] + fn send2() { let (tx, rx) = sync_channel::(0); - spawn(move|| { drop(rx); }); - assert_eq!(tx.send_opt(1), Err(1)); - } } + let _t = Thread::spawn(move|| { drop(rx); }); + assert!(tx.send(1).is_err()); + } - test! { fn send_opt3() { + #[test] + fn send3() { let (tx, rx) = sync_channel::(1); - assert_eq!(tx.send_opt(1), Ok(())); - spawn(move|| { drop(rx); }); - assert_eq!(tx.send_opt(1), Err(1)); - } } + assert_eq!(tx.send(1), Ok(())); + let _t =Thread::spawn(move|| { drop(rx); }); + assert!(tx.send(1).is_err()); + } - test! { fn send_opt4() { + #[test] + fn send4() { let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); let (done, donerx) = channel(); let done2 = done.clone(); - spawn(move|| { - assert_eq!(tx.send_opt(1), Err(1)); - done.send(()); + let _t = Thread::spawn(move|| { + assert!(tx.send(1).is_err()); + done.send(()).unwrap(); }); - spawn(move|| { - assert_eq!(tx2.send_opt(2), Err(2)); - done2.send(()); + let _t = Thread::spawn(move|| { + assert!(tx2.send(2).is_err()); + done2.send(()).unwrap(); }); drop(rx); - donerx.recv(); - donerx.recv(); - } } + donerx.recv().unwrap(); + donerx.recv().unwrap(); + } - test! { fn try_send1() { + #[test] + fn try_send1() { let (tx, _rx) = sync_channel::(0); - assert_eq!(tx.try_send(1), Err(Full(1))); - } } + assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); + } - test! { fn try_send2() { + #[test] + fn try_send2() { let (tx, _rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); - assert_eq!(tx.try_send(1), Err(Full(1))); - } } + assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); + } - test! { fn try_send3() { + #[test] + fn try_send3() { let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); - assert_eq!(tx.try_send(1), Err(RecvDisconnected(1))); - } } - - test! { fn try_send4() { - let (tx, rx) = sync_channel::(0); - spawn(move|| { - for _ in range(0u, 1000) { Thread::yield_now(); } - assert_eq!(tx.try_send(1), Ok(())); - }); - assert_eq!(rx.recv(), 1); - } #[ignore(reason = "flaky on libnative")] } + assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); + } - test! { fn issue_15761() { + #[test] + fn issue_15761() { fn repro() { let (tx1, rx1) = sync_channel::<()>(3); let (tx2, rx2) = sync_channel::<()>(3); - spawn(move|| { - rx1.recv(); + let _t = Thread::spawn(move|| { + rx1.recv().unwrap(); tx2.try_send(()).unwrap(); }); tx1.try_send(()).unwrap(); - rx2.recv(); + rx2.recv().unwrap(); } for _ in range(0u, 100) { repro() } - } } + } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index e21aa3ef7e91b..4afd5bb63f4fe 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -41,7 +41,7 @@ use sys_common::rwlock as sys; /// ``` /// use std::sync::RwLock; /// -/// let lock = RwLock::new(5); +/// let lock = RwLock::new(5i); /// /// // many reader locks can be held at once /// { From 4b359e3aeeaf97a190c5a7ecff8815b7b5734ece Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Jan 2015 19:13:38 -0800 Subject: [PATCH 106/106] More test fixes! --- src/libcollections/dlist.rs | 1 + src/libcore/iter.rs | 157 ------------------ src/libcoretest/iter.rs | 2 +- src/libgraphviz/lib.rs | 2 +- src/librand/chacha.rs | 4 +- src/librand/lib.rs | 2 +- .../middle/infer/region_inference/mod.rs | 4 +- src/librustc_trans/back/write.rs | 4 +- src/librustc_trans/trans/base.rs | 2 +- src/librustc_typeck/check/_match.rs | 4 +- src/librustc_typeck/check/regionck.rs | 2 +- src/libserialize/json_stage0.rs | 2 +- src/libserialize/serialize_stage0.rs | 2 +- src/libstd/dynamic_lib.rs | 2 +- src/libstd/lib.rs | 2 - src/libstd/rand/mod.rs | 4 +- src/libstd/sys/windows/process.rs | 14 +- src/libsyntax/feature_gate.rs | 14 +- src/libsyntax/parse/parser.rs | 12 +- src/libsyntax/show_span.rs | 4 +- src/test/auxiliary/traitimpl.rs | 2 +- src/test/auxiliary/two_macros.rs | 2 - ...pe-projection-from-multiple-supertraits.rs | 2 - ...ociated-type-projection-from-supertrait.rs | 2 - ...s-binding-to-type-defined-in-supertrait.rs | 2 - .../associated-types-feature-gate.rs | 33 ---- ...ted-types-invalid-trait-ref-issue-18865.rs | 2 - .../associated-types-issue-17359.rs | 2 - .../gated-default-type-param-usage.rs | 22 --- .../compile-fail/gated-default-type-params.rs | 15 -- src/test/compile-fail/gated-glob-imports.rs | 14 -- src/test/compile-fail/macros-no-semicolon.rs | 2 +- .../compile-fail/mut-pattern-mismatched.rs | 4 +- ...gions-close-associated-type-into-object.rs | 2 - src/test/compile-fail/unsized3.rs | 2 +- src/test/run-pass/const-str-ptr.rs | 2 - .../run-pass/method-recursive-blanket-impl.rs | 2 +- ...ions-on-closures-to-inference-variables.rs | 4 +- src/test/run-pass/running-with-no-runtime.rs | 4 +- src/test/run-pass/unsized.rs | 6 +- src/test/run-pass/unsized2.rs | 6 +- src/test/run-pass/vec-macro-no-std.rs | 6 +- 42 files changed, 50 insertions(+), 328 deletions(-) delete mode 100644 src/test/compile-fail/associated-types-feature-gate.rs delete mode 100644 src/test/compile-fail/gated-default-type-param-usage.rs delete mode 100644 src/test/compile-fail/gated-default-type-params.rs delete mode 100644 src/test/compile-fail/gated-glob-imports.rs diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 14d61edca0438..5e08f90ce1c53 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -1066,6 +1066,7 @@ mod tests { } #[allow(deprecated)] + #[test] fn test_append() { { let mut m = DList::new(); diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 9a2245501a814..e5753f6cc2e78 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1171,134 +1171,6 @@ impl_multiplicative! { uint, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } -<<<<<<< HEAD -======= -/// A trait for iterators over elements which can be compared to one another. -#[unstable = "recently renamed for new extension trait conventions"] -pub trait IteratorOrdExt { - /// Consumes the entire iterator to return the maximum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// assert!(a.iter().max().unwrap() == &5); - /// ``` - fn max(self) -> Option; - - /// Consumes the entire iterator to return the minimum element. - /// - /// # Example - /// - /// ```rust - /// let a = [1i, 2, 3, 4, 5]; - /// assert!(a.iter().min().unwrap() == &1); - /// ``` - fn min(self) -> Option; - - /// `min_max` finds the minimum and maximum elements in the iterator. - /// - /// The return type `MinMaxResult` is an enum of three variants: - /// - /// - `NoElements` if the iterator is empty. - /// - `OneElement(x)` if the iterator has exactly one element. - /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two - /// values are equal if and only if there is more than one - /// element in the iterator and all elements are equal. - /// - /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. - /// - /// # Example - /// - /// ```rust - /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; - /// - /// let v: [int; 0] = []; - /// assert_eq!(v.iter().min_max(), NoElements); - /// - /// let v = [1i]; - /// assert!(v.iter().min_max() == OneElement(&1)); - /// - /// let v = [1i, 2, 3, 4, 5]; - /// assert!(v.iter().min_max() == MinMax(&1, &5)); - /// - /// let v = [1i, 2, 3, 4, 5, 6]; - /// assert!(v.iter().min_max() == MinMax(&1, &6)); - /// - /// let v = [1i, 1, 1, 1]; - /// assert!(v.iter().min_max() == MinMax(&1, &1)); - /// ``` - fn min_max(self) -> MinMaxResult; -} - -#[unstable = "trait is unstable"] -impl IteratorOrdExt for I where I: Iterator, T: Ord { - #[inline] - fn max(self) -> Option { - self.fold(None, |max, x| { - match max { - None => Some(x), - Some(y) => Some(cmp::max(x, y)) - } - }) - } - - #[inline] - fn min(self) -> Option { - self.fold(None, |min, x| { - match min { - None => Some(x), - Some(y) => Some(cmp::min(x, y)) - } - }) - } - - fn min_max(mut self) -> MinMaxResult { - let (mut min, mut max) = match self.next() { - None => return NoElements, - Some(x) => { - match self.next() { - None => return OneElement(x), - Some(y) => if x < y {(x, y)} else {(y,x)} - } - } - }; - - loop { - // `first` and `second` are the two next elements we want to look at. - // We first compare `first` and `second` (#1). The smaller one is then compared to - // current minimum (#2). The larger one is compared to current maximum (#3). This - // way we do 3 comparisons for 2 elements. - let first = match self.next() { - None => break, - Some(x) => x - }; - let second = match self.next() { - None => { - if first < min { - min = first; - } else if first > max { - max = first; - } - break; - } - Some(x) => x - }; - if first < second { - if first < min {min = first;} - if max < second {max = second;} - } else { - if second < min {min = second;} - if max < first {max = first;} - } - } - - MinMax(min, max) - } -} - ->>>>>>> parent of f031671... Remove i suffix in docs /// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail. #[derive(Clone, PartialEq, Show)] #[unstable = "unclear whether such a fine-grained result is widely useful"] @@ -1386,35 +1258,6 @@ impl ExactSizeIterator for Cloned where I: ExactSizeIterator + Iterator, {} -<<<<<<< HEAD -======= -#[unstable = "recently renamed for extension trait conventions"] -/// An extension trait for cloneable iterators. -pub trait CloneIteratorExt { - /// Repeats an iterator endlessly - /// - /// # Example - /// - /// ```rust - /// use std::iter::{CloneIteratorExt, count}; - /// - /// let a = count(1i,1i).take(1); - /// let mut cy = a.cycle(); - /// assert_eq!(cy.next(), Some(1)); - /// assert_eq!(cy.next(), Some(1)); - /// ``` - #[stable] - fn cycle(self) -> Cycle; -} - -impl CloneIteratorExt for I where I: Iterator + Clone { - #[inline] - fn cycle(self) -> Cycle { - Cycle{orig: self.clone(), iter: self} - } -} - ->>>>>>> parent of f031671... Remove i suffix in docs /// An iterator that repeats endlessly #[derive(Clone, Copy)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 2aa2a229f90fa..73db72d0313e6 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -769,7 +769,7 @@ fn test_range_step_inclusive() { #[test] fn test_reverse() { let mut ys = [1i, 2, 3, 4, 5]; - ys.iter_mut().reverse_(); + ys.iter_mut().reverse_in_place(); assert!(ys == [5, 4, 3, 2, 1]); } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index e3bcf70e8c82f..64cc490f4b163 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -587,7 +587,7 @@ pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N mod tests { use self::NodeLabels::*; use super::{Id, Labeller, Nodes, Edges, GraphWalk, render}; - use super::LabelText::{mod, LabelStr, EscStr}; + use super::LabelText::{self, LabelStr, EscStr}; use std::io::IoResult; use std::borrow::IntoCow; use std::iter::repeat; diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index ce055a84d3f2a..815fc0e7ec7ad 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -27,7 +27,7 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of /// /// [1]: D. J. Bernstein, [*ChaCha, a variant of /// Salsa20*](http://cr.yp.to/chacha.html) -#[deriving(Copy, Clone)] +#[derive(Copy, Clone)] pub struct ChaChaRng { buffer: [u32; STATE_WORDS], // Internal buffer of output state: [u32; STATE_WORDS], // Initial state @@ -284,7 +284,7 @@ mod test { #[test] fn test_rng_clone() { - let seed : &[_] = &[0u32, ..8]; + let seed : &[_] = &[0u32; 8]; let mut rng: ChaChaRng = SeedableRng::from_seed(seed); let mut clone = rng.clone(); for _ in range(0u, 16) { diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 8eae769737614..c4dd08f9917e2 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -403,7 +403,7 @@ pub trait SeedableRng: Rng { /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of /// Statistical Software*. Vol. 8 (Issue 14). #[allow(missing_copy_implementations)] -#[deriving(Clone)] +#[derive(Clone)] pub struct XorShiftRng { x: u32, y: u32, diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 23e96dafa611b..d30a6ff1cd9d5 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -22,7 +22,7 @@ use super::cres; use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable}; use middle::region; -use middle::ty::{mod, Ty}; +use middle::ty::{self, Ty}; use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid}; use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound}; use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; @@ -69,7 +69,7 @@ pub enum Verify<'tcx> { VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec), } -#[deriving(Clone, Show, PartialEq, Eq)] +#[derive(Clone, Show, PartialEq, Eq)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 089d7f737d3cf..98e2b4b9dddb5 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,7 +22,7 @@ use syntax::codemap; use syntax::diagnostic; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; -use std::ffi::{mod, CString}; +use std::ffi::{self, CString}; use std::io::Command; use std::io::fs; use std::iter::Unfold; @@ -32,7 +32,7 @@ use std::mem; use std::sync::{Arc, Mutex}; use std::sync::mpsc::channel; use std::thread; -use libc::{mod, c_uint, c_int, c_void}; +use libc::{self, c_uint, c_int, c_void}; #[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)] pub enum OutputType { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 7031710c679ad..edcfaae0f802d 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -88,7 +88,7 @@ use util::nodemap::NodeMap; use arena::TypedArena; use libc::{c_uint, uint64_t}; -use std::ffi::{mod, CString}; +use std::ffi::{self, CString}; use std::cell::{Cell, RefCell}; use std::collections::HashSet; use std::mem; diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c5b5325e9d441..80e7e70605956 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -195,10 +195,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ast::PatRegion(ref inner, mutbl) => { let inner_ty = fcx.infcx().next_ty_var(); - // SNAP c894171 remove this `if`-`else` entirely after next snapshot + // SNAP b2085d9 remove this `if`-`else` entirely after next snapshot let mutbl = if mutbl == ast::MutImmutable { ty::deref(fcx.infcx().shallow_resolve(expected), true) - .map(|mt| mt.mutbl).unwrap_or(ast::MutImmutable); + .map(|mt| mt.mutbl).unwrap_or(ast::MutImmutable) } else { mutbl }; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b7397b5f9ee61..c7df5ed8453fd 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -92,7 +92,7 @@ use middle::region::CodeExtent; use middle::traits; use middle::ty::{ReScope}; use middle::ty::{self, Ty, MethodCall}; -use middle::infer::{mod, GenericKind}; +use middle::infer::{self, GenericKind}; use middle::pat_util; use util::ppaux::{ty_to_string, Repr}; diff --git a/src/libserialize/json_stage0.rs b/src/libserialize/json_stage0.rs index 9932f8d0306b3..a157d91727498 100644 --- a/src/libserialize/json_stage0.rs +++ b/src/libserialize/json_stage0.rs @@ -2298,7 +2298,7 @@ impl ::Decoder for Decoder { } /// A trait for converting values to JSON -pub trait ToJson for Sized? { +pub trait ToJson { /// Converts the value of `self` to an instance of JSON fn to_json(&self) -> Json; } diff --git a/src/libserialize/serialize_stage0.rs b/src/libserialize/serialize_stage0.rs index c4317b99dce06..fd37bb63230af 100644 --- a/src/libserialize/serialize_stage0.rs +++ b/src/libserialize/serialize_stage0.rs @@ -172,7 +172,7 @@ pub trait Decoder { fn error(&mut self, err: &str) -> E; } -pub trait Encodable, E> for Sized? { +pub trait Encodable, E> { fn encode(&self, s: &mut S) -> Result<(), E>; } diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index 66cb1f2c948d9..2d013a8a5b830 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -128,8 +128,8 @@ impl DynamicLibrary { // This function should have a lifetime constraint of 'a on // T but that feature is still unimplemented + let raw_string = CString::from_slice(symbol.as_bytes()); let maybe_symbol_value = dl::check_for_errors_in(|| { - let raw_string = CString::from_slice(symbol.as_bytes()); dl::symbol(self.handle, raw_string.as_ptr()) }); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e937cd24d8d78..b9f226c5aca73 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -253,8 +253,6 @@ pub mod num; /* Runtime and platform support */ -pub mod thread_local; // first for macros - #[cfg_attr(stage0, macro_escape)] #[cfg_attr(not(stage0), macro_use)] pub mod thread_local; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index cadaae5de5c20..8855a7e5293ac 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -245,7 +245,7 @@ pub mod reader; /// The standard RNG. This is designed to be efficient on the current /// platform. -#[deriving(Copy, Clone)] +#[derive(Copy, Clone)] pub struct StdRng { rng: IsaacWordRng, } @@ -322,7 +322,7 @@ static THREAD_RNG_RESEED_THRESHOLD: uint = 32_768; type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. -#[deriving(Clone)] +#[derive(Clone)] pub struct ThreadRng { rng: Rc>, } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 9b3f2ca03736e..7b667416b1714 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -466,19 +466,17 @@ fn free_handle(handle: *mut ()) { #[cfg(test)] mod tests { - use c_str::ToCStr; + use prelude::v1::*; + use str; + use ffi::CString; + use super::make_command_line; #[test] fn test_make_command_line() { - use prelude::v1::*; - use str; - use c_str::CString; - use super::make_command_line; - fn test_wrapper(prog: &str, args: &[&str]) -> String { - make_command_line(&prog.to_c_str(), + make_command_line(&CString::from_slice(prog.as_bytes()), args.iter() - .map(|a| a.to_c_str()) + .map(|a| CString::from_slice(a.as_bytes())) .collect::>() .as_slice()) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 43e4039330837..0810d4ee93ac7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -267,7 +267,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - ast::ItemImpl(_, polarity, _, _, _, ref items) => { + ast::ItemImpl(_, polarity, _, _, _, _) => { match polarity { ast::ImplPolarity::Negative => { self.gate_feature("optin_builtin_traits", @@ -294,18 +294,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { i.span, "the new orphan check rules will eventually be strictly enforced"); } - - for item in items.iter() { - match *item { - ast::MethodImplItem(_) => {} - ast::TypeImplItem(ref typedef) => { - self.gate_feature("associated_types", - typedef.span, - "associated types are \ - experimental") - } - } - } } _ => {} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index cdfbd2c74b6af..32f8f5ee3d63b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1244,7 +1244,7 @@ impl<'a> Parser<'a> { let _ = self.parse_ret_ty(); - self.obsolete(ty_closure_span, ObsoleteClosureType); + self.obsolete(ty_closure_span, ObsoleteSyntax::ClosureType); TyInfer } @@ -3897,16 +3897,10 @@ impl<'a> Parser<'a> { _ => { let e = self.mk_mac_expr(span.lo, span.hi, -<<<<<<< HEAD - macro.and_then(|m| m.node)); + mac.and_then(|m| m.node)); let e = self.parse_dot_or_call_expr_with(e); let e = self.parse_more_binops(e, 0); let e = self.parse_assign_expr_with(e); -======= - mac.and_then(|m| m.node)); - let e = - self.parse_dot_or_call_expr_with(e); ->>>>>>> kmc/macro-reform self.handle_expression_like_statement( e, ast::DUMMY_NODE_ID, @@ -5082,7 +5076,7 @@ impl<'a> Parser<'a> { } let _tref = Parser::trait_ref_from_ident(ident, span); - self.obsolete(span, ObsoleteForSized); + self.obsolete(span, ObsoleteSyntax::ForSized); None } else { diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 51d655ec0f2c5..57520257fe1b3 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -65,8 +65,8 @@ impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> { visit::walk_ty(self, t); } - fn visit_mac(&mut self, macro: &ast::Mac) { - visit::walk_mac(self, macro); + fn visit_mac(&mut self, mac: &ast::Mac) { + visit::walk_mac(self, mac); } } diff --git a/src/test/auxiliary/traitimpl.rs b/src/test/auxiliary/traitimpl.rs index fd454509b3940..33824af6187a2 100644 --- a/src/test/auxiliary/traitimpl.rs +++ b/src/test/auxiliary/traitimpl.rs @@ -10,7 +10,7 @@ // Test inherant trait impls work cross-crait. -pub trait Bar<'a> for ?Sized : 'a {} +pub trait Bar<'a> : 'a {} impl<'a> Bar<'a> { pub fn bar(&self) {} diff --git a/src/test/auxiliary/two_macros.rs b/src/test/auxiliary/two_macros.rs index 11b6108b99ed9..060960f0dbc88 100644 --- a/src/test/auxiliary/two_macros.rs +++ b/src/test/auxiliary/two_macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// force-host - #[macro_export] macro_rules! macro_one { () => ("one") } diff --git a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs index 6555aa3202779..c55e24e81adc2 100644 --- a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs +++ b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs @@ -11,8 +11,6 @@ // Test equality constraints in a where clause where the type being // equated appears in a supertrait. -#![feature(associated_types)] - pub trait Vehicle { type Color; diff --git a/src/test/compile-fail/associated-type-projection-from-supertrait.rs b/src/test/compile-fail/associated-type-projection-from-supertrait.rs index 01f9bd3541fc5..abaf79fb4cb1b 100644 --- a/src/test/compile-fail/associated-type-projection-from-supertrait.rs +++ b/src/test/compile-fail/associated-type-projection-from-supertrait.rs @@ -11,8 +11,6 @@ // Test equality constraints in a where clause where the type being // equated appears in a supertrait. -#![feature(associated_types)] - pub trait Vehicle { type Color; diff --git a/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs index a362529bee8e4..b1194154911c9 100644 --- a/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs +++ b/src/test/compile-fail/associated-types-binding-to-type-defined-in-supertrait.rs @@ -11,8 +11,6 @@ // Test equality constraints in a where clause where the type being // equated appears in a supertrait. -#![feature(associated_types)] - pub trait Vehicle { type Color; diff --git a/src/test/compile-fail/associated-types-feature-gate.rs b/src/test/compile-fail/associated-types-feature-gate.rs deleted file mode 100644 index d95b94f006760..0000000000000 --- a/src/test/compile-fail/associated-types-feature-gate.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -trait Get { - type Value; //~ ERROR associated types are experimental - fn get(&self) -> Get::Value; -} - -struct Struct { - x: int, -} - -impl Get for Struct { - type Value = int; //~ ERROR associated types are experimental - fn get(&self) -> int { - self.x - } -} - -fn main() { - let s = Struct { - x: 100, - }; - assert_eq!(s.get(), 100); -} - diff --git a/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs index 8afd86195ff53..b04b83e575bf4 100644 --- a/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs +++ b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs @@ -11,8 +11,6 @@ // Test that we report an error if the trait ref in an qualified type // uses invalid type arguments. -#![feature(associated_types)] - trait Foo { type Bar; fn get_bar(&self) -> Self::Bar; diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs index 764b79c4cc649..6c79105abee8f 100644 --- a/src/test/compile-fail/associated-types-issue-17359.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -11,8 +11,6 @@ // Test that we do not ICE when an impl is missing an associated type (and that we report // a useful error, of course). -#![feature(associated_types)] - trait Trait { type Type; } diff --git a/src/test/compile-fail/gated-default-type-param-usage.rs b/src/test/compile-fail/gated-default-type-param-usage.rs deleted file mode 100644 index 4c8b5de4c864b..0000000000000 --- a/src/test/compile-fail/gated-default-type-param-usage.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -// aux-build:default_type_params_xc.rs - -#![deny(default_type_param_usage)] - -extern crate default_type_params_xc; - -pub struct FooAlloc; - -pub type VecFoo = default_type_params_xc::FakeVec; -//~^ ERROR: default type parameters are experimental - -fn main() {} diff --git a/src/test/compile-fail/gated-default-type-params.rs b/src/test/compile-fail/gated-default-type-params.rs deleted file mode 100644 index 65575d4fa8507..0000000000000 --- a/src/test/compile-fail/gated-default-type-params.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -struct Heap; - -struct Vec; //~ ERROR: default type parameters are experimental - -fn main() {} diff --git a/src/test/compile-fail/gated-glob-imports.rs b/src/test/compile-fail/gated-glob-imports.rs deleted file mode 100644 index cc7ba785e7e65..0000000000000 --- a/src/test/compile-fail/gated-glob-imports.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 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. - -use std::*; -//~^ ERROR: glob import statements are experimental - -fn main() {} diff --git a/src/test/compile-fail/macros-no-semicolon.rs b/src/test/compile-fail/macros-no-semicolon.rs index fd5f5866f0940..0e85551e2161c 100644 --- a/src/test/compile-fail/macros-no-semicolon.rs +++ b/src/test/compile-fail/macros-no-semicolon.rs @@ -10,7 +10,7 @@ fn main() { assert!(1 == 2) - assert!(3 == 4) //~ ERROR expected one of `.`, `;`, or `}`, found `assert` + assert!(3 == 4) //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `assert` println!("hello"); } diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs index 74e6141a2b3ff..81985a3d6aa5b 100644 --- a/src/test/compile-fail/mut-pattern-mismatched.rs +++ b/src/test/compile-fail/mut-pattern-mismatched.rs @@ -13,8 +13,8 @@ fn main() { // (separate lines to ensure the spans are accurate) - // SNAP c894171 uncomment this after the next snapshot - // NOTE(stage0) just in case tidy doesn't check SNAP's in tests + // SNAP b2085d9 uncomment this after the next snapshot + // NOTE(stage0) just in case tidy doesn't check snap's in tests // let &_ // ~ ERROR expected `&mut int`, found `&_` // = foo; let &mut _ = foo; diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index 84664078d5629..816314529b5e8 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait X {} trait Iter { diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 1b0368a351abc..9b7d10b0d0f76 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -20,7 +20,7 @@ fn f2(x: &X) { } // Bounded. -trait T for {} +trait T {} fn f3(x: &X) { f4::(x); //~^ ERROR the trait `core::kinds::Sized` is not implemented diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index 1a84236793b4f..e846501be6ee5 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -18,8 +18,6 @@ pub fn main() { unsafe { let foo = &A as *const u8; assert_eq!(str::from_utf8_unchecked(&A), "hi"); - assert_eq!(String::from_raw_buf_len(foo, A.len()), "hi".to_string()); - assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string()); assert!(*C == A[0]); assert!(*(&B[0] as *const u8) == A[0]); } diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs index 4e4fb75b428cc..e81244d4beabc 100644 --- a/src/test/run-pass/method-recursive-blanket-impl.rs +++ b/src/test/run-pass/method-recursive-blanket-impl.rs @@ -16,7 +16,7 @@ use std::kinds::Sized; // Note: this must be generic for the problem to show up -trait Foo for ?Sized { +trait Foo { fn foo(&self); } diff --git a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs index aa0ed023da3e2..2bdc883b9ce59 100644 --- a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs +++ b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs @@ -27,7 +27,7 @@ struct Foo<'a,'tcx:'a> { impl<'a,'tcx> Foo<'a,'tcx> { fn bother(&mut self) -> int { - self.elaborate_bounds(|this| { + self.elaborate_bounds(box |this| { // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`, // where `'f0` and `'f1` are fresh, free regions that // result from the bound regions on the closure, and `'2` @@ -50,7 +50,7 @@ impl<'a,'tcx> Foo<'a,'tcx> { fn elaborate_bounds( &mut self, - mk_cand: for<'b>|this: &mut Foo<'b, 'tcx>| -> int) + mut mk_cand: Box FnMut(&mut Foo<'b, 'tcx>) -> int>) -> int { mk_cand(self) diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index fc53737bb445a..6f807fc34995e 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ffi; use std::io::process::{Command, ProcessOutput}; use std::os; use std::rt::unwind::try; @@ -34,7 +35,8 @@ fn start(argc: int, argv: *const *const u8) -> int { let args = unsafe { range(0, argc as uint).map(|i| { - String::from_raw_buf(*argv.offset(i as int)).into_bytes() + let ptr = *argv.offset(i as int) as *const _; + ffi::c_str_to_bytes(&ptr).to_vec() }).collect::>() }; let me = args[0].as_slice(); diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index 07b9fac66554e..e6dd8d46952eb 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -12,9 +12,9 @@ // Test syntax checks for `?Sized` syntax. -trait T1 for ?Sized {} -pub trait T2 for ?Sized {} -trait T3 for ?Sized: T2 {} +trait T1 {} +pub trait T2 {} +trait T3 : T2 {} trait T4 {} trait T5 {} trait T6 {} diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index 8d2c99d4414c9..c7e8b2a05ec5b 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -22,7 +22,7 @@ fn f2(x: &X) { } // Bounded. -trait T for ?Sized {} +trait T {} fn f3(x: &X) { f3::(x); } @@ -32,7 +32,7 @@ fn f4(x: &X) { } // Self type. -trait T2 for ?Sized { +trait T2 { fn f() -> Box; } struct S; @@ -48,7 +48,7 @@ fn f6(x: &X) { let _: Box = T2::f(); } -trait T3 for ?Sized { +trait T3 { fn f() -> Box; } impl T3 for S { diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index c04afffb12037..7b2c35aa08d30 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -11,6 +11,8 @@ #![feature(lang_items)] #![no_std] +extern crate "std" as other; + #[macro_use] extern crate core; extern crate libc; @@ -22,10 +24,6 @@ use core::option::Option::Some; use core::slice::SliceExt; use collections::vec::Vec; -#[lang = "stack_exhausted"] extern fn stack_exhausted() {} -#[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } - // Issue #16806 #[start]