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;
% The Rust Macros Guide
-<div class="unstable-feature">
-<b>Warning:</b> 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
-<code>macro_rules</code> <a href="reference.html#compiler-features">feature
-attribute</a>.
-</div>
-
# Introduction
Functions are the primary tool that programmers can use to build abstractions.
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);
// ...
## 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,
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 {
$(
_ => {}
}
)
-);
+}
// ...
early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
// ...
Now consider code like the following:
~~~~
-# #![feature(macro_rules)]
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
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
_ => { $err }
};
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
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
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
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 ; )*
);
// 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
binds $( $bind_res ),*
);
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
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 {
$e
}
);
-);
+}
fn main() {
'x: loop {
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
// 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
}
# 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
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
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);
Then code like
```ignore
-#[phase(plugin)]
-extern crate lint_plugin_test;
+#[plugin] extern crate lint_plugin_test;
fn lintme() { }
```
| 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
| 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 `$`.)
### 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
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.
* `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
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
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
// 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;
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 {
ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
}
)
- );
+ }
matches!(
token::Literal(token::Byte(..), _),
#![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
#![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;
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;
// 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.
($($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),*])
+}
#[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<int> = vec![];
test_show_vec!(empty, "[]");
test_show_vec!(vec![1i], "[1]");
#[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<int>);
#[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],
&[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
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_]);
subseqidx = i;
res.as_mut_vec().push_all(REPLACEMENT);
}
- }));
+ })}
if byte < 128u8 {
// subseqidx handles this
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;
#![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;
#[doc(hidden)]
mod core {
pub use panicking;
+ pub use fmt;
}
#[doc(hidden)]
// 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 {
});
}
-/// 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) => (
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<int>) {
+/// 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"))
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
#![doc(hidden)]
macro_rules! assert_approx_eq {
// 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) => (
// 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) => (
//!
//! ```
//! # #![feature(macro_rules)]
-//! macro_rules! try(
+//! macro_rules! try {
//! ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
-//! );
+//! }
//! # fn main() { }
//! ```
//!
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,
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![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;
// 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::*;
}
}
-));
+)}
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;
// 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::*;
assert!(5u.checked_div(0) == None);
}
}
-));
+
+)}
#![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;
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::*;
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::*;
//! # Examples
//!
//! ```
-//! #![feature(phase)]
-//! #[phase(plugin, link)] extern crate log;
+//! #[macro_use] extern crate log;
//!
//! fn main() {
//! debug!("this is a debug {}", "message");
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
//! Logging macros
-#![macro_escape]
-
/// The standard logging macro
///
/// This macro will generically log over a provided level (of type u32) with a
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// log!(log::WARN, "this is a warning {}", "message");
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let error = 3u;
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let code = 3u;
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let ret = 3;
/// # 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);
/// # 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 } }
// 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());
assert_eq!(wc.ind_sample(&mut rng), val)
}
}}
- );
+ }
t!(vec!(Weighted { weight: 1, item: 10i}), [10]);
#[test]
fn test_integers() {
let mut rng = ::test::rng();
- macro_rules! t (
+ macro_rules! t {
($($ty:ty),*) => {{
$(
let v: &[($ty, $ty)] = &[(0, 10),
}
)*
}}
- );
+ }
t!(i8, i16, i32, i64, int,
u8, u16, u32, u64, uint)
}
#[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),
}
)*
}}
- );
+ }
t!(f32, f64)
}
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;
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];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
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);
/// 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;
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];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
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);
#![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::*;
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::*;
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)]
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
}
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,
//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
//! in `context.rs`.
-#![macro_escape]
-
pub use self::Level::*;
pub use self::LintSource::*;
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;
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;
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;
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);
}
}
}
}
-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 {
should_link: bool,
}
-fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
- 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<Span>) {
let err = |&: s: &str| {
match (sp, sess) {
}
}
-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::<Vec<&ast::Attribute>>();
- 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::<Vec<&ast::Attribute>>();
- 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<Span>,
name: String,
sess.cstore.add_used_library(name, kind);
}
-fn existing_match(e: &Env, name: &str,
- hash: Option<&Svh>) -> Option<ast::CrateNum> {
- 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<Path>,
+ 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<cstore::crate_metadata>),
+ 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<CratePaths>,
- ident: &str,
- name: &str,
- span: Span,
- lib: loader::Library)
- -> (ast::CrateNum, Rc<cstore::crate_metadata>,
- 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<CratePaths>,
- ident: &str,
- name: &str,
- hash: Option<&Svh>,
- span: Span,
- kind: PathKind)
- -> (ast::CrateNum, Rc<cstore::crate_metadata>,
- 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<CrateInfo> {
+ 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::<Vec<&ast::Attribute>>();
+ 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::<Vec<&ast::Attribute>>();
+ 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<ast::CrateNum> {
+ 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<CratePaths>,
- 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::crate_metadata>,
+ 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<CratePaths>,
+ ident: &str,
+ name: &str,
+ hash: Option<&Svh>,
+ span: Span,
+ kind: PathKind)
+ -> (ast::CrateNum, Rc<cstore::crate_metadata>,
+ 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<CratePaths>,
+ 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!(),
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<ast::MacroDef> {
+ 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
}
}
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
}
-pub fn get_exported_macros(data: &[u8]) -> Vec<String> {
- let macros = reader::get_doc(rbml::Doc::new(data),
- tag_exported_macros);
- let mut result = Vec::new();
+pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
+ F: FnMut(ast::Name, Vec<ast::Attribute>, 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)
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;
}
}
-/// 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();
}
// 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.
"target type not found for const cast")
});
- macro_rules! define_casts(
+ macro_rules! define_casts {
($val:ident, {
$($ty_pat:pat => (
$intermediate_ty:ty,
},)*
_ => Err("can't cast this type".to_string())
})
- );
+ }
eval_const_expr_partial(tcx, &**base)
.and_then(|val| define_casts!(val, {
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 {
// 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<String>,
- /// Path to the shared library file.
- pub lib: Option<Path>,
- /// Symbol name of the plugin registrar function.
- pub registrar_symbol: Option<String>,
-}
-
/// Pointer to a registrar function.
pub type PluginRegistrarFun =
fn(&mut Registry);
+pub struct PluginRegistrar {
+ pub fun: PluginRegistrarFun,
+ pub args: P<ast::MetaItem>,
+}
+
/// Information about loaded plugins.
pub struct Plugins {
- /// Source code of exported macros.
- pub macros: Vec<ExportedMacros>,
+ /// Imported macros.
+ pub macros: Vec<ast::MacroDef>,
/// Registrars, as function pointers.
- pub registrars: Vec<PluginRegistrarFun>,
+ pub registrars: Vec<PluginRegistrar>,
}
struct PluginLoader<'a> {
sess: &'a Session,
- reader: PluginMetadataReader<'a>,
+ span_whitelist: HashSet<Span>,
+ reader: CrateReader<'a>,
plugins: Plugins,
}
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!(),
pub fn load_plugins(sess: &Session, krate: &ast::Crate,
addl_plugins: Option<Plugins>) -> 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;
// 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.
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();
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
}
}
}
//! 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.
//! 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;
/// 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<P<ast::MetaItem>>,
+
#[doc(hidden)]
pub krate_span: Span,
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
}
-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!(),
}
}
+ /// 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<ast::MetaItem> {
+ 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.
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;
+ }
}));
}
#![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;
// 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) => (
{
$H += sum0($A) + maj($A, $B, $C);
}
)
- );
+ }
read_u32v_be(w.slice_mut(0, 16), data);
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.
// 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 {
// 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);
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()
)
);
} );
- );
+ }
key!(cpu);
key!(linker);
}
// 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("-", "_");
}
}
)
- );
+ }
load_specific!(
x86_64_unknown_linux_gnu,
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;
#![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.
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;
// 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.
= 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);
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);
}
});
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));
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;
// 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)
}
}
#![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;
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;
}
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
- macro_rules! ifn (
+ macro_rules! ifn {
($name:expr fn() -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(
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);
// 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!
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);
// 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) => (
{
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;
#![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;
}
}
+ // Special macro vars are like keywords
+ token::SpecialVarNt(_) => "kw-2",
+
token::Lifetime(..) => "lifetime",
token::DocComment(..) => "doccomment",
token::Underscore | token::Eof | token::Interpolated(..) |
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
// 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;
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;
}
}
// 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),
}
}
}
#[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;
// except according to those terms.
#![experimental]
-#![macro_escape]
//! A typesafe bitmask flag generator.
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};
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
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
//! Various utility functions useful for writing I/O tests
-#![macro_escape]
-
use prelude::v1::*;
use libc;
#![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
/* 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;
/* 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;
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;
//! library.
#![experimental]
-#![macro_escape]
/// The entry point for panic of Rust tasks.
///
($($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]
#[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
(
$($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 {
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! 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<Any>` 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<int>) {
+/// 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 */ }) }
+}
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
macro_rules! assert_approx_eq {
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
macro_rules! int_module { ($T:ty) => (
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
#![allow(unsigned_negation)]
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);
assert!(mo.as_slice() == $exp);
}
)
- );
+ }
t!("foo", "foo");
t!(b"foo\x80", "foo\u{FFFD}");
#[test]
fn test_display() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr, $expf:expr) => (
{
let path = Path::new($path);
assert!(f == $expf);
}
)
- );
+ }
t!(b"foo", "foo", "foo");
t!(b"foo/bar", "foo/bar", "bar");
#[test]
fn test_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $exp:expr) => (
{
let path = Path::new($path);
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"));
#[test]
fn test_push() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr) => (
{
let path = $path;
assert!(p1 == p2.join(join));
}
)
- );
+ }
t!(s: "a/b/c", "..");
t!(s: "/a/b/c", "d");
#[test]
fn test_push_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
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");
#[test]
fn test_push_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
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");
#[test]
fn test_pop() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $left:expr, $right:expr) => (
{
let mut p = Path::new($path);
assert!(result == $right);
}
)
- );
+ }
t!(b: b"a/b/c", b"a/b", true);
t!(b: b"a", b".", true);
#[test]
fn test_join_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert!(res.as_str() == Some($exp));
}
)
- );
+ }
t!(s: "a/b/c", "..", "a/b");
t!(s: "/a/b/c", "d", "/a/b/c/d");
#[test]
fn test_join_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
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");
#[test]
fn test_setters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
{
let path = $path;
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");
#[test]
fn test_getters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
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);
#[test]
fn test_is_absolute() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $abs:expr, $rel:expr) => (
{
let path = Path::new($path);
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);
#[test]
fn test_is_ancestor_of() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $dest:expr, $exp:expr) => (
{
let path = Path::new($path);
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);
#[test]
fn test_ends_with_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(path.ends_with_path(&child), $exp);
}
)
- );
+ }
t!(s: "a/b/c", "c", true);
t!(s: "a/b/c", "d", false);
#[test]
fn test_path_relative_from() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $other:expr, $exp:expr) => (
{
let path = Path::new($path);
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"));
#[test]
fn test_components_iter() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
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"]);
#[test]
fn test_str_components() {
- macro_rules! t(
+ macro_rules! t {
(b: $arg:expr, $exp:expr) => (
{
let path = Path::new($arg);
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]);
#[test]
fn test_parse_prefix() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr) => (
{
let path = $path;
"parse_prefix(\"{}\"): expected {}, found {}", path, exp, res);
}
)
- );
+ }
t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5)));
t!("\\\\", None);
#[test]
fn test_display() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr, $expf:expr) => (
{
let path = Path::new($path);
assert_eq!(f, $expf);
}
)
- );
+ }
t!("foo", "foo", "foo");
t!("foo\\bar", "foo\\bar", "bar");
#[test]
fn test_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $exp:expr) => (
{
let path = $path;
assert!(path.$op() == $exp);
}
)
- );
+ }
t!(v: b"a\\b\\c", filename, Some(b"c"));
t!(s: "a\\b\\c", filename_str, "c");
#[test]
fn test_push() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr) => (
{
let path = $path;
assert!(p1 == p2.join(join));
}
)
- );
+ }
t!(s: "a\\b\\c", "..");
t!(s: "\\a\\b\\c", "d");
#[test]
fn test_push_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
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");
#[test]
fn test_push_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
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");
#[test]
fn test_pop() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $left:expr, $right:expr) => (
{
let pstr = $path;
assert!(result == $right);
}
)
- );
+ }
t!(s: "a\\b\\c", "a\\b", true);
t!(s: "a", ".", true);
#[test]
fn test_join_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(res.as_str(), Some($exp));
}
)
- );
+ }
t!(s: "a\\b\\c", "..", "a\\b");
t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
#[test]
fn test_join_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
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");
#[test]
fn test_with_helpers() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $arg:expr, $res:expr) => (
{
let pstr = $path;
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");
#[test]
fn test_setters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
{
let path = $path;
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");
#[test]
fn test_getters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
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);
#[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);
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);
#[test]
fn test_is_ancestor_of() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $dest:expr, $exp:expr) => (
{
let path = Path::new($path);
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);
#[test]
fn test_ends_with_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(path.ends_with_path(&child), $exp);
}
);
- );
+ }
t!(s: "a\\b\\c", "c", true);
t!(s: "a\\b\\c", "d", false);
#[test]
fn test_path_relative_from() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $other:expr, $exp:expr) => (
{
let path = Path::new($path);
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"));
#[test]
fn test_str_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(comps, exp);
}
);
- );
+ }
t!(s: b"a\\b\\c", ["a", "b", "c"]);
t!(s: "a\\b\\c", ["a", "b", "c"]);
#[test]
fn test_components_iter() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(comps, exp);
}
)
- );
+ }
t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
t!(s: ".", [b"."]);
#[test]
fn test_make_non_verbatim() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr) => (
{
let path = Path::new($path);
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"));
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",
//! 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)*))
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
//! 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?
//! });
//! ```
-#![macro_escape]
#![unstable = "scoped TLS has yet to have wide enough use to fully consider \
stabilizing its interface"]
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;
pub attrs: Vec<Attribute>,
pub config: CrateConfig,
pub span: Span,
- pub exported_macros: Vec<P<Item>>
+ pub exported_macros: Vec<MacroDef>,
}
pub type MetaItem = Spanned<MetaItem_>;
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
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),
IIForeign(P<ForeignItem>),
}
+/// 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<Attribute>,
+ pub id: NodeId,
+ pub span: Span,
+ pub imported_from: Option<Ident>,
+ pub export: bool,
+ pub use_locally: bool,
+ pub body: Vec<TokenTree>,
+}
+
#[cfg(test)]
mod test {
use serialize::json;
// 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 });
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;
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,
/// 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<MacroDef> {
- None
- }
/// Create an expression.
fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
None
///
IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
- /// 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<IdentMacroExpander + 'static>, Option<Span>),
+ /// Represents `macro_rules!` itself.
+ MacroRulesTT,
}
pub type NamedSyntaxExtension = (Name, 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));
pub mod_path: Vec<ast::Ident> ,
pub trace_mac: bool,
- pub exported_macros: Vec<P<ast::Item>>,
+ pub exported_macros: Vec<ast::MacroDef>,
pub syntax_env: SyntaxEnv,
pub recursion_count: uint,
}
}
}
+
+ 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:
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));
})
}
} }
- );
+ }
let trait_def = TraitDef {
span: span,
push: F) where
F: FnOnce(P<Item>),
{
- 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));
})
}
} }
- );
+ }
let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"]));
let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"],
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),
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use self::Either::*;
use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
use ast::{Local, Ident, MacInvocTT};
use visit;
use visit::Visitor;
-enum Either<L,R> {
- Left(L),
- Right(R)
-}
-
pub fn expand_type(t: P<ast::Ty>,
fld: &mut MacroExpander,
impl_ty: Option<P<ast::Ty>>)
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();
}
}
-// 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<ast::Item>, fld: &mut MacroExpander)
- -> SmallVector<P<ast::Item>> {
+pub fn expand_item_mac(it: P<ast::Item>,
+ fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
let (extname, path_span, tts) = match it.node {
ItemMac(codemap::Spanned {
node: MacInvocTT(ref pth, ref tts, _),
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: '{}!'",
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 {
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,
}
};
- 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())[]);
}
/// 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<P<Stmt>> {
let (mac, style) = match s.node {
StmtMac(mac, style) => (mac, style),
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)
}
}
_ => 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)
}
}
}
}
-pub struct ExportedMacros {
- pub crate_name: Ident,
- pub macros: Vec<String>,
-}
-
pub fn expand_crate(parse_sess: &parse::ParseSess,
cfg: ExpansionConfig,
// these are the macros being imported to this crate:
- imported_macros: Vec<ExportedMacros>,
+ imported_macros: Vec<ast::MacroDef>,
user_exts: Vec<NamedSyntaxExtension>,
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() {
}
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");
}
#[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};
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(
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 {
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};
/// 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();
struct MacroRulesMacroExpander {
name: Ident,
+ imported_from: Option<Ident>,
lhses: Vec<Rc<NamedMatch>>,
rhses: Vec<Rc<NamedMatch>>,
}
generic_extension(cx,
sp,
self.name,
+ self.imported_from,
arg,
self.lhses[],
self.rhses[])
}
}
-struct MacroRulesDefiner {
- def: Option<MacroDef>
-}
-impl MacResult for MacroRulesDefiner {
- fn make_def(&mut self) -> Option<MacroDef> {
- 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<Ident>,
arg: &[ast::TokenTree],
lhses: &[Rc<NamedMatch>],
rhses: &[Rc<NamedMatch>])
};
// `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())
// 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.
//
// 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<ast::TokenTree> )
- -> Box<MacResult+'cx> {
+/// 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");
// 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,
// 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<MacResult+'cx>
+ NormalTT(exp, Some(def.span))
}
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;
stack: Vec<TtFrame>,
/* for MBE-style macro transcription */
interpolations: HashMap<Ident, Rc<NamedMatch>>,
+ imported_from: Option<Ident>,
+
+ // Some => return imported_from as the next token
+ crate_name_next: Option<Span>,
repeat_idx: Vec<uint>,
repeat_len: Vec<uint>,
/* cached: */
/// should) be none.
pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+ imported_from: Option<Ident>,
src: Vec<ast::TokenTree> )
-> TtReader<'a> {
let mut r = TtReader {
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,
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);
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;
// 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),
("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),
}
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");
}
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");
}
}
}
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 {
}
}
-pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate,
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, mut exported_macros, span}: Crate,
folder: &mut T) -> Crate {
let config = folder.fold_meta_items(config);
}, Vec::new(), span)
};
+ for def in exported_macros.iter_mut() {
+ def.id = folder.new_id(def.id);
+ }
+
Crate {
module: module,
attrs: attrs,
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)
}
}
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 {
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;
// 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,
pub fn tts_to_parser<'a>(sess: &'a ParseSess,
tts: Vec<ast::TokenTree>,
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)
}
// 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,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
pub use self::PathParsingMode::*;
use self::ItemOrViewItem::*;
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;
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 };
&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,
}));
_ => {
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,
fn parse_view_path(&mut self) -> P<ViewPath> {
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(
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),
// 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
}
}
+ 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)]
(56, Abstract, "abstract");
(57, Final, "final");
(58, Override, "override");
+ (59, Macro, "macro");
}
}
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),
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
});
// 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
}
}
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)
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);
visitor.visit_pat(&**postpattern)
}
}
- PatMac(ref macro) => visitor.visit_mac(macro),
+ PatMac(ref mac) => visitor.visit_mac(mac),
}
}
StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
visitor.visit_expr(&**expression)
}
- StmtMac(ref macro, _) => visitor.visit_mac(&**macro),
+ StmtMac(ref mac, _) => visitor.visit_mac(&**mac),
}
}
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)
}
#![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)]
/// Parse a compiled terminfo entry, using long capability names if `longnames` is true
pub fn parse(file: &mut io::Reader, longnames: bool)
-> Result<Box<TermInfo>, 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;
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)]
// 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;
// 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;
// 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;
#![crate_name="lint_stability"]
#![crate_type = "lib"]
-#![feature(macro_rules)]
-#![macro_escape]
-
#[deprecated]
pub fn deprecated() {}
#[deprecated="text"]
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()));
-);
+}
// 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<T>() {
fn death() -> int { panic!() }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
// 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)
-);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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);
+}
// force-host
-#![feature(plugin_registrar, macro_rules, quote)]
+#![feature(plugin_registrar, quote)]
extern crate syntax;
extern crate rustc;
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) {
// 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)
- );
+ }
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+#[macro_export]
+macro_rules! reexported {
+ () => ( 3u )
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[macro_use] #[no_link]
+extern crate macro_reexport_1;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[no_link]
+extern crate macro_reexport_1;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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<ast::MetaItem>,
+}
+
+impl TTMacroExpander for Expander {
+ fn expand<'cx>(&self,
+ ecx: &'cx mut ExtCtxt,
+ sp: Span,
+ _: &[ast::TokenTree]) -> Box<MacResult+'cx> {
+
+ 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));
+}
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+
+#[macro_export]
+macro_rules! macro_one { () => ("one") }
+
+#[macro_export]
+macro_rules! macro_two { () => ("two") }
// 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;
// ignore-lexer-test FIXME #15679
// Microbenchmarks for various functions in std and extra
-#![feature(macro_rules)]
#![feature(unboxed_closures)]
use std::io::File;
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);
// 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)]
// ignore-stage1
// ignore-cross-compile #12102
-#![feature(macro_rules, phase, slicing_syntax)]
+#![feature(plugin, slicing_syntax)]
extern crate regex;
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// 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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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() {}
// 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'
// 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'
// 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'
// 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'
// 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'
// 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() {
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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`
+}
// 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() {}
// ignore-stage1
// ignore-android
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate macro_crate_test;
fn main() {
// 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// 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`
-}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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() { }
// 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
// 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;
// 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[phase(blah)]
+//~^ ERROR #[phase] is deprecated
+extern crate foo;
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use()]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
// 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
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-macro_rules! foo(() => ());
-//~^ ERROR: macro definitions are not stable enough for use
-
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
() => { break 'x; }
}
// 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 } }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
() => { break 'x; }
}
// 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 } }
}
// 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) => {{
// 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!()
// error-pattern:
-#![feature(macro_rules)]
-
macro_rules! foo{
() => {{
macro_rules! bar{() => (())}
// ignore-test
-#![feature(macro_rules)]
-
-macro_rules! f(() => (n))
+macro_rules! f { () => (n) }
fn main() -> (){
for n in range(0i, 1) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! prob1 {
(0) => {
0
// 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);
// 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;
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![deny(unsafe_blocks)]
-#![feature(macro_rules)]
-
unsafe fn allowed() {}
#[allow(unsafe_blocks)] fn also_allowed() { unsafe {} }
//
// 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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() {
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! ignored_item {
() => {
fn foo() {}
// 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)],
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn macro() { //~ ERROR `macro` is a reserved keyword
+}
+
+pub fn main() {
+}
// 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!()
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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
+}
// 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)],
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_reexport] //~ ERROR bad macro reexport
+extern crate std;
+
+fn main() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_reexport="foo"] //~ ERROR bad macro reexport
+extern crate std;
+
+fn main() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport
+extern crate std;
+
+fn main() { }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use(foo(bar))] //~ ERROR bad macro import
+extern crate std;
+
+fn main() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use(foo="bar")] //~ ERROR bad macro import
+extern crate std;
+
+fn main() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_one)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
// 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use(foo, bar)] //~ ERROR arguments to macro_use are not allowed here
+mod foo {
+}
+
+fn main() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[plugin]
+#[plugin] //~ ERROR #[plugin] specified multiple times
+extern crate std;
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[no_link]
+extern crate libc;
+
+fn main() {
+ unsafe {
+ libc::abs(0); //~ ERROR Use of undeclared type or module `libc`
+ //~^ ERROR unresolved name `libc::abs`
+ }
+}
// 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;
// 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"]
// 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
// 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
// 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
// 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
// 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
// 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
// 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`
// 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) => {{
// lldb-command:continue
-#![feature(macro_rules)]
#![omit_gdb_pretty_printer_section]
macro_rules! trivial {
-#![feature(phase)]
#![no_std]
#![feature(globs)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate "std" as std;
#[prelude_import]
use std::prelude::v1::*;
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
fn main() {
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
use std::thread::Thread;
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
fn main() {
// 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() {
// 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() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
// minimal junk
#![no_std]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
// minimal junk
#![no_std]
// 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!();
// 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'
// ignore-stage1
// compile-flags: -A test-lint
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { }
// 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'
// 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() {
// 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() {}
// 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]
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// 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();
-}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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();
+}
// aux-build:roman_numerals.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate roman_numerals;
pub fn main() {
// 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() {
// Check that we do not ICE when compiling this
// macro, which reuses the expression `$id`
-#![feature(macro_rules)]
-
struct Foo {
a: int
impl Foo {
fn elaborate_stm(&mut self, s: Box<Bar>) -> Box<Bar> {
- 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!()
// 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};
// 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 }
}
#[cfg(not(foo))]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { false }
// 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 }
}
#[cfg(not(foo))]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { false }
// 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;
// statement or end of block, as appropriate given the temporary
// lifetime rules.
-#![feature(macro_rules)]
-
use std::ops::Drop;
static mut FLAGS: u64 = 0;
}
}
-macro_rules! end_of_block(
+macro_rules! end_of_block {
($pat:pat, $expr:expr) => (
{
println!("end_of_block({})", stringify!({let $pat = $expr;}));
check_flags(1);
}
)
-);
+}
-macro_rules! end_of_stmt(
+macro_rules! end_of_stmt {
($pat:pat, $expr:expr) => (
{
println!("end_of_stmt({})", stringify!($expr));
check_flags(0);
}
)
-);
+}
pub fn main() {
// no-pretty-expanded
#![allow(unused_must_use, dead_code, deprecated)]
-#![feature(macro_rules)]
-
use std::io::MemWriter;
use std::fmt;
// 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() {
// 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;
// General test that function items in static blocks
// can be generated with a macro.
-#![feature(macro_rules)]
-
struct MyType {
desc: &'static str,
data: uint,
// 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;
// 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;
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();
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ use ::std::mem;
+ mem::drop(2u);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty
+
+mod foo {
+ #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+ //~^ HELP consider an outer attribute
+}
+
+fn main() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty
+
+#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+mod foo {
+}
+
+fn main() {
+}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(phase)]
-
-//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin)
-#[phase(syntax, link)]
-extern crate log;
-
-fn main() {
- debug!("foo");
-}
// 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!();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
#[derive(Show)]
struct Unit;
// 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 {
// 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
// A test of the macro system. Can we do HTML literals?
-#![feature(macro_rules)]
-
/*
*/
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),*))*];
);
( []; [:$e:expr]; ) => ( $e );
-);
+}
pub fn main() {
let _page = html! (
// 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
// 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
// no-pretty-expanded unnecessary unsafe block generated
// ignore-lexer-test FIXME #15679
-#![feature(macro_rules)]
#![deny(warnings)]
#![allow(unused_must_use)]
}
}
-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
// 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" {
// 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() {}
// 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>;
// 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);
// 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;
// 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!("::[");
// FIXME: #9970
print!("{}", "]\n");
})
-);
+}
pub fn main() {
print_hd_tl!(x, y, z, w)
// 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<T> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
struct Element;
macro_rules! foo {
// 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 }
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
&mut $field as &mut FooBar
}
}
-));
+)}
generate_test!(Foo, self, self.bar);
// 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");
// 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)
B(uint)
}
-macro_rules! test(
+macro_rules! test {
($id:ident, $e:expr) => (
fn foo(t: T) -> int {
match t {
}
}
)
-);
+}
test!(y, 10 + (y as int));
// 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!();
// ignore-pretty
-#![feature(macro_rules)]
-
pub trait bomb { fn boom(&self, Ident); }
pub struct S;
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!();
// 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;
// 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);
// 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)
// 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() {
// exec-env:RUST_LOG=logging-enabled=info
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
pub fn main() {
// ignore-windows
// exec-env:RUST_LOG=debug
-#![feature(phase)]
-
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
use std::io::Command;
// 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);
}
// 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
// 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
// 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}
}
// aux-build:macro_crate_def_only.rs
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate macro_crate_def_only;
pub fn main() {
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo2 {
() => {
"foo"
//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() {
// 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
}
})
-);
+}
pub fn main() {
assert!(overly_complicated!(f, x, Option<uint>, { return Some(x); },
// 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!()];
// ignore-pretty - token trees can't pretty print
// compile-flags: --cfg foo
-#![feature(macro_rules)]
-
macro_rules! compiles_fine {
($at:meta) => {
#[cfg($at)]
// 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})}
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
-macro_rules! make_foo(
+macro_rules! make_foo {
() => (
struct Foo;
fn bar(&self) {}
}
)
-);
+}
make_foo!();
// 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!( () );
// 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)));
// 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<char>) -> uint {
match c {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
mod m {
pub type t = int;
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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);
+}
// 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);
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);
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use]
+#[macro_use()]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_one, macro_two)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_two)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!();
+}
// 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);
// 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);
// 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)*) => {
// 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);
// 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 {
// 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!();
// 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,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::mem;
enum E<T> { Thing(int, T), Nothing((), ((), ()), [i8; 0]) }
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-#![feature(phase)]
-
-#[phase(plugin)]
-use std::mem;
-
-fn main() {}
-
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin]");
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin()]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin()]");
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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\"))]");
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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\"]");
+}
// 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};
// 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)]
// aux-build:svh-b.rs
// aux-build:svh-a-comment.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-doc.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-macro.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-no-change.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-redundant-cfg.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-whitespace.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// 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 {
}
}
-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.\
// 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
})
// one test task to ensure that errors are timeouts, not file descriptor
// exhaustion.
-#![feature(macro_rules)]
#![allow(experimental)]
#![reexport_test_harness_main = "test_main"]
// ignore-android needs extra network permissions
// exec-env:RUST_LOG=debug
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate libc;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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!();
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
enum T {
A(int),
B(f64)
// 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) {
}
}
)
-);
+}
test!(x,y,x + y);
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![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<u8> = vec![0, 1, 2];
+ match x.last() {
+ Some(&2) => (),
+ _ => panic!(),
+ }
+ 0
+}
// 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();