552 Commits

Author SHA1 Message Date
Deadbeef
69326878ee parse const trait Trait 2025-07-17 18:06:26 +08:00
Nicholas Nethercote
fb7aa9e4fd Improve path segment joining.
There are many places that join path segments with `::` to produce a
string. A lot of these use `join("::")`. Many in rustdoc use
`join_with_double_colon`, and a few use `.joined("..")`. One in Clippy
uses `itertools::join`. A couple of them look for `kw::PathRoot` in the
first segment, which can be important.

This commit introduces `rustc_ast::join_path_{syms,ident}` to do the
joining for everyone. `rustc_ast` is as good a location for these as
any, being the earliest-running of the several crates with a `Path`
type. Two functions are needed because `Ident` printing is more complex
than simple `Symbol` printing.

The commit also removes `join_with_double_colon`, and
`estimate_item_path_byte_length` with it.

There are still a handful of places that join strings with "::" that are
unchanged. They are not that important: some of them are in tests, and
some of them first split a path around "::" and then rejoin with "::".

This fixes one test case where `{{root}}` shows up in an error message.
2025-07-17 08:37:19 +10:00
Jubilee Young
0a4f87a144 compiler: rename {ast,hir}::BareFn* to FnPtr*
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>
2025-07-06 15:03:08 -07:00
Jacob Pratt
05f5690d81
Rollup merge of #143380 - cjgillot:kw_span, r=compiler-errors
Replace kw_span by full span for generic const parameters.

Small simplification extracted from https://github.com/rust-lang/rust/pull/127241
2025-07-04 05:47:27 +02:00
Camille GILLOT
3380bfd1a0 Replace kw_span by full span. 2025-07-03 14:59:27 +00:00
Jana Dönszelmann
f6d37a25a9
Rollup merge of #134006 - klensy:typos, r=nnethercote
setup typos check in CI

This allows to check typos in CI, currently for compiler only (to reduce commit size with fixes). With current setup, exclude list is quite short, so it worth trying?

Also includes commits with actual typo fixes.

MCP: https://github.com/rust-lang/compiler-team/issues/817

typos check currently turned for:
* ./compiler
* ./library
* ./src/bootstrap
* ./src/librustdoc

After merging, PRs which enables checks for other crates (tools) can be implemented too.

Found typos will **not break** other jobs immediately: (tests, building compiler for perf run). Job will be marked as red on completion in ~ 20 secs, so you will not forget to fix it whenever you want, before merging pr.

Check typos: `python x.py test tidy --extra-checks=spellcheck`
Apply typo fixes: `python x.py test tidy --extra-checks=spellcheck:fix` (in case if there only 1 suggestion of each typo)

Current fail in this pr is expected and shows how typo errors emitted. Commit with error will be removed after r+.
2025-07-03 13:29:35 +02:00
klensy
c76d032f01 setup CI and tidy to use typos for spellchecking and fix few typos 2025-07-03 10:51:06 +03:00
Matthias Krüger
6ebf642a04
Rollup merge of #142237 - benschulz:unused-parens-fn, r=fee1-dead
Detect more cases of unused_parens around types

With this change, more unused parentheses around bounds and types nested within bounds are detected.
2025-07-02 19:29:35 +02:00
Michael Goulet
2516c33982 Remove support for dyn* 2025-07-01 19:00:21 +00:00
Benjamin Schulz
7d6764a45b Detect more cases of unused_parens around types 2025-07-01 08:56:20 +02:00
Nicholas Nethercote
478f8287c0 Introduce ByteSymbol.
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.
2025-06-30 20:42:27 +10:00
Matthias Krüger
36c2b011cb
Rollup merge of #139858 - oli-obk:new-const-traits-syntax, r=fee1-dead
New const traits syntax

This PR only affects the AST and doesn't actually change anything semantically.

All occurrences of `~const` outside of libcore have been replaced by `[const]`. Within libcore we have to wait for rustfmt to be bumped in the bootstrap compiler. This will happen "automatically" (when rustfmt is run) during the bootstrap bump, as rustfmt converts `~const` into `[const]`. After this we can remove the `~const` support from the parser

