| Age | Commit message (Collapse) | Author | Lines |
|
mbe stands for macro-by-example
|
|
|
|
|
|
|
|
NamedMatch is already cheap to clone due to Lrc's inside.
|
|
Add meta-variable checks in macro definitions
This is an implementation of #61053. It is not sound (some errors are not reported) and not complete (reports may not be actual errors). This is due to the possibility to define macros in macros in indirect ways. See module documentation of `macro_check` for more details.
What remains to be done:
- [x] Migrate from an error to an allow-by-default lint.
- [x] Add more comments in particular for the handling of nested macros.
- [x] Add more tests if needed.
- [x] Try to avoid cloning too much (one idea is to use lists on the stack).
- [ ] Run crater with deny-by-default lint (measure rate of false positives).
- [ ] Remove extra commit for deny-by-default lint
- [x] Create a PR to remove the old `question_mark_macro_sep` lint #62160
|
|
This is needed for having complete error messages where reporting macro variable
errors. Here is what they would look like:
error: meta-variable repeats with different kleene operator
--> $DIR/issue-61053-different-kleene.rs:3:57
|
LL | ( $( $i:ident = $($j:ident),+ );* ) => { $( $( $i = $j; )* )* };
| - expected repetition ^^ - conflicting repetition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The current code (expensively) clones the value within an `Rc`. This
commit changes things so that the `Rc` itself is (cheaply) cloned
instead, avoid some allocations.
This requires converting a few `Rc` instances to `Lrc`.
|
|
It's present within `Token::Interpolated` as an optimization, so that if
a nonterminal is converted to a `TokenStream` multiple times, the
first-computed value is saved and reused.
But in practice it's not needed. `interpolated_to_tokenstream()` is a
cold function: it's only called a few dozen times while compiling rustc
itself, and a few hundred times across the entire `rustc-perf` suite.
Furthermore, when it is called, it is almost always the first
conversion, so no benefit is gained from it.
So this commit removes `LazyTokenStream`, along with the now-unnecessary
`Token::interpolated()`.
As well as a significant simplification, the removal speeds things up
slightly, mostly due to not having to `drop` the `LazyTokenStream`
instances.
|
|
|
|
This commit changes `syntax::fold::Folder` from a functional style
(where most methods take a `T` and produce a new `T`) to a more
imperative style (where most methods take and modify a `&mut T`), and
renames it `syntax::mut_visit::MutVisitor`.
The first benefit is speed. The functional style does not require any
reallocations, due to the use of `P::map` and
`MoveMap::move_{,flat_}map`. However, every field in the AST must be
overwritten; even those fields that are unchanged are overwritten with
the same value. This causes a lot of unnecessary memory writes. The
imperative style reduces instruction counts by 1--3% across a wide range
of workloads, particularly incremental workloads.
The second benefit is conciseness; the imperative style is usually more
concise. E.g. compare the old functional style:
```
fn fold_abc(&mut self, abc: ABC) {
ABC {
a: fold_a(abc.a),
b: fold_b(abc.b),
c: abc.c,
}
}
```
with the imperative style:
```
fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
visit_a(a);
visit_b(b);
}
```
(The reductions get larger in more complex examples.)
Overall, the patch removes over 200 lines of code -- even though the new
code has more comments -- and a lot of the remaining lines have fewer
characters.
Some notes:
- The old style used methods called `fold_*`. The new style mostly uses
methods called `visit_*`, but there are a few methods that map a `T`
to something other than a `T`, which are called `flat_map_*` (`T` maps
to multiple `T`s) or `filter_map_*` (`T` maps to 0 or 1 `T`s).
- `move_map.rs`/`MoveMap`/`move_map`/`move_flat_map` are renamed
`map_in_place.rs`/`MapInPlace`/`map_in_place`/`flat_map_in_place` to
reflect their slightly changed signatures.
- Although this commit renames the `fold` module as `mut_visit`, it
keeps it in the `fold.rs` file, so as not to confuse git. The next
commit will rename the file.
|
|
`TokenStream` is currently recursive in *two* ways:
- the `TokenTree` variant contains a `ThinTokenStream`, which can
contain a `TokenStream`;
- the `TokenStream` variant contains a `Vec<TokenStream>`.
The latter is not necessary and causes significant complexity. This
commit replaces it with the simpler `Vec<(TokenTree, IsJoint)>`.
This reduces complexity significantly. In particular, `StreamCursor` is
eliminated, and `Cursor` becomes much simpler, consisting now of just a
`TokenStream` and an index.
The commit also removes the `Extend` impl for `TokenStream`, because it
is only used in tests. (The commit also removes those tests.)
Overall, the commit reduces the number of lines of code by almost 200.
|
|
|
|
`TokenStream::new` is a better name for the former, and the latter is
now just equivalent to `TokenStream::Stream`.
|
|
Because it's an extra type layer that doesn't really help; in a couple
of places it actively gets in the way, and overall removing it makes the
code nicer. It does, however, move `tokenstream::TokenTree` further away
from the `TokenTree` in `quote.rs`.
More importantly, this change reduces the size of `TokenStream` from 48
bytes to 40 bytes on x86-64, which is enough to slightly reduce
instruction counts on numerous benchmarks, the best by 1.5%.
Note that `open_tt` and `close_tt` have gone from being methods on
`Delimited` to associated methods of `TokenTree`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remove variant `Token::SubstNt` in favor of `quoted::TokenTree::MetaVar`.
|
|
This reduces duplication, thereby increasing expansion speed.
|
|
This is mostly removing stray ampersands, needless returns and lifetimes.
|
|
|
|
|
|
|