diff --git a/mk/docs.mk b/mk/docs.mk index 2a7ef5164f0e9..274598feada67 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/mk/main.mk b/mk/main.mk index 0d9419cccfa83..a97e68af59b38 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= @@ -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 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. CFG_PACKAGE_VERS=nightly endif ifeq ($(CFG_RELEASE_CHANNEL),dev) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 48610b6b526d2..0ce31a335d8ab 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/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 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/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 -
-Warning: There are currently various problems with invoking macros, how -they interact with their environment, and how they are used outside of the -location in which they are defined. Macro definitions are likely to change -slightly in the future. For this reason, they are hidden behind the -macro_rules feature -attribute. -
- # 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-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. 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/guide-testing.md b/src/doc/guide-testing.md index 4606a1ba846ff..4c3d93bdfbe5f 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 @@ -556,8 +558,12 @@ extern crate test; # struct X; # impl X { fn iter(&self, _: F) where F: FnMut() -> 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 +579,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. diff --git a/src/doc/guide.md b/src/doc/guide.md index e60740db353bc..66551ec499a89 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -355,7 +355,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. @@ -977,7 +977,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. diff --git a/src/doc/reference.md b/src/doc/reference.md index 5c00993d918d7..0f1f26d3e711c 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 @@ -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 `$`.) @@ -1259,8 +1261,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 @@ -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 @@ -3484,8 +3490,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; @@ -4316,73 +4323,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 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$}} 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 @@ + diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 5588152a244c4..dce6d3f66879e 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 @@ -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 @@ -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 diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index db26ca6ffa5d5..9194c7a47663d 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)] extern crate syntax; extern crate rustc; -#[phase(link)] extern crate regex; -#[phase(link, plugin)] +#[macro_use] extern crate log; use std::collections::HashMap; @@ -269,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 { @@ -285,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/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..6df8bb5f7aaf4 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,15 @@ impl fmt::Show for Box { } } -impl Deref for Box { +#[stable] +impl Deref for Box { type Target = T; fn deref(&self) -> &T { &**self } } -impl DerefMut for Box { +#[stable] +impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } } 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/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 4a550e5ce277d..01693391abed5 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -148,6 +148,7 @@ //! ``` #![allow(missing_docs)] +#![stable] use core::prelude::*; @@ -561,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() } @@ -593,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, } @@ -618,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/btree/map.rs b/src/libcollections/btree/map.rs index ea504530c4b21..b85ea65f5ce58 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 { @@ -878,7 +878,7 @@ impl Show for BTreeMap { } #[stable] -impl Index for BTreeMap +impl Index for BTreeMap where Q: BorrowFrom + Ord { type Output = V; @@ -889,7 +889,7 @@ impl Index for BTreeMap } #[stable] -impl IndexMut for BTreeMap +impl IndexMut for BTreeMap where Q: BorrowFrom + Ord { type Output = V; @@ -1111,7 +1111,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>> { @@ -1122,7 +1122,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. @@ -1362,7 +1362,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/dlist.rs b/src/libcollections/dlist.rs index ca8e75ac43c8d..5e08f90ce1c53 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; @@ -1064,6 +1066,7 @@ mod tests { } #[allow(deprecated)] + #[test] fn test_append() { { let mut m = DList::new(); diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index db2367950387b..5bf5f78af94c2 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; @@ -51,6 +70,11 @@ pub use string::String; pub use vec::Vec; pub use vec_map::VecMap; +// Needed for the vec! macro +pub use alloc::boxed; + +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; pub mod binary_heap; @@ -65,19 +89,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::*; } @@ -109,8 +137,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/macros.rs b/src/libcollections/macros.rs index ce4b1e467739e..0c5929e8661d6 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -8,9 +8,9 @@ // 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)] macro_rules! vec { ($($e:expr),*) => ({ // leading _ to allow empty construction without a warning. @@ -21,3 +21,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/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index ce9643b3b4391..11775f62b1c54 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -12,12 +12,14 @@ //! 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; 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 +32,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 +126,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 +155,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 +359,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 { + self.copy_nonoverlapping(new_tail, self.tail, 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 { - 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, len); } - self.tail = count - (oldcap - self.tail); + 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 +851,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 +923,7 @@ impl RingBuf { /// /// Panics if `i` is greater than ringbuf's length /// - /// # Example + /// # Examples /// ```rust /// use std::collections::RingBuf; /// @@ -945,7 +1125,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 +1170,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 +1285,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 { @@ -2270,6 +2481,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 @@ -2341,6 +2596,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(); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 3602bfc10c307..9e5aa7d645ba0 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"] -pub trait SliceExt for Sized? { +#[stable] +pub trait SliceExt { + #[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; @@ -989,7 +991,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; @@ -1090,6 +1092,7 @@ struct SizeDirection { dir: Direction, } +#[stable] impl Iterator for ElementSwaps { type Item = (uint, uint); @@ -2460,13 +2463,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 +2489,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..c0482702ccdb6 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::*; @@ -59,7 +60,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; @@ -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; @@ -401,7 +407,8 @@ Section: Trait implementations */ /// Any string that can be represented as a slice. -pub trait StrExt for Sized?: ops::Slice { +#[stable] +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 { @@ -1340,6 +1347,7 @@ pub trait StrExt for Sized?: ops::Slice { } } +#[stable] impl StrExt for str {} #[cfg(test)] @@ -1838,7 +1846,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 +1868,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..0bf311e4d3f6e 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 @@ -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. @@ -711,7 +687,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 +696,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 +808,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 +840,7 @@ impl ops::Slice for String { } } -#[experimental = "waiting on Deref stabilization"] +#[stable] impl ops::Deref for String { type Target = str; @@ -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/libcollections/vec.rs b/src/libcollections/vec.rs index 4e3fd44072784..99231e7253c3c 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1251,19 +1251,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 { @@ -1393,6 +1393,7 @@ impl AsSlice for Vec { } } +#[unstable = "recent addition, needs more experience"] impl<'a, T: Clone> Add<&'a [T]> for Vec { type Output = Vec; @@ -1404,6 +1405,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 @@ -1449,6 +1451,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)) @@ -1494,6 +1497,7 @@ impl IntoIter { } } +#[stable] impl Iterator for IntoIter { type Item = T; @@ -1530,6 +1534,7 @@ impl Iterator for IntoIter { } } +#[stable] impl DoubleEndedIterator for IntoIter { #[inline] fn next_back<'a>(&'a mut self) -> Option { @@ -1553,9 +1558,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 @@ -1577,6 +1584,7 @@ pub struct Drain<'a, T> { marker: ContravariantLifetime<'a>, } +#[stable] impl<'a, T> Iterator for Drain<'a, T> { type Item = T; @@ -1613,6 +1621,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 { @@ -1636,9 +1645,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, @@ -1671,7 +1682,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/atomic.rs b/src/libcore/atomic.rs index 0ac0dc396cc1a..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, } @@ -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"] +#[unstable = "awaiting int/uint conventions, may be renamed"] 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"] +#[unstable = "awaiting int/uint conventions, may be renamed"] 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; @@ -413,6 +403,7 @@ impl AtomicBool { } } +#[unstable = "awaiting int/uint conventions, types may change"] impl AtomicInt { /// Creates a new `AtomicInt`. /// @@ -424,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)} } @@ -447,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) } } @@ -470,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); } } @@ -489,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) } } @@ -511,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) } } @@ -528,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) } } @@ -545,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) } } @@ -561,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) } } @@ -577,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) } } @@ -593,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`. /// @@ -610,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) } } @@ -633,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) } } @@ -656,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); } } @@ -675,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) } } @@ -697,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) } } @@ -714,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) } } @@ -731,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) } } @@ -747,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) } } @@ -763,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) } } @@ -779,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) } } diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7e4d73d598d8d..2c08b97635580 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -53,57 +53,61 @@ use option::Option; use self::Cow::*; /// A trait for borrowing data. -pub trait BorrowFrom for Sized? { +#[old_orphan_check] +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 { +#[old_orphan_check] +pub trait BorrowFromMut : 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> { +#[old_orphan_check] +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 } } /// A generalization of Clone to borrowed data. -pub trait ToOwned for Sized?: BorrowFrom { +#[old_orphan_check] +pub trait ToOwned: BorrowFrom { /// Create owned data from borrowed data, usually by copying. fn to_owned(&self) -> Owned; } @@ -129,7 +133,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 +142,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 +154,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 +195,8 @@ 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 { +#[stable] +impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned { type Target = B; fn deref(&self) -> &B { @@ -203,10 +208,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 +219,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 +230,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/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/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..af5e98ed30324 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -69,7 +69,8 @@ use option::Option::{self, Some, None}; /// only if `a != b`. #[lang="eq"] #[stable] -pub trait PartialEq for Sized? { +#[old_orphan_check] +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 +91,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 +165,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 +225,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] @@ -428,14 +429,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 +451,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 +483,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 +499,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..951f5c29f00e8 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; @@ -78,9 +81,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 { @@ -222,7 +225,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 +233,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; } @@ -592,10 +595,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..d8b9cf9594d6a 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); } @@ -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/iter.rs b/src/libcore/iter.rs index 29077deb21de1..e5753f6cc2e78 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), @@ -2416,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; @@ -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}; diff --git a/src/libcore/kinds.rs b/src/libcore/kinds.rs index e50aaef5f09f3..5d69938fccff7 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 } @@ -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/lib.rs b/src/libcore/lib.rs index d646245510d50..aff0065c52744 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -62,11 +62,24 @@ #![feature(default_type_params, unboxed_closures, associated_types)] #![deny(missing_docs)] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] 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"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod float_macros; + +#[path = "num/int_macros.rs"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod int_macros; + +#[path = "num/uint_macros.rs"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod uint_macros; #[path = "num/int.rs"] pub mod int; #[path = "num/i8.rs"] pub mod i8; @@ -130,6 +143,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..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 { @@ -30,7 +28,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 +55,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/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/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/libcore/ops.rs b/src/libcore/ops.rs index 17e4c5f8215a8..97d94e73bb33a 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; } @@ -747,8 +802,8 @@ shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 } /// } /// ``` #[lang="index"] -pub trait Index for Sized? { - type Sized? Output; +pub trait Index { + type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation fn index<'a>(&'a self, index: &Index) -> &'a Self::Output; @@ -784,8 +839,8 @@ pub trait Index for Sized? { /// } /// ``` #[lang="index_mut"] -pub trait IndexMut for Sized? { - type Sized? Output; +pub trait IndexMut { + type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output; @@ -829,7 +884,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..] @@ -878,7 +933,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..] @@ -893,11 +948,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, @@ -907,6 +964,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; @@ -931,6 +989,7 @@ impl Iterator for Range { } } +#[unstable = "API still in development"] impl DoubleEndedIterator for Range { #[inline] fn next_back(&mut self) -> Option { @@ -943,16 +1002,19 @@ impl DoubleEndedIterator for Range { } } +#[unstable = "API still in development"] 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, } +#[unstable = "API still in development"] impl Iterator for RangeFrom { type Item = Idx; @@ -968,6 +1030,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, @@ -1005,20 +1068,25 @@ pub struct RangeTo { /// } /// ``` #[lang="deref"] -pub trait Deref for Sized? { - type Sized? Target; +#[stable] +pub trait Deref { + #[stable] + type Target: ?Sized; /// The method called to dereference a value + #[stable] fn deref<'a>(&'a self) -> &'a Self::Target; } -impl<'a, Sized? T> Deref for &'a T { +#[stable] +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 { +#[stable] +impl<'a, T: ?Sized> Deref for &'a mut T { type Target = T; fn deref(&self) -> &T { *self } @@ -1062,38 +1130,44 @@ impl<'a, Sized? T> Deref for &'a mut T { /// } /// ``` #[lang="deref_mut"] -pub trait DerefMut for Sized? : Deref { +#[stable] +pub trait DerefMut: Deref { /// The method called to mutably dereference a value + #[stable] fn deref_mut<'a>(&'a mut self) -> &'a mut ::Target; } -impl<'a, Sized? T> DerefMut for &'a mut T { +#[stable] +impl<'a, T: ?Sized> 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"] -pub trait Fn for Sized? { +#[unstable = "uncertain about variadic generics, input versus associated types"] +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? { +#[unstable = "uncertain about variadic generics, input versus associated types"] +pub trait FnMut { /// This is called when the call operator is used. extern "rust-call" fn call_mut(&mut self, args: Args) -> Result; } /// 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; } -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/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/raw.rs b/src/libcore/raw.rs index 3bef1d1536377..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)] @@ -52,7 +51,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/result.rs b/src/libcore/result.rs index 7135faaa76516..8e9bf5487e3ed 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() { } //! ``` //! @@ -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 7aed16173e988..093ed0b242f5f 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]; @@ -614,7 +614,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]; } @@ -626,13 +626,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) } } @@ -650,7 +650,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; @@ -688,7 +688,7 @@ macro_rules! iterator { } } - #[experimental = "needs review"] + #[stable] impl<'a, T> DoubleEndedIterator for $name<'a, T> { #[inline] fn next_back(&mut self) -> Option<$elem> { @@ -771,7 +771,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] @@ -779,7 +779,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 { @@ -865,7 +865,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 @@ -897,7 +897,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]; @@ -925,7 +925,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]> { @@ -970,7 +970,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]; @@ -1005,7 +1005,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, { @@ -1038,7 +1038,6 @@ struct GenericSplitN { invert: bool } -#[experimental = "needs review"] impl> Iterator for GenericSplitN { type Item = T; @@ -1061,6 +1060,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> } @@ -1068,12 +1068,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> } @@ -1081,12 +1083,14 @@ 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> } 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 { @@ -1112,12 +1116,13 @@ 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 } +#[stable] impl<'a, T> Iterator for Windows<'a, T> { type Item = &'a [T]; @@ -1149,13 +1154,13 @@ 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 } -#[experimental = "needs review"] +#[stable] impl<'a, T> Iterator for Chunks<'a, T> { type Item = &'a [T]; @@ -1184,7 +1189,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]> { @@ -1200,7 +1205,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 { @@ -1224,13 +1229,13 @@ 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 } -#[experimental = "needs review"] +#[stable] impl<'a, T> Iterator for ChunksMut<'a, T> { type Item = &'a mut [T]; @@ -1260,7 +1265,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]> { @@ -1338,7 +1343,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 }) } @@ -1350,12 +1355,11 @@ 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; /// 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); } @@ -1439,7 +1443,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..a39787b8207b5 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; @@ -142,6 +144,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 +168,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) }) @@ -190,7 +194,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; @@ -230,7 +234,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] @@ -247,6 +251,7 @@ Section: Iterators /// /// Created with the method `.chars()`. #[derive(Clone, Copy)] +#[stable] pub struct Chars<'a> { iter: slice::Iter<'a, u8> } @@ -275,6 +280,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 { } } +#[stable] impl<'a> Iterator for Chars<'a> { type Item = char; @@ -320,6 +326,7 @@ impl<'a> Iterator for Chars<'a> { } } +#[stable] impl<'a> DoubleEndedIterator for Chars<'a> { #[inline] fn next_back(&mut self) -> Option { @@ -356,11 +363,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 +393,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 +475,7 @@ impl<'a, Sep> CharSplits<'a, Sep> { } } +#[stable] impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> { type Item = &'a str; @@ -499,6 +510,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 +552,7 @@ impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> { } } +#[stable] impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> { type Item = &'a str; @@ -848,6 +861,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,13 +872,14 @@ 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, finished: bool } +#[stable] impl<'a> Iterator for MatchIndices<'a> { type Item = (uint, uint); @@ -881,6 +896,7 @@ impl<'a> Iterator for MatchIndices<'a> { } } +#[stable] impl<'a> Iterator for SplitStr<'a> { type Item = &'a str; @@ -948,17 +964,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, @@ -1056,8 +1073,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; @@ -1130,7 +1146,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; } @@ -1140,7 +1156,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) } } @@ -1171,7 +1187,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. @@ -1586,6 +1602,7 @@ impl<'a> Default for &'a str { fn default() -> &'a str { "" } } +#[stable] impl<'a> Iterator for Lines<'a> { type Item = &'a str; @@ -1593,11 +1610,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 +1624,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/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/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/libcoretest/lib.rs b/src/libcoretest/lib.rs index b6fc6457fce4d..50ae59e70dc93 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/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 8885d3a52082c..b98432e26b215 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -8,9 +8,7 @@ // 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) => ( +macro_rules! int_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; @@ -205,4 +203,4 @@ mod tests { } } -)); +)} diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 651e8640e912a..f86c85f821638 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -14,13 +14,20 @@ use core::num::{NumCast, cast}; use core::ops::{Add, Sub, Mul, Div, Rem}; use core::kinds::Copy; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod int_macros; + mod i8; mod i16; mod i32; mod i64; mod int; + +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] 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..04d8fb15cf5aa 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -8,9 +8,7 @@ // 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) => ( +macro_rules! uint_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; @@ -125,4 +123,5 @@ mod tests { assert!(5u.checked_div(0) == None); } } -)); + +)} diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index aa1550ae5b874..6ac311fe4b646 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(unboxed_closures, associated_types)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(test)] #[macro_use] 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/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/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/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/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/liblog/lib.rs b/src/liblog/lib.rs index 0508402ff19d8..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"); @@ -183,7 +182,10 @@ use regex::Regex; use directive::LOG_LEVEL_NAMES; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] 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..5249e971439cd 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 @@ -21,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"); @@ -70,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; @@ -96,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; @@ -121,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; @@ -148,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); @@ -172,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/chacha.rs b/src/librand/chacha.rs index 71ce882e98ca9..815fc0e7ec7ad 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)] +#[derive(Copy, Clone)] pub struct ChaChaRng { buffer: [u32; STATE_WORDS], // Internal buffer of output state: [u32; STATE_WORDS], // Initial state @@ -283,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/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..84328360ce324 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); @@ -179,6 +180,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 { @@ -294,15 +302,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 +321,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 +342,7 @@ impl Isaac64Rng { self.mem[i+6]=g; self.mem[i+7]=h; } }} - ); + } memloop!(self.rsl); memloop!(self.mem); @@ -359,49 +367,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); @@ -415,6 +425,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 +502,7 @@ impl Rand for Isaac64Rng { } } + #[cfg(test)] mod test { use std::prelude::v1::*; @@ -594,4 +612,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()); + } + } } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 0f8dbc78cde32..c4dd08f9917e2 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::*; @@ -243,7 +261,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. @@ -385,6 +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)] +#[derive(Clone)] pub struct XorShiftRng { x: u32, y: u32, @@ -392,17 +411,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 +515,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/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/lint/builtin.rs b/src/librustc/lint/builtin.rs index 6666a21c31fee..425e34cd9f042 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -546,20 +546,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); } @@ -568,21 +568,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) { @@ -607,7 +607,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); } _ => {} @@ -666,6 +666,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/lint/context.rs b/src/librustc/lint/context.rs index 69e5b4889c288..5c0fd8944368f 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, @@ -208,7 +214,7 @@ impl LintStore { add_builtin_with_new!(sess, TypeLimits, - RawPointerDeriving, + RawPointerDerive, MissingDoc, ); @@ -247,6 +253,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/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/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 b0cf322b0688e..171bfd74a816b 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; @@ -29,43 +28,27 @@ 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; 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(), - }; - visit_crate(&e, krate); - visit::walk_crate(&mut e, krate); - 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) { - 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,42 +88,8 @@ 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" || - attr.meta_item_list().map_or(false, |phases| { - attr::contains_name(phases[], "link") - }) - }) -} - -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 => () - } + !attr::contains_name(i.attrs[], "no_link") } struct CrateInfo { @@ -150,32 +99,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 +121,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,172 +148,341 @@ 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 } +pub struct PluginMetadata<'a> { + sess: &'a Session, + metadata: PMDSource, + dylib: Option, + info: CrateInfo, + vi_span: Span, + target_only: bool, +} - match hash { - Some(hash) if *hash == data.hash() => { ret = Some(cnum); return } - Some(..) => return, - None => {} - } +enum PMDSource { + Registered(Rc), + Owned(MetadataBlob), +} - // 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); - } - } - None => ret = Some(cnum), +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(), } - }); - 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 }; +impl<'a> CrateReader<'a> { + pub fn new(sess: &'a Session) -> CrateReader<'a> { + CrateReader { + sess: sess, + next_crate_num: sess.cstore.next_crate_num(), + } + } - let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span); + // 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); - let loader::Library{ dylib, rlib, metadata } = lib; + if log_enabled!(log::DEBUG) { + dump_crates(&self.sess.cstore); + } + warn_if_multiple_versions(self.sess.diagnostic(), &self.sess.cstore); - let cmeta = Rc::new( cstore::crate_metadata { - name: name.to_string(), - data: metadata, - cnum_map: cnum_map, - cnum: cnum, - span: span, - }); + for &(ref name, kind) in self.sess.opts.libs.iter() { + register_native_lib(self.sess, None, name.clone(), kind); + } + } - let source = cstore::CrateSource { - dylib: dylib, - rlib: rlib, - cnum: cnum, - }; + 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()), + None => { /* fallthrough */ } + } + } + } - e.sess.cstore.set_crate_data(cnum, cmeta.clone()); - e.sess.cstore.add_used_crate_source(source.clone()); - (cnum, cmeta, source) -} + fn process_view_item(&mut self, i: &ast::ViewItem) { + if !should_link(i) { + return; + } -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) + 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 => () } - 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, + 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 */ } + } + } + + // 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 => {} + } + } + } + _ => { } + } + } + + 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; + } + + fn register_crate(&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, _, _) = resolve_crate(e, root, - dep.name[], - dep.name[], - Some(&dep.hash), - span, - PathKind::Dependency); - (dep.cnum, local_cnum) - }).collect() -} + 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 }; -pub struct PluginMetadataReader<'a> { - env: Env<'a>, -} + let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span); + + let loader::Library{ dylib, rlib, metadata } = lib; + + let cmeta = Rc::new( cstore::crate_metadata { + name: name.to_string(), + data: metadata, + cnum_map: cnum_map, + cnum: cnum, + span: span, + }); + + 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) + } -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(), + 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()) } } - pub fn read_plugin_metadata(&mut self, - krate: &ast::ViewItem) -> PluginMetadata { - let info = extract_crate_info(&self.env, krate).unwrap(); - let target_triple = self.env.sess.opts.target_triple[]; + // 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 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.env.sess, - span: krate.span, - ident: info.ident[], - crate_name: info.name[], + sess: self.sess, + span: vi.span, + ident: ident[], + crate_name: 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!(), @@ -479,49 +492,106 @@ impl<'a> PluginMetadataReader<'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) - load_ctxt.triple = target_triple; - load_ctxt.filesearch = self.env.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[]); - // 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(); - } + // 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; - lib + + load_ctxt.triple = target_triple; + load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); + load_ctxt.load_library_crate() } None => { load_ctxt.report_load_errs(); unreachable!() }, }; - let macros = decoder::get_exported_macros(library.metadata.as_slice()); - 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.env.sess.span_err(krate.span, message[]); - // No need to abort because the loading code will just ignore this - // empty dylib. - } - let pc = PluginMetadata { - lib: library.dylib.clone(), - macros: macros, - registrar_symbol: registrar, + + 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) }; - if should_link && existing_match(&self.env, 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); + + 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(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. + 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, + // overridden in plugin/load.rs + export: false, + use_locally: false, + + body: body, + }); + true + } + ); + macros + } + + /// 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 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/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/decoder.rs b/src/librustc/metadata/decoder.rs index ac8dfc1675942..ed0a1f6211b16 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 14ab471a4b831..e4226ddde85b6 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; @@ -1817,25 +1818,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(); } @@ -2153,7 +2150,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/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 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/const_eval.rs b/src/librustc/middle/const_eval.rs index a95523f2e0600..32482fce4daa8 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/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..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; +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}; @@ -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), +} + +#[derive(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/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/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dd61db4270ce3..2b8c9b532e593 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1235,8 +1235,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/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 55abe895183f1..42b6e54420b40 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)); @@ -153,8 +143,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) @@ -164,14 +154,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/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/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, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7cda6c21853a3..c359233eca173 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1776,6 +1776,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 { @@ -6167,8 +6171,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/plugin/load.rs b/src/librustc/plugin/load.rs index a2e334543206c..44a223954858a 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -8,47 +8,46 @@ // 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::PluginMetadataReader; +use metadata::creader::CrateReader; 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::codemap::Span; +use syntax::parse::token; +use syntax::ptr::P; use syntax::visit; use syntax::visit::Visitor; -use syntax::ext::expand::ExportedMacros; use syntax::attr::AttrMetaMethods; -/// Plugin-related crate metadata. -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, -} - /// Pointer to a registrar function. pub type PluginRegistrarFun = fn(&mut Registry); +pub struct PluginRegistrar { + pub fun: PluginRegistrarFun, + pub args: P, +} + /// 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, + pub registrars: Vec, } struct PluginLoader<'a> { sess: &'a Session, - reader: PluginMetadataReader<'a>, + span_whitelist: HashSet, + reader: CrateReader<'a>, plugins: Plugins, } @@ -56,7 +55,8 @@ impl<'a> PluginLoader<'a> { fn new(sess: &'a Session) -> PluginLoader<'a> { PluginLoader { sess: sess, - reader: PluginMetadataReader::new(sess), + reader: CrateReader::new(sess), + span_whitelist: HashSet::new(), plugins: Plugins { macros: vec!(), registrars: vec!(), @@ -69,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; @@ -89,41 +97,112 @@ 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(name, _, _) => { - let mut plugin_phase = false; + ast::ViewItemExternCrate(..) => (), + _ => return, + } - 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 plugin_attr = None; + 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; + match attr.name().get() { + "phase" => { + self.sess.span_err(attr.span, "#[phase] is deprecated; use \ + #[macro_use], #[plugin], and/or #[no_link]"); + } + "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() { + // 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"); + } + } } - if attr::contains_name(phases, "syntax") { - plugin_phase = true; - self.sess.span_warn(attr.span, - "phase(syntax) is a deprecated synonym for phase(plugin)"); + } + "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 { + attr::mark_used(attr); + } + } - if !plugin_phase { return; } + let mut macros = vec![]; + let mut registrar = None; - let PluginMetadata { macros, lib, registrar_symbol } = - self.reader.read_plugin_metadata(vi); + let load_macros = match macro_selection.as_ref() { + Some(sel) => sel.len() != 0 || reexport.len() != 0, + None => true, + }; + let load_registrar = plugin_attr.is_some(); - self.plugins.macros.push(ExportedMacros { - crate_name: name, - macros: macros, - }); + 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"); + } - match (lib, registrar_symbol) { - (Some(lib), Some(symbol)) - => self.dylink_registrar(vi, lib, symbol), - _ => (), - } + if load_macros || load_registrar { + let pmd = self.reader.read_plugin_metadata(vi); + if load_macros { + macros = pmd.exported_macros(); + } + if load_registrar { + registrar = pmd.plugin_registrar(); } - _ => (), + } + + for mut def in macros.into_iter() { + 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); + } + + if let Some((lib, symbol)) = registrar { + let fun = self.dylink_registrar(vi, lib, symbol); + self.plugins.registrars.push(PluginRegistrar { + fun: fun, + args: plugin_attr.unwrap(), + }); } } + fn visit_mac(&mut self, _: &ast::Mac) { // bummer... can't see plugins inside macros. // do nothing. @@ -132,7 +211,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(); @@ -154,13 +236,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/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/plugin/registry.rs b/src/librustc/plugin/registry.rs index 99e870a901e08..feec97f02da55 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -11,12 +11,14 @@ //! 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; +use syntax::ptr::P; use syntax::ast; use std::collections::HashMap; @@ -29,7 +31,14 @@ 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 args_hidden: Option>, + #[doc(hidden)] pub krate_span: Span, @@ -43,10 +52,12 @@ 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, + args_hidden: None, krate_span: krate.span, syntax_exts: vec!(), lint_passes: vec!(), @@ -54,6 +65,14 @@ impl Registry { } } + /// 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. @@ -63,8 +82,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/session/config.rs b/src/librustc/session/config.rs index f9f899401b175..138f648049c73 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, @@ -299,7 +300,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), @@ -823,6 +823,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"), @@ -1143,6 +1144,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 770e8d73ec761..abb780615ae7b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -201,8 +201,8 @@ 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) } pub fn print_enum_sizes(&self) -> bool { self.debugging_opt(config::PRINT_ENUM_SIZES) 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 e6ee16d1789c0..8c2a9993004d9 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; } @@ -601,7 +601,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/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_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/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_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_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index e1f0c9ec26677..20949151557cb 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; 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/driver.rs b/src/librustc_driver/driver.rs index 9540c3fa3d7e8..74f81ae9d6d1e 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; @@ -146,8 +146,8 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) println!("{}", json::as_json(&krate)); } - if sess.show_span() { - 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 @@ -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. @@ -216,9 +216,9 @@ 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", (), |_| { + 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); } }); @@ -272,7 +273,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(), }; @@ -352,7 +352,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)); @@ -572,7 +572,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 983188c709000..89b2e0f257acd 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; @@ -134,7 +148,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 @@ -145,7 +159,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) @@ -162,6 +176,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 { 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/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index 53992d4567a34..d3555e4c04363 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -13,7 +13,7 @@ use libc; use ArchiveRef; -use std::c_str::ToCStr; +use std::ffi::CString; use std::mem; use std::raw; @@ -30,9 +30,8 @@ impl ArchiveRO { /// raised. pub fn open(dst: &Path) -> 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..8a9334be985f7 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; @@ -47,7 +48,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 +2115,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_resolve/lib.rs b/src/librustc_resolve/lib.rs index a2c86c3cdb756..58102fe5629d9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -19,9 +19,23 @@ #![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; +#[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/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..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::c_str::{ToCStr, 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::{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 { @@ -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/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_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/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 56c1e2ddba0b5..edcfaae0f802d 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::{self, 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 { @@ -331,9 +331,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 @@ -472,15 +471,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 @@ -534,11 +535,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()) } } } @@ -2639,11 +2637,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); @@ -2664,9 +2661,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, @@ -2773,9 +2770,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") { @@ -2817,9 +2814,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 => () @@ -2986,17 +2982,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; } @@ -3004,8 +2999,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(); @@ -3035,7 +3028,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); } } @@ -3051,9 +3045,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/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/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 7e47c8f3b959a..a3861e71d83de 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..3726cf14023ee 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) } @@ -741,7 +736,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 +754,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 +878,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 +891,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/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 84ae088f5beae..3f0f7fd9bd303 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}; @@ -755,14 +755,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); }; } @@ -824,22 +825,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. @@ -1383,28 +1382,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(), @@ -1509,19 +1506,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); } @@ -1544,19 +1540,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); } } @@ -1601,19 +1596,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) } } @@ -1625,29 +1620,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()) } } @@ -1673,42 +1664,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, @@ -1753,14 +1743,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); @@ -1788,16 +1776,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>, @@ -1833,16 +1819,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; } @@ -1854,16 +1839,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; } @@ -2473,14 +2457,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(); @@ -2504,20 +2488,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() @@ -2548,24 +2531,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, @@ -2676,21 +2657,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(); @@ -2714,30 +2694,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; @@ -3464,7 +3442,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); } @@ -4011,18 +3989,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, @@ -4060,7 +4038,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 { @@ -4092,8 +4071,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 491c6a83ca9bf..2fd9031fdfe4c 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; @@ -486,11 +486,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/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/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/meth.rs b/src/librustc_trans/trans/meth.rs index e219b45d3d9f4..f6d69959dadf9 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; @@ -762,9 +762,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/mod.rs b/src/librustc_trans/trans/mod.rs index 72c4def15a215..fa9cd5a698bbe 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -16,8 +16,11 @@ pub use self::base::trans_crate; pub use self::context::CrateContext; pub use self::common::gensym_name; -mod doc; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; + +mod doc; mod inline; mod monomorphize; mod controlflow; 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/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bde834c2ff899..183b8c5c830ef 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -361,14 +361,6 @@ fn create_substs_for_ast_path<'tcx>( 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/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 56cf4acc184e5..80e7e70605956 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; @@ -46,6 +48,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 +69,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, @@ -71,17 +92,29 @@ 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); + + // 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) => { 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); @@ -89,20 +122,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); @@ -124,8 +166,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); @@ -138,7 +181,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 { @@ -146,19 +192,26 @@ 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 b2085d9 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(|mt| mt.mutbl).unwrap_or(ast::MutImmutable) + } else { + mutbl + }; let mt = ty::mt { ty: inner_ty, mutbl: mutbl }; let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span)); 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 { @@ -181,14 +234,18 @@ 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) }) } }; 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 +267,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/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 5b586bb0b669a..a51e89c1669de 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 2940d55616968..1b51434a58cc1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4554,7 +4554,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) } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 5a8263263808e..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; +use middle::infer::{self, 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())); } } } @@ -1427,31 +1427,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 @@ -1467,22 +1467,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 7a9961e750c21..7ca21bdf5b83f 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> { @@ -121,8 +122,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); @@ -211,12 +211,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, @@ -373,16 +382,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/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index d90bfe04ea1e7..77d71e740d681 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/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 3146a1181396b..dc434f1401585 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/clean/mod.rs b/src/librustdoc/clean/mod.rs index e01dbac68ee8d..bb9a9ac430340 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2220,7 +2220,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/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/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/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/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3accbbfb1a2e7..ddb14d6944b9d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2253,9 +2253,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 9d4f341a30e25..a5a4825414109 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 { @@ -470,6 +479,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); + } + }; + }()); + }()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 106fe452f46a6..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 @@ -49,11 +56,13 @@ use rustc::session::search_paths::SearchPaths; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +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/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/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 bd4cb1884a69a..8b0fb75b438fe 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -2302,7 +2302,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/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/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/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0646ee1758fc0..a04f67f765108 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>; } @@ -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..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>; } @@ -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/ascii.rs b/src/libstd/ascii.rs index bcd87f6786d35..671408acebf0d 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; @@ -38,7 +37,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; @@ -53,7 +52,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; } 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/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/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index c35be86420de8..a3fc38c34e84f 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 { @@ -1227,7 +1227,7 @@ impl, V, S, H: Hasher + Default> Default for HashMap } #[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 { type Output = V; @@ -1239,7 +1239,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 { type Output = V; @@ -1331,7 +1331,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>, @@ -1339,7 +1339,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 @@ -1409,7 +1409,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>> { @@ -1455,7 +1455,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 @@ -1482,7 +1482,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..211bfe2c10e8f 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -18,10 +18,12 @@ 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}; + +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::{Ok, Err}; use super::map::{self, HashMap, Keys, INITIAL_CAPACITY}; @@ -451,7 +453,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 +563,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() @@ -605,7 +607,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); 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/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::*; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index de3d75ffb3242..2d013a8a5b830 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() } }); @@ -130,10 +128,9 @@ 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(|| { - symbol.with_c_str(|raw_string| { - dl::symbol(self.handle, raw_string) - }) + 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/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/buffered.rs b/src/libstd/io/buffered.rs index c56acd38e810f..d590aa8419453 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -14,15 +14,18 @@ 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}; -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/io/mod.rs b/src/libstd/io/mod.rs index 3fa0b5645c528..5bef473db990c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -282,10 +282,13 @@ pub mod net; pub mod pipe; pub mod process; pub mod stdio; -pub mod test; pub mod timer; pub mod util; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +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 @@ -1012,12 +1015,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 +1600,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/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/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/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 608ad9882b977..b9f226c5aca73 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -95,7 +95,7 @@ //! and `format!`, also available to all Rust code. #![crate_name = "std"] -#![unstable] +#![stable] #![crate_type = "rlib"] #![crate_type = "dylib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -117,13 +117,36 @@ #![reexport_test_harness_main = "test_main"] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; -extern crate alloc; -extern crate unicode; +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +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)] +#[phase(plugin, link)] +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; +extern crate alloc; +extern crate unicode; extern crate libc; // Make std testable by not duplicating lang items. See #2912 @@ -167,7 +190,18 @@ pub use unicode::char; /* Exported macros */ +#[cfg(stage0)] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +pub mod macros_stage0; + +#[cfg(not(stage0))] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod macros; + +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod bitflags; mod rtdeps; @@ -179,9 +213,20 @@ 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"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod float_macros; + +#[path = "num/int_macros.rs"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod int_macros; + +#[path = "num/uint_macros.rs"] +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +mod uint_macros; #[path = "num/int.rs"] pub mod int; #[path = "num/i8.rs"] pub mod i8; @@ -208,10 +253,12 @@ pub mod num; /* Runtime and platform support */ +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod thread_local; -pub mod c_str; -pub mod c_vec; + pub mod dynamic_lib; +pub mod ffi; pub mod fmt; pub mod io; pub mod os; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 63fd3209cc019..d96441e09a813 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. /// @@ -246,34 +245,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 +277,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 +321,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..48d62e73e13ed --- /dev/null +++ b/src/libstd/macros_stage0.rs @@ -0,0 +1,648 @@ +// 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] + +/// 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/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/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..b020164158cff 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; @@ -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 @@ -892,11 +892,11 @@ 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() } } -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() @@ -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..d9981ace0301e 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) { @@ -344,7 +321,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; @@ -558,7 +535,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 +550,7 @@ mod tests { assert!(mo.as_slice() == $exp); } ) - ); + } t!("foo", "foo"); t!(b"foo\x80", "foo\u{FFFD}"); @@ -585,7 +562,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 +572,7 @@ mod tests { assert!(f == $expf); } ) - ); + } t!(b"foo", "foo", "foo"); t!(b"foo/bar", "foo/bar", "bar"); @@ -608,7 +585,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 +606,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 +669,7 @@ mod tests { #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -703,7 +680,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a/b/c", ".."); t!(s: "/a/b/c", "d"); @@ -713,7 +690,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 +699,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 +711,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 +726,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 +739,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 +756,7 @@ mod tests { assert!(result == $right); } ) - ); + } t!(b: b"a/b/c", b"a/b", true); t!(b: b"a", b".", true); @@ -818,7 +795,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 +804,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 +816,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 +831,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 +894,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 +915,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 +938,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 +969,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 +1008,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 +1016,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 +1029,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 +1037,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 +1063,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 +1078,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 +1102,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 +1111,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 +1147,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 +1173,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 +1193,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 +1205,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..4b5d793355b60 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] @@ -1149,7 +1127,7 @@ mod tests { #[test] fn test_parse_prefix() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = $path; @@ -1159,7 +1137,7 @@ mod tests { "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res); } ) - ); + } t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5))); t!("\\\\", None); @@ -1348,7 +1326,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 +1336,7 @@ mod tests { assert_eq!(f, $expf); } ) - ); + } t!("foo", "foo", "foo"); t!("foo\\bar", "foo\\bar", "bar"); @@ -1367,7 +1345,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 +1368,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 +1468,7 @@ mod tests { #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -1501,7 +1479,7 @@ mod tests { assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a\\b\\c", ".."); t!(s: "\\a\\b\\c", "d"); @@ -1525,7 +1503,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 +1512,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 +1555,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 +1570,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 +1584,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 +1605,7 @@ mod tests { assert!(result == $right); } ) - ); + } t!(s: "a\\b\\c", "a\\b", true); t!(s: "a", ".", true); @@ -1695,7 +1673,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 +1682,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 +1696,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 +1711,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 +1724,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 +1737,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 +1809,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 +1830,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 +1854,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 +1885,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 +1920,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 +1939,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 +1960,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 +1972,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 +2063,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 +2071,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 +2095,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 +2108,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 +2229,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 +2243,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 +2287,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 +2299,7 @@ mod tests { assert_eq!(comps, exp); } ) - ); + } t!(s: "a\\b\\c", [b"a", b"b", b"c"]); t!(s: ".", [b"."]); @@ -2330,7 +2308,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 +2317,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/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; 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/rand/mod.rs b/src/libstd/rand/mod.rs index aa28c8266d193..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. -#[derive(Copy)] +#[derive(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. +#[derive(Clone)] pub struct ThreadRng { rng: Rc>, } 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/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/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/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/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/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/mod.rs b/src/libstd/sync/mod.rs index 6ce278726e9de..6fff6765bd348 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -15,15 +15,15 @@ //! 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; 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::{RWLockReadGuard, RWLockWriteGuard}; +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}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6bc3f561bb3c7..7c18b8a43faad 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) => { @@ -587,7 +590,7 @@ 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(())) } } @@ -657,6 +660,7 @@ impl Clone for Sender { } #[unsafe_destructor] +#[stable] impl Drop for Sender { fn drop(&mut self) { match *unsafe { self.inner_mut() } { @@ -720,6 +724,7 @@ impl Clone for SyncSender { } #[unsafe_destructor] +#[stable] impl Drop for SyncSender { fn drop(&mut self) { unsafe { (*self.inner.get()).drop_chan(); } @@ -935,7 +940,7 @@ impl select::Packet for Receiver { } } -#[unstable] +#[stable] impl<'a, T: Send> Iterator for Iter<'a, T> { type Item = T; @@ -943,6 +948,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/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)] 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. diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index b2367ff8352fb..4afd5bb63f4fe 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 /// { @@ -59,26 +59,26 @@ use sys_common::rwlock as sys; /// } // write lock is dropped here /// ``` #[stable] -pub struct RWLock { - inner: Box, +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. +/// 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 /// /// ``` -/// 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(); @@ -90,18 +90,18 @@ unsafe impl Sync for RWLock {} /// } /// unsafe { LOCK.destroy() } // free all resources /// ``` -#[unstable = "may be merged with RWLock in the future"] -pub struct StaticRWLock { +#[unstable = "may be merged with RwLock in the future"] +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"] -pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { +#[unstable = "may be merged with RwLock in the future"] +pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock { lock: sys::RWLOCK_INIT, poison: poison::FLAG_INIT, }; @@ -110,8 +110,8 @@ pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { /// dropped. #[must_use] #[stable] -pub struct RWLockReadGuard<'a, T: 'a> { - __lock: &'a StaticRWLock, +pub struct RwLockReadGuard<'a, T: 'a> { + __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __marker: marker::NoSend, } @@ -120,18 +120,18 @@ pub struct RWLockReadGuard<'a, T: 'a> { /// dropped. #[must_use] #[stable] -pub struct RWLockWriteGuard<'a, T: 'a> { - __lock: &'a StaticRWLock, +pub struct RwLockWriteGuard<'a, T: 'a> { + __lock: &'a StaticRwLock, __data: &'a UnsafeCell, __poison: poison::Guard, __marker: marker::NoSend, } -impl RWLock { - /// Creates a new instance of an RWLock which is unlocked and read to go. +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 RW_LOCK_INIT, data: UnsafeCell::new(t) } } /// Locks this rwlock with shared read access, blocking the current thread @@ -148,14 +148,14 @@ 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] #[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. @@ -169,15 +169,15 @@ 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. #[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) } @@ -194,14 +194,14 @@ 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] #[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. @@ -212,15 +212,15 @@ 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. #[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) } @@ -228,7 +228,8 @@ impl RWLock { } #[unsafe_destructor] -impl Drop for RWLock { +#[stable] +impl Drop for RwLock { fn drop(&mut self) { unsafe { self.inner.lock.destroy() } } @@ -238,27 +239,27 @@ 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. /// - /// See `RWLock::read`. + /// See `RwLock::read`. #[inline] - #[unstable = "may be merged with RWLock in the future"] - pub fn read(&'static self) -> LockResult> { + #[unstable = "may be merged with RwLock in the future"] + 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. /// - /// 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> { + -> 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) } @@ -267,23 +268,23 @@ 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"] - pub fn write(&'static self) -> LockResult> { + #[unstable = "may be merged with RwLock in the future"] + 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. /// - /// 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> { + -> 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) } @@ -295,17 +296,17 @@ 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() } } -impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { - fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) - -> LockResult> { +impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { + fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) + -> LockResult> { poison::map_result(lock.poison.borrow(), |_| { - RWLockReadGuard { + RwLockReadGuard { __lock: lock, __data: data, __marker: marker::NoSend, @@ -313,11 +314,11 @@ impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { }) } } -impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { - fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell) - -> LockResult> { +impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { + fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) + -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { - RWLockWriteGuard { + RwLockWriteGuard { __lock: lock, __data: data, __poison: guard, @@ -327,31 +328,36 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { } } -impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> { +#[stable] +impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } -impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> { +#[stable] +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> { +#[stable] +impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } } } #[unsafe_destructor] -impl<'a, T> Drop for RWLockReadGuard<'a, T> { +#[stable] +impl<'a, T> Drop for RwLockReadGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.lock.read_unlock(); } } } #[unsafe_destructor] -impl<'a, T> Drop for RWLockWriteGuard<'a, T> { +#[stable] +impl<'a, T> Drop for RwLockWriteGuard<'a, T> { fn drop(&mut self) { self.__lock.poison.done(&self.__poison); unsafe { self.__lock.lock.write_unlock(); } @@ -365,11 +371,11 @@ mod tests { use rand::{self, 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() { - let l = RWLock::new(()); + let l = RwLock::new(()); drop(l.read().unwrap()); drop(l.write().unwrap()); drop((l.read().unwrap(), l.read().unwrap())); @@ -378,7 +384,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 +394,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; @@ -414,7 +420,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 +431,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 +442,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 +453,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 +465,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 +503,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) { 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/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..7b667416b1714 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); @@ -467,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/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 { diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index d3b4fab96810b..e0cbaa8ca50ed 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -34,13 +34,14 @@ //! 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; +#[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/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/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/libstd/tuple.rs b/src/libstd/tuple.rs index f40b62182d42c..e76dcef226ddc 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. @@ -35,6 +29,17 @@ //! //! # 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: //! //! ``` diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e779821342a17..7aa7c4fcfb301 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; @@ -572,7 +572,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: @@ -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), @@ -1689,6 +1696,21 @@ 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 export: bool, + pub use_locally: bool, + pub body: Vec, +} + #[cfg(test)] mod test { use serialize::json; 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/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/ext/base.rs b/src/libsyntax/ext/base.rs index 91cc8a2462205..91ae7396ea469 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; @@ -28,19 +29,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 +128,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 @@ -328,13 +309,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 +340,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)); @@ -475,7 +450,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, @@ -594,6 +569,17 @@ impl<'a> ExtCtxt<'a> { } } } + + pub fn insert_macro(&mut self, def: ast::MacroDef) { + if def.export { + self.exported_macros.push(def.clone()); + } + 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. /// /// `span_err` should be strongly preferred where-ever possible: diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 84d30a99004a4..7cb7ee3d35533 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 f9c8d95b30848..c126238be8293 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/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 1fb8189c63c81..1aa430c4a0829 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -937,7 +937,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/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b9acde4bf6be9..844bd80d1610a 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/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/expand.rs b/src/libsyntax/ext/expand.rs index b3f30dd4581c9..212ec3b090325 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}; @@ -33,11 +32,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>) @@ -445,9 +439,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(); @@ -527,15 +521,34 @@ 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 // 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, + fld: &mut MacroExpander) -> SmallVector> { let (extname, path_span, tts) = match it.node { ItemMac(codemap::Spanned { node: MacInvocTT(ref pth, ref tts, _), @@ -548,8 +561,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 +613,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 +624,26 @@ 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 def = ast::MacroDef { + ident: it.ident, + attrs: it.attrs.clone(), + id: ast::DUMMY_NODE_ID, + 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); + + // 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 +654,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())[]); @@ -664,9 +677,6 @@ pub fn expand_item_mac(it: P, fld: &mut MacroExpander) } /// 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), @@ -976,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) } } @@ -1013,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) } } @@ -1161,7 +1171,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,38 +1179,23 @@ 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, } } } -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 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, &mut expander); - } + for def in imported_macros.into_iter() { + expander.cx.insert_macro(def); } for (name, extension) in user_exts.into_iter() { @@ -1290,8 +1284,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"); } @@ -1300,7 +1294,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}; @@ -1397,9 +1391,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( @@ -1409,16 +1403,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/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/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 08014dc13383f..9837c8088fa45 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}; @@ -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(); @@ -110,6 +110,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: Ident, + imported_from: Option, lhses: Vec>, rhses: Vec>, } @@ -123,25 +124,18 @@ impl TTMacroExpander for MacroRulesMacroExpander { generic_extension(cx, sp, self.name, + self.imported_from, arg, self.lhses[], self.rhses[]) } } -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, name: Ident, + imported_from: Option, arg: &[ast::TokenTree], lhses: &[Rc], rhses: &[Rc]) @@ -165,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()) @@ -186,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. @@ -212,14 +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, - arg: Vec ) - -> Box { +/// 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"); @@ -256,7 +247,8 @@ 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, - arg.clone()); + None, + def.body.clone()); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader, @@ -265,24 +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, + name: def.ident, + imported_from: def.imported_from, lhses: lhses, rhses: rhses, }; - box MacroRulesDefiner { - def: Some(MacroDef { - name: token::get_ident(name).to_string(), - ext: NormalTT(exp, Some(sp)) - }) - } as Box + NormalTT(exp, Some(def.span)) } 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/feature_gate.rs b/src/libsyntax/feature_gate.rs index cb6277069e1a2..0810d4ee93ac7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -36,15 +36,15 @@ 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), + ("globs", Accepted), + ("macro_rules", Accepted), ("struct_variant", Accepted), ("asm", Active), ("managed_boxes", Removed), ("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), @@ -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), @@ -67,13 +67,15 @@ 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), ("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), @@ -112,7 +114,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 +126,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, @@ -163,32 +163,11 @@ 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; + 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") { - 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"); } @@ -232,19 +211,13 @@ 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"{ - 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"); } } } @@ -294,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", @@ -314,16 +287,12 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { 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") - } - } + 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"); } } @@ -333,17 +302,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, @@ -379,20 +337,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", @@ -498,7 +442,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"), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 396b0033b815f..c45a4005339ba 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 { @@ -1104,7 +1104,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); @@ -1135,6 +1135,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, @@ -1257,7 +1261,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)) }, @@ -1472,8 +1476,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/lib.rs b/src/libsyntax/lib.rs index 18cdb3fc64789..b7bfd346d506b 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/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8598571e5c37a..b0969a573e66b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,8 +24,11 @@ use std::num::Int; use std::str; use std::iter; -pub mod lexer; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod parser; + +pub mod lexer; pub mod token; pub mod attr; @@ -166,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, @@ -291,7 +296,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) } @@ -307,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, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 75b2c17b81bd4..a49680d7e1c03 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,17 +22,19 @@ 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, - ObsoleteClosureType, + Sized, + ForSized, + OwnedType, + OwnedExpr, + OwnedPattern, + OwnedVector, + OwnedSelf, + ImportRenaming, + SubsliceMatch, + ExternCrateRenaming, + ProcType, + ProcExpr, + ClosureType, } pub trait ParserObsoleteMethods { @@ -56,50 +56,59 @@ 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::ForSized => ( + "for Sized?", + "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \ + by default", + ), + 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" ), - ObsoleteClosureType => ( + ObsoleteSyntax::ClosureType => ( "`|uint| -> bool` closure type syntax", "use unboxed closures instead, no type annotation needed" - ) + ), + 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 28c7293fc26a3..32f8f5ee3d63b 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::*; @@ -74,8 +72,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; @@ -1155,7 +1153,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 } @@ -1246,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 } @@ -1511,8 +1509,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)) { @@ -2275,7 +2275,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(); @@ -2737,6 +2737,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 }; @@ -2850,9 +2853,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(); @@ -2966,14 +2969,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(); @@ -2991,8 +2997,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 @@ -3223,7 +3230,7 @@ impl<'a> Parser<'a> { } else { let _ = self.parse_pat(); let span = self.span; - self.obsolete(span, ObsoleteSubsliceMatch); + self.obsolete(span, ObsoleteSyntax::SubsliceMatch); } continue } @@ -3339,7 +3346,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, @@ -3347,11 +3354,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, @@ -3870,13 +3882,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, })); @@ -3885,9 +3897,10 @@ 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); + 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); self.handle_expression_like_statement( e, ast::DUMMY_NODE_ID, @@ -4080,8 +4093,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; @@ -4090,6 +4103,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); @@ -4453,7 +4467,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 } @@ -4504,7 +4518,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 @@ -4880,67 +4894,116 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "`virtual` structs have been removed from the language"); } - self.parse_where_clause(&mut generics); + // 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. + + 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)) + }; - let mut fields: Vec; - let is_tuple_like; + (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(generics); self.expect(&token::Semi); - } else if self.eat(&token::Semi) { - // 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 @@ -4993,6 +5056,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; @@ -5010,8 +5074,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, ObsoleteSyntax::ForSized); + + None } else { None } @@ -5333,7 +5400,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 @@ -5960,6 +6027,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( @@ -5990,7 +6061,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, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b7e89b32b709e..094aacf3207fc 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)] @@ -550,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/print/pprust.rs b/src/libsyntax/print/pprust.rs index e44cc2257c24c..402583b60fae5 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), @@ -1056,7 +1058,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()); @@ -1075,10 +1076,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()); @@ -2081,8 +2084,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/show_span.rs b/src/libsyntax/show_span.rs index 354ba854b101a..57520257fe1b3 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_mac(&mut self, macro: &ast::Mac) { - visit::walk_mac(self, macro); + 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, mac: &ast::Mac) { + visit::walk_mac(self, mac); } } -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); } 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/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/libsyntax/visit.rs b/src/libsyntax/visit.rs index 737f1b73b3290..3f91304dcc5f2 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); @@ -511,7 +511,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) => { @@ -538,7 +538,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), } } @@ -738,7 +738,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), } } @@ -885,7 +885,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/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/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/libtest/lib.rs b/src/libtest/lib.rs index 3fb2211eff23a..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, phase, globs, slicing_syntax)] +#![feature(asm, globs, slicing_syntax)] #![feature(unboxed_closures, default_type_params)] #![feature(old_orphan_check)] diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 7e7f36f6e83fa..8daabf6101022 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. /// @@ -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/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/llvm b/src/llvm index ec1fdb3b9d3b1..b820135911e17 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit ec1fdb3b9d3b1fb9e1dae97a65dd3a13db9bfb23 +Subproject commit b820135911e17c7a46b901db56baa48e5155bf46 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 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/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/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/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/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/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/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/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/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 82af18b189b68..708830d025986 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -10,9 +10,6 @@ #![crate_name="lint_stability"] #![crate_type = "lib"] -#![feature(macro_rules)] -#![macro_escape] - #[deprecated] pub fn deprecated() {} #[deprecated="text"] @@ -181,16 +178,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/logging_right_crate.rs b/src/test/auxiliary/logging_right_crate.rs index 399dfb9fa9a5b..67037a3ac9e08 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_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/auxiliary/macro_crate_def_only.rs b/src/test/auxiliary/macro_crate_def_only.rs index ad3e72f5fa221..4f55ac4f65fd4 100644 --- a/src/test/auxiliary/macro_crate_def_only.rs +++ b/src/test/auxiliary/macro_crate_def_only.rs @@ -8,9 +8,7 @@ // 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( +macro_rules! make_a_5 { () => (5) -); +} diff --git a/src/test/auxiliary/macro_crate_nonterminal.rs b/src/test/auxiliary/macro_crate_nonterminal.rs new file mode 100644 index 0000000000000..922efc1aec38f --- /dev/null +++ b/src/test/auxiliary/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. + +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/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index b82cfcbc8fcb2..99f02cf2d58ba 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, quote)] extern crate syntax; extern crate rustc; @@ -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..84e944f69b98e 100644 --- a/src/test/auxiliary/macro_export_inner_module.rs +++ b/src/test/auxiliary/macro_export_inner_module.rs @@ -8,11 +8,9 @@ // 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( + macro_rules! foo { () => (1) - ); + } } 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/auxiliary/macro_reexport_1.rs b/src/test/auxiliary/macro_reexport_1.rs new file mode 100644 index 0000000000000..a913749bc66a9 --- /dev/null +++ b/src/test/auxiliary/macro_reexport_1.rs @@ -0,0 +1,15 @@ +// 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"] +#[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..15d9f9cc9146d --- /dev/null +++ b/src/test/auxiliary/macro_reexport_2.rs @@ -0,0 +1,15 @@ +// 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"] + +#[macro_reexport(reexported)] +#[macro_use] #[no_link] +extern crate macro_reexport_1; 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/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/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/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/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/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/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/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 new file mode 100644 index 0000000000000..060960f0dbc88 --- /dev/null +++ b/src/test/auxiliary/two_macros.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_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } 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/core-std.rs b/src/test/bench/core-std.rs index ee7c442da195c..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; @@ -28,11 +27,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/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) { 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-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-meteor.rs b/src/test/bench/shootout-meteor.rs index cdc7617fec8b0..ca3d10afa5d47 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-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs index 4f87171f5d3fa..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, phase, slicing_syntax)] +#![feature(plugin, slicing_syntax)] extern crate regex; 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-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 new file mode 100644 index 0000000000000..cff2e5eaf8786 --- /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(plugin)] + +#[plugin] #[no_link] +extern crate macro_crate_MacroRulesTT; + +fn main() { } 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 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-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 5743216b6ca69..183781e9e2417 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,11 +12,11 @@ // just propagate the error. #![crate_type = "lib"] -#![feature(associated_types, default_type_params, lang_items)] +#![feature(lang_items)] #![no_std] #[lang="sized"] -pub trait Sized for Sized? { +pub trait Sized { // Empty. } 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-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-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..b04b83e575bf4 --- /dev/null +++ b/src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.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. + +// Test that we report an error if the trait ref in an qualified type +// uses invalid type arguments. + +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() { } diff --git a/src/test/compile-fail/gated-default-type-param-usage.rs b/src/test/compile-fail/associated-types-issue-17359.rs similarity index 65% rename from src/test/compile-fail/gated-default-type-param-usage.rs rename to src/test/compile-fail/associated-types-issue-17359.rs index 4c8b5de4c864b..6c79105abee8f 100644 --- a/src/test/compile-fail/gated-default-type-param-usage.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:default_type_params_xc.rs +// Test that we do not ICE when an impl is missing an associated type (and that we report +// a useful error, of course). -#![deny(default_type_param_usage)] +trait Trait { + type Type; +} -extern crate default_type_params_xc; - -pub struct FooAlloc; - -pub type VecFoo = default_type_params_xc::FakeVec; -//~^ ERROR: default type parameters are experimental +impl Trait for int {} //~ ERROR missing: `Type` fn main() {} + 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..db39eafc1912b 100644 --- a/src/test/compile-fail/associated-types-unsized.rs +++ b/src/test/compile-fail/associated-types-unsized.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(associated_types)] - trait Get { - type Sized? Value; + type Value: ?Sized; 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..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(associated_types, 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 e51ca6a70f28b..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(associated_types, default_type_params)] - use std::ops::Add; fn double_move>(x: T) { 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..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(associated_types, default_type_params)] - use std::ops::Add; #[derive(Copy)] 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/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/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/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/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/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/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-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/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs index 99c63c3c6e95e..3c75b5b6eddb8 100644 --- a/src/test/compile-fail/dst-object-from-unsized-type.rs +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -10,15 +10,15 @@ // Test that we cannot create objects from unsized types. -trait Foo for Sized? {} +trait Foo {} 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/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/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/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/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/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/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/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/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 22ac2eb1f7d5d..74835f4bf22ca 100644 --- a/src/test/compile-fail/infinite-macro-expansion.rs +++ b/src/test/compile-fail/infinite-macro-expansion.rs @@ -8,13 +8,9 @@ // 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` - ) - ); +macro_rules! recursive { + () => (recursive!()) //~ ERROR recursion limit reached while expanding the macro `recursive` +} fn main() { 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 300831b100773..d4de4e177f026 100644 --- a/src/test/compile-fail/issue-15167.rs +++ b/src/test/compile-fail/issue-15167.rs @@ -15,9 +15,7 @@ // ignore-test -#![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-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-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-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/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-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-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/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-6596.rs b/src/test/compile-fail/issue-6596.rs index 3222b2cd53719..c5be0da5f4b2a 100644 --- a/src/test/compile-fail/issue-6596.rs +++ b/src/test/compile-fail/issue-6596.rs @@ -8,15 +8,13 @@ // 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( +macro_rules! e { ($inp:ident) => ( $nonexistent ); -); +} fn main() { e!(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-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 { diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 8e1723ddab24c..0e24269ec4449 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -13,19 +13,19 @@ // aux-build:stability_cfg1.rs // aux-build:stability_cfg2.rs -#![feature(globs, phase)] #![deny(unstable)] #![deny(deprecated)] #![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 - #[phase(plugin, link)] - 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/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/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/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index e92faa6bdaf6e..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,9 +10,7 @@ // // regression test for #8005 -#![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-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() { +} 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 f64b7be50e307..e4fc5bb462700 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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/gated-glob-imports.rs b/src/test/compile-fail/macro-keyword.rs similarity index 74% rename from src/test/compile-fail/gated-glob-imports.rs rename to src/test/compile-fail/macro-keyword.rs index cc7ba785e7e65..9d4ec9c176cce 100644 --- a/src/test/compile-fail/gated-glob-imports.rs +++ b/src/test/compile-fail/macro-keyword.rs @@ -1,4 +1,4 @@ -// Copyright 2013 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,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::*; -//~^ ERROR: glob import statements are experimental +fn macro() { //~ ERROR `macro` is a reserved keyword +} -fn main() {} +pub fn main() { +} diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 150187aa07d3c..a66b638701436 100644 --- a/src/test/compile-fail/macro-match-nonterminal.rs +++ b/src/test/compile-fail/macro-match-nonterminal.rs @@ -8,9 +8,7 @@ // 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 +macro_rules! test { ($a, $b) => (()); } //~ ERROR Cannot transcribe fn main() { test!() 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 +} diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs index 6d59c203d14bd..a0f23c72bc41e 100644 --- a/src/test/compile-fail/macro-outer-attributes.rs +++ b/src/test/compile-fail/macro-outer-attributes.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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/gated-default-type-params.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs similarity index 81% rename from src/test/compile-fail/gated-default-type-params.rs rename to src/test/compile-fail/macro-reexport-malformed-1.rs index 65575d4fa8507..b9f754b2778bc 100644 --- a/src/test/compile-fail/gated-default-type-params.rs +++ b/src/test/compile-fail/macro-reexport-malformed-1.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Heap; +#[macro_reexport] //~ ERROR bad macro reexport +extern crate std; -struct Vec; //~ ERROR: default type parameters are experimental - -fn main() {} +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..9ced5be8479ba --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-2.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. + +#[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 new file mode 100644 index 0000000000000..c8bd0a0509cdc --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-3.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. + +#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport +extern crate std; + +fn main() { } 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/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/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/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index 747b4815ac2ae..f4740492651ae 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -10,11 +10,9 @@ // forbid-output: in expansion of -#![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/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/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/compile-fail/gated-macro-rules.rs b/src/test/compile-fail/multi-plugin-attr.rs similarity index 73% rename from src/test/compile-fail/gated-macro-rules.rs rename to src/test/compile-fail/multi-plugin-attr.rs index ae2f03fd5f798..1d98cd26a38f5 100644 --- a/src/test/compile-fail/gated-macro-rules.rs +++ b/src/test/compile-fail/multi-plugin-attr.rs @@ -1,4 +1,4 @@ -// Copyright 2013 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,7 +8,8 @@ // 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 +#[plugin] +#[plugin] //~ ERROR #[plugin] specified multiple times +extern crate std; fn main() {} 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..81985a3d6aa5b --- /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 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; + + let bar = &1i; + let &_ = bar; + let &mut _ //~ ERROR expected `&int`, found `&mut _` + = bar; +} 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/no-link.rs b/src/test/compile-fail/no-link.rs new file mode 100644 index 0000000000000..a9c2b6a942c65 --- /dev/null +++ b/src/test/compile-fail/no-link.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. + +#[no_link] +extern crate libc; + +fn main() { + unsafe { + libc::abs(0); //~ ERROR Use of undeclared type or module `libc` + //~^ ERROR unresolved name `libc::abs` + } +} 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() { } diff --git a/src/test/compile-fail/pattern-macro-hygiene.rs b/src/test/compile-fail/pattern-macro-hygiene.rs index 3322fecf950c1..1c79c9a2293a0 100644 --- a/src/test/compile-fail/pattern-macro-hygiene.rs +++ b/src/test/compile-fail/pattern-macro-hygiene.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - -macro_rules! foo ( () => ( x ) ); +macro_rules! foo { () => ( x ) } fn main() { let foo!() = 2; 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..92f3a57c69d0b 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -8,10 +8,10 @@ // 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? {} +#[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/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/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..816314529b5e8 --- /dev/null +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -0,0 +1,81 @@ +// 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 {} + +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() {} + 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/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/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/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/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/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..82355ddf68176 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -11,16 +11,16 @@ // 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 { fn dummy(&self, t: T, u: U, v: V); } -trait Eq for Sized? { } -impl Eq for X { } -fn eq() where A : Eq { } +trait Eq { } +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..f36fad306704f 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 { } +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..2617be295cd2a 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 { } +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..5ace9e115ec78 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; @@ -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 { } +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/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/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 0a75240f2d89d..9b7d10b0d0f76 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 } @@ -20,8 +20,8 @@ fn f2(x: &X) { } // Bounded. -trait T for Sized? {} -fn f3(x: &X) { +trait T {} +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..b4f0a4912cf30 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -11,32 +11,32 @@ // Test `Sized?` local variables. -trait T for Sized? {} +trait T {} -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..8a54771112f8e 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -10,14 +10,14 @@ // Test sized-ness checking in substitution in impls. -trait T for Sized? {} +trait T {} // I would like these to fail eventually. // 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/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/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index 7aa6ead89d7e0..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(associated_types, default_type_params)] - use std::ops::Mul; struct Vec1 { 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/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/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-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-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-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-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-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..6d59161ff9345 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,11 +14,9 @@ // `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. -#![feature(associated_types, default_type_params)] - 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-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..1d264655bc479 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,12 +11,10 @@ // 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; -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..742bab0578e9c 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -11,12 +11,10 @@ // 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; -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-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/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs index 822db63971e21..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 @@ -24,12 +22,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/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/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/cfg-macros-foo.rs b/src/test/run-pass/cfg-macros-foo.rs index ec9ef38150136..aeb6fcbbc0f01 100644 --- a/src/test/run-pass/cfg-macros-foo.rs +++ b/src/test/run-pass/cfg-macros-foo.rs @@ -13,10 +13,8 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-notfoo.rs) -#![feature(macro_rules)] - #[cfg(foo)] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { true } @@ -24,7 +22,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..adc27d556227e 100644 --- a/src/test/run-pass/cfg-macros-notfoo.rs +++ b/src/test/run-pass/cfg-macros-notfoo.rs @@ -13,10 +13,8 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-foo.rs) -#![feature(macro_rules)] - #[cfg(foo)] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { true } @@ -24,7 +22,7 @@ mod foo { } #[cfg(not(foo))] -#[macro_escape] +#[macro_use] mod foo { macro_rules! bar { () => { false } 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 42f6914e081a3..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; @@ -61,7 +59,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 +72,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 +89,7 @@ macro_rules! end_of_stmt( check_flags(0); } ) -); +} pub fn main() { 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() { } 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/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/const-binops.rs b/src/test/run-pass/const-binops.rs index cac805189b82e..11590ceb19d48 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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/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/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index 5e028d3774fc5..e846501be6ee5 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; @@ -19,12 +18,7 @@ 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]); - - 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/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index c1db8a6eb13f4..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; @@ -26,9 +25,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/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/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-phase-syntax.rs b/src/test/run-pass/deprecated-macro_escape.rs similarity index 76% rename from src/test/run-pass/deprecated-phase-syntax.rs rename to src/test/run-pass/deprecated-macro_escape.rs index df835dab4d4e0..b03905e1a0d63 100644 --- a/src/test/run-pass/deprecated-phase-syntax.rs +++ b/src/test/run-pass/deprecated-macro_escape.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(phase)] +// ignore-pretty -//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin) -#[phase(syntax, link)] -extern crate log; +#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use +mod foo { +} fn main() { - debug!("foo"); } diff --git a/src/test/run-pass/deriving-in-macro.rs b/src/test/run-pass/deriving-in-macro.rs index 97f6ee341a71f..c9b60d22ecb7b 100644 --- a/src/test/run-pass/deriving-in-macro.rs +++ b/src/test/run-pass/deriving-in-macro.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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/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/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/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/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/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index 38d1093762432..1fb434f7d7619 100644 --- a/src/test/run-pass/exponential-notation.rs +++ b/src/test/run-pass/exponential-notation.rs @@ -8,14 +8,14 @@ // 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}; 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/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/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/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/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/html-literals.rs b/src/test/run-pass/html-literals.rs index 0d56f28e8fae7..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)] - /* @@ -27,13 +25,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 +83,7 @@ macro_rules! parse_node ( ); ( []; [:$e:expr]; ) => ( $e ); -); +} pub fn main() { let _page = html! ( 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 1efae89f66563..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)] @@ -37,7 +36,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/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..ed88b3c65e09c 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -9,16 +9,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(globs, macro_rules, intrinsics)] +#![feature(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-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-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-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/issue-14919.rs b/src/test/run-pass/issue-14919.rs index d5590e99f2cb9..21bda93ecec65 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-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-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 01c96b7563a75..6d1813f8aa437 100644 --- a/src/test/run-pass/issue-15189.rs +++ b/src/test/run-pass/issue-15189.rs @@ -10,9 +10,9 @@ // ignore-pretty -#![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..e3c102e01ec5e 100644 --- a/src/test/run-pass/issue-15221.rs +++ b/src/test/run-pass/issue-15221.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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-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-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-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-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-17904.rs b/src/test/run-pass/issue-17904.rs new file mode 100644 index 0000000000000..3ce347d67e3d9 --- /dev/null +++ b/src/test/run-pass/issue-17904.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. + +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() {} 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-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; } 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-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-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 741f168482da2..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(associated_types, default_type_params, old_orphan_check)] +#![feature(old_orphan_check)] use std::ops::Mul; diff --git a/src/test/run-pass/issue-5060.rs b/src/test/run-pass/issue-5060.rs index 0cd25bc2c719b..7c3b0a5f1f014 100644 --- a/src/test/run-pass/issue-5060.rs +++ b/src/test/run-pass/issue-5060.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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 +19,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-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-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/issue-7911.rs b/src/test/run-pass/issue-7911.rs index c69b66f4dbd76..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 } @@ -27,7 +25,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 +35,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..865905bf50441 100644 --- a/src/test/run-pass/issue-8709.rs +++ b/src/test/run-pass/issue-8709.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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..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) @@ -20,7 +18,7 @@ enum T { B(uint) } -macro_rules! test( +macro_rules! test { ($id:ident, $e:expr) => ( fn foo(t: T) -> int { match t { @@ -29,7 +27,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..09d0f20c96d6c 100644 --- a/src/test/run-pass/issue-9110.rs +++ b/src/test/run-pass/issue-9110.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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 3ca060f45a5f5..5d5240272e542 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; @@ -19,8 +17,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..e5a287d014919 100644 --- a/src/test/run-pass/issue-9737.rs +++ b/src/test/run-pass/issue-9737.rs @@ -10,9 +10,9 @@ // ignore-test #9737 -#![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..a6060bebbc5cd 100644 --- a/src/test/run-pass/lambda-var-hygiene.rs +++ b/src/test/run-pass/lambda-var-hygiene.rs @@ -10,10 +10,10 @@ // ignore-test #9383 -#![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..2287cc48b66ce 100644 --- a/src/test/run-pass/let-var-hygiene.rs +++ b/src/test/run-pass/let-var-hygiene.rs @@ -8,10 +8,11 @@ // 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})); +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/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-2.rs b/src/test/run-pass/macro-2.rs index 7b4d376993aa9..80b2f408c1915 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -10,16 +10,14 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - 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-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-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 new file mode 100644 index 0000000000000..cb919297b0406 --- /dev/null +++ b/src/test/run-pass/macro-crate-nonterminal-renamed.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. + +// aux-build:macro_crate_nonterminal.rs +// ignore-stage1 + +#[macro_use] +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..9882f806a9eea --- /dev/null +++ b/src/test/run-pass/macro-crate-nonterminal.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. + +// aux-build:macro_crate_nonterminal.rs +// ignore-stage1 + +#[macro_use] +extern crate macro_crate_nonterminal; + +pub fn main() { + macro_crate_nonterminal::check_local(); + assert_eq!(increment!(5), 6); +} 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..fbbe0105cf4fe --- /dev/null +++ b/src/test/run-pass/macro-crate-use.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. + +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); +} 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-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-interpolation.rs b/src/test/run-pass/macro-interpolation.rs index 45712f5c62a6e..ff5b29d6ac88b 100644 --- a/src/test/run-pass/macro-interpolation.rs +++ b/src/test/run-pass/macro-interpolation.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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 +20,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..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,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - -macro_rules! four ( +macro_rules! four { () => (4) -); +} fn main() { let _x: [u16; four!()]; 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 4fb130f0e1314..f78f93e84810c 100644 --- a/src/test/run-pass/macro-multiple-items.rs +++ b/src/test/run-pass/macro-multiple-items.rs @@ -10,9 +10,7 @@ // ignore-pretty - token trees can't pretty print -#![feature(macro_rules)] - -macro_rules! make_foo( +macro_rules! make_foo { () => ( struct Foo; @@ -20,7 +18,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..c6efc2f2bc83b 100644 --- a/src/test/run-pass/macro-nt-list.rs +++ b/src/test/run-pass/macro-nt-list.rs @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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..3276aa0265f70 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -8,14 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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..07b75389cf4ff 100644 --- a/src/test/run-pass/macro-pat.rs +++ b/src/test/run-pass/macro-pat.rs @@ -8,37 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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-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-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-reexport.rs b/src/test/run-pass/macro-reexport.rs new file mode 100644 index 0000000000000..9701610cbd964 --- /dev/null +++ b/src/test/run-pass/macro-reexport.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. + +// aux-build:macro_reexport_1.rs +// aux-build:macro_reexport_2.rs +// ignore-stage1 + +#[macro_use] #[no_link] +extern crate macro_reexport_2; + +fn main() { + assert_eq!(reexported!(), 3u); +} diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 7be49e1acd844..cb5370c8bcba1 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -10,23 +10,21 @@ // ignore-pretty - token trees can't pretty print -#![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 +33,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-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/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs index 631fc8666713d..3f9d07466cc81 100644 --- a/src/test/run-pass/macro-with-attrs1.rs +++ b/src/test/run-pass/macro-with-attrs1.rs @@ -10,13 +10,11 @@ // compile-flags: --cfg foo -#![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..f90a0dfa6b31e 100644 --- a/src/test/run-pass/macro-with-attrs2.rs +++ b/src/test/run-pass/macro-with-attrs2.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![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..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,11 +8,9 @@ // 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 }); +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..e4886ddaa0ed3 100644 --- a/src/test/run-pass/match-in-macro.rs +++ b/src/test/run-pass/match-in-macro.rs @@ -8,19 +8,17 @@ // 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}, } -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..984f675b4dc7d 100644 --- a/src/test/run-pass/match-var-hygiene.rs +++ b/src/test/run-pass/match-var-hygiene.rs @@ -10,12 +10,10 @@ // ignore-test #9384 -#![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/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/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/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index 9151564b3407b..8b41670734f95 100644 --- a/src/test/run-pass/non-built-in-quote.rs +++ b/src/test/run-pass/non-built-in-quote.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - -macro_rules! quote_tokens ( () => (()) ); +macro_rules! quote_tokens { () => (()) } pub fn main() { quote_tokens!(); 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/operator-multidispatch.rs b/src/test/run-pass/operator-multidispatch.rs index 5999840091967..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(associated_types, default_type_params)] - use std::ops; #[derive(Show,PartialEq,Eq)] 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-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); } - 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/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() {} 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\"]"); +} 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/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/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/compile-fail/associated-types-feature-gate.rs b/src/test/run-pass/regions-reassign-match-bound-pointer.rs similarity index 57% rename from src/test/compile-fail/associated-types-feature-gate.rs rename to src/test/run-pass/regions-reassign-match-bound-pointer.rs index d95b94f006760..18312b17339ce 100644 --- a/src/test/compile-fail/associated-types-feature-gate.rs +++ b/src/test/run-pass/regions-reassign-match-bound-pointer.rs @@ -8,26 +8,19 @@ // 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, -} +// 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). -impl Get for Struct { - type Value = int; //~ ERROR associated types are experimental - fn get(&self) -> int { - self.x +fn foo(x: &int) { + let a = 1; + match x { + mut z => { + z = &a; + } } } -fn main() { - let s = Struct { - x: 100, - }; - assert_eq!(s.get(), 100); +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..2bdc883b9ce59 --- /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(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` + // 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, + mut mk_cand: Box FnMut(&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 +} 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/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/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/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/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 f6708536a9d99..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 { @@ -21,12 +19,12 @@ pub mod m1 { } } -macro_rules! indirect_line( () => ( line!() ) ); +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/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..4ab089b6eaa1c 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -16,7 +16,6 @@ // one test task to ensure that errors are timeouts, not file descriptor // exhaustion. -#![feature(macro_rules, globs)] #![allow(experimental)] #![reexport_test_harness_main = "test_main"] 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/tempfile.rs b/src/test/run-pass/tempfile.rs index 33e10cc77b7c1..bf108ecd6764a 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()); 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}; 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!(); +} 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..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) @@ -20,7 +18,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 +28,7 @@ macro_rules! test( } } ) -); +} test!(x,y,x + y); 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/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index 3e7718970258f..9600a242ca109 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: F) where F: FnOnce(*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()); }); } 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..7b2c35aa08d30 --- /dev/null +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -0,0 +1,37 @@ +// 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(lang_items)] +#![no_std] + +extern crate "std" as other; + +#[macro_use] +extern crate core; +extern crate libc; + +#[macro_use] +extern crate collections; + +use core::option::Option::Some; +use core::slice::SliceExt; +use collections::vec::Vec; + +// 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 +} 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();