Commit Graph

1574 Commits

Author SHA1 Message Date
Stuart Cook
25d282efd4
Rollup merge of #139641 - BoxyUwU:allow_parend_array_len_infer, r=compiler-errors
Allow parenthesis around inferred array lengths

In #135272 it was noticed that we weren't handling `Vec<(((((_)))))>` correctly under the new desugaring for `generic_arg_infer`, this had to be fixed in order to not regress stable code for types that should continue working. This has the side effect of *also* allowing the following to work:
```rust
#![feature(generic_arg_infer)]
struct Bar<const N: usize>;
fn main() {
    let a: Bar<((_))> = Bar::<10>;
}
```

However I did not make the same change for array lengths resulting in the following not compiling:
```rust
#![feature(generic_arg_infer)]
fn main() {
    let a: [u8; (((_)))] = [2; 2];
    let a: [u8; 2] = [2; (((((_)))))];
}
```

This is rather inconsistent as parenthesis around `_` *are* supported for const args to non-arrays, and type args. This PR fixes this allowing the above example to compile. No stable impact.

r? compiler-errors
2025-04-11 13:31:49 +10:00
Boxy
8f00b1fdad Allow parenthesis around inferred array lengths 2025-04-10 18:57:42 +01:00
Matthias Krüger
7fbd7bdfa8
Rollup merge of #139614 - nnethercote:fix-139512, r=oli-obk
Avoid empty identifiers for delegate params and args.

Details in individual commits.

r? `@oli-obk`
2025-04-10 17:27:16 +02:00
Nicholas Nethercote
9bb1008e1d Avoid empty identifiers for delegate params and args.
Instead use `argN`. The empty identifiers could flow to
`Liveness::should_warn`, where they would trigger a bounds error.

Fixes #139512.
2025-04-10 14:46:53 +10:00
Nicholas Nethercote
1b3fc585cb Rename some name variables as ident.
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.
2025-04-10 09:30:55 +10:00
Stuart Cook
9209c5eb60
Rollup merge of #139455 - Skgland:remove_rust-intrinsic_ABI, r=oli-obk
Remove support for `extern "rust-intrinsic"` blocks

Part of rust-lang/rust#132735

Looked manageable and there didn't appear to have been progress in the last two weeks,
so decided to give it a try.
2025-04-07 22:29:20 +10: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
Skgland
5eb535c568
remove compiler support for extern "rust-intrinsic" blocks 2025-04-06 21:32:58 +02:00
Guillaume Gomez
b1d67b2492
Rollup merge of #139391 - TaKO8Ki:check-if-merged-attrs-list-is-empty, r=jdonszelmann
Check if merged attributes list is empty in expr

Fixes #139373

In the example code, an [`UnrecognizedReprHint`](6b5ccfc87f/compiler/rustc_attr_parsing/src/attributes/repr.rs (L155)) error is output, and the list of merged attributes becomes empty. This causes a [panic](6b5ccfc87f/compiler/rustc_ast_lowering/src/lib.rs (L618)) to occur. So, it's necessary to check if merged attributes list is empty as other functions do.

ref: 6b5ccfc87f/compiler/rustc_ast_lowering/src/lib.rs (L896)
2025-04-06 18:08:11 +02:00
Stuart Cook
66ccc4fe28
Rollup merge of #139341 - nnethercote:fix-137874, r=petrochenkov
Apply `Recovery::Forbidden` when reparsing pasted macro fragments.

Fixes #137874.

The changes to the output of `tests/ui/associated-consts/issue-93835.rs`
partly undo the changes seen when `NtTy` was removed in #133436, which
is good.

r? ``@petrochenkov``
2025-04-05 13:18:17 +11:00
Takayuki Maeda
6b5ccfc87f check if merged attributes list is empty 2025-04-05 06:09:14 +09:00
Mara Bos
3123df8ef0 Implement super let. 2025-04-04 09:44:19 +02:00
Nicholas Nethercote
aa1b7bf070 Remove an unwanted comment.
I accidentally added this in #138740.
2025-04-04 09:59:25 +11: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
Mara Bos
cc5ee70b1a Simplify expansion for format_args!().
Instead of calling new(), we can just use a struct expression directly.

