| Age | Commit message (Collapse) | Author | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
In the implementation (#140035), this was left as an open question for
the tracking issue (#136889). My assumption is that this should be
carried over.
Thankfully, either way, `-Zunpretty` is unstable and we can always
change it even if we stabilize frontmatter.
|
|
|
|
Fix some comments and related types and locals where it is obvious, e.g.
- bare_fn -> fn_ptr
- LifetimeBinderKind::BareFnType -> LifetimeBinderKind::FnPtrType
Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
|
|
|
|
It's like `Symbol` but for byte strings. The interner is now used for
both `Symbol` and `ByteSymbol`. E.g. if you intern `"dog"` and `b"dog"`
you'll get a `Symbol` and a `ByteSymbol` with the same index and the
characters will only be stored once.
The motivation for this is to eliminate the `Arc`s in `ast::LitKind`, to
make `ast::LitKind` impl `Copy`, and to avoid the need to arena-allocate
`ast::LitKind` in HIR. The latter change reduces peak memory by a
non-trivial amount on literal-heavy benchmarks such as `deep-vector` and
`tuple-stress`.
`Encoder`, `Decoder`, `SpanEncoder`, and `SpanDecoder` all get some
changes so that they can handle normal strings and byte strings.
This change does slow down compilation of programs that use
`include_bytes!` on large files, because the contents of those files are
now interned (hashed). This makes `include_bytes!` more similar to
`include_str!`, though `include_bytes!` contents still aren't escaped,
and hashing is still much cheaper than escaping.
|
|
Implement parsing of pinned borrows
This PR implements part of #130494.
EDIT: It introduces `&pin mut $place` and `&pin const $place` as sugars for `std::pin::pin!($place)` and its shared reference equivalent, except that `$place` will not be moved when borrowing. The borrow check will be in charge of enforcing places cannot be moved or mutably borrowed since being pinned till dropped.
### Implementation steps:
- [x] parse the `&pin mut $place` and `&pin const $place` syntaxes
- [ ] borrowck of `&pin mut|const`
- [ ] support autoref of `&pin mut|const` when needed
|
|
|
|
|
|
Introduce `-Zmacro-stats`
Introduce `-Zmacro-stats`.
It collects data about macro expansions and prints them in a table after expansion finishes. It's very useful for detecting macro bloat, especially for proc macros.
r? `@petrochenkov`
|
|
Implement asymmetrical precedence for closures and jumps
I have been through a series of asymmetrical precedence designs in Syn, and finally have one that I like and is worth backporting into rustc. It is based on just 2 bits of state: `next_operator_can_begin_expr` and `next_operator_can_continue_expr`.
Asymmetrical precedence is the thing that enables `(return 1) + 1` to require parentheses while `1 + return 1` does not, despite `+` always having stronger precedence than `return` [according to the Rust Reference](https://doc.rust-lang.org/1.83.0/reference/expressions.html#expression-precedence). This is facilitated by `next_operator_can_continue_expr`.
Relatedly, it is the thing that enables `(return) - 1` to require parentheses while `return + 1` does not, despite `+` and `-` having exactly the same precedence. This is facilitated by `next_operator_can_begin_expr`.
**Example:**
```rust
macro_rules! repro {
($e:expr) => {
$e - $e;
$e + $e;
};
}
fn main() {
repro!{return}
repro!{return 1}
}
```
`-Zunpretty=expanded` **Before:**
```console
fn main() {
(return) - (return);
(return) + (return);
(return 1) - (return 1);
(return 1) + (return 1);
}
```
**After:**
```console
fn main() {
(return) - return;
return + return;
(return 1) - return 1;
(return 1) + return 1;
}
```
|
|
It collects data about macro expansions and prints them in a table after
expansion finishes. It's very useful for detecting macro bloat,
especially for proc macros.
Details:
- It measures code snippets by pretty-printing them and then measuring
lines and bytes. This required a bunch of additional pretty-printing
plumbing, in `rustc_ast_pretty` and `rustc_expand`.
- The measurement is done in `MacroExpander::expand_invoc`.
- The measurements are stored in `ExtCtxt::macro_stats`.
|
|
So they match the order of the parts in the source code, e.g.:
```
struct Foo<T, U> { t: T, u: U }
<-><----> <------------>
/ | \
ident generics variant_data
```
|
|
|
|
|
|
|
|
All the box open/close issues have been fixed.
|
|
They don't appear to do anything -- no test output is affected -- and no
other pretty-printing code looks like this.
|
|
pretty-print: Print shebang at the top of the output
Shebang should stay at the top of the file, even after pretty-printing.
Closes #134643
|
|
Improve pretty-printing of braces
r? ````@petrochenkov````
|
|
implement or-patterns for pattern types
These are necessary to represent `NonZeroI32`, as the range for that is `..0 | 1..`. The `rustc_scalar_layout_range_*` attributes avoided this by just implementing wraparound and having a single `1..=-1` range effectively. See https://rust-lang.zulipchat.com/#narrow/channel/481660-t-lang.2Fpattern-types/topic/.60or.20pattern.60.20representation.20in.20type.20system/with/504217694 for some background discussion
cc https://github.com/rust-lang/rust/issues/123646
r? `@BoxyUwU`
|
|
Most notably, the `FIXME` for suboptimal printing of `use` groups in
`tests/ui/macros/stringify.rs` is fixed. And all other test output
changes result in pretty printed output being closer to the original
formatting in the source code.
|
|
|
|
They all have a single call site, aren't that big, and removing them
avoids having to pass some `BoxMarker`s.
|
|
|
|
The pretty-printers open and close "boxes" of text a lot. The open and
close operations must be matched. The matching is currently all implicit
and very easy to get wrong. (#140280 and #140246 are two recent
pretty-printing fixes that both involved unclosed boxes.)
This commit introduces `BoxMarker`, a marker type that represents an
open box. It makes box opening/closing explicit, which makes it much
easier to understand and harder to get wrong.
The commit also removes many comments are on `end` calls saying things
like "end outer head-block", "Close the outer-box". These demonstrate
how confusing the implicit approach was, but aren't necessary any more.
|
|
Improve if/else pretty printing
AST/HIR pretty printing of if/else is currently pretty bad. This PR improves it a lot.
r? `@Nadrieril`
|
|
Fix never pattern printing
It's currently broken, but there's an easy fix.
r? `@Nadrieril`
|
|
In the AST the "then" block is represented as a `Block`. In HIR the
"then" block is represented as an `Expr` that happens to always be.
`ExprKind::Block`. By deconstructing the `ExprKind::Block` to extract
the block within, things print properly.
For `issue-82392.rs`, note that we no longer print a type after the
"then" block. This is good, it now matches how we don't print a type for
the "else" block. (Well, we do print a type after the "else" block, but
it's for the whole if/else.)
Also tighten up some of the pattern matching -- these block expressions
within if/else will never have labels.
|
|
By removing some of the over-indenting. AST pretty printing now looks
correct. HIR pretty printing is better, but still over-indents some.
|
|
Indents for `cbox` and `ibox` are 0 or `INDENT_UNIT` (4) except for a
couple of places which are `INDENT_UNIT - 1` for no clear reason.
This commit changes the three space indents to four spaces.
|
|
|
|
Remove unnecessary clones
r? `@SparrowLii`
|
|
I found these by grepping for `&[a-z_\.]*\.clone()`, i.e. expressions
like `&a.b.clone()`, which are sometimes unnecessary clones, and also
looking at clones nearby to cases like that.
|
|
By replacing them with `{Open,Close}{Param,Brace,Bracket,Invisible}`.
PR #137902 made `ast::TokenKind` more like `lexer::TokenKind` by
replacing the compound `BinOp{,Eq}(BinOpToken)` variants with fieldless
variants `Plus`, `Minus`, `Star`, etc. This commit does a similar thing
with delimiters. It also makes `ast::TokenKind` more similar to
`parser::TokenType`.
This requires a few new methods:
- `TokenKind::is_{,open_,close_}delim()` replace various kinds of
pattern matches.
- `Delimiter::as_{open,close}_token_kind` are used to convert
`Delimiter` values to `TokenKind`.
Despite these additions, it's a net reduction in lines of code. This is
because e.g. `token::OpenParen` is so much shorter than
`token::OpenDelim(Delimiter::Parenthesis)` that many multi-line forms
reduce to single line forms. And many places where the number of lines
doesn't change are still easier to read, just because the names are
shorter, e.g.:
```
- } else if self.token != token::CloseDelim(Delimiter::Brace) {
+ } else if self.token != token::CloseBrace {
```
|
|
nnethercote:rm-Nonterminal-and-TokenKind-Interpolated, r=petrochenkov
Remove `Nonterminal` and `TokenKind::Interpolated`
A third attempt at this; the first attempt was #96724 and the second was #114647.
r? `@ghost`
|
|
It bugs me when variables of type `Ident` are called `name`. It leads to
silly things like `name.name`. `Ident` variables should be called
`ident`, and `name` should be used for variables of type `Symbol`.
This commit improves things by by doing `s/name/ident/` on a bunch of
`Ident` variables. Not all of them, but a decent chunk.
|
|
Implement `super let`
Tracking issue: https://github.com/rust-lang/rust/issues/139076
This implements `super let` as proposed in #139080, based on the following two equivalence rules.
1. For all expressions `$expr` in any context, these are equivalent:
- `& $expr`
- `{ super let a = & $expr; a }`
2. And, additionally, these are equivalent in any context when `$expr` is a temporary (aka rvalue):
- `& $expr`
- `{ super let a = $expr; & a }`
So far, this experiment has a few interesting results:
## Interesting result 1
In this snippet:
```rust
super let a = f(&temp());
```
I originally expected temporary `temp()` would be dropped at the end of the statement (`;`), just like in a regular `let`, because `temp()` is not subject to temporary lifetime extension.
However, it turns out that that would break the fundamental equivalence rules.
For example, in
```rust
g(&f(&temp()));
```
the temporary `temp()` will be dropped at the `;`.
The first equivalence rule tells us this must be equivalent:
```rust
g({ super let a = &f(&temp()); a });
```
But that means that `temp()` must live until the last `;` (after `g()`), not just the first `;` (after `f()`).
While this was somewhat surprising to me at first, it does match the exact behavior we need for `pin!()`: The following _should work_. (See also https://github.com/rust-lang/rust/issues/138718)
```rust
g(pin!(f(&mut temp())));
```
Here, `temp()` lives until the end of the statement. This makes sense from the perspective of the user, as no other `;` or `{}` are visible. Whether `pin!()` uses a `{}` block internally or not should be irrelevant.
This means that _nothing_ in a `super let` statement will be dropped at the end of that super let statement. It does not even need its own scope.
This raises questions that are useful for later on:
- Will this make temporaries live _too long_ in cases where `super let` is used not in a hidden block in a macro, but as a visible statement in code like the following?
```rust
let writer = {
super let file = File::create(&format!("/home/{user}/test"));
Writer::new(&file)
};
```
- Is a `let` statement in a block still the right syntax for this? Considering it has _no_ scope of its own, maybe neither a block nor a statement should be involved
This leads me to think that instead of `{ super let $pat = $init; $expr }`, we might want to consider something like `let $pat = $init in $expr` or `$expr where $pat = $init`. Although there are also issues with these, as it isn't obvious anymore if `$init` should be subject to temporary lifetime extension. (Do we want both `let _ = _ in ..` and `super let _ = _ in ..`?)
## Interesting result 2
What about `super let x;` without initializer?
```rust
let a = {
super let x;
x = temp();
&x
};
```
This works fine with the implementation in this PR: `x` is extended to live as long as `a`.
While it matches my expectations, a somewhat interesting thing to realize is that these are _not_ equivalent:
- `super let x = $expr;`
- `super let x; x = $expr;`
In the first case, all temporaries in $expr will live at least as long as (the result of) the surrounding block.
In the second case, temporaries will be dropped at the end of the assignment statement. (Because the assignment statement itself "is not `super`".)
This difference in behavior might be confusing, but it _might_ be useful.
One might want to extend the lifetime of a variable without extending all the temporaries in the initializer expression.
On the other hand, that can also be expressed as:
- `let x = $expr; super let x = x;` (w/o temporary lifetime extension), or
- `super let x = { $expr };` (w/ temporary lifetime extension)
So, this raises these questions:
- Do we want to accept `super let x;` without initializer at all?
- Does it make sense for statements other than let statements to be "super"? An expression statement also drops temporaries at its `;`, so now that we discovered that `super let` basically disables that `;` (see interesting result 1), is there a use to having other statements without their own scope? (I don't think that's ever useful?)
## Interesting result 3
This works now:
```rust
super let Some(x) = a.get(i) else { return };
```
I didn't put in any special cases for `super let else`. This is just the behavior that 'naturally' falls out when implementing `super let` without thinking of the `let else` case.
- Should `super let else` work?
## Interesting result 4
This 'works':
```rust
fn main() {
super let a = 123;
}
```
I didn't put in any special cases for `super let` at function scope. I had expected the code to cause an ICE or other weird failure when used at function body scope, because there's no way to let the variable live as long as the result of the function.
This raises the question:
- Does this mean that this behavior is the natural/expected behavior when `super let` is used at function scope? Or is this just a quirk and should we explicitly disallow `super let` in a function body? (Probably the latter.)
---
The questions above do not need an answer to land this PR. These questions should be considered when redesigning/rfc'ing/stabilizing the feature.
|
|
Add new `PatKind::Missing` variants
To avoid some ugly uses of `kw::Empty` when handling "missing" patterns, e.g. in bare fn tys. Helps with #137978. Details in the individual commits.
r? ``@oli-obk``
|
|
Co-authored-by: lcnr <rust@lcnr.de>
|
|
|
|
In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and
`AssocOp::AssignOp`, even though this allows some nonsensical
combinations. E.g. there is no `&&=` operator. Likewise for HIR and
THIR.
This commit introduces `AssignOpKind` which only includes the ten
assignable operators, and uses it in `ExprKind::AssignOp` and
`AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and
`thir::ExprKind`.) This avoids the possibility of nonsensical
combinations, as seen by the removal of the `bug!` case in
`lang_item_for_binop`.
The commit is mostly plumbing, including:
- Adds an `impl From<AssignOpKind> for BinOpKind` (AST) and `impl
From<AssignOp> for BinOp` (MIR/THIR).
- `BinOpCategory` can now be created from both `BinOpKind` and
`AssignOpKind`.
- Replaces the `IsAssign` type with `Op`, which has more information and
a few methods.
- `suggest_swapping_lhs_and_rhs`: moves the condition to the call site,
it's easier that way.
- `check_expr_inner`: had to factor out some code into a separate
method.
I'm on the fence about whether avoiding the nonsensical combinations is
worth the extra code.
|
|
Because it's nice to avoid passing in unnecessary data.
|
|
`NtBlock` is the last remaining variant of `Nonterminal`, so once it is
gone then `Nonterminal` can be removed as well.
|
|
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
|