for `~str`/`~[]`.
Note that `~self` still remains, since I forgot to add support for
`Box<self>` before the snapshot.
How to update your code:
* Instead of `~EXPR`, you should write `box EXPR`.
* Instead of `~TYPE`, you should write `Box<Type>`.
* Instead of `~PATTERN`, you should write `box PATTERN`.
[breaking-change]
There's now one unified way to return things from a macro, instead of
being able to choose the `AnyMacro` trait or the `MRItem`/`MRExpr`
variants of the `MacResult` enum. This does simplify the logic handling
the expansions, but the biggest value of this is it makes macros in (for
example) type position easier to implement, as there's this single thing
to modify.
By my measurements (using `-Z time-passes` on libstd and librustc etc.),
this appears to have little-to-no impact on expansion speed. There are
presumably larger costs than the small number of extra allocations and
virtual calls this adds (notably, all `macro_rules!`-defined macros have
not changed in behaviour, since they had to use the `AnyMacro` trait
anyway).
When linking, all crates in the local CStore are used to link the final product.
With #[phase(syntax)], crates want to be omitted from this linkage phase, and
this was achieved by dumping the entire CStore after loading crates. This causes
crates like the standard library to get loaded twice. This loading process is a
fairly expensive operation when dealing with decompressing metadata.
This commit alters the loading process to never register syntax crates in
CStore. Instead, only phase(link) crates ever make their way into the map of
crates. The CrateLoader trait was altered to return everything in one method
instead of having separate methods for finding information.
syntax: allow `trace_macros!` and `log_syntax!` in item position.
Previously
trace_macros!(true)
fn main() {}
would complain about `trace_macros` being an expression macro in item
position. This is a pointless limitation, because the macro is purely
compile-time, with no runtime effect. (And similarly for log_syntax.)
This also changes the behaviour of `trace_macros!` very slightly, it
used to be equivalent to
macro_rules! trace_macros {
(true $($_x: tt)*) => { true };
(false $($_x: tt)*) => { false }
}
I.e. you could invoke it with arbitrary trailing arguments, which were
ignored. It is changed to accept only exactly `true` or `false` (with no
trailing arguments) and expands to `()`.
Previously
trace_macros!(true)
fn main() {}
would complain about `trace_macros` being an expression macro in item
position. This is a pointless limitation, because the macro is purely
compile-time, with no runtime effect. (And similarly for log_syntax.)
This also changes the behaviour of `trace_macros!` very slightly, it
used to be equivalent to
macro_rules! trace_macros {
(true $($_x: tt)*) => { true };
(false $($_x: tt)*) => { false }
}
I.e. you could invoke it with arbitrary trailing arguments, which were
ignored. It is changed to accept only exactly `true` or `false` (with no
trailing arguments) and expands to `()`.
This commit removes all internal support for the previously used __log_level()
expression. The logging subsystem was previously modified to not rely on this
magical expression. This also removes the only other function to use the
module_data map in trans, decl_gc_metadata. It appears that this is an ancient
function from a GC only used long ago.
This does not remove the crate map entirely, as libgreen still uses it to hook
in to the event loop provided by libgreen.
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
Where ItemDecorator creates new items given a single item, ItemModifier
alters the tagged item in place. The expansion rules for this are a bit
weird, but I think are the most reasonable option available.
When an item is expanded, all ItemModifier attributes are stripped from
it and the item is folded through all ItemModifiers. At that point, the
process repeats until there are no ItemModifiers in the new item.
If #[feature(default_type_parameters)] is enabled for a crate, then
deriving(Hash) will expand with Hash<W: Writer> instead of Hash<SipState> so
more hash algorithms can be used.
A couple of syntax extensions manually expanded expressions, but it
wasn't done universally, most noticably inside of asm!().
There's also a bit of random cleanup.
These two containers are indeed collections, so their place is in
libcollections, not in libstd. There will always be a hash map as part of the
standard distribution of Rust, but by moving it out of the standard library it
makes libstd that much more portable to more platforms and environments.
This conveniently also removes the stuttering of 'std::hashmap::HashMap',
although 'collections::HashMap' is only one character shorter.
Closes#11692. Instead of returning the original expression, a dummy expression
(with identical span) is returned. This prevents infinite loops of failed
expansions as well as odd double error messages in certain situations.
The old method of building up a list of items and threading it through
all of the decorators was unwieldy and not really scalable as
non-deriving ItemDecorators become possible. The API is now that the
decorator gets an immutable reference to the item it's attached to, and
a callback that it can pass new items to. If we want to add syntax
extensions that can modify the item they're attached to, we can add that
later, but I think it'll have to be separate from ItemDecorator to avoid
strange ordering issues.
@huonw
The old method of building up a list of items and threading it through
all of the decorators was unwieldy and not really scalable as
non-deriving ItemDecorators become possible. The API is now that the
decorator gets an immutable reference to the item it's attached to, and
a callback that it can pass new items to. If we want to add syntax
extensions that can modify the item they're attached to, we can add that
later, but I think it'll have to be separate from ItemDecorator to avoid
strange ordering issues.
The first setp for #9880 is to add a new `crate` keyword. This PR does exactly that. I took a chance to refactor `parse_item_foreign_mod` and I broke it down into 2 separate methods to isolate each feature.
The next step will be to push a new stage0 snapshot and then get rid of all `extern mod` around the code.
Externally loaded libraries are able to do things that cause references
to them to survive past the expansion phase (e.g. creating @-box cycles,
launching a task or storing something in task local data). As such, the
library has to stay loaded for the lifetime of the process.
This patch replaces all `crate` usage with `krate` before introducing the
new keyword. This ensures that after introducing the keyword, there
won't be any compilation errors.
krate might not be the most expressive substitution for crate but it's a
very close abbreviation for it. `module` was already used in several
places already.
fourcc!() allows you to embed FourCC (or OSType) values that are
evaluated as u32 literals. It takes a 4-byte ASCII string and produces
the u32 resulting in interpreting those 4 bytes as a u32, using either
the platform-native endianness, or explicitly as big or little endian.
Now that procedural macros can be implemented outside of the compiler,
it's more important to have a reasonable API to work with. Here are the
basic changes:
* Rename SyntaxExpanderTTTrait to MacroExpander, SyntaxExpanderTT to
BasicMacroExpander, etc. I think "procedural macro" is the right
term for these now, right? The other option would be SynExtExpander
or something like that.
* Stop passing the SyntaxContext to extensions. This was only ever used
by macro_rules, which doesn't even use it anymore. I can't think of
a context in which an external extension would need it, and removal
allows the API to be significantly simpler - no more
SyntaxExpanderTTItemExpanderWithoutContext wrappers to worry about.
The old method of serializing the AST gives totally bogus spans if the
expansion of an imported macro causes compilation errors. The best
solution seems to be to serialize the actual textual macro definition
and load it the same way the std-macros are. I'm not totally confident
that getting the source from the CodeMap will always do the right thing,
but it seems to work in simple cases.
Renamed the invert() function in iter.rs to flip().
Also renamed the Invert<T> type to Flip<T>.
Some related code comments changed. Documentation that I could find has
been updated, and all the instances I could locate where the
function/type were called have been updated as well.
The old method of serializing the AST gives totally bogus spans if the
expansion of an imported macro causes compilation errors. The best
solution seems to be to serialize the actual textual macro definition
and load it the same way the std-macros are. I'm not totally confident
that getting the source from the CodeMap will always do the right thing,
but it seems to work in simple cases.
This means that compilation continues for longer, and so we can see more
errors per compile. This is mildly more user-friendly because it stops
users having to run rustc n times to see n macro errors: just run it
once to see all of them.