Before:

        Placeholder::new(…, …, …, …)

After:

        Placeholder {
                position: …,
                flags: …,
                width: …,
                precision: …,
        }
2025-03-30 10:42:00 +02:00
Nicholas Nethercote
8d2c63f514 Don't use kw::Empty in hir::Lifetime::ident.
`hir::Lifetime::ident` currently sometimes uses `kw::Empty` for elided
lifetimes and sometimes uses `kw::UnderscoreLifetime`, and the
distinction is used when creating some error suggestions, e.g. in
`Lifetime::suggestion` and `ImplicitLifetimeFinder::visit_ty`. I found
this *really* confusing, and it took me a while to understand what was
going on.

This commit replaces all uses of `kw::Empty` in `hir::Lifetime::ident`
with `kw::UnderscoreLifetime`. It adds a new field
`hir::Lifetime::is_path_anon` that mostly replaces the old
empty/underscore distinction and makes things much clearer.

Some other notable changes:

- Adds a big comment to `Lifetime` talking about permissable field
  values.

- Adds some assertions in `new_named_lifetime` about what ident values
  are permissible for the different `LifetimeRes` values.

- Adds a `Lifetime::new` constructor that does some checking to make
  sure the `is_elided` and `is_anonymous` states are valid.

- `add_static_impl_trait_suggestion` now looks at `Lifetime::res`
  instead of the ident when creating the suggestion. This is the one
  case where `is_path_anon` doesn't replace the old empty/underscore
  distinction.

- A couple of minor pretty-printing improvements.
2025-03-28 10:15:23 +11:00
Nicholas Nethercote
909f449247 Remove kw::Extra checks that are no longer necessary.
Thanks to the introduction of `PatKind::Missing`.
2025-03-28 09:20:40 +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
19a53b7d3f
Rollup merge of #138954 - compiler-errors:hash-opaques, r=oli-obk
Ensure `define_opaque` attrs are accounted for in HIR hash

Fixes #138948

r? oli-obk
2025-03-26 19:40:30 +11:00
Jacob Pratt
5bd69d940e
Rollup merge of #138911 - compiler-errors:define-opaque, r=oli-obk
Allow defining opaques in statics and consts

r? oli-obk

Fixes https://github.com/rust-lang/rust/issues/138902
2025-03-25 20:34:49 -04:00
Jacob Pratt
1c84c063f0
Rollup merge of #138128 - compiler-errors:precise-capturing-in-traits, r=oli-obk,traviscross
Stabilize `#![feature(precise_capturing_in_traits)]`

# Precise capturing (`+ use<>` bounds) in traits - Stabilization Report

Fixes https://github.com/rust-lang/rust/issues/130044.

## Stabilization summary

This report proposes the stabilization of `use<>` precise capturing bounds in return-position impl traits in traits (RPITITs). This completes a missing part of [RFC 3617 "Precise capturing"].