Caveat discovered during impl: there is no legacy bare trait object recovery for `[const] Trait` as that snippet in type position goes down the slice /array parsing code and will error

r? ``@fee1-dead``

cc ``@nikomatsakis`` ``@traviscross`` ``@compiler-errors``
2025-06-27 22:13:00 +02:00
Oli Scherer
eb7245a864 Change const trait bound syntax from ~const to [const] 2025-06-26 13:46:45 +00:00
Folkert de Vries
1dfc8406dc
make tidy-alphabetical use a natural sort 2025-06-25 22:52:38 +02:00
Jubilee
4f477427b8
Rollup merge of #135731 - frank-king:feature/pin-borrow, r=eholk,traviscross
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
2025-06-24 19:45:29 -07:00
Jacob Pratt
e95fb09dfb
Rollup merge of #142371 - fee1-dead-contrib:push-xqlkumzurkus, r=petrochenkov
avoid `&mut P<T>` in `visit_expr` etc methods

trying a different way than rust-lang/rust#141636
r? ghost
2025-06-17 23:19:34 +02:00
Frank King
e627f88f88 Implement pinned borrows, part of pin_ergonomics 2025-06-15 10:21:29 +08:00
David Tolnay
2171f89eb2
Reduce precedence of expressions that have an outer attr 2025-06-13 18:09:13 -07:00
bors
8da623945f Auto merge of #142443 - matthiaskrgr:rollup-l1l6d0v, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#128425 (Make `missing_fragment_specifier` an unconditional error)
 - rust-lang/rust#135927 (retpoline and retpoline-external-thunk flags (target modifiers) to enable retpoline-related target features)
 - rust-lang/rust#140770 (add `extern "custom"` functions)
 - rust-lang/rust#142176 (tests: Split dont-shuffle-bswaps along opt-levels and arches)
 - rust-lang/rust#142248 (Add supported asm types for LoongArch32)
 - rust-lang/rust#142267 (assert more in release in `rustc_ast_lowering`)
 - rust-lang/rust#142274 (Update the stdarch submodule)
 - rust-lang/rust#142276 (Update dependencies in `library/Cargo.lock`)
 - rust-lang/rust#142308 (Upgrade `object`, `addr2line`, and `unwinding` in the standard library)

Failed merges:

 - rust-lang/rust#140920 (Extract some shared code from codegen backend target feature handling)

r? `@ghost`
`@rustbot` modify labels: rollup

try-job: aarch64-apple
try-job: x86_64-msvc-1
try-job: x86_64-gnu
try-job: dist-i586-gnu-i586-i686-musl
try-job: test-various
2025-06-13 17:44:15 +00:00
Matthias Krüger
9639a7c522
Rollup merge of #142069 - nnethercote:Zmacro-stats, r=petrochenkov
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`
2025-06-13 05:16:56 +02:00
Matthias Krüger
b12bb2530b
Rollup merge of #134847 - dtolnay:asymmetrical, r=fmease
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;
}
```
2025-06-13 05:16:54 +02:00
Folkert de Vries
5f73ce2b7e
add extern "custom" functions 2025-06-12 20:27:10 +02:00
Deadbeef
5f0dd44b3b avoid &mut P<T> in visit_expr etc methods 2025-06-12 17:36:03 +08:00
Nicholas Nethercote
fb73893e51 Add some useful Path/PathSegment equality operations.
They will be used in a subsequent commit.
2025-06-12 15:26:06 +10:00
Guillaume Gomez
93ca0af08c
Rollup merge of #141603 - nnethercote:reduce-P, r=fee1-dead
Reduce `ast::ptr::P` to a typedef of `Box`

As per the MCP at https://github.com/rust-lang/compiler-team/issues/878.

r? `@fee1-dead`
2025-06-06 23:53:16 +02:00
Matthias Krüger
96531418f8
Rollup merge of #141945 - nnethercote:rm-Path-is_ident, r=compiler-errors
Remove `Path::is_ident`.

