554 Commits

Author SHA1 Message Date
Esteban Küber b849e10d38 Make span_suggestions always verbose
`span_suggestions` is to provide mutually exclusive suggestions. When it was introduced, we made its behavior be that if a single suggestion is given to it, we present the suggestion inline, otherwise in patch format. Changing this to make all of its uses be verbose, as that is closer in intent of output.
2026-04-15 01:38:14 +00:00
Jacob Adam db8ce5fafb Update results for tests affected by the change 2026-04-07 10:08:49 +01:00
Jonathan Brouwer 3c24746323 Rollup merge of #154554 - folkertdev:track-caller-extern-missing-abi, r=TaKO8Ki
emit error on `#[track_caller]` with `extern fn`

fixes https://github.com/rust-lang/rust/issues/154541

A `extern fn` implicitly uses `extern "C"`, but needs some custom logic to emit an error when used in conjunction with `#[track_caller]` which is only allowed on `extern "Rust"` functions. This issue was introduced in https://github.com/rust-lang/rust/pull/153920.
2026-04-06 10:58:15 +02:00
yukang 86796ddaa0 Label overwritten assignments for never read assignments 2026-03-31 20:44:11 +08:00
Jonathan Brouwer 2a18b885ce Rollup merge of #154074 - dianne:dbg-temp-scopes, r=Mark-Simulacrum
don't drop arguments' temporaries in `dbg!`

Fixes rust-lang/rust#153850

Credit to @theemathas for help with macro engineering ^^

r? libs
2026-03-29 21:39:26 +02:00
dianne 7d1b41cbb3 update diagnostic for variables moved by dbg! 2026-03-29 09:48:41 -07:00
Folkert de Vries 3ce8cfbc58 emit error on #[track_caller] with extern fn
such a function implicitly uses `extern "C"
2026-03-29 18:31:34 +02:00
dianne 51816efcc0 don't drop arguments' temporaries in dbg! 2026-03-29 06:38:38 -07:00
Ralf Jung 7881a31ccf Rollup merge of #152880 - JohnTitor:tweak-assoc-item-note, r=fmease
Tweak incorrect assoc item note

Fix rust-lang/rust#142797
r? @fmease
2026-03-28 13:15:48 +01:00
Yuki Okushi 531631c7ad Make messages more generic 2026-03-28 16:18:11 +09:00
bors 3ea2fbcb2a Auto merge of #154010 - estebank:issue-42753, r=nnethercote
Suggest using equality comparison instead of pattern matching on non-structural constant in pattern

When encountering a pattern containing a non-structural constant (not marked as `#[derive(PartialEq)]` to make it suitable for pattern matching, `C` in the examples below), we would previously not provide additional guidance. With this PR, the `help` in the following examples are added:

```
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:16:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |             Some(C) => {}
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
   |
LL -             Some(C) => {}
LL +             Some(binding) if binding == C => {}
   |
```

```
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:22:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |         let Some(C) = Some(S) else { return; };
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: check for equality instead of pattern matching
   |
LL -         let Some(C) = Some(S) else { return; };
LL +         if Some(C) == Some(S) { return; };
   |
```