Precise capturing in traits was not ready for stabilization when the first subset was proposed for stabilization (namely, RPITs on free and inherent functions - https://github.com/rust-lang/rust/pull/127672) since this feature has a slightly different implementation, and it hadn't yet been implemented or tested at the time. It is now complete, and the type system implications of this stabilization are detailed below.

## Motivation

Currently, RPITITs capture all in-scope lifetimes, according to the decision made in the ["lifetime capture rules 2024" RFC](https://rust-lang.github.io/rfcs/3498-lifetime-capture-rules-2024.html#return-position-impl-trait-in-trait-rpitit). However, traits can be designed such that some lifetimes in arguments may not want to be captured. There is currently no way to express this.

## Major design decisions since the RFC

No major decisions were made. This is simply an extension to the RFC that was understood as a follow-up from the original stabilization.

## What is stabilized?

Users may write `+ use<'a, T>` bounds on their RPITITs. This conceptually modifies the desugaring of the RPITIT to omit the lifetimes that we would copy over from the method. For example,

```rust
trait Foo {
    fn method<'a>(&'a self) -> impl Sized;

    // ... desugars to something like:
    type RPITIT_1<'a>: Sized;
    fn method_desugared<'a>(&'a self) -> Self::RPITIT_1<'a>;

    // ... whereas with precise capturing ...
    fn precise<'a>(&'a self) -> impl Sized + use<Self>;

    // ... desugars to something like:
    type RPITIT_2: Sized;
    fn precise_desugared<'a>(&'a self) -> Self::RPITIT_2;
}
```

And thus the GAT doesn't name `'a`. In the compiler internals, it's not implemented exactly like this, but not in a way that users should expect to be able to observe.

#### Limitations on what generics must be captured

Currently, we require that all generics from the trait (including the `Self`) type are captured. This is because the generics from the trait are required to be *invariant* in order to do associated type normalization.

And like regular precise capturing bounds, all type and const generics in scope must be captured.

Thus, only the in-scope method lifetimes may be relaxed with this syntax today.

## What isn't stabilized? (a.k.a. potential future work)

See section above. Relaxing the requirement to capture all type and const generics in scope may be relaxed when https://github.com/rust-lang/rust/issues/130043 is implemented, however it currently interacts with some underexplored corners of the type system (e.g. unconstrained type bivariance) so I don't expect it to come soon after.

## Implementation summary

This functionality is implemented analogously to the way that *opaque type* precise capturing works.

Namely, we currently use *variance* to model the capturedness of lifetimes. However, since RPITITs are anonymous GATs instead of opaque types, we instead modify the type relation of GATs to consider variances for RPITITs (along with opaque types which it has done since https://github.com/rust-lang/rust/pull/103491).

30f168ef81/compiler/rustc_middle/src/ty/util.rs (L954-L976)

30f168ef81/compiler/rustc_type_ir/src/relate.rs (L240-L244)

Using variance to model capturedness is an implementation detail, and in the future it would be desirable if opaques and RPITITs simply did not include the uncaptured lifetimes in their generics. This can be changed in a forwards-compatible way, and almost certainly would not be observable by users (at least not negatively, since it may indeed fix some bugs along the way).

## Tests

* Test that the lifetime isn't actually captured: `tests/ui/impl-trait/precise-capturing/rpitit.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs`.
* Technical test for variance computation: `tests/ui/impl-trait/in-trait/variance.rs`.
* Test that you must capture all trait generics: `tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs`.
* Test that you cannot capture more than what the trait specifies: `tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs` and `tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs`.
* Undercapturing (refinement) lint: `tests/ui/impl-trait/in-trait/refine-captures.rs`.

### What other unstable features may be exposed by this feature?

I don't believe that this exposes any new unstable features indirectly.

## Remaining bugs and open issues

Not aware of any open issues or bugs.

## Tooling support

Rustfmt:  Supports formatting `+ use<>` everywhere.

Clippy:  No support needed, unless specific clippy lints are impl'd to care for precise capturing itself.

Rustdoc:  Rendering `+ use<>` precise capturing bounds is supported.

Rust-analyzer:  Parser support, and then lifetime support isn't needed https://github.com/rust-lang/rust/pull/138128#issuecomment-2705292494 (previous: ~~ There is parser support, but I am unsure of rust-analyzer's level of support for RPITITs in general.~~)

## History

Tracking issue: https://github.com/rust-lang/rust/issues/130044

* https://github.com/rust-lang/rust/pull/131033
* https://github.com/rust-lang/rust/pull/132795
* https://github.com/rust-lang/rust/pull/136554
2025-03-25 20:34:45 -04:00
Michael Goulet
4b22ac5296 Ensure define_opaque is accounted for in HIR hash 2025-03-26 00:15:34 +00:00
Matthias Krüger
1107fc7ad2
Rollup merge of #138929 - oli-obk:assoc-ctxt-of-trait, r=compiler-errors
Visitors track whether an assoc item is in a trait impl or an inherent impl

`AssocCtxt::Impl` now contains an `of_trait` field. This allows ast lowering and nameres to not have to track whether we're in a trait impl or an inherent impl.
2025-03-25 18:09:07 +01:00
Michael Goulet
f8df298d74 Allow defining opaques in statics and consts 2025-03-25 16:44:59 +00:00
Oli Scherer
59e3380744 Avoid some more global state 2025-03-25 10:33:25 +00:00
Oli Scherer
7cdc456727 Track whether an assoc item is in a trait impl or an inherent impl 2025-03-25 10:12:07 +00:00
Takayuki Maeda
3757104071
Rollup merge of #138895 - oli-obk:dedup-owner-id-creation, r=compiler-errors
Add a helper for building an owner id in ast lowering

Just some deduplication of owner-id creations. Will also help me later split up ast lowering into per-owner queries, as it won't be possible anymore to go from a NodeId to a DefId of an owner without doing extra work to check whether we have an owner id. So I'd just do that in the new `owner_id` function and keep the `local_def_id` function free of that logic
2025-03-25 15:36:36 +09:00
Oli Scherer
67e0b899f0 Add a helper for building an owner id in ast lowering 2025-03-24 15:41:33 +00:00
Michael Goulet
eb3707e4b4 Stabilize precise_capturing_in_traits 2025-03-23 14:11:04 +00:00
Takayuki Maeda
20f4a0d586 fix ICE #138415 2025-03-23 17:02:42 +09:00
bors
0ce1369bde Auto merge of #136974 - m-ou-se:fmt-options-64-bit, r=scottmcm
Reduce FormattingOptions to 64 bits

This is part of https://github.com/rust-lang/rust/issues/99012

This reduces FormattingOptions from 6-7 machine words (384 bits on 64-bit platforms, 224 bits on 32-bit platforms) to just 64 bits (a single register on 64-bit platforms).

Before:

```rust
pub struct FormattingOptions {
    flags: u32, // only 6 bits used
    fill: char,
    align: Option<Alignment>,
    width: Option<usize>,
    precision: Option<usize>,
}
```

After:

```rust
pub struct FormattingOptions {
    /// Bits:
    ///  - 0-20: fill character (21 bits, a full `char`)
    ///  - 21: `+` flag
    ///  - 22: `-` flag
    ///  - 23: `#` flag
    ///  - 24: `0` flag
    ///  - 25: `x?` flag
    ///  - 26: `X?` flag
    ///  - 27: Width flag (if set, the width field below is used)
    ///  - 28: Precision flag (if set, the precision field below is used)
    ///  - 29-30: Alignment (0: Left, 1: Right, 2: Center, 3: Unknown)
    ///  - 31: Always set to 1
    flags: u32,
    /// Width if width flag above is set. Otherwise, always 0.
    width: u16,
    /// Precision if precision flag above is set. Otherwise, always 0.
    precision: u16,
}
```
2025-03-22 10:56:14 +00:00
Matthias Krüger
915576935a
Rollup merge of #138685 - nnethercote:use-Option-Ident-for-lowered-param-names, r=compiler-errors
Use `Option<Ident>` for lowered param names.

Parameter patterns are lowered to an `Ident` by `lower_fn_params_to_names`, which is used when lowering bare function types, trait methods, and foreign functions. Currently, there are two exceptional cases where the lowered param can become an empty `Ident`.

- If the incoming pattern is an empty `Ident`. This occurs if the parameter is anonymous, e.g. in a bare function type.

- If the incoming pattern is neither an ident nor an underscore. Any such parameter will have triggered a compile error (hence the `span_delayed_bug`), but lowering still occurs.

This commit replaces these empty `Ident` results with `None`, which eliminates a number of `kw::Empty` uses, and makes it impossible to fail to check for these exceptional cases.

Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It actually should have been removed in #138482, the precursor to this PR. That PR changed the lowering of wild patterns to `_` symbols instead of empty symbols, which made the mentioned underscore check load-bearing.

r? ``@compiler-errors``
2025-03-20 15:36:17 +01:00
Matthias Krüger
d752721636
Rollup merge of #138435 - eholk:prefix-yield, r=oli-obk
Add support for postfix yield expressions

We've been having a discussion about whether we want postfix yield, or want to stick with prefix yield, or have both. I figured it's easy enough to support both for now and let us play around with them while the feature is still experimental.

This PR treats `yield x` and `x.yield` as semantically equivalent. There was a suggestion to make `yield x` have a `()` type (so it only works in coroutines with `Resume = ()`. I think that'd be worth trying, either in a later PR, or before this one merges, depending on people's opinions.

#43122
2025-03-20 15:36:15 +01:00
Nicholas Nethercote
8121958fda Use -Wunused_crate_dependencies for compiler crates.
It's very useful. There are some false positives involving integration
tests in `rustc_pattern_analysis` and `rustc_serialize`. There is also a
false positive involving `rustc_driver_impl`'s
`rustc_randomized_layouts` feature. And I removed a `rustc_span` mention
in a doc comment in `rustc_log` because it wasn't integral to the
comment but caused a dev-dependency.
2025-03-20 08:59:43 +11:00
Nicholas Nethercote
f27cab806e Use Option<Ident> for lowered param names.
Parameter patterns are lowered to an `Ident` by
`lower_fn_params_to_names`, which is used when lowering bare function
types, trait methods, and foreign functions. Currently, there are two
exceptional cases where the lowered param can become an empty `Ident`.

- If the incoming pattern is an empty `Ident`. This occurs if the
  parameter is anonymous, e.g. in a bare function type.

- If the incoming pattern is neither an ident nor an underscore. Any
  such parameter will have triggered a compile error (hence the
  `span_delayed_bug`), but lowering still occurs.

This commit replaces these empty `Ident` results with `None`, which
eliminates a number of `kw::Empty` uses, and makes it impossible to fail
to check for these exceptional cases.

Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It
actually should have been removed in #138482, the precursor to this PR.
That PR changed the lowering of wild patterns to `_` symbols instead of
empty symbols, which made the mentioned underscore check load-bearing.
2025-03-19 20:54:10 +11:00
Eric Holk
2bd7f73c21
Refactor YieldKind so postfix yield must have an expression 2025-03-18 12:19:43 -07:00
bors
259fdb5212 Auto merge of #138630 - matthiaskrgr:rollup-kk1gogr, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #138384 (Move `hir::Item::ident` into `hir::ItemKind`.)
 - #138508 (Clarify "owned data" in E0515.md)
 - #138531 (Store test diffs in job summaries and improve analysis formatting)
 - #138533 (Only use `DIST_TRY_BUILD` for try jobs that were not selected explicitly)
 - #138556 (Fix ICE: attempted to remap an already remapped filename)
 - #138608 (rustc_target: Add target feature constraints for LoongArch)
 - #138619 (Flatten `if`s in `rustc_codegen_ssa`)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-03-18 05:58:46 +00:00
Nicholas Nethercote
f2ddbcd24b Move hir::Item::ident into hir::ItemKind.
`hir::Item` has an `ident` field.

- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
  `Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
  Trait`, TraitAalis`.

- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
  `Impl`.

- For `Use`, it is non-empty for `UseKind::Single` and empty for
  `UseKind::{Glob,ListStem}`.

All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". 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.

- A similar transformation makes sense for `ast::Item`, but this is
  already a big change. That can be done later.

- Lots of assertions are added to item lowering to ensure that
  identifiers are empty/non-empty as expected. These will be removable
  when `ast::Item` is done later.

- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.

- `lower_use_tree` is significantly simpler. No more confusing `&mut
  Ident` to deal with.

- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
  used with `unwrap` in a few places; sometimes it's hard to tell
  exactly which item kinds might occur. None of these unwraps fail on
  the test suite. It's conceivable that some might fail on alternative
  input. We can deal with those if/when they happen.

- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
  things end up much clearer that way.

- `named_span` no longer checks for an empty name; instead the call site
  now checks for a missing identifier if necessary.

- `maybe_inline_local` doesn't need the `glob` argument, it can be
  computed in-function from the `renamed` argument.

- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
  that was just getting the ident from the item kinds that had one. It
  could be mostly replaced by a single call to the new `ItemKind::ident`
  method.

- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
  and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-18 06:29:50 +11:00
Matthias Krüger
1e58d51290
Rollup merge of #138588 - nnethercote:avoid-double-lower_ident, r=compiler-errors
Avoid double lowering of idents

It's easy to double lower idents and spans because they don't change type when lowered.

r? `@cjgillot`
2025-03-17 16:34:52 +01:00
Gary Guo
292c622507 Stabilize asm_goto 2025-03-17 11:12:10 +00:00
Nicholas Nethercote
adf2bb75ea Avoid double lowering of generic identifiers.
`lower_generic_bound_predicate` calls `lower_ident`, and then passes the
lowered ident into `new_named_lifetime`, which lowers it again. This
commit avoids the first lowering. This requires adding a `lower_ident`
call on a path that doesn't involve `new_named_lifetime`.
2025-03-17 15:48:37 +11:00
Nicholas Nethercote
6496d6943f Make the match in new_named_lifetime exhaustive. 2025-03-17 15:45:06 +11:00
Nicholas Nethercote
fe4d14495f Avoid double lowering of lifetime identifiers.
`LoweringContext::new_named_lifetime` lowers the `ident` passed in. Both
of its call sites *also* lower `ident` *before* passing it in. I.e. both
call sites cause the ident to be lowered twice. This commit removes the
lowering at the two call sites, so the ident is only lowered once.
2025-03-17 15:36:01 +11:00
Nicholas Nethercote
87457f6e00 Inline and remove LoweringContext::new_named_lifetime_with_res.
It has a single call site.
2025-03-17 15:20:22 +11:00
León Orell Valerian Liehr
370f8fb99d
Rollup merge of #138482 - nnethercote:fix-hir-printing, r=compiler-errors
Fix HIR printing of parameters

HIR pretty printing does the wrong thing for anonymous parameters, and there is no test coverage for it. This PR remedies both of those things.

r? ``@lcnr``
2025-03-15 00:18:25 +01:00
Eric Holk
1c0916a2b3
Preserve yield position during pretty printing 2025-03-14 12:21:59 -07:00
Nicholas Nethercote
958bc7b365 Handle _ properly in a couple of places.
Currently (PatKind::Wild` (i.e. `_`) gets turned by
`lower_fn_params_to_names` into an empty identifier, which means it is
printed incorrectly by HIR pretty printing.

And likewise for `lower_fn_params_to_names`, which affects some error
messages.

This commit fixes them. This requires a slight tweak in a couple of
places to continue using parameter numbers in some error messages. And
it improves the output of `tests/ui/typeck/cyclic_type_ice.rs`:
`/* _ */` is a better suggestion than `/*  */`.
2025-03-14 09:45:38 +11:00
Matthias Krüger
41d6e6e8da
Rollup merge of #138399 - Bryanskiy:delegation-extern-fn, r=petrochenkov
Delegation: allow foreign fns `reuse`

In example:
```rust
unsafe extern "C" {
    fn foo();
}

reuse foo as bar;
```

Desugaring before:

```rust
fn bar() {
    foo()
    //~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
}
```

after:

```rust
unsafe extern "C" fn bar() {
    foo()
}
```

Fixes https://github.com/rust-lang/rust/issues/127412

r? `@petrochenkov`
2025-03-13 17:44:07 +01:00