This makes the "shadowing labels" warning *not* print the entire loop
as a span, but only the lifetime.
Also makes #31719 go away, but does not fix its root cause (the span
of the expanded loop is still wonky, but not used anymore).
This commit is an implementation of [RFC 1513] which allows applications to
alter the behavior of panics at compile time. A new compiler flag, `-C panic`,
is added and accepts the values `unwind` or `panic`, with the default being
`unwind`. This model affects how code is generated for the local crate, skipping
generation of landing pads with `-C panic=abort`.
[RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md
Panic implementations are then provided by crates tagged with
`#![panic_runtime]` and lazily required by crates with
`#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic
runtime must match the final product, and if the panic strategy is not `abort`
then the entire DAG must have the same panic strategy.
With the `-C panic=abort` strategy, users can expect a stable method to disable
generation of landing pads, improving optimization in niche scenarios,
decreasing compile time, and decreasing output binary size. With the `-C
panic=unwind` strategy users can expect the existing ability to isolate failure
in Rust code from the outside world.
Organizationally, this commit dismantles the `sys_common::unwind` module in
favor of some bits moving part of it to `libpanic_unwind` and the rest into the
`panicking` module in libstd. The custom panic runtime support is pretty similar
to the custom allocator support with the only major difference being how the
panic runtime is injected (takes the `-C panic` flag into account).
The extra filename and line was mainly there to keep the indentation
relative to the main snippet; now that this doesn't include
filename/line-number as a prefix, it is distracted.
Feature gate clean
This PR does a bit of cleaning in the feature-gate-handling code of libsyntax. It also fixes two bugs (#32782 and #32648). Changes include:
* Change the way the existing features are declared in `feature_gate.rs`. The array of features and the `Features` struct are now defined together by a single macro. `featureck.py` has been updated accordingly. Note: there are now three different arrays for active, removed and accepted features instead of a single one with a `Status` item to tell wether a feature is active, removed, or accepted. This is mainly due to the way I implemented my macro in the first time and I can switch back to a single array if needed. But an advantage of the way it is now is that when an active feature is used, the parser only searches through the list of active features. It goes through the other arrays only if the feature is not found. I like to think that error checking (in this case, checking that an used feature is active) does not slow down compilation of valid code. :) But this is not very important...
* Feature-gate checking pass now use the `Features` structure instead of looking through a string vector. This should speed them up a bit. The construction of the `Features` struct should be faster too since it is build directly when parsing features instead of calling `has_feature` dozens of times.
* The MacroVisitor pass has been removed, it was mostly useless since the `#[cfg]-stripping` phase happens before (fixes#32648). The features that must actually be checked before expansion are now checked at the time they are used. This also allows us to check attributes that are generated by macro expansion and not visible to MacroVisitor, but are also removed by macro expansion and thus not visible to PostExpansionVisitor either. This fixes#32782. Note that in order for `#[derive_*]` to be feature-gated but still accepted when generated by `#[derive(Trait)]`, I had to do a little bit of trickery with spans that I'm not totally confident into. Please review that part carefully. (It's in `libsyntax_ext/deriving/mod.rs`.)::
Note: this is a [breaking change], since programs with feature-gated attributes on macro-generated macro invocations were not rejected before. For example:
```rust
macro_rules! bar (
() => ()
);
macro_rules! foo (
() => (
#[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
bar!();
);
);
```
foo!();
Paths are mostly parsed without taking whitespaces into account, e.g. `std :: vec :: Vec :: new ()` parses successfully, however, there are some special cases involving keywords `super`, `self` and `Self`. For example, `self::` is considered a path start only if there are no spaces between `self` and `::`. These restrictions probably made sense when `self` and friends weren't keywords, but now they are unnecessary.
The first two commits remove this special treatment of whitespaces by removing `token::IdentStyle` entirely and therefore fix https://github.com/rust-lang/rust/issues/14109.
This change also affects naked `self` and `super` (which are not tightly followed by `::`, obviously) they can now be parsed as paths, however they are still not resolved correctly in imports (cc @jseyfried, see `compile-fail/use-keyword.rs`), so https://github.com/rust-lang/rust/issues/29036 is not completely fixed.
The third commit also makes `super`, `self`, `Self` and `static` keywords nominally (before this they acted as keywords for all purposes) and removes most of remaining \"special idents\".
The last commit (before tests) contains some small improvements - some qualified paths with type parameters are parsed correctly, `parse_path` is not used for parsing single identifiers, imports are sanity checked for absence of type parameters - such type parameters can be generated by syntax extensions or by macros when https://github.com/rust-lang/rust/issues/10415 is fixed (~~soon!~~already!).
This patch changes some pretty basic things in `libsyntax`, like `token::Token` and the keyword list, so it's a plugin-[breaking-change].
r? @eddyb
syntax: Merge PathParsingMode::NoTypesAllowed and PathParsingMode::ImportPrefix
syntax: Rename PathParsingMode and its variants to better express their purpose
syntax: Remove obsolete error message about 'self lifetime
syntax: Remove ALLOW_MODULE_PATHS workaround
syntax/resolve: Adjust some error messages
resolve: Compare unhygienic (not renamed) names with keywords::Invalid, invalid identifiers may appear to be valid after renaming
This pass was supposed to check use of gated features before
`#[cfg]`-stripping but this was not the case since it in fact happens
after. Checks that are actually important and must be done before macro
expansion are now made where the features are actually used. Close#32648.
Also ensure that attributes on macro-generated macro invocations are
checked as well. Close#32782 and #32655.
Automated conversion using the untry tool [1] and the following command:
```
$ find -name '*.rs' -type f | xargs untry
```
at the root of the Rust repo.
[1]: https://github.com/japaric/untry
See RFC amendment 1384 and tracking issue 30450:
https://github.com/rust-lang/rfcs/pull/1384https://github.com/rust-lang/rust/issues/30450
Moved old check_matcher code into check_matcher_old
combined the two checks to enable a warning cycle (where we will
continue to error if the two checks agree to reject, accept if the new
check says accept, and warn if the old check accepts but the new check
rejects).
The motivation (other than removing boilerplate) is that this is a baby step towards a parser with error recovery.
[breaking-change] if you use any of the changed functions, you'll need to remove a try! or panictry!
This PR reverts #29543 and instead implements proper support for "=*m" and "+*m" indirect output operands. This provides a framework on top of which support for plain memory operands ("m", "=m" and "+m") can be implemented.
This also fixes the liveness analysis pass not handling read/write operands correctly.
This commit is the standard API stabilization commit for the 1.6 release cycle.
The list of issues and APIs below have all been through their cycle-long FCP and
the libs team decisions are listed below
Stabilized APIs
* `Read::read_exact`
* `ErrorKind::UnexpectedEof` (renamed from `UnexpectedEOF`)
* libcore -- this was a bit of a nuanced stabilization, the crate itself is now
marked as `#[stable]` and the methods appearing via traits for primitives like
`char` and `str` are now also marked as stable. Note that the extension traits
themeselves are marked as unstable as they're imported via the prelude. The
`try!` macro was also moved from the standard library into libcore to have the
same interface. Otherwise the functions all have copied stability from the
standard library now.
* The `#![no_std]` attribute
* `fs::DirBuilder`
* `fs::DirBuilder::new`
* `fs::DirBuilder::recursive`
* `fs::DirBuilder::create`
* `os::unix::fs::DirBuilderExt`
* `os::unix::fs::DirBuilderExt::mode`
* `vec::Drain`
* `vec::Vec::drain`
* `string::Drain`
* `string::String::drain`
* `vec_deque::Drain`
* `vec_deque::VecDeque::drain`
* `collections::hash_map::Drain`
* `collections::hash_map::HashMap::drain`
* `collections::hash_set::Drain`
* `collections::hash_set::HashSet::drain`
* `collections::binary_heap::Drain`
* `collections::binary_heap::BinaryHeap::drain`
* `Vec::extend_from_slice` (renamed from `push_all`)
* `Mutex::get_mut`
* `Mutex::into_inner`
* `RwLock::get_mut`
* `RwLock::into_inner`
* `Iterator::min_by_key` (renamed from `min_by`)
* `Iterator::max_by_key` (renamed from `max_by`)
Deprecated APIs
* `ErrorKind::UnexpectedEOF` (renamed to `UnexpectedEof`)
* `OsString::from_bytes`
* `OsStr::to_cstring`
* `OsStr::to_bytes`
* `fs::walk_dir` and `fs::WalkDir`
* `path::Components::peek`
* `slice::bytes::MutableByteVector`
* `slice::bytes::copy_memory`
* `Vec::push_all` (renamed to `extend_from_slice`)
* `Duration::span`
* `IpAddr`
* `SocketAddr::ip`
* `Read::tee`
* `io::Tee`
* `Write::broadcast`
* `io::Broadcast`
* `Iterator::min_by` (renamed to `min_by_key`)
* `Iterator::max_by` (renamed to `max_by_key`)
* `net::lookup_addr`
New APIs (still unstable)
* `<[T]>::sort_by_key` (added to mirror `min_by_key`)
Closes#27585Closes#27704Closes#27707Closes#27710Closes#27711Closes#27727Closes#27740Closes#27744Closes#27799Closes#27801
cc #27801 (doesn't close as `Chars` is still unstable)
Closes#28968
See https://github.com/rust-lang/rfcs/pull/16 and https://github.com/rust-lang/rust/issues/15701
- Added syntax support for attributes on expressions and all syntax nodes in statement position.
- Extended `#[cfg]` folder to allow removal of statements, and
of expressions in optional positions like expression lists and trailing
block expressions.
- Extended lint checker to recognize lint levels on expressions and
locals.
- As per RFC, attributes are not yet accepted on `if` expressions.
Examples:
```rust
let x = y;
{
...
}
assert_eq!((1, #[cfg(unset)] 2, 3), (1, 3));
let FOO = 0;
```
Implementation wise, there are a few rough corners and open questions:
- The parser work ended up a bit ugly.
- The pretty printer change was based mostly on guessing.
- Similar to the `if` case, there are some places in the grammar where a new `Expr` node starts,
but where it seemed weird to accept attributes and hence the parser doesn't. This includes:
- const expressions in patterns
- in the middle of an postfix operator chain (that is, after `.`, before indexing, before calls)
- on range expressions, since `#[attr] x .. y` parses as `(#[attr] x) .. y`, which is inconsistent with
`#[attr] .. y` which would parse as `#[attr] (.. y)`
- Attributes are added as additional `Option<Box<Vec<Attribute>>>` fields in expressions and locals.
- Memory impact has not been measured yet.
- A cfg-away trailing expression in a block does not currently promote the previous `StmtExpr` in a block to a new trailing expr. That is to say, this won't work:
```rust
let x = {
#[cfg(foo)]
Foo { data: x }
#[cfg(not(foo))]
Foo { data: y }
};
```
- One-element tuples can have their inner expression removed to become Unit, but just Parenthesis can't. Eg, `(#[cfg(unset)] x,) == ()` but `(#[cfg(unset)] x) == error`. This seemed reasonable to me since tuples and unit are type constructors, but could probably be argued either way.
- Attributes on macro nodes are currently unconditionally dropped during macro expansion, which seemed fine since macro disappear at that point?
- Attributes on `ast::ExprParens` will be prepend-ed to the inner expression in the hir folder.
- The work on pretty printer tests for this did trigger, but not fix errors regarding macros:
- expression `foo![]` prints as `foo!()`
- expression `foo!{}` prints as `foo!()`
- statement `foo![];` prints as `foo!();`
- statement `foo!{};` prints as `foo!();`
- statement `foo!{}` triggers a `None` unwrap ICE.
Fixes#13677
This does the same sort of suggestion for misspelt macros that we already do for misspelt identifiers.
Example. Compiling this program:
```rust
macro_rules! foo {
($e:expr) => ( $e )
}
fn main() {
fob!("hello!");
}
```
gives the following error message:
```
/Users/mcp/temp/test.rs:7:5: 7:8 error: macro undefined: 'fob!'
/Users/mcp/temp/test.rs:7 fob!("hello!");
^~~
/Users/mcp/temp/test.rs:7:5: 7:8 help: did you mean `foo`?
/Users/mcp/temp/test.rs:7 fob!("hello!");
```
I had to move the levenshtein distance function into libsyntax for this. Maybe this should live somewhere else (some utility crate?), but I couldn't find a crate to put it in that is imported by libsyntax and the other rustc crates.
nodes in statement position.
Extended #[cfg] folder to allow removal of statements, and
of expressions in optional positions like expression lists and trailing
block expressions.
Extended lint checker to recognize lint levels on expressions and
locals.
This is my first code contribution to Rust, so I'm sure there are some issues with the changes I've made.
I've added the `quote_arg!`, `quote_block!`, `quote_path!`, and `quote_meta_item!` quasiquoting macros. From my experience trying to build AST in compiler plugins, I would like to be able to build any AST piece with a quasiquoting macro (e.g., `quote_struct_field!` or `quote_variant!`) and then use those AST pieces in other quasiquoting macros, but this pull request just adds some of the low-hanging fruit.
I'm not sure if these additions are desirable, and I'm sure these macros can be implemented in an external crate if not.
Stricter checking of stability attributes + enforcement of their invariants at compile time
(+ removed dead file librustc_front/attr.rs)
I intended to enforce use of `reason` for unstable items as well (it normally presents for new items), but it turned out too intrusive, many older unstable items don't have `reason`s.
r? @aturon
I'm studying how stability works and do some refactoring along the way, so it's probably not the last PR.
This PR removes random remaining `Ident`s outside of libsyntax and performs general cleanup
In particular, interfaces of `Name` and `Ident` are tidied up, `Name`s and `Ident`s being small `Copy` aggregates are always passed to functions by value, and `Ident`s are never used as keys in maps, because `Ident` comparisons are tricky.
Although this PR closes https://github.com/rust-lang/rust/issues/6993 there's still work related to it:
- `Name` can be made `NonZero` to compress numerous `Option<Name>`s and `Option<Ident>`s but it requires const unsafe functions.
- Implementation of `PartialEq` on `Ident` should be eliminated and replaced with explicit hygienic, non-hygienic or member-wise comparisons.
- Finally, large parts of AST can potentially be converted to `Name`s in the same way as HIR to clearly separate identifiers used in hygienic and non-hygienic contexts.
r? @nrc
Make sure Name, SyntaxContext and Ident are passed by value
Make sure Idents don't serve as keys (or parts of keys) in maps, Ident comparison is not well defined
This is a [breaking-change] for syntax extension authors. The fix is to use MultiModifier or MultiDecorator, which have the same functionality but are more flexible. Users of syntax extensions are unaffected.
This is a [breaking-change] for syntax extension authors. The fix is to use MultiModifier or MultiDecorator, which have the same functionality but are more flexible. Users of syntax extensions are unaffected.
This is theoretically a breaking change, but GitHub search turns up no
uses of it, and most non-built-in cfg's are passed via cargo features,
which look like `feature = "..."`, and hence can't overlap.
This pull request implements the functionality for [RFC 873](https://github.com/rust-lang/rfcs/blob/master/text/0873-type-macros.md). This is currently just an update of @freebroccolo's branch from January, the corresponding commits are linked in each commit message.
@nikomatsakis and I had talked about updating the macro language to support a lifetime fragment specifier, and it is possible to do that work on this branch as well. If so we can (collectively) talk about it next week during the pre-RustCamp work week.
This commit is an implementation of [RFC 1184][rfc] which tweaks the behavior of
the `#![no_std]` attribute and adds a new `#![no_core]` attribute. The
`#![no_std]` attribute now injects `extern crate core` at the top of the crate
as well as the libcore prelude into all modules (in the same manner as the
standard library's prelude). The `#![no_core]` attribute disables both std and
core injection.
[rfc]: https://github.com/rust-lang/rfcs/pull/1184
Fixes#25022
This adapts the deriving mechanism to not repeat bounds for the same type parameter. To give an example: for the following code:
```rust
#[derive(Clone)]
pub struct FlatMap<I, U: IntoIterator, F> {
iter: I,
f: F,
frontiter: Option<U::IntoIter>,
backiter: Option<U::IntoIter>,
}
```
the latest nightly generates the following impl signature:
```rust
impl <I: ::std::clone::Clone,
U: ::std::clone::Clone + IntoIterator,
F: ::std::clone::Clone>
::std::clone::Clone for FlatMap<I, U, F> where
I: ::std::clone::Clone,
F: ::std::clone::Clone,
U::IntoIter: ::std::clone::Clone,
U::IntoIter: ::std::clone::Clone
```
With these changes, the signature changes to this:
```rust
impl <I, U: IntoIterator, F> ::std::clone::Clone for FlatMap<I, U, F> where
I: ::std::clone::Clone,
F: ::std::clone::Clone,
U::IntoIter: ::std::clone::Clone
```
(Nothing in the body of the impl changes)
Note that the second impl is more permissive, as it doesn't have a `Clone` bound on `U` at all. There was a compile-fail test that failed due to this. I don't understand why we would want the old behaviour (and nobody on IRC could tell me either), so please tell me if there is a good reason that I missed.
`LocalSource` indicated wether a let binding originated from for-loop desugaring to enable specialized error messages, but for-loop expansion has changed and this is now achieved through `MatchSource::ForLoopDesugar`.
This introduces a test for #23389 and improves the error behaviour to treat the malformed LHS as an error, not a compiler bug.
The parse phase that precedes the call to `check_lhs_nt_follows` could possibly be enhanced to police the format itself (which the old code suggests was the original intention), but I'm not sure that's any nicer than just parsing the matcher as generic rust code and then policing the specific requirements for being a macro matcher afterwards (as this does).
Fixes#23389
(Over time the stability checking has gotten more finicky; in
particular one must attach the (whole) span of the original `in PLACE
BLOCK` expression to the injected references to unstable paths, as
noted in the comments.)
call `push_compiler_expansion` during the placement-`in` expansion.
Even after expansion, the generated expressions still track depth of
such pushes (i.e. how often you have "pushed" without a corresponding
"pop"), and we add a rule that in a context with a positive
`push_unsafe!` depth, it is effectively an `unsafe` block context.
(This way, we can inject code that uses `unsafe` features, but still
contains within it a sub-expression that should inherit the outer
safety checking setting, outside of the injected code.)
This is a total hack; it not only needs a feature-gate, but probably
should be feature-gated forever (if possible).
ignore-pretty in test/run-pass/pushpop-unsafe-okay.rs
This commit expands the follow set of the `ty` and `path` macro fragments to
include the semicolon token as well. A semicolon is already allowed after these
tokens, so it's currently a little too restrictive to not have a semicolon
allowed. For example:
extern {
fn foo() -> i32; // semicolon after type
}
fn main() {
struct Foo;
Foo; // semicolon after path
}
This commit expands the follow set of the `ty` and `path` macro fragments to
include the semicolon token as well. A semicolon is already allowed after these
tokens, so it's currently a little too restrictive to not have a semicolon
allowed. For example:
extern {
fn foo() -> i32; // semicolon after type
}
fn main() {
struct Foo;
Foo; // semicolon after path
}
The common pattern `iter::repeat(elt).take(n).collect::<Vec<_>>()` is
exactly equivalent to `vec![elt; n]`, do this replacement in the whole
tree.
(Actually, vec![] is smart enough to only call clone n - 1 times, while
the former solution would call clone n times, and this fact is
virtually irrelevant in practice.)
The new code generated for deriving on enums looks something like this:
```rust
let __self0_vi = unsafe {
std::intrinsics::discriminant_value(&self) } as i32;
let __self1_vi = unsafe {
std::intrinsics::discriminant_value(&__arg1) } as i32;
let __self2_vi = unsafe {
std::intrinsics::discriminant_value(&__arg2) } as i32;
///
if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
match (...) {
(Variant1, Variant1, ...) => Body1
(Variant2, Variant2, ...) => Body2,
...
_ => ::core::intrinsics::unreachable()
}
}
else {
... // catch-all remainder can inspect above variant index values.
}
```
This helps massively for C-like enums since they will be compiled as a
single comparison giving observed speedups of up to 8x. For more complex
enums the speedup is more difficult to measure but it should not be
slower to generate code this way regardless.
Needed to support:
```rust
match X {
pattern if Y ...
}
for pattern in Y {}
```
IMO, this shouldn't require an RFC because it can't interfere with any future language changes (because `pattern if` and `pattern in` are already legal in rust) and can't cause any ambiguity.
This is a port of @eddyb's `const-fn` branch. I rebased it, tweaked a few things, and added tests as well as a feature gate. The set of tests is still pretty rudimentary, I'd appreciate suggestions on new tests to write. Also, a double-check that the feature-gate covers all necessary cases.
One question: currently, the feature-gate allows the *use* of const functions from stable code, just not the definition. This seems to fit our usual strategy, and implies that we might (perhaps) allow some constant functions in libstd someday, even before stabilizing const-fn, if we were willing to commit to the existence of const fns but found some details of their impl unsatisfactory.
r? @pnkfelix
- add feature gate
- add basic tests
- adjust parser to eliminate conflict between `const fn` and associated
constants
- allow `const fn` in traits/trait-impls, but forbid later in type check
- correct some merge conflicts
This allows compiling entire crates from memory or preprocessing source files before they are tokenized.
Minor API refactoring included, which is a [breaking-change] for libsyntax users:
* `ParseSess::{next_node_id, reserve_node_ids}` moved to rustc's `Session`
* `new_parse_sess` -> `ParseSess::new`
* `new_parse_sess_special_handler` -> `ParseSess::with_span_handler`
* `mk_span_handler` -> `SpanHandler::new`
* `default_handler` -> `Handler::new`
* `mk_handler` -> `Handler::with_emitter`
* `string_to_filemap(sess source, path)` -> `sess.codemap().new_filemap(path, source)`
There were still some mentions of `~[T]` and `~T`, mostly in comments and debugging statements. I tried to do my best to preserve meaning, but I might have gotten some wrong-- I'm happy to fix anything :)
I've found that there are still huge amounts of occurrences of `task`s in the documentation. This PR tries to eliminate all of them in favor of `thread`.
An automated script was run against the `.rs` and `.md` files,
subsituting every occurrence of `task` with `thread`. In the `.rs`
files, only the texts in the comment blocks were affected.
There are two interesting kinds of breakage illustrated here:
1. `Box<Trait>` in many contexts is treated as `Box<Trait + 'static>`,
due to [RFC 599]. However, in a type like `&'a Box<Trait>`, the
`Box<Trait>` type will be expanded to `Box<Trait + 'a>`, again due
to [RFC 599]. This, combined with the fix to Issue 25199, leads to
a borrowck problem due the combination of this function signature
(in src/libstd/net/parser.rs):
```rust
fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T>>]) -> Option<T>;
```
with this call site (again in src/libstd/net/parser.rs):
```rust
fn read_ip_addr(&mut self) -> Option<IpAddr> {
let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr().map(|v4| IpAddr::V4(v4));
let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr().map(|v6| IpAddr::V6(v6));
self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
}
```
yielding borrowck errors like:
```
parser.rs:265:27: 265:69 error: borrowed value does not live long enough
parser.rs:265 self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
(full log at: https://gist.github.com/pnkfelix/e2e80f1a71580f5d3103 )
The issue here is perhaps subtle: the `parsers` argument is
inferred to be taking a slice of boxed objects with the implicit
lifetime bound attached to the `self` parameter to `read_or`.
Meanwhile, the fix to Issue 25199 (added in a forth-coming commit)
is forcing us to assume that each boxed object may have a
destructor that could refer to state of that lifetime, and
*therefore* that inferred lifetime is required to outlive the boxed
object itself.
In this case, the relevant boxed object here is not going to make
any such references; I believe it is just an artifact of how the
expression was built that it is not assigned type:
`Box<FnMut(&mut Parser) -> Option<T> + 'static>`.
(i.e., mucking with the expression is probably one way to fix this
problem).
But the other way to fix it, adopted here, is to change the
`read_or` method type to force make the (presumably-intended)
`'static` bound explicit on the boxed `FnMut` object.
(Note: this is still just the *first* example of breakage.)
2. In `macro_rules.rs`, the `TTMacroExpander` trait defines a method
with signature:
```rust
fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, ...) -> Box<MacResult+'cx>;
```
taking a `&'cx mut ExtCtxt` as an argument and returning a
`Box<MacResult'cx>`.
The fix to Issue 25199 (added in aforementioned forth-coming
commit) assumes that a value of type `Box<MacResult+'cx>` may, in
its destructor, refer to a reference of lifetime `'cx`; thus the
`'cx` lifetime is forced to outlive the returned value.
Meanwhile, within `expand.rs`, the old code was doing:
```rust
match expander.expand(fld.cx, ...).make_pat() { ... => immutable borrow of fld.cx ... }
```
The problem is that the `'cx` lifetime, inferred for the
`expander.expand` call, has now been extended so that it has to
outlive the temporary R-value returned by `expanded.expand`. But
call is also reborrowing `fld.cx` *mutably*, which means that this
reborrow must end before any immutable borrow of `fld.cx`; but
there is one of those within the match body. (Note that the
temporary R-values for the input expression to `match` all live as
long as the whole `match` expression itself (see Issue #3511 and PR
#11585).
To address this, I moved the construction of the pat value into its
own `let`-statement, so that the `Box<MacResult>` will only live
for as long as the initializing expression for the `let`-statement,
and thus allow the subsequent immutable borrow within the `match`.
[RFC 599]: https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md
This changes the `ToTokens` implementations for expressions, statements,
etc. with almost-trivial ones that produce `Interpolated(*Nt(...))`
pseudo-tokens. In this way, quasiquote now works the same way as macros
do: already-parsed AST fragments are used as-is, not reparsed.
The `ToSource` trait is removed. Quasiquote no longer involves
pretty-printing at all, which removes the need for the
`encode_with_hygiene` hack. All associated machinery is removed.
A new `Nonterminal` is added, NtArm, which the parser now interpolates.
This is just for quasiquote, not macros (although it could be in the
future).
`ToTokens` is no longer implemented for `Arg` (although this could be
added again) and `Generics` (which I don't think makes sense).
This breaks any compiler extensions that relied on the ability of
`ToTokens` to turn AST fragments back into inspectable token trees. For
this reason, this closes#16987.
As such, this is a [breaking-change].
Fixes#16472.
Fixes#15962.
Fixes#17397.
Fixes#16617.
Changes the style guidelines regarding unit tests to recommend using a
sub-module named "tests" instead of "test" for unit tests as "test"
might clash with imports of libtest.
This is a little bit tricky, since with include_str!, we know that we
are including utf-8 content, so it's safe to store the source as a
String in a FileMap. We don't know that for include_bytes!, but I don't
think we actually need to track the contents anyways, so I'm passing "".
new_filemap does check for the zero length content, and it should be
reasonable, howeven I'm not sure if it would be better to pass None
instead of Some(Rc::new("")) as the src component of a FileMap.
Fixes bug #24348
This is a little bit tricky, since with include_str!, we know that we
are including utf-8 content, so it's safe to store the source as a
String in a FileMap. We don't know that for include_bytes!, but I don't
think we actually need to track the contents anyways, so I'm passing "".
new_filemap does check for the zero length content, and it should be
reasonable, howeven I'm not sure if it would be better to pass None
instead of Some(Rc::new("")) as the src component of a FileMap.
Fixes bug #24348
There are syntax extensions that call `std::rt::begin_unwind` passing it a `usize`. I updated the syntax extension to instead pass `u32`, but for bootstrapping reasons, I needed to create a `#[cfg(stage0)]` version of `std::rt::begin_unwind` and therefore also `panic!`.
`format_args!` uses `#[allow_internal_unstable]` to access internal
functions and structs that are marked unstable. For this to work, the
spans on AST nodes referencing unstable internals must be equal (same
lo/hi values) to the `format_args!` call site, so that the stability
checker can recognize that the AST node was generated by the macro.
* In noop_fold_expr, call new_span in these cases:
- ExprMethodCall's identifier
- ExprField's identifier
- ExprTupField's integer
Calling new_span for ExprMethodCall's identifier is necessary to print
an acceptable diagnostic for write!(&2, ""). We see this error:
<std macros>:2:20: 2:66 error: type `&mut _` does not implement any method in scope named `write_fmt`
<std macros>:2 ( & mut * $ dst ) . write_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With this change, we also see a macro expansion backtrace leading to
the write!(&2, "") call site.
* After fully expanding a macro, we replace the expansion expression's
span with the original span. Call fld.new_span to add a backtrace to
this span. (Note that I'm call new_span after bt.pop(), so the macro
just expanded isn't on the backtrace.)
The motivating example for this change is println!("{}"). The format
string literal is concat!($fmt, "arg") and is inside the libstd macro.
We need to see the backtrace to find the println! call site.
* Add a backtrace to the format_args! format expression span.
Addresses #23459
Statement macros are now treated somewhat like item macros, in that a statement macro can now expand into a series of statements, rather than just a single statement.
This allows statement macros to be nested inside other kinds of macros and expand properly, where previously the expansion would only work when no nesting was present.
See:
- `src/test/run-pass/macro-stmt_macro_in_expr_macro.rs`
- `src/test/run-pass/macro-nested_stmt_macro.rs`
This changes the interface of the MacResult trait. make_stmt has become make_stmts and now returns a vector, rather than a single item. Plugin writers who were implementing MacResult will have breakage, as well as anyone using MacEager::stmt.
See:
- `src/libsyntax/ext/base.rs`
This also causes a minor difference in behavior to the diagnostics produced by certain malformed macros.
See:
- `src/test/compile-fail/macro-incomplete-parse.rs`