```rust
macro_rules! m { () => { let x = 1; x } }
macro_rules! n { () => {
m!() //< This can now expand into statements
}}
fn main() { n!(); }
```
and revert needless fallout fixes.
Fix expansion performance regression
**syntax-[breaking-change] cc #31645**
This fixes#34630 by reverting commit 5bf7970 of PR #33943, which landed in #34424.
By removing the `Rc<_>` wrapping around `Delimited` and `SequenceRepetition` in `TokenTree`, 5bf7970 made cloning `TokenTree`s more expensive. While this had no measurable performance impact on the compiler's crates, it caused an order of magnitude performance regression on some macro-heavy code in the wild. I believe this is due to clones of `TokenTree`s in `macro_parser.rs` and/or `macro_rules.rs`.
r? @nrc
Support `cfg_attr` on `path` attributes
Fixes#25544.
This is technically a [breaking-change]. For example, the following would break:
```rust
mod foo; // Suppose `foo.rs` existed in the appropriate location
```
Identify when documetation comments have been missplaced in the
following places:
* After a struct element:
```rust
// file.rs:
struct X {
a: u8 /** document a */,
}
```
```bash
$ rustc file.rs
file.rs:2:11: 2:28 error: found documentation comment that doesn't
document anything
file.rs:2 a: u8 /** document a */,
^~~~~~~~~~~~~~~~~
file.rs:2:11: 2:28 help: doc comments must come before what they document,
maybe a comment was intended with `//`?
```
* As the last line of a struct:
```rust
// file.rs:
struct X {
a: u8,
/// incorrect documentation
}
```
```bash
$ rustc file.rs
file.rs:3:5: 3:27 error: found a documentation comment that doesn't
document anything
file.rs:3 /// incorrect documentation
^~~~~~~~~~~~~~~~~~~~~~
file.rs:3:5: 3:27 help: doc comments must come before what they document,
maybe a comment was intended with `//`?
```
* As the last line of a `fn`:
```rust
// file.rs:
fn main() {
let x = 1;
/// incorrect documentation
}
```
```bash
$ rustc file.rs
file.rs:3:5: 3:27 error: found a documentation comment that doesn't
document anything
file.rs:3 /// incorrect documentation
^~~~~~~~~~~~~~~~~~~~~~
file.rs:3:5: 3:27 help: doc comments must come before what they document,
maybe a comment was intended with `//`?
```
Fix#27429, #30322
This is a spiritual succesor to #34268/8531d581, in which we replaced a
number of matches of None to the unit value with `if let` conditionals
where it was judged that this made for clearer/simpler code (as would be
recommended by Manishearth/rust-clippy's `single_match` lint). The same
rationale applies to matches of None to the empty block.
To allow these braced macro invocation, this PR removes the optional expression from `ast::Block` and instead uses a `StmtKind::Expr` at the end of the statement list.
Currently, braced macro invocations in blocks can expand into statements (and items) except when they are last in a block, in which case they can only expand into expressions.
For example,
```rust
macro_rules! make_stmt {
() => { let x = 0; }
}
fn f() {
make_stmt! {} //< This is OK...
let x = 0; //< ... unless this line is commented out.
}
```
Fixes#34418.
syntax-[breaking-change] cc #31645
(Only breaking because ast::TokenTree is now tokenstream::TokenTree.)
This pull request refactors TokenTrees into their own file as src/libsyntax/tokenstream.rs, moving them out of src/libsyntax/ast.rs, in order to prepare for an accompanying TokenStream implementation (per RFC 1566).
This PR refactors the 'errors' part of libsyntax into its own crate (librustc_errors). This is the first part of a few refactorings to simplify error reporting and potentially support more output formats (like a standardized JSON output and possibly an --explain mode that can work with the user's code), though this PR stands on its own and doesn't assume further changes.
As part of separating out the errors crate, I have also refactored the code position portion of codemap into its own crate (libsyntax_pos). While it's helpful to have the common code positions in a separate crate for the new errors crate, this may also enable further simplifications in the future.
**syntax-[breaking-change]** cc #31645
New `TraitItemKind::Macro` variant
This change adds support for macro expansion inside trait items by adding the new `TraitItemKind::Macro` and associated parsing code.
Casual grepping revealed some places in the codebase (some of which
antedated `if let`'s December 2014 stabilization in c200ae5a) where we
were using a match with a `None => ()` arm where (in the present
author's opinion) an `if let` conditional would be more readable. (Other
places where matching to the unit value did seem to better express the
intent were left alone.)
It's likely that we don't care about making such trivial,
non-functional, sheerly æsthetic changes.
But if we do, this is a patch.
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).
Fix spans and expected token lists, fix#33413 + other cosmetic improvements
Add test for #33413
Convert between `Arg` and `ExplicitSelf` precisely
Simplify pretty-printing for methods
parser: do not try to continue with `unsafe` on foreign fns
The changed line makes it look like `unsafe` is allowed, but the first statement of `parse_item_foreign_fn` is:
```
self.expect_keyword(keywords::Fn)?;
```
So we get the strange "expected one of `fn`, `pub`, `static`, or `unsafe`, found `unsafe`".
Fixes: #27361
parser: fix suppression of syntax errors in range RHS
Invalid expressions on the RHS were just swallowed without generating an error. The new version more closely mirrors the code for parsing `..x` in the `parse_prefix_range_expr` method below, where no cancel is done either.
Fixes#33262.
parser: change warning into an error on `T<A=B, C>`
part of #32214
This seems to be the obvious fix, and the error message is consistent with all the other parser errors ("expected x, found y").
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.
The changed line makes it look like `unsafe` is allowed, but the
first statement of `parse_item_foreign_fn` is:
`self.expect_keyword(keywords::Fn)?;`
So we get the strange "expected one of `fn`, `pub`, `static`, or
`unsafe`, found `unsafe`".
Fixes: #27361
Invalid expressions on the RHS were just swallowed without generating
an error. The new code more closely mirrors the code for parsing
`..x` in the `parse_prefix_range_expr` method, where no cancel is done
either.
Fixes#33262.
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
Implement `pub(restricted)` privacy (RFC 1422)
This implements `pub(restricted)` privacy from RFC 1422 (cc #32409) behind a feature gate.
`pub(restricted)` paths currently cannot use re-exported modules both for simplicity of implementation and for future compatibility with RFC 1560 (cf #31783).
r? @nikomatsakis
[breaking-batch] Add support for `pub(restricted)` syntax in the AST
This PR allows the AST to represent the `pub(restricted)` syntax from RFC 1422 (cc #32409).
More specifically, it makes `ast::Visibility` non-`Copy` and adds two new variants, `Visibility::Crate` for `pub(crate)` and `Visitibility::Restricted { path: P<Path>, id: NodeId }` for `pub(path)`.
plugin-[breaking-change] cc #31645
r? @pnkfelix
Prevent bumping the parser past the EOF.
Makes `Parser::bump` after EOF into an ICE, forcing callers to avoid repeated EOF bumps.
This ICE is intended to break infinite loops where EOF wasn't stopping the loop.
For example, the handling of EOF in `parse_trait_items`' recovery loop fixes#32446.
But even without this specific fix, the ICE is triggered, which helps diagnosis and UX.
This is a `[breaking-change]` for plugins authors who eagerly eat multiple EOFs.
See https://github.com/docopt/docopt.rs/pull/171 for such an example and the necessary fix.
melt the ICE when lowering an impossible range
Emit a fatal error instead of panicking when HIR lowering encounters a range with no `end` point.
This involved adding a method to wire up `LoweringContext::span_fatal`.
Fixes#32245 (cc @nodakai).
r? @nrc
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
Make errors for unnecessary visibility qualifiers consistent
This PR refactors away `syntax::parse::parser::ParsePub` so that unnecessary visibility qualifiers on variant fields are reported not by the parser but by `privacy::SanePrivacyVisitor` (thanks to @petrochenkov's drive-by improvements in #31919).
r? @nikomatsakis
The `?` postfix operator is sugar equivalent to the try! macro, but is more amenable to chaining:
`File::open("foo")?.metadata()?.is_dir()`.
`?` is accepted on any *expression* that can return a `Result`, e.g. `x()?`, `y!()?`, `{z}?`,
`(w)?`, etc. And binds more tightly than unary operators, e.g. `!x?` is parsed as `!(x?)`.
cc #31436
This PR implements [RFC 1192](https://github.com/rust-lang/rfcs/blob/master/text/1192-inclusive-ranges.md), which is triple-dot syntax for inclusive range expressions. The new stuff is behind two feature gates (one for the syntax and one for the std::ops types). This replaces the deprecated functionality in std::iter. Along the way I simplified the desugaring for all ranges.
This is my first contribution to rust which changes more than one character outside of a test or comment, so please review carefully! Some of the individual commit messages have more of my notes. Also thanks for putting up with my dumb questions in #rust-internals.
- For implementing `std::ops::RangeInclusive`, I took @Stebalien's suggestion from https://github.com/rust-lang/rfcs/pull/1192#issuecomment-137864421. It seemed to me to make the implementation easier and increase type safety. If that stands, the RFC should be amended to avoid confusion.
- I also kind of like @glaebhoerl's [idea](https://github.com/rust-lang/rfcs/pull/1254#issuecomment-147815299), which is unified inclusive/exclusive range syntax something like `x>..=y`. We can experiment with this while everything is behind a feature gate.
- There are a couple of FIXMEs left (see the last commit). I didn't know what to do about `RangeArgument` and I haven't added `Index` impls yet. Those should be discussed/finished before merging.
cc @Gankro since you [complained](https://www.reddit.com/r/rust/comments/3xkfro/what_happened_to_inclusive_ranges/cy5j0yq)
cc #27777#30877rust-lang/rust#1192rust-lang/rfcs#1254
relevant to #28237 (tracking issue)
This PR changes the visibility of extern crate declarations to match that of items (fixes#26775).
To avoid breakage, the PR makes it a `public_in_private` lint to reexport a private extern crate, and it adds the lint `inaccessible_extern_crate` for uses of an inaccessible extern crate.
The lints can be avoided by making the appropriate `extern crate` declaration public.
This PR disallows non-inline modules without path annotations that are either in a block or in an inline module whose containing file is not a directory owner (fixes#29765).
This is a [breaking-change].
r? @nikomatsakis
Some tests just add the extra errors, others I fix by doing some simple error recovery. I've tried to avoid doing too much in the hope of doing something more principled later.
In general error messages are getting worse at this stage, but I think in the long run they will get better.