The suggestion accounts for a few conditions:

 - if the type is not from the local crate and has no `PartialEq` impl, the user can't make it structural, so we don't provide the suggestion
 - regardless of whether the type is local or remote, if it has a manual `PartialEq`, explain that with a derived `PartialEq` you could use equality
 - if the type is local and has no impl, suggest adding a derived `PartialEq` and use equality check instead of pattern matching
 - when suggesting equality, account for `if-let` to suggest chaining (edition dependent), `match` arm with a present `if` check, `match` arm without an existing `if` check
 - when encountering `let-else`, we suggest turning it into an `if` expression instead (this doesn't check for additional bindings beyond the constant, which would suggest incorrect code in some more complex cases).

Fix rust-lang/rust#42753.
2026-03-26 05:30:08 +00:00
cyrgani 9b0be7857a allow incomplete_features in most UI tests 2026-03-21 20:10:07 +00:00
Esteban Küber 3f08f6759a Suggest using equality comparison instead of pattern matching on non-strutural constant in pattern
```
error: constant of non-structural type `partial_eq::S` in a pattern
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:16:18
   |
LL |     struct S;
   |     -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL |     const C: S = S;
   |     ---------- constant defined here
...
LL |             Some(C) => {}
   |                  ^ constant of non-structural type
   |
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
  --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5
   |
LL |     impl PartialEq<S> for S {
   |     ^^^^^^^^^^^^^^^^^^^^^^^
help: add a condition to the match arm checking for equality
   |
LL -             Some(C) => {}
LL +             Some(binding) if binding == C => {}
   |
```
2026-03-17 17:54:01 +00:00
Jonathan Brouwer f4cc98ae79 Rollup merge of #153920 - folkertdev:track-caller-abi-error, r=JonathanBrouwer
improve `#[track_caller]` invalid ABI error

Niche but we can provide more context by emitting the error earlier.
2026-03-17 17:51:34 +01:00
Folkert de Vries 461038f0c9 improve #[track_caller] invalid ABI error 2026-03-15 17:17:36 +01:00
Esteban Küber 39631fdac1 Point at unit structs on foreign crates in type errors when they are the pattern of a let binding
Consts and unit structs in patterns can be confusing if they are mistaken for new bindings. We already provide some context for unit structs and consts that come from the current crate, we now also point at those from foreign crates, and we properly skip cases where the pattern has type parameters which can't be confused with a new binding. Make new binding suggestion verbose.
2026-03-15 01:50:36 +00:00
arferreira 407e421f7f Unify same-span labels in move error diagnostics 2026-03-10 09:35:03 -04:00
Jonathan Brouwer 23e27344e9 Rollup merge of #153300 - fmease:test-attrs-tweaks, r=JonathanBrouwer
Tweak some of our internal `#[rustc_*]` TEST attributes

I think I might be the one who's used the internal TEST attrs `#[rustc_{dump_predicates,object_lifetime_default,outlives,variance}]` the most in recent times, I might even be the only one. As such I've noticed some recent-ish issues that haven't been fixed so far and which keep bothering me. Moreover I have a longstanding urge to rename several of these attributes which I couldn't contain anymore.

[`#[rustc_*]` TEST attributes](https://rustc-dev-guide.rust-lang.org/compiler-debugging.html#rustc_-test-attributes) are internal attributes that basically allow you to dump the output of specific queries for use in UI tests or for debugging purposes.

1. When some of these attributes were ported over to the new parsing API, their targets were unnecessarily restricted. I've kept encountering these incorrect "attribute cannot be used" errors all the while HIR analysis happily & correctly dumped the requested data below it. I've now relaxed their targets.
2. Since we now have target checking for the internal attributes I figured that it's unhelpful if we still intentionally crashed on invalid targets, so I've got rid of that.
3. I've always been annoyed that most of these (very old) attributes don't contain the word `dump` in their name (rendering their purpose non-obvious) and that some of their names diverge quite a bit from the corresponding query name. I've now rectified that. The new names take longer to type but it's still absolutely acceptable imo.

---

I haven't renamed all of the TEST attributes to follow the `rustc_dump_` scheme since that's quite tedious. If it's okay with you I'd like to postpone that (e.g., `rustc_{def_path,hidden_type…,layout,regions,symbol_name}`).

I've noticed that the parsers for TEST attrs are spread across `rustc_dump.rs`, `rustc_internal.rs` & `test_attrs.rs` which is a bit confusing. Since the new names are prefixed with `rustc_dump_` I've moved their parsers into `rustc_dump.rs` but of course they are still TEST attrs. IIRC, `test_attrs.rs` also contains non-`rustc_`-TEST attrs, so we can't just merge these two files. I guess that'll sort itself out in the future when I tackle the other internal TEST attrs.

r\? Jana || Jonathan
2026-03-04 19:30:39 +01:00
Daniel Scherzer 158ac1a10b Comments and docs: add missing periods to "ie."
"i.e." is short for the Latin "id est" and thus both letters should be followed
by periods.
2026-03-02 18:11:13 -08:00
León Orell Valerian Liehr c3a40e26e4 Rename #[rustc_outlives] to #[rustc_dump_inferred_outlives] 2026-03-02 19:31:14 +01:00
mu001999 dfd18b7e89 Print path root when printing path 2026-02-26 23:34:41 +08:00
Guillaume Gomez d926c1b06e Migrate rustc_mir_build to use TyCtxt::emit_diag_node_span_lint 2026-02-24 20:12:42 +01:00
Jonathan Brouwer ff7d14e17d Rollup merge of #146972 - mu001999-contrib:fix/use-dollar-crate, r=petrochenkov
Support importing path-segment keyword with renaming

*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/146972)*

#### Reference PR

- https://github.com/rust-lang/reference/pull/2010
- https://github.com/rust-lang/reference/pull/2136

#### Description

This PR unifies and extends the behavior of importing path-segment keywords (`crate`/`$crate`/`super`/`self`), resolving several long-standing inconsistencies.

Previously, Rust only allowed `use crate as name;` without renaming support for other path keywords. This PR enables importing these keywords with explicit renaming. And it also denies importing these keywords without renaming.

##### What's now allowed

For **`crate`** and **`$crate`**:
- `use crate as name;`
- `use crate::{self as name};`
- `use $crate as name;`
- `use $crate::{self as name};`

For **`super`** (including chained `super::super`):
- `use super as name;`
- `use super::{self as name};`
- `use super::super as name;`
- `use super::super::{self as name};`

For **`self`**:
- `use self as name;`
- `use self::{self as name};`

##### Removed error codes

Two error codes are no longer emitted:

- **E0430**: Previously emitted for duplicate `self` imports like `std::fmt::{self, self}`. The existing E0252 ("name defined multiple times") provides sufficient guidance.
- **E0431**: Previously emitted for `use {self [as name]};` and `use ::{self [as name]};`. These patterns are now allowed or denied but with new clearer errors.
    - For `use {self as name};` and `use ::{self as name};` (in edition 2015), they are allowed now and equivalent to `use crate as name`;
    - For `use {self};` and `use ::{self};` (in edition 2015) without renaming, they are equivalent to `use crate;`, the new clearer error suggests adding an explicit rename.
    - For `use ::{self [as name]};` after edition 2015, it is equivalent to `use ${extern-prelude} [as name];`, it is denied with new errors.

##### Future

We plan to remove error [E0429](https://doc.rust-lang.org/stable/error_codes/E0429.html#error-code-e0429) and support `self` at the end of paths (https://github.com/rust-lang/rust/pull/146972#issuecomment-3719825627). This language extension and lint for redundant `::self` instead of hard error `E0429` will be landed separately in the future.

---

Fixes rust-lang/rust#29036
Fixes rust-lang/rust#35612
Fixes rust-lang/rust#37156
Fixes rust-lang/rust#146967
Fixes rust-lang/rust#149811

r? petrochenkov
2026-02-20 22:00:54 +01:00
mu001999 58e5475683 Rewrite build_reduced_graph_for_use_tree 2026-02-20 10:58:58 +08:00
Hegui Dai 4f31ff893d Not linting irrefutable_let_patterns on let chains
inline rest of the check
try fix ci errors
inline in check_let
2026-02-19 22:27:26 +08:00
bors e0cb264b81 Auto merge of #141295 - Kivooeo:if-let-guard-stable, r=fee1-dead,est31
Stabilize `if let` guards (`feature(if_let_guard)`)



## Summary

This proposes the stabilization of `if let` guards (tracking issue: rust-lang/rust#51114, RFC: rust-lang/rfcs#2294). This feature allows `if let` expressions to be used directly within match arm guards, enabling conditional pattern matching within guard clauses.

## What is being stabilized

The ability to use `if let` expressions within match arm guards.

Example:

```rust
enum Command {
    Run(String),
    Stop,
    Pause,
}

fn process_command(cmd: Command, state: &mut String) {
    match cmd {
        Command::Run(name) if let Some(first_char) = name.chars().next() && first_char.is_ascii_alphabetic() => {
            // Both `name` and `first_char` are available here
            println!("Running command: {} (starts with '{}')", name, first_char);
            state.push_str(&format!("Running {}", name));
        }
        Command::Run(name) => {
            println!("Cannot run command '{}'. Invalid name.", name);
        }
        Command::Stop if state.contains("running") => {
            println!("Stopping current process.");
            state.clear();
        }
        _ => {
            println!("Unhandled command or state.");
        }
    }
}
```

## Motivation

The primary motivation for `if let` guards is to reduce nesting and improve readability when conditional logic depends on pattern matching. Without this feature, such logic requires nested `if let` statements within match arms:

```rust
// Without if let guards
match value {
    Some(x) => {
        if let Ok(y) = compute(x) {
            // Both `x` and `y` are available here
            println!("{}, {}", x, y);
        }
    }
    _ => {}
}

// With if let guards
match value {
    Some(x) if let Ok(y) = compute(x) => {
        // Both `x` and `y` are available here
        println!("{}, {}", x, y);
    }
    _ => {}
}
```

## Implementation and Testing

The feature has been implemented and tested comprehensively across different scenarios:

### Core Functionality Tests

**Scoping and variable binding:**
- [`scope.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/scope.rs) - Verifies that bindings created in `if let` guards are properly scoped and available in match arms
- [`shadowing.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs) - Tests that variable shadowing works correctly within guards
- [`scoping-consistency.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/scoping-consistency.rs) - Ensures temporaries in guards remain valid for the duration of their match arms

**Type system integration:**
- [`type-inference.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs) - Confirms type inference works correctly in `if let` guards  
- [`typeck.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs) - Verifies type mismatches are caught appropriately

**Pattern matching semantics:**
- [`exhaustive.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs) - Validates that `if let` guards are correctly handled in exhaustiveness analysis
- [`move-guard-if-let.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs) and [`move-guard-if-let-chain.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs) - Test that conditional moves in guards are tracked correctly by the borrow checker

### Error Handling and Diagnostics

- [`warns.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs) - Tests warnings for irrefutable patterns and unreachable code in guards
- [`parens.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs) - Ensures parentheses around `let` expressions are properly rejected
- [`macro-expanded.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs) - Verifies macro expansions that produce invalid constructs are caught
- [`guard-mutability-2.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs) - Tests mutability and ownership violations in guards
- [`ast-validate-guards.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2497-if-let-chains/ast-validate-guards.rs) - Validates AST-level syntax restrictions

### Drop Order and Temporaries

**Key insight:** Unlike `let_chains` in regular `if` expressions, `if let` guards do not have drop order inconsistencies because:
1. Match guards are clearly scoped to their arms
2. There is no "else block" equivalent that could cause temporal confusion

- [`drop-order.rs`](https://github.com/rust-lang/rust/blob/5796073c134eaac30475f9a19462c4e716c9119c/tests/ui/rfcs/rfc-2294-if-let-guard/drop-order.rs) - Check drop order of temporaries create in match guards
- [`compare-drop-order.rs`](https://github.com/rust-lang/rust/blob/aef3f5fdf052fbbc16e174aef5da6d50832ca316/tests/ui/rfcs/rfc-2294-if-let-guard/compare-drop-order.rs) - Compares drop order between `if let` guards and nested `if let` in match arms, confirming they behave identically across all editions
- rust-lang/rust#140981 - A complicated drop order test involved `let chain` was made by @est31
- [`drop-order-comparisons-let-chains.rs`](https://github.com/rust-lang/rust/blob/902b4d28783e03e231d8513082cc30c4fcce5d95/tests/ui/drop/drop-order-comparisons-let-chains.rs) - Compares drop order between `let chains` in `if let guard` and regular `if` expressions
- [`if-let-guards.rs`](https://github.com/rust-lang/rust/blob/5650d716e0589e2e145ce9027f35bd534e5f862a/tests/ui/drop/if-let-guards.rs) - Test correctness of drop order for bindings and temporaries
- [`if-let-guards-2`](https://github.com/rust-lang/rust/blob/3a6c8c8f3d7ae654fdb6ce1255182bda21680655/tests/ui/drop/if-let-guards-2.rs) - The same test as above but more comprehensive and tests more interactions between different features and their drop order, checking that drop order is correct, created by @traviscross 

## Edition Compatibility

This feature stabilizes on all editions, unlike `let chains` which was limited to edition 2024. This is safe because:

1. `if let` guards don't suffer from the drop order issues that affected `let chains` in regular `if` expressions
2. The scoping is unambiguous - guards are clearly tied to their match arms
3. Extensive testing confirms identical behavior across all editions

## Interactions with Future Features

The lang team has reviewed potential interactions with planned "guard patterns" and determined that stabilizing `if let` guards now does not create obstacles for future work. The scoping and evaluation semantics established here align with what guard patterns will need.

## Unresolved Issues

- [x] - rust-lang/rust#140981
- [x] - added tests description by @jieyouxu request
- [x] - Concers from @scottmcm about stabilizing this across all editions
- [x] - check if drop order in all edition when using `let chains` inside `if let` guard is the same
- [x] - interactions with guard patters
- [x] - pattern bindings drops before guard bindings https://github.com/rust-lang/rust/pull/143376
- [x] - documentaion (https://github.com/rust-lang/reference/pull/1957)
- [ ] (non-blocking) add tests for [this](https://github.com/rust-lang/rust/issues/145237) and [this](https://github.com/rust-lang/rust/pull/141295#issuecomment-3173059821)

---

**Related:**
- Tracking Issue: rust-lang/rust#51114  
- RFC: rust-lang/rfcs#2294
- Documentation PR: https://github.com/rust-lang/reference/pull/1957
2026-02-18 20:49:50 +00:00
Esteban Küber c73b3d20c6 Unify wording of resolve error
Remove "failed to resolve" and use the same format we use in other resolution errors "cannot find `name`".

```
error[E0433]: cannot find `nonexistent` in `existent`
  --> $DIR/custom_attr_multisegment_error.rs:5:13
   |
LL | #[existent::nonexistent]
   |             ^^^^^^^^^^^ could not find `nonexistent` in `existent`
```
2026-02-17 16:51:44 +00:00
Kivooeo 964b63f42e if let guard stabilize 2026-02-16 12:24:15 +00:00
bors f8463896a9 Auto merge of #150681 - meithecatte:always-discriminate, r=JonathanBrouwer,Nadrieril
Make operational semantics of pattern matching independent of crate and module

The question of "when does matching an enum against a pattern of one of its variants read its discriminant" is currently an underspecified part of the language, causing weird behavior around borrowck, drop order, and UB.

Of course, in the common cases, the discriminant must be read to distinguish the variant of the enum, but currently the following exceptions are implemented:

1. If the enum has only one variant, we currently skip the discriminant read.
     - This has the advantage that single-variant enums behave the same way as structs in this regard.
     - However, it means that if the discriminant exists in the layout, we can't say that this discriminant being invalid is UB. This makes me particularly uneasy in its interactions with niches – consider the following example ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=5904a6155cbdd39af4a2e7b1d32a9b1a)), where miri currently doesn't detect any UB (because the semantics don't specify any):

        <details><summary>Example 1</summary>

        ```rust
        #![allow(dead_code)]
        use core::mem::{size_of, transmute};
        
        #[repr(u8)]
        enum Inner {
            X(u8),
        }
        
        enum Outer {
            A(Inner),
            B(u8),
        }
        
        fn f(x: &Inner) {
            match x {
                Inner::X(v) => {
                    println!("{v}");
                }
            }
        }
        
        fn main() {
            assert_eq!(size_of::<Inner>(), 2);
            assert_eq!(size_of::<Outer>(), 2);
            let x = Outer::B(42);
            let y = &x;
            f(unsafe { transmute(y) });
        }
        ```

      </details>

2. For the purpose of the above, enums with marked with `#[non_exhaustive]` are always considered to have multiple variants when observed from foreign crates, but the actual number of variants is considered in the current crate.
    - This means that whether code has UB can depend on which crate it is in: https://github.com/rust-lang/rust/issues/147722
    - In another case of `#[non_exhaustive]` affecting the runtime semantics, its presence or absence can change what gets captured by a closure, and by extension, the drop order: https://github.com/rust-lang/rust/issues/147722#issuecomment-3674554872
    - Also at the above link, there is an example where removing `#[non_exhaustive]` can cause borrowck to suddenly start failing in another crate.
3. Moreover, we currently make a more specific check: we only read the discriminant if there is more than one *inhabited* variant in the enum.
    - This means that the semantics can differ between `foo<!>`, and a copy of `foo` where `T` was manually replaced with `!`: rust-lang/rust#146803
    - Moreover, due to the privacy rules for inhabitedness, it means that the semantics of code can depend on the *module* in which it is located.
    - Additionally, this inhabitedness rule is even uglier due to the fact that closure capture analysis needs to happen before we can determine whether types are uninhabited, which means that whether the discriminant read happens has a different answer specifically for capture analysis.
    - For the two above points, see the following example ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=a07d8a3ec0b31953942e96e2130476d9)):

        <details><summary>Example 2</summary>

        ```rust
        #![allow(unused)]
        
        mod foo {
            enum Never {}
            struct PrivatelyUninhabited(Never);
            pub enum A {
                V(String, String),
                Y(PrivatelyUninhabited),
            }
            
            fn works(mut x: A) {
                let a = match x {
                    A::V(ref mut a, _) => a,
                    _ => unreachable!(),
                };
                
                let b = match x {
                    A::V(_, ref mut b) => b,
                    _ => unreachable!(),
                };
            
                a.len(); b.len();
            }
            
            fn fails(mut x: A) {
                let mut f = || match x {
                    A::V(ref mut a, _) => (),
                    _ => unreachable!(),
                };
                
                let mut g = || match x {
                    A::V(_, ref mut b) => (),
                    _ => unreachable!(),
                };
            
                f(); g();
            }
        }
        
        use foo::A;
        
        fn fails(mut x: A) {
            let a = match x {
                A::V(ref mut a, _) => a,
                _ => unreachable!(),
            };
            
            let b = match x {
                A::V(_, ref mut b) => b,
                _ => unreachable!(),
            };
        
            a.len(); b.len();
        }
        
        
        fn fails2(mut x: A) {
            let mut f = || match x {
                A::V(ref mut a, _) => (),
                _ => unreachable!(),
            };
            
            let mut g = || match x {
                A::V(_, ref mut b) => (),
                _ => unreachable!(),
            };
        
            f(); g();
        }
        ```

        </details>

In light of the above, and following the discussion at rust-lang/rust#138961 and rust-lang/rust#147722, this PR ~~makes it so that, operationally, matching on an enum *always* reads its discriminant.~~ introduces the following changes to this behavior:

 - matching on a `#[non_exhaustive]` enum will always introduce a discriminant read, regardless of whether the enum is from an external crate
 - uninhabited variants now count just like normal ones, and don't get skipped in the checks

As per the discussion below, the resolution for point (1) above is that it should land as part of a separate PR, so that the subtler decision can be more carefully considered.

Note that this is a breaking change, due to the aforementioned changes in borrow checking behavior, new UB (or at least UB newly detected by miri), as well as drop order around closure captures. However, it seems to me that the combination of this PR with rust-lang/rust#138961 should have smaller real-world impact than rust-lang/rust#138961 by itself.

Fixes rust-lang/rust#142394 
Fixes rust-lang/rust#146590
Fixes rust-lang/rust#146803 (though already marked as duplicate)
Fixes parts of rust-lang/rust#147722
Fixes rust-lang/miri#4778

r? @Nadrieril @RalfJung 

@rustbot label +A-closures +A-patterns +T-opsem +T-lang
2026-02-14 12:53:09 +00:00
Alan Egerton c43a33eec7 Feed ErrorGuaranteed from late lifetime resolution to RBV
If late lifetime resolution fails for whatever reason, forward to RBV
the guarantee that an error was emitted - thereby eliminating the need
for a "hack" to suppress subsequent/superfluous error diagnostics.
2026-02-13 16:24:39 +00:00
Jonathan Brouwer eeb3a24813 Rollup merge of #151833 - clubby789:union-adt, r=JonathanBrouwer
Treat unions as 'data types' in attr parsing diagnostics

I found 'data types _and_ unions' to be a little surprising
2026-01-29 17:47:32 +01:00
Jamie Hill-Daniel b226583d94 Treat unions as 'data types' in attr parsing diagnostics 2026-01-29 15:51:43 +00:00
Stuart Cook 36a2726bb4 Rollup merge of #151475 - KaiTomotake:add-foreign-type-tests, r=Kivooeo
add foregin type tests for issue 64458

add tests/ui/rfcs/rfc-1861-extern-types/comparison.rs

close rust-lang/rust#64458
2026-01-29 22:34:09 +11:00
Esteban Küber 4a27be6972 Do not mention -Zmacro-backtrace for std macros that are a wrapper around a compiler intrinsic 2026-01-26 17:34:31 +00:00
KaiTomotake e86cfa0577 add foregin type tests
add tests/ui/rfcs/rfc-1861-extern-types/comparison.rs
2026-01-23 08:56:44 +09:00
joboet ee24f22b7c update UI tests 2026-01-21 19:20:04 +01:00
Maja Kądziołka af302a67fd discriminant reads: make semantics independent of module/crate 2026-01-15 19:12:13 +01:00
Jonathan Brouwer cbcd1c3eef Rollup merge of #151036 - issue-151026, r=mati865
Better handle when trying to iterate on a `Range` of a type that isn't `Step`

Mention when a trait bound corresponds to an unstable trait.

Mention `Range` when `Step` bound is unment, and explain that only some std types impl `Iterator` for `Range`.

CC rust-lang/rust#151026
2026-01-14 11:05:40 +01:00
Lukas Bergdoll 506762f3ff Explicitly export core and std macros
Currently all core and std macros are automatically added to the prelude
via #[macro_use]. However a situation arose where we want to add a new macro
`assert_matches` but don't want to pull it into the standard prelude for
compatibility reasons. By explicitly exporting the macros found in the core and
std crates we get to decide on a per macro basis and can later add them via
the rust_20xx preludes.
2026-01-13 08:47:48 +01:00
Esteban Küber cafe91749f On unmet trait bound, mention if trait is unstable 2026-01-13 01:16:58 +00:00
Rémy Rakic fa77598824 update tests and bless expectations
just to show the diagnostics impact
2025-12-10 14:47:49 +00:00
Christian Poveda b2ab7cf980 Gate 2015 UI tests 2025-11-27 11:19:00 -05:00
reddevilmidzy d3e4dd29a8 Use let...else consistently in user-facing diagnostics 2025-11-24 11:41:52 +09:00
Esteban Küber 71b0755a98 Provide more context when mutably borrowing an imutable borrow
Point at statics and consts being mutable borrowed or written to:

```
error[E0594]: cannot assign to immutable static item `NUM`
  --> $DIR/E0594.rs:4:5
   |
LL | static NUM: i32 = 18;
   | --------------- this `static` cannot be written to
...
LL |     NUM = 20;
   |     ^^^^^^^^ cannot assign
```

Point at the expression that couldn't be mutably borrowed from a pattern:

```
error[E0596]: cannot borrow data in a `&` reference as mutable
  --> $DIR/mut-pattern-of-immutable-borrow.rs:19:14
   |
LL |     match &arg.field {
   |           ---------- this cannot be borrowed as mutable
LL |         Some(ref mut s) => s.push('a'),
   |              ^^^^^^^^^ cannot borrow as mutable
```
2025-11-09 22:14:48 +00:00
Jonathan Brouwer 66b8a9db1f Update uitests with new unused_attributes warnings
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
2025-10-18 21:17:48 +02:00
Matthias Krüger a5d38ede1d Rollup merge of #145724 - folkertdev:track-caller-drop-no-mangle, r=fee1-dead
the `#[track_caller]` shim should not inherit `#[no_mangle]`

fixes https://github.com/rust-lang/rust/issues/143162

builds on https://github.com/rust-lang/rust/pull/143293 which introduced a mechanism to strip attributes from shims.

cc `@Jules-Bertholet` `@workingjubilee` `@bjorn3`

---

Summary:

This PR fixes an interaction between `#[track_caller]`, `#[no_mangle]`, and casting to a function pointer.

A function annotated with `#[track_caller]` internally has a hidden extra argument for the panic location. The `#[track_caller]` attribute is only allowed on `extern "Rust"` functions. When a function is annotated with both `#[no_mangle]` and `#[track_caller]`, the exported symbol has the signature that includes the extra panic location argument. This works on stable rust today:

```rust
extern "Rust" {
    #[track_caller]
    fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>;
}

mod provides {
    use std::panic::Location;
    #[track_caller] // UB if we did not have this!
    #[no_mangle]
    fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static> {
        Location::caller()
    }
}
```

When a `#[track_caller]` function is converted to a function pointer, a shim is added to drop the additional argument. So this is a valid program:

```rust
#[track_caller]
fn foo() {}

fn main() {
    let f = foo as fn();
    f();
}
```

The issue arises when `foo` is additionally annotated with `#[no_mangle]`, the generated shim currently inherits this attribute, also exporting a symbol named `foo`, but one without the hidden panic location argument. The linker rightfully complains about a duplicate symbol.

The solution of this PR is to have the generated shim drop the `#[no_mangle]` attribute.
2025-10-18 08:08:36 +02:00
Camille GILLOT ca0379d6cd Diagnose liveness on MIR. 2025-10-11 20:50:21 +00:00
Folkert de Vries 9db778155e add indirect call example to track-caller-ffi.rs 2025-10-02 20:53:13 +02:00
Folkert de Vries 20d62469ba the #[track_caller] shim should not inherit #[no_mangle] 2025-10-02 20:53:12 +02:00
Guillaume Gomez a535c7be54 Ignore more failing ui tests for GCC backend 2025-09-26 15:33:48 +02:00