Remove `impl IntoQueryParam<P> for &'a P`.
`IntoQueryParam` is a trait that lets query callers be a bit sloppy with the passed-in key.
- Types similar to `DefId` will be auto-converted to `DefId`. Likewise for `LocalDefId`.
- Reference types will be auto-derefed.
The auto-conversion is genuinely useful; the auto-derefing much less so. In practice it's only used for passing `&DefId` to queries that accept `DefId`, which is an anti-pattern because `DefId` is marked with `#[rustc_pass_by_value]`.
This commit removes the auto-deref impl and makes the necessary sigil adjustments. (I generally avoid using `*` to deref manually at call sites, preferring to deref via `&` in patterns or via `*` in match expressions. Mostly because that way a single deref often covers multiple call sites.)
r? @cjgillot
fix(codegen): Use `body_codegen_attrs` For Caller In `adjust_target_feature_sig`
### Summary:
#### Problem:
Coercing a `#[target_feature]` `const fn` to a function pointer inside a `const` body triggers an ICE (debug builds only):
```rust
#[target_feature(enable = "sse2")]
const fn with_target_feature() {}
const X: () = unsafe {
let _: unsafe fn() = with_target_feature; // ICE
};
```
```text
assertion failed: def_kind.has_codegen_attrs()
unexpected `def_kind` in `codegen_fn_attrs`: Const
```
#### Root Cause:
Introduced in rust-lang/rust#135504 (2025-01-14, commit `8fee6a77394`). `adjust_target_feature_sig` unconditionally calls `codegen_fn_attrs(caller)` to get the caller's target features. `codegen_fn_attrs` requires that the `DefId` satisfies `has_codegen_attrs()`. `DefKind::Const`, `AssocConst`, and `InlineConst` do not — they have no codegen attributes by design. The debug assertion fires.
In release builds the call "worked" accidentally: `codegen_fn_attrs` on a const would reach the query machinery and happen to return empty attributes, producing a correct (but unguaranteed) result. The bug was latent until debug builds exposed it.
#### Solution:
Replace `codegen_fn_attrs(caller)` with `body_codegen_attrs(caller)`. `body_codegen_attrs` exists precisely for this case: it delegates to `codegen_fn_attrs` for function-like `DefKind`s and returns `CodegenFnAttrs::EMPTY` for const items. A const body has no target features, so returning empty is semantically correct.
Also fix the pre-existing variable name `callee_features` → `caller_features` (the variable holds the *caller*'s features, not the callee's).
### Changes:
- `compiler/rustc_middle/src/ty/context.rs`: `adjust_target_feature_sig` — use `body_codegen_attrs` for `caller`; rename `callee_features` → `caller_features`.
- `tests/ui/target-feature/const-target-feature-fn-ptr-coercion.rs`: regression test covering `Const`, `AssocConst`, and `InlineConst` caller contexts.
Fixesrust-lang/rust#152340.
Test(lib/win/proc): Skip `raw_attributes` doctest under Win7
The current doctest for `ProcThreadAttributeListBuilder::raw_attribute` uses `CreatePseudoConsole`, which is only available on Windows 10 October 2018 Update and above. On older versions of Windows, the test fails due to trying to link against a function that is not present in the kernel32 DLL. This therefore ensures the test is still built, but not run under the Win7 target.
@rustbot label T-libs A-process A-doctests O-windows-7
reduce the amount of panics in `{TokenStream, Literal}::from_str` calls
*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/147859)*
Before this PR, calling `TokenStream::from_str` or `Literal::from_str` with an invalid argument would always cause a compile error, even if the `TokenStream` is not used afterwards at all.
This PR changes this so it returns a `LexError` instead in some cases.
This is very theoretically a breaking change, but the doc comment on the impl already says
```
/// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
/// change these errors into `LexError`s later.
```
Fixes some cases of rust-lang/rust#58736.
Simplify internals of `{Rc,Arc}::default`
This commit simplifies the internal implementation of `Default` for these two pointer types to have the same performance characteristics as before (a side effect of changes in rust-lang/rust#131460) while avoid use of internal private APIs of Rc/Arc. To preserve the same codegen as before some non-generic functions needed to be tagged as `#[inline]` as well, but otherwise the same IR is produced before/after this change.
The motivation of this commit is I was studying up on the state of initialization of `Arc` and `Rc` and figured it'd be nicer to reduce the use of internal APIs and instead use public stable APIs where possible, even in the implementation itself.
Fix ICE in const eval of packed SIMD types with non-power-of-two element counts
fixesrust-lang/rust#151537
const evaluation of packed SIMD types with non-power-of-two element counts (like `Simd<_, 3>`) was hitting an ICE. the issue was in `check_simd_ptr_alignment` - it asserted that `backend_repr` must be `BackendRepr::SimdVector`, but for packed SIMD types with non-power-of-two counts the compiler uses `BackendRepr::Memory` instead (as mentioned in `rustc_abi/src/layout.rs:1511`).
was fixed by making `check_simd_ptr_alignment` accept both `BackendRepr::SimdVector` and `BackendRepr::Memory` for SIMD types. added a check to ensure we're dealing with a SIMD type, and the alignment logic works the same for both representations.
also i added a test that reproduces the original ICE.
rustc_target: callconv: powerpc64: Use the ABI set in target options instead of guessing
All PowerPC64 targets except AIX explicitly set the ABI in the target options. We can therefore stop hardcoding the ABI to be used based on the target environment or OS, except for the AIX special case.
The fallback based on endianness is kept for the sake of compatibility with custom targets.
This makes it so that big endian targets not explicitly accounted for before (powerpc64-unknown-openbsd) and targets that don't use the expected default ABI (big-endian ELFv2 Glibc targets) use the correct ABI in the calling convention code.
The second commit is a tiny change to validate the `llvm_abiname` set on PowerPC64(LE) targets. See the commit messages for details.
CC @RalfJung who pointed out the missing `llvm_abiname` validation
Simplify `size/align_of_val<T: Sized>` to `size/align_of<T>` instead
This is relevant to things like `Box<[u8; 1024]>` where the drop looks at the `size_of_val` (since obviously it might be DST in general) but where we don't actually need to do that since it's always that same value for the `Sized` type.
(Equivalent to rust-lang/rust#152681, but flipped in the rebase so it can land before rust-lang/rust#152641 instead of depending on it.)
Perform many const checks in typeck
Some smaller diagnostic changes, the biggest ones avoided by https://github.com/rust-lang/rust/pull/148641
We should be able to move various checks in mir const checking to using `span_bug!` instead of reporting an error, just like mir typeck does as a sanity check. I would like to start doing so separately though, as this PR is a big enough (in what effects it causes, pun intended).
r? @fee1-dead
Simplify the canonical enum clone branches to a copy statement
I have overhauled MatchBranchSimplification in this PR. This pass tries to unify statements one by one, which is more readable and extensible.
This PR also unifies the following pattern that is mostly generated by GVN into one basic block that contains the copy statement:
```rust
match a {
Foo::A(_) => *a,
Foo::B => Foo::B
}
```
Fixes https://github.com/rust-lang/rust/issues/128081.
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`](5796073c13/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`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs) - Tests that variable shadowing works correctly within guards
- [`scoping-consistency.rs`](5796073c13/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`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs) - Confirms type inference works correctly in `if let` guards
- [`typeck.rs`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/typeck.rs) - Verifies type mismatches are caught appropriately
**Pattern matching semantics:**
- [`exhaustive.rs`](5796073c13/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`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs) and [`move-guard-if-let-chain.rs`](5796073c13/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`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/warns.rs) - Tests warnings for irrefutable patterns and unreachable code in guards
- [`parens.rs`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs) - Ensures parentheses around `let` expressions are properly rejected
- [`macro-expanded.rs`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs) - Verifies macro expansions that produce invalid constructs are caught
- [`guard-mutability-2.rs`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs) - Tests mutability and ownership violations in guards
- [`ast-validate-guards.rs`](5796073c13/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`](5796073c13/tests/ui/rfcs/rfc-2294-if-let-guard/drop-order.rs) - Check drop order of temporaries create in match guards
- [`compare-drop-order.rs`](aef3f5fdf0/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`](902b4d2878/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`](5650d716e0/tests/ui/drop/if-let-guards.rs) - Test correctness of drop order for bindings and temporaries
- [`if-let-guards-2`](3a6c8c8f3d/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
Support JSON target specs in bootstrap
JSON target specs were destabilized in https://github.com/rust-lang/rust/pull/150151 and https://github.com/rust-lang/rust/pull/151534. However, this broke trying to build rustc itself with a JSON target spec. This is because in a few places bootstrap is manually calling `rustc` without the ability for the user to provide additional flags (primarily, `-Zunstable-options` to enable JSON targets).
There's a few different ways to fix this. One would be to change these calls to `rustc` to include flags provided by the user (such as `RUSTFLAGS_NOT_BOOTSTRAP`). Just to keep things simple, this PR proposes to just unconditionally pass `-Zunstable-options`.
Another consideration here is how maintainable this is. A possible improvement here would be to have a function somewhere (BootstrapCommand, TargetSelection, free function) that would handle appropriately adding the `--target` flag. For example, that's what cargo does in [`CompileKind::add_target_arg`](592058c7ce/src/cargo/core/compiler/compile_kind.rs (L144-L154)).
I have only tested building the compiler and a few tools like rustdoc. I have not tested doing things like building other tools, running tests, etc.
This would be much easier if there was a Docker image for testing the use case of building rustc with a custom target spec (and even better if that ran in CI).
After the next beta branch, using target JSON specs will become more cumbersome because target specs with the `.json` extension will now require passing `-Zjson-target-spec` (from
https://github.com/rust-lang/cargo/pull/16557). This does not affect target specs without the `.json` extension (such as those from RUST_TARGET_PATH). From my testing, it should be sufficient to pass `CARGOFLAGS_NOT_BOOTSTRAP="-Zjson-target-spec"`. I think that should be fine, since this is not a particularly common use case AFAIK. We could extend bootstrap to auto-detect if the target is a file path, and pass `-Zjson-target-spec` appropriately. I tried something similar in f0bdd35483, which could be adapted if desired.
It would be nice if all of this is documented somewhere. https://rustc-dev-guide.rust-lang.org/building/new-target.html does not really say how to build the compiler with a custom json target.
Fixes https://github.com/rust-lang/rust/issues/151729
Revert "Fix an ICE in the vtable iteration for a trait reference"
The ICE fix appears to be unsound, causing a miscompilation involving `dyn Trait` and `async {}` which induces segfaults in safe Rust code. As the patch only hid an ICE, it does not seem worth the risk.
This addresses the problem in rust-lang/rust#152735 but it may still merit team discussion even if this PR is merged.
This reverts commit 8afd63610b0a261d3c39e24140c6a87d3bff075c, reversing changes made to 19122c03c7bea6bde1dfa5c81fca5810953d9f39.
Suppress unstable-trait notes under `-Zforce-unstable-if-unmarked`
- Fixes https://github.com/rust-lang/rust/issues/152692.
---
https://github.com/rust-lang/rust/pull/151036 adds extra diagnostic text (“the nightly-only, unstable trait”) to note when a not-implemented trait is unstable.
However, that extra text is usually unhelpful when building a crate graph with `-Zforce-unstable-if-unmarked` (such as the compiler or stdlib), because *any* trait not explicitly marked stable will be treated as unstable.
(For typical compiler contributors using the stage0 compiler, this fix won't take effect until the next bootstrap beta bump.)
Fix mis-constructed `file_span` when generating scraped examples
Fixesrust-lang/rust#152601. Seemingly relative with rust-lang/rust#147399 but I could not reproduce the original ICE.
This PR removes the `file_span` logic from scraped example generation. The original implementation did not read or write items using `file_span`; it only used it to locate a source file, `context.href_from_span`. However, the span was validated against the wrong file, which could trigger ICEs on inputs such as multibyte characters due to an incorrectly constructed span. Since scraped examples do not use the span and the `url` is already given, the safest and simplest fix is to remove it.
Tested against the crate and MCVE documented in the original issue.
P.S. there seems to be some bug when rendering call sites, but since fixing mis-behavior is a change rather than a bug-fix that would be implemented in another PR.
Avoid ICE in From/TryFrom diagnostic under -Znext-solver
Fixesrust-lang/rust#152518.
Under `-Znext-solver=globally`, `trait_ref.args` may contain fewer
elements than expected. The diagnostic logic in
`fulfillment_errors.rs` assumed at least two elements and
unconditionally called `type_at(1)`, which could lead to an
index out-of-bounds panic during error reporting.
This change adds a defensive check before accessing the second
argument to avoid the ICE. A UI regression test has been added.
Implement RFC 3678: Final trait methods
Tracking: https://github.com/rust-lang/rust/issues/131179
This PR is based on rust-lang/rust#130802, with some minor changes and conflict resolution.
Futhermore, this PR excludes final methods from the vtable of a dyn Trait.
And some excerpt from the original PR description:
> Implements the surface part of https://github.com/rust-lang/rfcs/pull/3678.
>
> I'm using the word "method" in the title, but in the diagnostics and the feature gate I used "associated function", since that's more accurate.
cc @joshtriplett
Pass alignments through the shim as `Alignment` (not `usize`)
We're using `Layout` on both sides, so might as well skip the transmutes back and forth to `usize`.
The mir-opt test shows that doing so allows simplifying the boxed-slice drop slightly, for example.
the rhs of an ordinary assignment `x = *never_ptr` was inferred with
`ExprIsRead::No`, which prevented `NeverToAny` coercion for place
expressions of type `!`. this caused false type mismatches and missing
divergence detection. the destructuring assignment path and let binding
path both correctly use `ExprIsRead::Yes` for the rhs value, since the
value is always consumed (read). this makes the ordinary assignment path
consistent with both.
Use `scope` for `par_slice` instead of `join`
This uses `scope` instead of nested `join`s in `par_slice` so that each group of items are independent and do not end up blocking on another.
the standalone `contains_explicit_ref_binding` function only checked for
`BindingAnnotation::Ref`, missing `BindingAnnotation::RefMut`. this caused
`let ref mut x = expr` to incorrectly take the coercion path instead of
preserving the exact type of the rhs expression. the method version used
for match arms already handles both `Ref` and `RefMut` correctly.
the command 'cargo build --no-default-features --features borsh' failed with:
error[E0599]: no function or associated item named 'other' found for struct 'borsh::io::Error' in the current scope
--> lib/smol_str/src/borsh.rs:33:39
|
33 | .ok_or_else(|| Error::other("u8::vec_from_reader unexpectedly returned None"))?;
| ^^^^^ function or associated item not found in 'borsh::io::Error'
|
DepGraphQuery: correctly skip adding edges with not-yet-added nodes
Fixes https://github.com/rust-lang/rust/issues/142152.
The current logic already skips some edges, so I'm not sure how critical it is to have *all* the edges recorded, the logic seems to only be used for debug dumping.
Recording all edges requires supporting holes in the `LinkedGraph` data structure, to add nodes and edges out of order, https://github.com/rust-lang/rust/pull/151821 implements that at cost of complicating the data structure.
Port #[rustc_test_marker] to the attribute parser
Tracking issue: https://github.com/rust-lang/rust/issues/131229
Targets:
Const is for normal tests (const test::TestDescAndFn is inserted before the test fn)
Const/Static/Fn is for custom_test_framework's #[test_case] e.g. tests/ui/custom_test_frameworks/full.rs
r? @JonathanBrouwer
Again I left the use-sites as is since they are early uses.
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.
Fixesrust-lang/rust#142394Fixesrust-lang/rust#146590Fixesrust-lang/rust#146803 (though already marked as duplicate)
Fixes parts of rust-lang/rust#147722Fixesrust-lang/miri#4778
r? @Nadrieril @RalfJung
@rustbot label +A-closures +A-patterns +T-opsem +T-lang