From: Alex Crichton Date: Tue, 6 Jan 2015 03:01:17 +0000 (-0800) Subject: rollup merge of #20482: kmcallister/macro-reform X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=7975fd9cee750f26f9f6ef85b92a20b24ee24120;hp=563f6d8218cf15bf2590507c38ce4cbb734d6bba;p=rust.git rollup merge of #20482: kmcallister/macro-reform Conflicts: src/libflate/lib.rs src/libstd/lib.rs src/libstd/macros.rs src/libsyntax/feature_gate.rs src/libsyntax/parse/parser.rs src/libsyntax/show_span.rs src/test/auxiliary/macro_crate_test.rs src/test/compile-fail/lint-stability.rs src/test/run-pass/intrinsics-math.rs src/test/run-pass/tcp-connect-timeouts.rs --- diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 48610b6b526..0ce31a335d8 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/guide-macros.md b/src/doc/guide-macros.md index 58af5917407..dc6d281307a 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-plugin.md b/src/doc/guide-plugin.md index eb3e4ce75c4..025f0cced63 100644 --- a/src/doc/guide-plugin.md +++ b/src/doc/guide-plugin.md @@ -31,10 +31,14 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc. A plugin is a dynamic library crate with a designated "registrar" function that registers extensions with `rustc`. Other crates can use these extensions by -loading the plugin crate with `#[phase(plugin)] extern crate`. See the +loading the plugin crate with `#[plugin] extern crate`. See the [`rustc::plugin`](rustc/plugin/index.html) documentation for more about the mechanics of defining and loading a plugin. +Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by +rustc itself. They are provided to the plugin through the `Registry`'s [`args` +method](rustc/plugin/registry/struct.Registry.html#method.args). + # Syntax extensions Plugins can extend Rust's syntax in various ways. One kind of syntax extension @@ -105,10 +109,9 @@ pub fn plugin_registrar(reg: &mut Registry) { Then we can use `rn!()` like any other macro: ```ignore -#![feature(phase)] +#![feature(plugin)] -#[phase(plugin)] -extern crate roman_numerals; +#[plugin] extern crate roman_numerals; fn main() { assert_eq!(rn!(MMXV), 2015); @@ -217,8 +220,7 @@ pub fn plugin_registrar(reg: &mut Registry) { Then code like ```ignore -#[phase(plugin)] -extern crate lint_plugin_test; +#[plugin] extern crate lint_plugin_test; fn lintme() { } ``` diff --git a/src/doc/reference.md b/src/doc/reference.md index 635e216831f..0f1f26d3e71 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 `$`.) @@ -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 diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index aa20fe3c395..dce6d3f6687 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -56,7 +56,7 @@ syn match rustMacroRepeatCount ".\?[*+]" contained syn match rustMacroVariable "$\w\+" " Reserved (but not yet used) keywords {{{2 -syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override +syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro " Built-in types {{{2 syn keyword rustType int uint float char bool u8 u16 u32 u64 f32 diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index db26ca6ffa5..9194c7a4766 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 next(r: &mut lexer::StringReader) -> TokenAndSpan { 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 @@ macro_rules! matches ( ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok) } ) - ); + } matches!( token::Literal(token::Byte(..), _), diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d040f8ff863..001e02f9c0d 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -68,14 +68,33 @@ #![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)] #![feature(associated_types)] +#[cfg(stage0)] #[phase(plugin, link)] extern crate core; + +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + extern crate libc; // Allow testing this library -#[cfg(test)] #[phase(plugin, link)] extern crate std; -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate std; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate std; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; // Heaps provided for low-level allocation strategies diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index c9b090bfb23..5bf5f78af94 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 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; diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index ce4b1e46773..0c5929e8661 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/slice.rs b/src/libcollections/slice.rs index f286b99e045..1cb9e9009db 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -2598,13 +2598,13 @@ fn test_reverse_part() { #[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]"); @@ -2624,12 +2624,12 @@ macro_rules! test_show_vec( #[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 f994348ffe7..c0482702ccd 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1846,7 +1846,9 @@ fn test_is_utf8() { #[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], @@ -1866,7 +1868,9 @@ fn test_is_utf16() { &[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 6d7ebeff094..0bf311e4d3f 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -182,7 +182,7 @@ fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 { 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 @@ macro_rules! error(() => ({ subseqidx = i; res.as_mut_vec().push_all(REPLACEMENT); } - })); + })} if byte < 128u8 { // subseqidx handles this diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 7d92b707f98..951f5c29f00 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -20,12 +20,15 @@ use option::Option; use option::Option::{Some, None}; use ops::{Deref, FnOnce}; -use result::Result::{Ok, Err}; +use result::Result::Ok; use result; use slice::SliceExt; use slice; use str::{self, StrExt, Utf8Error}; +// NOTE: for old macros; remove after the next snapshot +#[cfg(stage0)] use result::Result::Err; + pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d646245510d..aff0065c527 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 @@ #[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 e8fbd9d930f..a579f9db416 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/num/float_macros.rs b/src/libcore/num/float_macros.rs index 97de61d7e27..20300d29fa0 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 522eab9180c..61cd8cbf7c1 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 82eca0d4659..535765840a0 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/result.rs b/src/libcore/result.rs index 7293ed6455b..8e9bf5487e3 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -220,9 +220,9 @@ //! //! ``` //! # #![feature(macro_rules)] -//! macro_rules! try( +//! macro_rules! try { //! ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) -//! ); +//! } //! # fn main() { } //! ``` //! diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d9749899b22..a39787b8207 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -964,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, diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index b6fc6457fce..50ae59e70dc 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 8885d3a5208..b98432e26b2 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 @@ fn test_from_str_radix() { } } -)); +)} diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 651e8640e91..f86c85f8216 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -14,13 +14,20 @@ 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 2311c19d557..04d8fb15cf5 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 @@ fn test_unsigned_checked_div() { assert!(5u.checked_div(0) == None); } } -)); + +)} diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index a0c9da3ae6d..6ac311fe4b6 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -21,9 +21,9 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(phase, unboxed_closures, associated_types)] +#![feature(unboxed_closures, associated_types)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(test)] #[macro_use] extern crate log; extern crate libc; diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index a4d89bf301e..917c6e99992 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 2063654077f..18077795e24 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -85,11 +85,11 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(globs, phase, slicing_syntax)] +#![feature(globs, slicing_syntax)] #![feature(unboxed_closures)] #![deny(missing_docs)] -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(test)] #[macro_use] extern crate log; use self::Name::*; use self::HasArg::*; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 0508402ff19..df85e89efd1 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 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 f41a4a8b901..5c7085b7b6c 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 = 3; @@ -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=10, y=20); @@ -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/distributions/mod.rs b/src/librand/distributions/mod.rs index e684fcf40f7..2fdba8a6c4f 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -297,7 +297,7 @@ fn test_weighted_choice() { // 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 @@ macro_rules! t ( 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 558fa201256..1038009522d 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -182,7 +182,7 @@ fn test_range_bad_limits_flipped() { #[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 @@ macro_rules! t ( } )* }} - ); + } t!(i8, i16, i32, i64, int, u8, u16, u32, u64, uint) } @@ -207,7 +207,7 @@ macro_rules! t ( #[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 @@ macro_rules! t ( } )* }} - ); + } t!(f32, f64) } diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 03b56963ba9..84328360ce3 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -69,7 +69,7 @@ fn init(&mut self, use_rsl: bool) { 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 @@ macro_rules! mix( 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 @@ macro_rules! memloop ( self.mem[i+6]=g; self.mem[i+7]=h; } }} - ); + } memloop!(self.rsl); memloop!(self.mem); @@ -129,41 +129,42 @@ fn isaac(&mut self) { 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); @@ -301,15 +302,15 @@ pub fn new_unseeded() -> 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; @@ -320,14 +321,14 @@ macro_rules! mix( 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]; @@ -341,7 +342,7 @@ macro_rules! memloop ( self.mem[i+6]=g; self.mem[i+7]=h; } }} - ); + } memloop!(self.rsl); memloop!(self.mem); @@ -366,49 +367,51 @@ fn isaac64(&mut self) { let mut b = self.b + self.c; const MIDPOINT: uint = RAND_SIZE_64 / 2; const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; - macro_rules! ind ( + macro_rules! ind { ($x:expr) => { *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1)) } - ); + } for &(mr_offset, m2_offset) in MP_VEC.iter() { for base in range(0, MIDPOINT / 4).map(|i| i * 4) { - macro_rules! rngstepp( + macro_rules! rngstepp { ($j:expr, $shift:expr) => {{ - let base = base + $j; - let mix = a ^ (a << $shift as uint); - let mix = if $j == 0 {!mix} else {mix}; - - unsafe { - let x = *self.mem.get_unchecked(base + mr_offset); - a = mix + *self.mem.get_unchecked(base + m2_offset); - let y = ind!(x) + a + b; - *self.mem.get_unchecked_mut(base + mr_offset) = y; - - b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.get_unchecked_mut(base + mr_offset) = b; - } - }} - ); - macro_rules! rngstepn( + let base = base + $j; + let mix = a ^ (a << $shift as uint); + let mix = if $j == 0 {!mix} else {mix}; + + unsafe { + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); + let y = ind!(x) + a + b; + *self.mem.get_unchecked_mut(base + mr_offset) = y; + + b = ind!(y >> RAND_SIZE_64_LEN) + x; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; + } + }} + } + + macro_rules! rngstepn { ($j:expr, $shift:expr) => {{ - let base = base + $j; - let mix = a ^ (a >> $shift as uint); - let mix = if $j == 0 {!mix} else {mix}; - - unsafe { - let x = *self.mem.get_unchecked(base + mr_offset); - a = mix + *self.mem.get_unchecked(base + m2_offset); - let y = ind!(x) + a + b; - *self.mem.get_unchecked_mut(base + mr_offset) = y; - - b = ind!(y >> RAND_SIZE_64_LEN) + x; - *self.rsl.get_unchecked_mut(base + mr_offset) = b; - } - }} - ); + let base = base + $j; + let mix = a ^ (a >> $shift as uint); + let mix = if $j == 0 {!mix} else {mix}; + + unsafe { + let x = *self.mem.get_unchecked(base + mr_offset); + a = mix + *self.mem.get_unchecked(base + m2_offset); + let y = ind!(x) + a + b; + *self.mem.get_unchecked_mut(base + mr_offset) = y; + + b = ind!(y >> RAND_SIZE_64_LEN) + x; + *self.rsl.get_unchecked_mut(base + mr_offset) = b; + } + }} + } + rngstepp!(0u, 21); rngstepn!(1u, 5); rngstepp!(2u, 12); diff --git a/src/librand/lib.rs b/src/librand/lib.rs index f538e0ade05..99dd505a9ef 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -29,11 +29,29 @@ #![no_std] #![experimental] +#[cfg(stage0)] #[phase(plugin, link)] extern crate core; -#[cfg(test)] #[phase(plugin, link)] extern crate std; -#[cfg(test)] #[phase(plugin, link)] extern crate log; +#[cfg(not(stage0))] +#[macro_use] +extern crate core; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate std; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate std; + +#[cfg(all(test, stage0))] +#[phase(plugin, link)] +extern crate log; + +#[cfg(all(test, not(stage0)))] +#[macro_use] +extern crate log; use core::prelude::*; diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 3acedac111d..e57542a6d14 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 b3807d31314..0084be49b56 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 122171e4691..3ed712b15df 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,8 +40,22 @@ 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/context.rs b/src/librustc/lint/context.rs index 521e5e305bc..5c0fd894436 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -167,21 +167,27 @@ fn register_renamed(&mut self, old_name: &str, new_name: &str) { } pub fn register_builtin(&mut self, sess: Option<&Session>) { - macro_rules! add_builtin ( ( $sess:ident, $($name:ident),*, ) => ( - {$( - self.register_pass($sess, false, box builtin::$name as LintPassObject); - )*} - )); - - macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => ( - {$( - self.register_pass($sess, false, box builtin::$name::new() as LintPassObject); - )*} - )); - - macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => ( - self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); - )); + macro_rules! add_builtin { + ($sess:ident, $($name:ident),*,) => ( + {$( + self.register_pass($sess, false, box builtin::$name as LintPassObject); + )*} + ) + } + + macro_rules! add_builtin_with_new { + ($sess:ident, $($name:ident),*,) => ( + {$( + self.register_pass($sess, false, box builtin::$name::new() as LintPassObject); + )*} + ) + } + + macro_rules! add_lint_group { + ($sess:ident, $name:expr, $($lint:ident),*) => ( + self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); + ) + } add_builtin!(sess, HardwiredLints, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 461a67ba937..e9778fa05ff 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 ca7c65c8e2b..de9a09ffe44 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -206,8 +206,8 @@ pub fn from_uint(value : uint) -> Option { 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 struct LinkMeta { 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 b0cf322b068..171bfd74a81 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -16,11 +16,10 @@ 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::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 @@ pub fn read_plugin_metadata(&mut self, 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/decoder.rs b/src/librustc/metadata/decoder.rs index ac8dfc16759..ed0a1f6211b 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 14ab471a4b8..e4226ddde85 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -42,6 +42,7 @@ 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 @@ struct Stats { // 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/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index a95523f2e06..32482fce4da 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -503,7 +503,7 @@ fn fromb(b: bool) -> Result { Ok(const_int(b as i64)) } "target type not found for const cast") }); - macro_rules! define_casts( + macro_rules! define_casts { ($val:ident, { $($ty_pat:pat => ( $intermediate_ty:ty, @@ -524,7 +524,7 @@ macro_rules! define_casts( },)* _ => Err("can't cast this type".to_string()) }) - ); + } eval_const_expr_partial(tcx, &**base) .and_then(|val| define_casts!(val, { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 291bb4c9820..c359233eca1 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -6171,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 a2e33454320..44a22395485 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 @@ fn new(sess: &'a Session) -> 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 @@ fn visit_mac(&mut self, _: &ast::Mac) { 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 @@ fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) { 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 8dd60880cdd..fd8873454b4 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 99e870a901e..feec97f02da 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 @@ /// 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 @@ pub fn new(krate: &ast::Crate) -> 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 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx 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_back/lib.rs b/src/librustc_back/lib.rs index 2bb99a7141f..238c84e88a9 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 1e55f442fb9..d606c5158d0 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -346,12 +346,12 @@ fn sigma1(x: u32) -> u32 { // 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 @@ macro_rules! sha2_round( $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 2ae88aa4476..86bd74d3f85 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -327,11 +327,11 @@ fn content(k: K) -> token::InternedString { k.get_content() } 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 @@ fn visit_mac(&mut self, macro: &Mac) { // 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 @@ fn visit_mac(&mut self, macro: &Mac) { // 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 d53f97c3a04..f14583bb9aa 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -239,7 +239,7 @@ pub fn from_json(obj: Json) -> 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 @@ macro_rules! key ( ) ); } ); - ); + } key!(cpu); key!(linker); @@ -305,7 +305,7 @@ fn load_file(path: &Path) -> Result { } // 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 @@ macro_rules! load_specific ( } } ) - ); + } load_specific!( x86_64_unknown_linux_gnu, diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index e1f0c9ec266..20949151557 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,15 +39,6 @@ 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 b886883c73a..0600ddba018 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 b029b4757c1..74f81ae9d6d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -12,7 +12,7 @@ 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; @@ -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); } }); @@ -351,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)); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2e8cde65890..89b2e0f257a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -39,11 +39,25 @@ extern crate rustc_resolve; extern crate rustc_trans; extern crate rustc_typeck; -#[phase(plugin, link)] extern crate log; -#[phase(plugin, link)] extern crate syntax; extern crate serialize; extern crate "rustc_llvm" as llvm; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate syntax; + +#[cfg(not(stage0))] +#[macro_use] +extern crate syntax; + pub use syntax::diagnostic; use rustc_trans::back::link; diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d972229e7c7..61fd7d16ab7 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -484,8 +484,8 @@ fn expr_to_block(rules: ast::BlockCheckMode, // 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_resolve/lib.rs b/src/librustc_resolve/lib.rs index adbcf8c2e8e..58102fe5629 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -21,8 +21,21 @@ #![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/lib.rs b/src/librustc_trans/lib.rs index 9dbff66aba2..705fecf4d19 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -37,11 +37,25 @@ 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/context.rs b/src/librustc_trans/trans/context.rs index f974a6faf4c..3726cf14023 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -736,7 +736,7 @@ pub fn report_overbig_object(&self, obj: Ty<'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( @@ -754,10 +754,10 @@ macro_rules! ifn ( return Some(f); } ) - ); - macro_rules! mk_struct ( + } + macro_rules! mk_struct { ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false)) - ); + } let i8p = Type::i8p(ccx); let void = Type::void(ccx); @@ -878,7 +878,7 @@ macro_rules! mk_struct ( // Some intrinsics were introduced in later versions of LLVM, but they have // fallbacks in libc or libm and such. Currently, all of these intrinsics // were introduced in LLVM 3.4, so we case on that. - macro_rules! compatible_ifn ( + macro_rules! compatible_ifn { ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => ( if unsafe { llvm::LLVMVersionMinor() >= 4 } { // The `if key == $name` is already in ifn! @@ -891,7 +891,7 @@ macro_rules! compatible_ifn ( return Some(f); } ) - ); + } compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32); compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64); diff --git a/src/librustc_trans/trans/macros.rs b/src/librustc_trans/trans/macros.rs index ab202975bfc..77efcc6fb00 100644 --- a/src/librustc_trans/trans/macros.rs +++ b/src/librustc_trans/trans/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - macro_rules! unpack_datum { ($bcx: ident, $inp: expr) => ( { diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 72c4def15a2..fa9cd5a698b 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -16,8 +16,11 @@ 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_typeck/lib.rs b/src/librustc_typeck/lib.rs index 3146a118139..dc434f14015 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -77,8 +77,21 @@ #![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/html/highlight.rs b/src/librustdoc/html/highlight.rs index cfaae1a9f80..30b9d6c63c5 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/lib.rs b/src/librustdoc/lib.rs index 106fe452f46..6e42c50f974 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,7 +32,14 @@ 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 @@ // 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 c98ec97ab87..ad67672ea6e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -73,7 +73,7 @@ pub fn visit(&mut self, krate: &ast::Crate) { 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 @@ pub fn visit_item(&mut self, item: &ast::Item, } // 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/lib.rs b/src/libserialize/lib.rs index 8ad2013f936..8fe15f00ded 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -31,8 +31,14 @@ #[cfg(test)] extern crate test; +#[cfg(stage0)] #[phase(plugin, link)] extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + extern crate unicode; extern crate collections; diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index 65cbce08543..ed3f2cbe1a1 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/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 91a5db2ba76..38ea4dad027 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -21,7 +21,9 @@ 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}; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c4e37264e2a..d590aa84194 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -18,11 +18,14 @@ 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 66416a21dd9..5bef473db99 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -282,10 +282,13 @@ 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 diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 3ce56c907b3..6eeef175f73 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 a1c52918637..e937cd24d8d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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 @@ /* 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 @@ /* 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; @@ -210,6 +255,10 @@ pub mod thread_local; // first for macros +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] +pub mod thread_local; + pub mod dynamic_lib; pub mod ffi; pub mod fmt; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index fb2d23b01b4..22cbf16e2b0 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 00000000000..48d62e73e13 --- /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 fd00f15662a..4c52f29b12d 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 fce150c4ad1..ebcb2086187 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 7818f4a0534..08ea1b024c9 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/path/posix.rs b/src/libstd/path/posix.rs index 1df02101ed0..d9981ace030 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -535,7 +535,7 @@ macro_rules! t { 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); @@ -550,7 +550,7 @@ macro_rules! t( assert!(mo.as_slice() == $exp); } ) - ); + } t!("foo", "foo"); t!(b"foo\x80", "foo\u{FFFD}"); @@ -562,7 +562,7 @@ macro_rules! t( #[test] fn test_display() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr, $expf:expr) => ( { let path = Path::new($path); @@ -572,7 +572,7 @@ macro_rules! t( assert!(f == $expf); } ) - ); + } t!(b"foo", "foo", "foo"); t!(b"foo/bar", "foo/bar", "bar"); @@ -585,7 +585,7 @@ macro_rules! t( #[test] fn test_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $exp:expr) => ( { let path = Path::new($path); @@ -606,7 +606,7 @@ macro_rules! t( 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")); @@ -669,7 +669,7 @@ macro_rules! t( #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -680,7 +680,7 @@ macro_rules! t( assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a/b/c", ".."); t!(s: "/a/b/c", "d"); @@ -690,7 +690,7 @@ macro_rules! t( #[test] fn test_push_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -699,7 +699,7 @@ macro_rules! t( 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"); @@ -711,7 +711,7 @@ macro_rules! t( #[test] fn test_push_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -726,7 +726,7 @@ macro_rules! t( 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"); @@ -739,7 +739,7 @@ macro_rules! t( #[test] fn test_pop() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $left:expr, $right:expr) => ( { let mut p = Path::new($path); @@ -756,7 +756,7 @@ macro_rules! t( assert!(result == $right); } ) - ); + } t!(b: b"a/b/c", b"a/b", true); t!(b: b"a", b".", true); @@ -795,7 +795,7 @@ fn test_join() { #[test] fn test_join_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -804,7 +804,7 @@ macro_rules! t( assert!(res.as_str() == Some($exp)); } ) - ); + } t!(s: "a/b/c", "..", "a/b"); t!(s: "/a/b/c", "d", "/a/b/c/d"); @@ -816,7 +816,7 @@ macro_rules! t( #[test] fn test_join_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -831,7 +831,7 @@ macro_rules! t( 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"); @@ -894,7 +894,7 @@ fn test_with_helpers() { #[test] fn test_setters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; @@ -915,7 +915,7 @@ macro_rules! t( 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"); @@ -938,7 +938,7 @@ macro_rules! t( #[test] fn test_getters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; @@ -969,7 +969,7 @@ macro_rules! t( 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); @@ -1008,7 +1008,7 @@ fn test_dir_path() { #[test] fn test_is_absolute() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $abs:expr, $rel:expr) => ( { let path = Path::new($path); @@ -1016,7 +1016,7 @@ macro_rules! t( 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); @@ -1029,7 +1029,7 @@ macro_rules! t( #[test] fn test_is_ancestor_of() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $dest:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1037,7 +1037,7 @@ macro_rules! t( 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); @@ -1063,7 +1063,7 @@ macro_rules! t( #[test] fn test_ends_with_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $child:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1078,7 +1078,7 @@ macro_rules! t( assert_eq!(path.ends_with_path(&child), $exp); } ) - ); + } t!(s: "a/b/c", "c", true); t!(s: "a/b/c", "d", false); @@ -1102,7 +1102,7 @@ macro_rules! t( #[test] fn test_path_relative_from() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $other:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1111,7 +1111,7 @@ macro_rules! t( 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")); @@ -1147,7 +1147,7 @@ macro_rules! t( #[test] fn test_components_iter() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1173,7 +1173,7 @@ macro_rules! t( 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"]); @@ -1193,7 +1193,7 @@ macro_rules! t( #[test] fn test_str_components() { - macro_rules! t( + macro_rules! t { (b: $arg:expr, $exp:expr) => ( { let path = Path::new($arg); @@ -1205,7 +1205,7 @@ macro_rules! t( 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 05129a7ab9d..4b5d793355b 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1127,7 +1127,7 @@ macro_rules! t { #[test] fn test_parse_prefix() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = $path; @@ -1137,7 +1137,7 @@ macro_rules! t( "parse_prefix(\"{}\"): expected {}, found {}", path, exp, res); } ) - ); + } t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5))); t!("\\\\", None); @@ -1326,7 +1326,7 @@ fn test_display_str() { #[test] fn test_display() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr, $expf:expr) => ( { let path = Path::new($path); @@ -1336,7 +1336,7 @@ macro_rules! t( assert_eq!(f, $expf); } ) - ); + } t!("foo", "foo", "foo"); t!("foo\\bar", "foo\\bar", "bar"); @@ -1345,7 +1345,7 @@ macro_rules! t( #[test] fn test_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $exp:expr) => ( { let path = $path; @@ -1368,7 +1368,7 @@ macro_rules! t( assert!(path.$op() == $exp); } ) - ); + } t!(v: b"a\\b\\c", filename, Some(b"c")); t!(s: "a\\b\\c", filename_str, "c"); @@ -1468,7 +1468,7 @@ macro_rules! t( #[test] fn test_push() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr) => ( { let path = $path; @@ -1479,7 +1479,7 @@ macro_rules! t( assert!(p1 == p2.join(join)); } ) - ); + } t!(s: "a\\b\\c", ".."); t!(s: "\\a\\b\\c", "d"); @@ -1503,7 +1503,7 @@ macro_rules! t( #[test] fn test_push_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -1512,7 +1512,7 @@ macro_rules! t( 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"); @@ -1555,7 +1555,7 @@ macro_rules! t( #[test] fn test_push_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::new($path); @@ -1570,7 +1570,7 @@ macro_rules! t( 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"); @@ -1584,7 +1584,7 @@ macro_rules! t( #[test] fn test_pop() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $left:expr, $right:expr) => ( { let pstr = $path; @@ -1605,7 +1605,7 @@ macro_rules! t( assert!(result == $right); } ) - ); + } t!(s: "a\\b\\c", "a\\b", true); t!(s: "a", ".", true); @@ -1673,7 +1673,7 @@ fn test_join() { #[test] fn test_join_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1682,7 +1682,7 @@ macro_rules! t( assert_eq!(res.as_str(), Some($exp)); } ) - ); + } t!(s: "a\\b\\c", "..", "a\\b"); t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d"); @@ -1696,7 +1696,7 @@ macro_rules! t( #[test] fn test_join_many() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1711,7 +1711,7 @@ macro_rules! t( 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"); @@ -1724,7 +1724,7 @@ macro_rules! t( #[test] fn test_with_helpers() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $op:ident, $arg:expr, $res:expr) => ( { let pstr = $path; @@ -1737,7 +1737,7 @@ macro_rules! t( 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"); @@ -1809,7 +1809,7 @@ macro_rules! t( #[test] fn test_setters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; @@ -1830,7 +1830,7 @@ macro_rules! t( 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"); @@ -1854,7 +1854,7 @@ macro_rules! t( #[test] fn test_getters() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; @@ -1885,7 +1885,7 @@ macro_rules! t( 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); @@ -1920,7 +1920,7 @@ fn test_dir_path() { #[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); @@ -1939,7 +1939,7 @@ macro_rules! t( 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); @@ -1960,7 +1960,7 @@ macro_rules! t( #[test] fn test_is_ancestor_of() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $dest:expr, $exp:expr) => ( { let path = Path::new($path); @@ -1972,7 +1972,7 @@ macro_rules! t( 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); @@ -2063,7 +2063,7 @@ macro_rules! t( #[test] fn test_ends_with_path() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $child:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2071,7 +2071,7 @@ macro_rules! t( assert_eq!(path.ends_with_path(&child), $exp); } ); - ); + } t!(s: "a\\b\\c", "c", true); t!(s: "a\\b\\c", "d", false); @@ -2095,7 +2095,7 @@ macro_rules! t( #[test] fn test_path_relative_from() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $other:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2108,7 +2108,7 @@ macro_rules! t( 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")); @@ -2229,7 +2229,7 @@ macro_rules! t( #[test] fn test_str_components() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2243,7 +2243,7 @@ macro_rules! t( assert_eq!(comps, exp); } ); - ); + } t!(s: b"a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\c", ["a", "b", "c"]); @@ -2287,7 +2287,7 @@ macro_rules! t( #[test] fn test_components_iter() { - macro_rules! t( + macro_rules! t { (s: $path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2299,7 +2299,7 @@ macro_rules! t( assert_eq!(comps, exp); } ) - ); + } t!(s: "a\\b\\c", [b"a", b"b", b"c"]); t!(s: ".", [b"."]); @@ -2308,7 +2308,7 @@ macro_rules! t( #[test] fn test_make_non_verbatim() { - macro_rules! t( + macro_rules! t { ($path:expr, $exp:expr) => ( { let path = Path::new($path); @@ -2317,7 +2317,7 @@ macro_rules! t( 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/rand/os.rs b/src/libstd/rand/os.rs index 6ae6a238c95..a79a6e35ebc 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/macros.rs b/src/libstd/rt/macros.rs index 0f35500a04a..bbc96d0b19f 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 2b0639c5705..e556888a470 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -39,6 +39,8 @@ pub mod backtrace; // Internals +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] mod macros; // These should be refactored/moved/made private over time diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index d3b4fab9681..e0cbaa8ca50 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 dc36fda3a02..714b71d5dbd 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 d48b0342b3b..ac1f0c5d803 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -17,8 +17,10 @@ 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/libsyntax/ast.rs b/src/libsyntax/ast.rs index 727f4157c1e..7aa7c4fcfb3 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; @@ -884,6 +884,7 @@ pub fn len(&self) -> uint { 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 @@ pub fn get_tt(&self, index: uint) -> 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/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 3107508a96a..34a193dffd3 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 91cc8a24622..91ae7396ea4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -16,6 +16,7 @@ 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 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 @@ fn expand<'cx>(&self, /// 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 builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension { } 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 @@ pub fn bt_pop(&mut self) { } } } + + 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 84d30a99004..7cb7ee3d355 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -61,7 +61,7 @@ fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { 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 @@ macro_rules! md ( }) } } } - ); + } 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 f9c8d95b308..c126238be82 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 @@ macro_rules! md ( }) } } } - ); + } let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"])); let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"], diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 14b19fee3df..e72c83b67c8 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 b3e839b4fb6..212ec3b0903 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 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 @@ fn fold_ident(&mut self, id: Ident) -> Ident { 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 @@ fn fold_pat(&mut self, pat: P) -> P { _ => 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) } } @@ -1175,31 +1185,17 @@ pub fn default(crate_name: String) -> ExpansionConfig { } } -pub struct ExportedMacros { - pub crate_name: Ident, - pub macros: Vec, -} - pub fn expand_crate(parse_sess: &parse::ParseSess, cfg: ExpansionConfig, // these are the macros being imported to this crate: - imported_macros: Vec, + imported_macros: Vec, user_exts: Vec, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander::new(&mut cx); - for ExportedMacros { crate_name, macros } in imported_macros.into_iter() { - let name = format!("<{} macros>", token::get_ident(crate_name)); - - for 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() { @@ -1288,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"); } @@ -1298,7 +1294,7 @@ fn visit_mac(&mut self, macro: &ast::Mac) { #[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}; @@ -1395,9 +1391,9 @@ fn test_ecfg() -> ExpansionConfig { 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( @@ -1407,16 +1403,6 @@ fn test_ecfg() -> ExpansionConfig { 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/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 08014dc1338..9837c8088fa 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 @@ fn make_stmt(self: Box>) -> Option> { struct MacroRulesMacroExpander { name: Ident, + imported_from: Option, lhses: Vec>, rhses: Vec>, } @@ -123,25 +124,18 @@ fn expand<'cx>(&self, 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 86e81ede8b0..e4e6f5ac6b0 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -15,7 +15,7 @@ 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 4dc4e69aa55..43e40393308 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -37,14 +37,14 @@ // if you change this list without updating src/doc/reference.md, @cmr will be sad static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("globs", Accepted), - ("macro_rules", Active), + ("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), @@ -74,6 +74,8 @@ ("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), @@ -161,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"); } @@ -233,10 +214,10 @@ fn visit_view_item(&mut self, i: &ast::ViewItem) { 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"); } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2999ef7ee86..c45a4005339 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -194,13 +194,13 @@ fn fold_local(&mut self, l: P) -> P { 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, @@ -1472,8 +1476,8 @@ impl Folder for ToZzIdentFolder { 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 18cdb3fc647..b7bfd346d50 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 8598571e5c3..b0969a573e6 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,8 +24,11 @@ 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/parser.rs b/src/libsyntax/parse/parser.rs index 58b08757cdf..cdfbd2c74b6 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::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; @@ -2739,6 +2737,9 @@ fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree { 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 }; @@ -3881,13 +3882,13 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, &mut stmts, &mut expr); } - StmtMac(macro, MacStmtWithoutBraces) => { + StmtMac(mac, MacStmtWithoutBraces) => { // statement macro without braces; might be an // expr depending on whether a semicolon follows match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(macro, + node: StmtMac(mac, MacStmtWithSemicolon), span: span, })); @@ -3896,10 +3897,16 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, _ => { let e = self.mk_mac_expr(span.lo, span.hi, +<<<<<<< HEAD macro.and_then(|m| m.node)); let e = self.parse_dot_or_call_expr_with(e); let e = self.parse_more_binops(e, 0); let e = self.parse_assign_expr_with(e); +======= + mac.and_then(|m| m.node)); + let e = + self.parse_dot_or_call_expr_with(e); +>>>>>>> kmc/macro-reform self.handle_expression_like_statement( e, ast::DUMMY_NODE_ID, @@ -6026,6 +6033,10 @@ fn parse_use(&mut self) -> ViewItem_ { fn parse_view_path(&mut self) -> P { let lo = self.span.lo; + // Allow a leading :: because the paths are absolute either way. + // This occurs with "use $crate::..." in macros. + self.eat(&token::ModSep); + if self.check(&token::OpenDelim(token::Brace)) { // use {foo,bar} let idents = self.parse_unspanned_seq( diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b7e89b32b70..094aacf3207 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 @@ pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { } } + 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 @@ pub mod 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 553e717f692..402583b60fa 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -272,6 +272,8 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()), + token::SpecialVarNt(var) => format!("${}", var.as_str()), + token::Interpolated(ref nt) => match *nt { token::NtExpr(ref e) => expr_to_string(&**e), token::NtMeta(ref e) => meta_item_to_string(&**e), diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 5a4d0cc3bd8..4ef7eb97a21 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -65,12 +65,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { 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 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { // 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/visit.rs b/src/libsyntax/visit.rs index cc71bafbbe5..3f91304dcc5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -115,13 +115,13 @@ fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { 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); @@ -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 3a442080077..dd42bede13a 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 fe96d7b8b7d..5f0111c7d7a 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -160,12 +160,12 @@ /// 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 3fb2211eff2..0419d85d391 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/test/auxiliary/issue-13560-3.rs b/src/test/auxiliary/issue-13560-3.rs index c80a7643e01..5510d3e2e0d 100644 --- a/src/test/auxiliary/issue-13560-3.rs +++ b/src/test/auxiliary/issue-13560-3.rs @@ -11,8 +11,7 @@ // no-prefer-dynamic #![crate_type = "rlib"] -#![feature(phase)] -#[phase(plugin)] extern crate "issue-13560-1" as t1; -#[phase(plugin, link)] extern crate "issue-13560-2" as t2; +#[macro_use] #[no_link] extern crate "issue-13560-1" as t1; +#[macro_use] extern crate "issue-13560-2" as t2; diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index add54ed01e0..097a5827fc4 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 6c78cdce28a..01ef08c4752 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 82af18b189b..708830d0259 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 enum Enum { 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 399dfb9fa9a..67037a3ac9e 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 00000000000..d50c27a4e75 --- /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 ad3e72f5fa2..4f55ac4f65f 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 00000000000..922efc1aec3 --- /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 39c4e83c4b9..99f02cf2d58 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -10,7 +10,7 @@ // force-host -#![feature(plugin_registrar, macro_rules, quote)] +#![feature(plugin_registrar, quote)] extern crate syntax; extern crate rustc; @@ -24,9 +24,9 @@ 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 9b4b1ceb5c1..84e944f69b9 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 00000000000..910fcd2e367 --- /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 00000000000..a913749bc66 --- /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 00000000000..15d9f9cc914 --- /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 00000000000..63142b0a699 --- /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/plugin_args.rs b/src/test/auxiliary/plugin_args.rs new file mode 100644 index 00000000000..b90c3f1d727 --- /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 c035f1203f8..12833daf604 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 614487c9817..9e74bf28135 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 99506309a59..c900550041b 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 8ec4eaebbe8..04f8eb3cf9b 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 ad120e12f86..c7e0a18768a 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 c68c13c0991..5100af32318 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 6c13e84a7fe..077c33cb90d 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 3d0973cb7ba..d481fa5a1fa 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 1ad9e5e1c0e..9e99a355ac1 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 6bd36b5a9b1..b8dd497ac99 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 c035f1203f8..12833daf604 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 d67c8f4c181..690ddc670f5 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 73798f37875..216e8e997f2 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -13,8 +13,6 @@ //! should not affect the strict version hash (SVH) computation //! (#14132). -#![feature(macro_rules)] - #![crate_name = "a"] macro_rules! three { diff --git a/src/test/auxiliary/two_macros.rs b/src/test/auxiliary/two_macros.rs new file mode 100644 index 00000000000..11b6108b99e --- /dev/null +++ b/src/test/auxiliary/two_macros.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. + +// force-host + +#[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 6a1f8588b60..39462fdc1e5 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 ee7c442da19..9007b4fd64c 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/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 4e8e0d64d52..16d6036d4c4 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -38,7 +38,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(macro_rules)] #![feature(simd)] #![allow(experimental)] diff --git a/src/test/bench/shootout-regex-dna.rs b/src/test/bench/shootout-regex-dna.rs index 4f87171f5d3..ef538eb6991 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/compile-fail-fulldeps/gated-phase.rs b/src/test/compile-fail-fulldeps/gated-phase.rs deleted file mode 100644 index 1f384b85633..00000000000 --- a/src/test/compile-fail-fulldeps/gated-phase.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:macro_crate_test.rs -// ignore-stage1 - -#[phase(plugin)] -//~^ ERROR compile time crate loading is experimental and possibly buggy -extern crate macro_crate_test; - -fn main() {} diff --git a/src/test/compile-fail-fulldeps/gated-plugin.rs b/src/test/compile-fail-fulldeps/gated-plugin.rs new file mode 100644 index 00000000000..89090d5f38a --- /dev/null +++ b/src/test/compile-fail-fulldeps/gated-plugin.rs @@ -0,0 +1,18 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:macro_crate_test.rs +// ignore-stage1 + +#[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 5edaa78eeea..11ae5563959 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 9eb39a9178c..62007d6575a 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 46aa4b6b5b7..da51c047f57 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 329d3e86c05..cf51958b53d 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 601faa22d77..9a36143f65c 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 fc7664c480f..46eb4d4b2ef 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/macro-crate-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs new file mode 100644 index 00000000000..adcdba04cc7 --- /dev/null +++ b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs @@ -0,0 +1,22 @@ +// 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. + +// aux-build:macro_crate_test.rs +// ignore-stage1 +// ignore-android + +#[macro_use] #[no_link] +extern crate macro_crate_test; + +fn main() { + macro_crate_test::foo(); + //~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test` + //~^^ ERROR unresolved name `macro_crate_test::foo` +} diff --git a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs index d4f286f20e8..1f44ac7cf9c 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 6a3b0b91ffe..b5ff8b71556 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 7a7eac7b709..65657eea1ef 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/phase-syntax-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs deleted file mode 100644 index 00aeb1c1bae..00000000000 --- a/src/test/compile-fail-fulldeps/phase-syntax-doesnt-resolve.rs +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -// aux-build:macro_crate_test.rs -// ignore-stage1 -// ignore-android - -#![feature(phase)] - -#[phase(plugin)] -extern crate macro_crate_test; - -fn main() { - macro_crate_test::foo(); - //~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test` - //~^^ ERROR unresolved name `macro_crate_test::foo` -} 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 00000000000..cff2e5eaf87 --- /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 1b8fb32a808..5ebcdb20b19 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/cleanup-rvalue-scopes-cf.rs b/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs index b79f4507d46..dcbb25ba5a9 100644 --- a/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs +++ b/src/test/compile-fail/cleanup-rvalue-scopes-cf.rs @@ -11,8 +11,6 @@ // Test that the borrow checker prevents pointers to temporaries // with statement lifetimes from escaping. -#![feature(macro_rules)] - use std::ops::Drop; static mut FLAGS: u64 = 0; diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs index 0a004c101ee..1814b1cd544 100644 --- a/src/test/compile-fail/const-block-non-item-statement.rs +++ b/src/test/compile-fail/const-block-non-item-statement.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - static A: uint = { 1u; 2 }; //~^ ERROR: blocks in constants are limited to items and tail expressions diff --git a/src/test/compile-fail/deprecated-phase.rs b/src/test/compile-fail/deprecated-phase.rs new file mode 100644 index 00000000000..1401494d987 --- /dev/null +++ b/src/test/compile-fail/deprecated-phase.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. + +#[phase(blah)] +//~^ ERROR #[phase] is deprecated +extern crate foo; + +fn main() {} 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 00000000000..fbf6287db94 --- /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 49a927b9879..6f75181c31c 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/gated-macro-rules.rs b/src/test/compile-fail/gated-macro-rules.rs deleted file mode 100644 index ae2f03fd5f7..00000000000 --- a/src/test/compile-fail/gated-macro-rules.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -macro_rules! foo(() => ()); -//~^ ERROR: macro definitions are not stable enough for use - -fn main() {} diff --git a/src/test/compile-fail/hygienic-label-1.rs b/src/test/compile-fail/hygienic-label-1.rs index 0e87dc97c26..dd6682a6f42 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 fe87e32459b..24194d7bbe9 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 b5954ac9930..4ff3bec3c64 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 67fa56b1306..174e8a2834f 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 88b6854bb1d..971f643c0fe 100644 --- a/src/test/compile-fail/if-let.rs +++ b/src/test/compile-fail/if-let.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - fn macros() { macro_rules! foo{ ($p:pat, $e:expr, $b:block) => {{ diff --git a/src/test/compile-fail/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 22ac2eb1f7d..74835f4bf22 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 36afc729de9..370a6228db6 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 300831b1007..d4de4e177f0 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 5adcd7c2bb6..68ac19b383f 100644 --- a/src/test/compile-fail/issue-16098.rs +++ b/src/test/compile-fail/issue-16098.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! prob1 { (0) => { 0 diff --git a/src/test/compile-fail/issue-6596.rs b/src/test/compile-fail/issue-6596.rs index 3222b2cd537..c5be0da5f4b 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/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 6d59f2c6501..0e24269ec44 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(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 8899d06804f..56d2b2cd6c0 100644 --- a/src/test/compile-fail/lint-unsafe-block.rs +++ b/src/test/compile-fail/lint-unsafe-block.rs @@ -11,8 +11,6 @@ #![allow(unused_unsafe)] #![allow(dead_code)] #![deny(unsafe_blocks)] -#![feature(macro_rules)] - unsafe fn allowed() {} #[allow(unsafe_blocks)] fn also_allowed() { unsafe {} } diff --git a/src/test/compile-fail/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index e92faa6bdaf..9cfffb5fa6b 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 00000000000..67aaf05c310 --- /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 71b656d0bbb..53b29ccb0c0 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 f64b7be50e3..e4fc5bb4627 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/macro-keyword.rs b/src/test/compile-fail/macro-keyword.rs new file mode 100644 index 00000000000..9d4ec9c176c --- /dev/null +++ b/src/test/compile-fail/macro-keyword.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn macro() { //~ ERROR `macro` is a reserved keyword +} + +pub fn main() { +} diff --git a/src/test/compile-fail/macro-match-nonterminal.rs b/src/test/compile-fail/macro-match-nonterminal.rs index 150187aa07d..a66b6387014 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 00000000000..4a427f121fc --- /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 6d59c203d14..a0f23c72bc4 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/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs new file mode 100644 index 00000000000..b9f754b2778 --- /dev/null +++ b/src/test/compile-fail/macro-reexport-malformed-1.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] //~ ERROR bad macro reexport +extern crate std; + +fn main() { } diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs new file mode 100644 index 00000000000..9ced5be8479 --- /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 00000000000..c8bd0a0509c --- /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 00000000000..c8e59f98d3c --- /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 00000000000..a73c4adb71f --- /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 00000000000..31efe857605 --- /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 00000000000..4e0486f0db7 --- /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 f1f31a99e97..314292085df 100644 --- a/src/test/compile-fail/macros-no-semicolon-items.rs +++ b/src/test/compile-fail/macros-no-semicolon-items.rs @@ -12,4 +12,3 @@ macro_rules! foo() //~ ERROR semicolon fn main() { } - diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index 747b4815ac2..f4740492651 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 00000000000..0153d71fb26 --- /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 00000000000..6d3038b4820 --- /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/multi-plugin-attr.rs b/src/test/compile-fail/multi-plugin-attr.rs new file mode 100644 index 00000000000..1d98cd26a38 --- /dev/null +++ b/src/test/compile-fail/multi-plugin-attr.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[plugin] +#[plugin] //~ ERROR #[plugin] specified multiple times +extern crate std; + +fn main() {} diff --git a/src/test/compile-fail/no-link.rs b/src/test/compile-fail/no-link.rs new file mode 100644 index 00000000000..a9c2b6a942c --- /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/pattern-macro-hygiene.rs b/src/test/compile-fail/pattern-macro-hygiene.rs index 3322fecf950..1c79c9a2293 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/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index de0d5c90fdd..6e1ecb10e3a 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -12,7 +12,6 @@ // deeply nested types that will fail the `Send` check by overflow // when the recursion limit is set very low. -#![feature(macro_rules)] #![allow(dead_code)] #![recursion_limit="10"] diff --git a/src/test/compile-fail/svh-change-lit.rs b/src/test/compile-fail/svh-change-lit.rs index 179fb11d5fe..c839ade75cf 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 1f65f3873a9..df0adf36ce2 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 4e4f7b232f4..4774384fecd 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 77b0a9211ca..51d3fd0a73a 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 13dcfa3b5da..609e0f3689e 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 7d26bdd15fb..c42714609b6 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 8e000024675..95cb17c215b 100644 --- a/src/test/compile-fail/trace_macros-format.rs +++ b/src/test/compile-fail/trace_macros-format.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules, trace_macros)] +#![feature(trace_macros)] fn main() { trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false` diff --git a/src/test/compile-fail/while-let.rs b/src/test/compile-fail/while-let.rs index ccf3d2dd750..adb8ee6940d 100644 --- a/src/test/compile-fail/while-let.rs +++ b/src/test/compile-fail/while-let.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - fn macros() { macro_rules! foo{ ($p:pat, $e:expr, $b:block) => {{ diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index be52ffff1b4..2aa31969a46 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 35bd22880ce..500305f5970 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -1,7 +1,6 @@ -#![feature(phase)] #![no_std] #![feature(globs)] -#[phase(plugin, link)] +#[macro_use] extern crate "std" as std; #[prelude_import] use std::prelude::v1::*; diff --git a/src/test/run-fail/rt-set-exit-status-panic.rs b/src/test/run-fail/rt-set-exit-status-panic.rs index e524a2432ac..fd7c3f8cc0e 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 972c85e376e..446ef6f97e2 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 bddf9b5a7ea..39ece8a464a 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 ab1cf96999d..11e042c8c4a 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 2028710cbd2..a38b2cfb962 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 bf60784ab58..6febe2ff7c1 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 c9d603c2e1c..c31b67b8043 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 08c9f8b4aa7..11e7da77029 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 726670b5d7f..7615b25f9e4 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 d3d1f1ea565..7144d2b0f1e 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 8c5269e2274..d11242f4fe6 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 0afd76e1659..a8762234ad9 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 dd585ea9794..d943cf0457b 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 0f5e2cb3b6b..4ffb8a3f74d 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/phase-syntax-link-does-resolve.rs deleted file mode 100644 index 47ff7d31df5..00000000000 --- a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -// aux-build:macro_crate_test.rs -// ignore-stage1 -// ignore-cross-compile -// -// macro_crate_test will not compile on a cross-compiled target because -// libsyntax is not compiled for it. - -#![feature(phase)] - -#[phase(plugin, link)] -extern crate macro_crate_test; - -fn main() { - assert_eq!(1, make_a_1!()); - macro_crate_test::foo(); -} diff --git a/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs b/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs new file mode 100644 index 00000000000..518d02e3d75 --- /dev/null +++ b/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs @@ -0,0 +1,26 @@ +// 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. + +// aux-build:macro_crate_test.rs +// ignore-stage1 +// ignore-cross-compile +// +// macro_crate_test will not compile on a cross-compiled target because +// libsyntax is not compiled for it. + +#![feature(plugin)] + +#[plugin] +extern crate macro_crate_test; + +fn main() { + assert_eq!(1, make_a_1!()); + macro_crate_test::foo(); +} diff --git a/src/test/run-pass-fulldeps/roman-numerals-macro.rs b/src/test/run-pass-fulldeps/roman-numerals-macro.rs index 73a4a51f31c..d76766094ed 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 b3fae671c52..1c74c8ad08e 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/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs index 822db63971e..28db3953a00 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/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index 3f6d6a02c79..e3e00410507 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 ec9ef381501..aeb6fcbbc0f 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 @@ macro_rules! bar { } #[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 fb44176ec22..adc27d55622 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 @@ macro_rules! bar { } #[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 932a5a044ad..8969cca2610 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 42f6914e081..59763e417a2 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 @@ fn drop(&mut self) { } } -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/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs index d2caecdf05b..ca7f761b80d 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 f87d92dc16f..e3bdbeb1692 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 cac805189b8..11590ceb19d 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 09f26b15734..03afe798954 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 3365f09cd80..d55b420db08 100644 --- a/src/test/run-pass/const-block-item.rs +++ b/src/test/run-pass/const-block-item.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - mod foo { pub trait Value { fn value(&self) -> uint; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index c1db8a6eb13..3298976de6c 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::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 00000000000..b2956f4e229 --- /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 00000000000..7960a91bdc4 --- /dev/null +++ b/src/test/run-pass/deprecated-macro_escape-inner.rs @@ -0,0 +1,19 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty + +mod foo { + #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use + //~^ HELP consider an outer attribute +} + +fn main() { +} diff --git a/src/test/run-pass/deprecated-macro_escape.rs b/src/test/run-pass/deprecated-macro_escape.rs new file mode 100644 index 00000000000..b03905e1a0d --- /dev/null +++ b/src/test/run-pass/deprecated-macro_escape.rs @@ -0,0 +1,18 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty + +#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use +mod foo { +} + +fn main() { +} diff --git a/src/test/run-pass/deprecated-phase-syntax.rs b/src/test/run-pass/deprecated-phase-syntax.rs deleted file mode 100644 index df835dab4d4..00000000000 --- a/src/test/run-pass/deprecated-phase-syntax.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#![feature(phase)] - -//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin) -#[phase(syntax, link)] -extern crate log; - -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 97f6ee341a7..c9b60d22ecb 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 f619c824d5e..e8086b8b7c6 100644 --- a/src/test/run-pass/deriving-show.rs +++ b/src/test/run-pass/deriving-show.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - #[derive(Show)] struct Unit; diff --git a/src/test/run-pass/enum-discrim-width-stuff.rs b/src/test/run-pass/enum-discrim-width-stuff.rs index 73abec89a2d..07941eca224 100644 --- a/src/test/run-pass/enum-discrim-width-stuff.rs +++ b/src/test/run-pass/enum-discrim-width-stuff.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - macro_rules! check { ($m:ident, $t:ty, $v:expr) => {{ mod $m { diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index 38d10937624..1fb434f7d76 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/html-literals.rs b/src/test/run-pass/html-literals.rs index 0d56f28e8fa..fbaeb1753f4 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 @@ */ 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 397ce75b6b9..17c0299cf4d 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 53c081ff83e..e899a1adb79 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 1efae89f665..d38b0ea2747 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } -macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) }); +macro_rules! t { + ($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) } +} pub fn main() { // Various edge cases without formats diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index 523e7ab02d4..ed88b3c65e0 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(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-14330.rs b/src/test/run-pass/issue-14330.rs index bac846dfa20..f983f233ee3 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-14936.rs b/src/test/run-pass/issue-14936.rs index 960dae8b704..a441729e2d0 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 01c96b7563a..6d1813f8aa4 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 a11b34e4762..e3c102e01ec 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-5060.rs b/src/test/run-pass/issue-5060.rs index 0cd25bc2c71..7c3b0a5f1f0 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 24dcc3838c5..32fca7a182c 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 f2167da31fc..589ccefd9ea 100644 --- a/src/test/run-pass/issue-5718.rs +++ b/src/test/run-pass/issue-5718.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] - struct Element; macro_rules! foo { diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index c69b66f4dbd..86948ebcb91 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 @@ fn get_mut(&mut $slf) -> &mut FooBar { &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 d4ea05004a0..865905bf504 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 5826a5f9919..b70711f9f39 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 @@ fn foo(t: T) -> int { } } ) -); +} 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 60011281d42..09d0f20c96d 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 3ca060f45a5..5d5240272e5 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 1f385b2fb15..e5a287d0149 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 5dfc4208554..a6060bebbc5 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 5eed791e058..2287cc48b66 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 4b97d274fba..262d9b21eb4 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 c4f7b1492ab..372cdc401b5 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 ebbe7fa65cd..0f13df644a1 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 7b4d376993a..80b2f408c19 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 3c170634c22..60217139cd7 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 4df3b94c1c9..521aef4b5ba 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 8a9fbbe2848..6c568d6d493 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 70080fcc3c9..7505fa6e684 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 00000000000..cb919297b04 --- /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 00000000000..9882f806a9e --- /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 00000000000..fbbe0105cf4 --- /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 f85c6f1fc93..c4012e2cf3c 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 88ca466b4af..ef22410751c 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 45712f5c62a..ff5b29d6ac8 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 @@ fn $fnname($arg: $ty) -> Option<$ty> $body } }) -); +} 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 ecd7c0458f7..ce748967498 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 4b01fdf8162..47e3a072399 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 aa6de9acf6b..fd16958d896 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 4fb130f0e13..f78f93e8481 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 @@ impl 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 9367a231d4f..c6efc2f2bc8 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 c47b5e11089..3276aa0265f 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 496cef9d644..07b75389cf4 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 97f6e2b50d7..4aa15879434 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 00000000000..77ef9421273 --- /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 00000000000..9701610cbd9 --- /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 7be49e1acd8..cb5370c8bcb 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 @@ macro_rules! mylet( 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 00000000000..b46910290a8 --- /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 00000000000..cf72d2c6230 --- /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 00000000000..4b0814bef04 --- /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 00000000000..7911fec94da --- /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 631fc866671..3f9d07466cc 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 3ac0d47e61a..f90a0dfa6b3 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 a6e579ddff3..93bb9557604 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 a776999ec8a..e4886ddaa0e 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 482fdf5b1d0..984f675b4dc 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/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index 9151564b340..8b41670734f 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 2660de619e9..9b9a7f68995 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 afc22be38b8..02fc0cf0291 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/phase-use-ignored.rs b/src/test/run-pass/phase-use-ignored.rs deleted file mode 100644 index 5015e43fa3f..00000000000 --- a/src/test/run-pass/phase-use-ignored.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -#![feature(phase)] - -#[phase(plugin)] -use std::mem; - -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 00000000000..5a91f603f96 --- /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 00000000000..d0ac22a5290 --- /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 00000000000..7cac8ac57e5 --- /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 00000000000..8563c8c178f --- /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/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index 2612483ded4..95f90ebbf8e 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/small-enums-with-fields.rs b/src/test/run-pass/small-enums-with-fields.rs index 247fa6453b8..46daa659430 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 bc9a371edf7..235c4e74d08 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 6599e493d25..365960b96e4 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 f4bfe3d8c7c..a0dbc96cdb0 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 7f702bd7ab5..98b7663c58e 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 b5a84843a54..650f76d729a 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 4a8058c9664..6612c93e90b 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 f6708536a9d..f85305cf319 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 fn where_am_i() -> String { } } -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/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index 2598679f921..4ab089b6eaa 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)] #![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 62b61c153c7..7d226aa9420 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/two-macro-use.rs b/src/test/run-pass/two-macro-use.rs new file mode 100644 index 00000000000..51c0b75e8fb --- /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 4dec227d520..673e8523562 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 @@ fn foo(a:T, b:T) -> T { } } ) -); +} test!(x,y,x + y); 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 00000000000..c04afffb120 --- /dev/null +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -0,0 +1,39 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(lang_items)] +#![no_std] + +#[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; + +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } + +// Issue #16806 + +#[start] +fn start(_argc: int, _argv: *const *const u8) -> int { + let x: Vec = vec![0, 1, 2]; + match x.last() { + Some(&2) => (), + _ => panic!(), + } + 0 +} diff --git a/src/test/run-pass/vec-macro-with-brackets.rs b/src/test/run-pass/vec-macro-with-brackets.rs index 2c784dade57..a263501f8fe 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();