It checks that a path has a single segment that matches the given symbol, and that there are zero generic arguments. It has a single use.

We also have `impl PartialEq<Symbol> for Path` which does exactly the same thing *except* it doesn't check for zero generic arguments, which seems like an oversight. It has numerous uses.

This commit removes `Path::is_ident`, adds a test for zero generic arguments to `PartialEq<Symbol> for Path`, and changes the single use of `is_ident` to instead use `==`.

r? `@wesleywiser`
2025-06-03 21:53:38 +02:00
Matthias Krüger
19437666d9
Rollup merge of #141724 - Sol-Ell:issue-141141-fix, r=nnethercote
fix(#141141): When expanding `PartialEq`, check equality of scalar types first.

Fixes rust-lang/rust#141141.

Now, `cs_eq` function of `partial_eq.rs` compares [scalar types](https://doc.rust-lang.org/rust-by-example/primitives.html#scalar-types) first.

- Add `is_scalar` field to `FieldInfo`.
- Add `is_scalar` method to `TyKind`.
- Pass `FieldInfo` via `CsFold::Combine` and refactor code relying on it.
- Implement `TryFrom<&str>` and `TryFrom<Symbol>` for FloatTy.
- Implement `TryFrom<&str>` and `TryFrom<Symbol>` for IntTy.
- Implement `TryFrom<&str>` and `TryFrom<Symbol>` for UintTy.
2025-06-03 15:00:32 +02:00
Nicholas Nethercote
04391045d0 Remove Path::is_ident.
It checks that a path has a single segment that matches the given
symbol, and that there are zero generic arguments. It has a single use.

We also have `impl PartialEq<Symbol> for Path` which does exactly the
same thing *except* it doesn't check for zero generic arguments, which
seems like an oversight. It has numerous uses.

This commit removes `Path::is_ident`, adds a test for zero generic
arguments to `PartialEq<Symbol> for Path`, and changes the single use of
`is_ident` to instead use `==`.
2025-06-03 15:21:33 +10:00
Ell
a6a1c1b247 Separately check equality of the scalar types and compound types in the order of declaration. 2025-06-02 15:29:34 +03:00
Matthias Krüger
a87bc9d9fe
Rollup merge of #141430 - fee1-dead-contrib:push-nmzoprvtsvww, r=petrochenkov
remove `visit_clobber` and move `DummyAstNode` to `rustc_expand`

`visit_clobber` is not really useful except for one niche purpose
involving generic code. We should just use the replace logic where we
can.
2025-05-30 07:01:29 +02:00
Deadbeef
5e7185583f remove visit_clobber and move DummyAstNode to rustc_expand
`visit_clobber` is not really useful except for one niche purpose
involving generic code. We should just use the replace logic where we
can.
2025-05-29 12:46:26 +08:00
Nicholas Nethercote
4c4a40f6df Reorder ast::ItemKind::{Struct,Enum,Union} fields.
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
```
2025-05-28 15:48:45 +10:00
Nicholas Nethercote
0f285e346f Remove the one use of P<[T]>.
A `Vec` is fine, the additional word (vector vs. boxed slice) doesn't
matter here.
2025-05-27 02:54:18 +10:00
Nicholas Nethercote
6973fa08a3 Remove P::map.
It's barely used, and the places that use it are better if they don't.
2025-05-27 02:07:15 +10:00
León Orell Valerian Liehr
4e5b1aa055
Rollup merge of #140746 - dianne:guard-pat-res, r=oli-obk
name resolution for guard patterns

This PR provides an initial implementation of name resolution for guard patterns [(RFC 3637)](https://github.com/rust-lang/rfcs/blob/master/text/3637-guard-patterns.md). This does not change the requirement that the bindings on either side of an or-pattern must be the same [(proposal here)](https://github.com/rust-lang/rfcs/blob/master/text/3637-guard-patterns.md#allowing-mismatching-bindings-when-possible); the code that handles that is separate from what this PR touches, so I'm saving it for a follow-up.

On a technical level, this separates "collecting the bindings in a pattern" (which was already done for or-patterns) from "introducing those bindings into scope". I believe the approach used here can be extended straightforwardly in the future to work with `if let` guard patterns, but I haven't tried it myself since we don't allow those yet.

Tracking issue for guard patterns: #129967

cc ``@Nadrieril``
2025-05-18 18:44:11 +02:00
dianne
f0b8ec1d71 name resolution for guard patterns 2025-05-18 04:21:57 -07:00
Nicholas Nethercote
5ebcbfc1e1 Remove AstDeref.
It's a "utility trait to reduce boilerplate" implemented for `P` and
`AstNodeWrapper`, but removing it gives a net reduction of twenty lines
of code. It's also simpler to just implement
`HasNodeId`/`HasAttrs`/`HasTokens` directly on types instead of via
`AstDeref`.

(I decided to make this change when doing some related refactoring and
the error messages involving `AstDeref` and `HasAttrs` were hard to
understand; removing it helped a lot.)
2025-05-10 08:58:47 +10:00
David Tolnay
6cca4ca82b
Implement asymmetrical precedence for closures and jumps 2025-05-03 23:27:29 -07:00
Nicholas Nethercote
0ea204a5ff Add useful comments on ExprKind::If variants.
Things that aren't obvious and took me a while to work out.
2025-05-02 15:53:39 +10:00
Oli Scherer
b023856f29 Add or-patterns to pattern types 2025-04-28 07:50:18 +00:00
Nicholas Nethercote
d88056c35e Derive HashStable for DelimArgs. 2025-04-23 19:26:54 +10:00
Matthias Krüger
bf49dfc943
Rollup merge of #139392 - compiler-errors:raw-expr, r=oli-obk
Detect and provide suggestion for `&raw EXPR`

When emitting an error in the parser, and we detect that the previous token was `raw` and we *could* have consumed `const`/`mut`, suggest that this may have been a mistyped raw ref expr. To do this, we add `const`/`mut` to the expected token set when parsing `&raw` as an expression (which does not affect the "good path" of parsing, for the record).

This is kind of a rudimentary error improvement, since it doesn't actually attempt to recover anything, leading to some other knock-on errors b/c we still treat `&raw` as the expression that was parsed... but at least we add the suggestion! I don't think the parser grammar means we can faithfully recover `&raw EXPR` early, i.e. during `parse_expr_borrow`.

Fixes #133231
2025-04-14 18:15:31 +02:00
Stuart Cook
27c6e40755
Rollup merge of #139112 - m-ou-se:super-let, r=lcnr
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.
2025-04-07 22:29:18 +10:00
Stuart Cook
82df6229b6
Rollup merge of #139035 - nnethercote:PatKind-Missing, r=oli-obk
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``
2025-04-07 22:29:17 +10:00
Michael Goulet
6dfbe7c986 Detect and provide suggestion for &raw EXPR 2025-04-04 21:36:12 +00:00
Mara Bos
3123df8ef0 Implement super let. 2025-04-04 09:44:19 +02:00
Nicholas Nethercote
ddcb370bc6 Tighten up assignment operator representations.
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.
2025-04-03 10:23:03 +11:00
Nicholas Nethercote
df247968f2 Move ast::Item::ident into ast::ItemKind.
`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`.
2025-04-01 14:08:57 +11:00
Nicholas Nethercote
9f089e080c Add {ast,hir,thir}::PatKind::Missing variants.
"Missing" patterns are possible in bare fn types (`fn f(u32)`) and
similar places. Currently these are represented in the AST with
`ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no
sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for
HIR and THIR.

This is a bit nasty. It's very non-obvious, and easy to forget to check
for the exceptional empty identifier case.

This commit adds a new variant, `PatKind::Missing`, to do it properly.

The process I followed:
- Add a `Missing` variant to `{ast,hir,thir}::PatKind`.
- Chang `parse_param_general` to produce `ast::PatKind::Missing`
  instead of `ast::PatKind::Missing`.
- Look through `kw::Empty` occurrences to find functions where an
  existing empty ident check needs replacing with a `PatKind::Missing`
  check: `print_param`, `check_trait_item`, `is_named_param`.
- Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive
  match identified by the compiler.
- Find which arms are actually reachable by running the test suite,
  changing them to something appropriate, usually by looking at what
  would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no
  `mut`, an empty ident, and no subpattern.

Quite a few of the `unreachable!()` arms were never reached. This makes
sense because `PatKind::Missing` can't happen in every pattern, only
in places like bare fn tys and trait fn decls.

I also tried an alternative approach: modifying `ast::Param::pat` to
hold an `Option<P<Pat>>` instead of a `P<Pat>`, but that quickly turned
into a very large and painful change. Adding `PatKind::Missing` is much
easier.
2025-03-28 09:18:57 +11:00
Stuart Cook
30344f7fa3
Rollup merge of #138898 - fmease:decrustify-parser-post-ty-ascr, r=compiler-errors
Mostly parser: Eliminate code that's been dead / semi-dead since the removal of type ascription syntax

**Disclaimer**: This PR is intended to mostly clean up code as opposed to bringing about behavioral changes. Therefore it doesn't aim to address any of the 'FIXME: remove after a month [dated: 2023-05-02]: "type ascription syntax has been removed, see issue [#]101728"'.

---

By commit:

1. Removes truly dead code:
   * Since 1.71 (#109128) `let _ = { f: x };` is a syntax error as opposed to a semantic error which allows the parse-time diagnostic (suggestion) "*struct literal body without path // you might have forgotten […]*" to kick in.
   * The analysis-time diagnostic (suggestion) from <=1.70 "*cannot find value \`f\` in this scope // you might have forgotten […]*" is therefore no longer reachable.
2. Updates `is_certainly_not_a_block` to be in line with the current grammar:
   * The seq. `{ ident:` is definitely not the start of a block. Before the removal of ty ascr, `{ ident: ty_start` would begin a block expr.
   * This shouldn't make more code compile IINM, it should *ultimately* only affect diagnostics.
   * For example, `if T { f: () } {}` will now be interpreted as an `if` with struct lit `T { f: () }` as its *condition* (which is banned in the parser anyway) as opposed to just `T` (with the *consequent* being `f : ()` which is also invalid (since 1.71)). The diagnostics are almost the same because we have two separate parse recovery procedures + diagnostics: `StructLiteralNeedingParens` (*invalid struct lit*) before and `StructLiteralNotAllowedHere` (*struct lits aren't allowed here*) now, as you can see from the diff.
   * (As an aside, even before this PR, fn `maybe_suggest_struct_literal` should've just used the much older & clearer `StructLiteralNotAllowedHere`)
   * NB: This does sadly regress the compiler output for `tests/ui/parser/type-ascription-in-pattern.rs` but that can be fixed in follow-up PRs. It's not super important IMO and a natural consequence.
3. Removes code that's become dead due to the prior commit.
   * Basically reverts #106620 + #112475 (without regressing rustc's output!).
   * Now the older & more robust parse recovery procedure (cc `StructLiteralNotAllowedHere`) takes care of the cases the removed code used to handle.
   * This automatically fixes the suggestions for \[[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=7e2030163b11ee96d17adc3325b01780)\]:
     * `if Ty::<i32> { f: K }.m() {}`: `if Ty::<i32> { SomeStruct { f: K } }.m() {}` (broken) → ` if (Ty::<i32> { f: K }).m() {}`
     * `if <T as Trait>::Out { f: K::<> }.m() {}`: `if <T as Trait>(::Out { f: K::<> }).m() {}` (broken) → `if (<T as Trait>::Out { f: K::<> }).m() {}`
4. Merge and simplify UI tests pertaining to this issue, so it's easier to add more regression tests like for the two cases mentioned above.
5. Merge UI tests and add the two regression tests.

Best reviewed commit by commit (on request I'll partially squash after approval).
2025-03-26 19:40:28 +11:00