Do not remove trivial `SwitchInt` in analysis MIR by compiler-errors · Pull Request #139042 · rust-lang/rust

@rustbot rustbot added S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

T-compiler

Relevant to the compiler team, which will review and decide on the PR/issue.

labels

Mar 28, 2025

compiler-errors

bors added a commit to rust-lang-ci/rust that referenced this pull request

Mar 28, 2025
…chint, r=<try>

Do not remove trivial `SwitchInt` with mir-opt-level=0

When mir-opt-level=0, do not optimize out `SwitchInt` terminators that all have the same terminator since it may remove a read which affects miri's ability to detect UB on that operand.

cc `@RalfJung`

Fixes rust-lang/miri#4237

This affects some tests... I guess I could mark them as `mir-opt-level=1`? Not sure.

@rustbot rustbot added S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

and removed S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

labels

Mar 28, 2025

RalfJung

bors added a commit to rust-lang-ci/rust that referenced this pull request

Mar 30, 2025
…chint, r=<try>

Do not remove trivial `SwitchInt` with mir-opt-level=0

When mir-opt-level=0, do not optimize out `SwitchInt` terminators that all have the same terminator since it may remove a read which affects miri's ability to detect UB on that operand.

cc `@RalfJung`

Fixes rust-lang/miri#4237

This affects some tests... I guess I could mark them as `mir-opt-level=1`? Not sure.

@bors bors added S-waiting-on-bors

Status: Waiting on bors to run and complete tests. Bors will change the label on completion.

and removed S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

labels

Apr 19, 2025

bors added a commit to rust-lang-ci/rust that referenced this pull request

Apr 19, 2025
…enton

Rollup of 7 pull requests

Successful merges:

 - rust-lang#139042 (Do not remove trivial `SwitchInt` in analysis MIR)
 - rust-lang#139533 (add next_index to Enumerate)
 - rust-lang#139843 (Setup editor file associations for non-rs extensions)
 - rust-lang#140000 (skip llvm-config in autodiff check builds, when its unavailable)
 - rust-lang#140008 (Improve `clean_maybe_renamed_item` function code a bit)
 - rust-lang#140024 (Remove early exits from JumpThreading.)
 - rust-lang#140039 (Add option for stable backport poll)

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

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Apr 20, 2025
Rollup merge of rust-lang#139042 - compiler-errors:do-not-optimize-switchint, r=saethlin

Do not remove trivial `SwitchInt` in analysis MIR

This PR ensures that we don't prematurely remove trivial `SwitchInt` terminators which affects both the borrow-checking and runtime semantics (i.e. UB) of the code. Previously the `SimplifyCfg` optimization was removing `SwitchInt` terminators when they was "trivial", i.e. when all arms branched to the same basic block, even if that `SwitchInt` terminator had the side-effect of reading an operand which (for example) may not be initialized or may point to an invalid place in memory.

This behavior is unlike all other optimizations, which are only applied after "analysis" (i.e. borrow-checking) is finished, and which Miri disables to make sure the compiler doesn't silently remove UB.

Fixing this code "breaks" (i.e. unmasks) code that used to borrow-check but no longer does, like:

```rust
fn foo() {
    let x;
    let (0 | _) = x;
}
```

This match expression should perform a read because `_` does not shadow the `0` literal pattern, and the compiler should have to read the match scrutinee to compare it to 0. I've checked that this behavior does not actually manifest in practice via a crater run which came back clean: rust-lang#139042 (comment)

As a side-note, it may be tempting to suggest that this is actually a good thing or that we should preserve this behavior. If we wanted to make this work (i.e. trivially optimize out reads from matches that are redundant like `0 | _`), then we should be enabling this behavior *after* fixing this. However, I think it's kinda unprincipled, and for example other variations of the code don't even work today, e.g.:

```rust
fn foo() {
    let x;
    let (0.. | _) = x;
}
```

github-actions bot pushed a commit to rust-lang/miri that referenced this pull request

Apr 20, 2025
…r=saethlin

Do not remove trivial `SwitchInt` in analysis MIR

This PR ensures that we don't prematurely remove trivial `SwitchInt` terminators which affects both the borrow-checking and runtime semantics (i.e. UB) of the code. Previously the `SimplifyCfg` optimization was removing `SwitchInt` terminators when they was "trivial", i.e. when all arms branched to the same basic block, even if that `SwitchInt` terminator had the side-effect of reading an operand which (for example) may not be initialized or may point to an invalid place in memory.

This behavior is unlike all other optimizations, which are only applied after "analysis" (i.e. borrow-checking) is finished, and which Miri disables to make sure the compiler doesn't silently remove UB.

Fixing this code "breaks" (i.e. unmasks) code that used to borrow-check but no longer does, like:

```rust
fn foo() {
    let x;
    let (0 | _) = x;
}
```

This match expression should perform a read because `_` does not shadow the `0` literal pattern, and the compiler should have to read the match scrutinee to compare it to 0. I've checked that this behavior does not actually manifest in practice via a crater run which came back clean: rust-lang/rust#139042 (comment)

As a side-note, it may be tempting to suggest that this is actually a good thing or that we should preserve this behavior. If we wanted to make this work (i.e. trivially optimize out reads from matches that are redundant like `0 | _`), then we should be enabling this behavior *after* fixing this. However, I think it's kinda unprincipled, and for example other variations of the code don't even work today, e.g.:

```rust
fn foo() {
    let x;
    let (0.. | _) = x;
}
```

wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this pull request

Jun 29, 2025
Pkgsrc changes:
 * Adjust patches to adapt to upstream changes and new versions.
 * associated checksums

Upstream changes relative to 1.87.0:

Version 1.88.0 (2025-06-26)
==========================

Language
--------
- [Stabilize `#![feature(let_chains)]` in the 2024 edition.]
  (rust-lang/rust#132833)
  This feature allows `&&`-chaining `let` statements inside `if`
  and `while`, allowing intermixture with boolean expressions. The
  patterns inside the `let` sub-expressions can be irrefutable or
  refutable.
- [Stabilize `#![feature(naked_functions)]`.]
  (rust-lang/rust#134213)
  Naked functions allow writing functions with no compiler-generated
  epilogue and prologue, allowing full control over the generated
  assembly for a particular function.
- [Stabilize `#![feature(cfg_boolean_literals)]`.]
  (rust-lang/rust#138632)
  This allows using boolean literals as `cfg` predicates, e.g.
  `#[cfg(true)]` and `#[cfg(false)]`.
- [Fully de-stabilize the `#[bench]` attribute]
  (rust-lang/rust#134273). Usage of `#[bench]`
  without `#![feature(custom_test_frameworks)]` already triggered
  a deny-by-default future-incompatibility lint since Rust 1.77,
  but will now become a hard error.
- [Add warn-by-default `dangerous_implicit_autorefs` lint against
  implicit autoref of raw pointer dereference.]
  (rust-lang/rust#123239) The
  lint [will be bumped to deny-by-default]
  (rust-lang/rust#141661) in the next
  version of Rust.
- [Add `invalid_null_arguments` lint to prevent invalid usage of
  null pointers.] (rust-lang/rust#119220)
  This lint is uplifted from `clippy::invalid_null_ptr_usage`.
- [Change trait impl candidate preference for builtin impls and
  trivial where-clauses.] (rust-lang/rust#138176)
- [Check types of generic const parameter defaults]
  (rust-lang/rust#139646)

Compiler
--------
- [Stabilize `-Cdwarf-version` for selecting the version of DWARF
  debug information to generate.]
  (rust-lang/rust#136926)

Platform Support
----------------
- [Demote `i686-pc-windows-gnu` to Tier 2.]
  (https://blog.rust-lang.org/2025/05/26/demoting-i686-pc-windows-gnu/)

Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.

[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html

Libraries
---------
- [Remove backticks from `#[should_panic]` test failure message.]
  (rust-lang/rust#136160)
- [Guarantee that `[T; N]::from_fn` is generated in order of
  increasing indices.] (rust-lang/rust#139099),
  for those passing it a stateful closure.
- [The libtest flag `--nocapture` is deprecated in favor of the
  more consistent `--no-capture` flag.]
  (rust-lang/rust#139224)
- [Guarantee that `{float}::NAN` is a quiet NaN.]
  (rust-lang/rust#139483)

Stabilized APIs
---------------

- [`Cell::update`]
  (https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.update)
- [`impl Default for *const T`]
  (https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*const+T)
- [`impl Default for *mut T`]
  (https://doc.rust-lang.org/nightly/std/primitive.pointer.html#impl-Default-for-*mut+T)
- [`HashMap::extract_if`]
  (https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.extract_if)
- [`HashSet::extract_if`]
  (https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html#method.extract_if)
- [`proc_macro::Span::line`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.line)
- [`proc_macro::Span::column`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.column)
- [`proc_macro::Span::start`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.start)
- [`proc_macro::Span::end`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.end)
- [`proc_macro::Span::file`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.file)
- [`proc_macro::Span::local_file`]
  (https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.local_file)

These previously stable APIs are now stable in const contexts:

- [`NonNull<T>::replace`]
  (https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.replace)
- [`<*mut T>::replace`]
  (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.replace)
- [`std::ptr::swap_nonoverlapping`]
  (rust-lang/rust#137280)
- [`Cell::{replace, get, get_mut, from_mut, as_slice_of_cells}`]
  (rust-lang/rust#137928)

Cargo
-----
- [Stabilize automatic garbage collection.]
  (rust-lang/cargo#14287)
- [use `zlib-rs` for gzip compression in rust code]
  (rust-lang/cargo#15417)

Rustdoc
-----
- [Doctests can be ignored based on target names using `ignore-*` attributes.]
  (rust-lang/rust#137096)
- [Stabilize the `--test-runtool` and `--test-runtool-arg` CLI
  options to specify a program (like qemu) and its arguments to run
  a doctest.] (rust-lang/rust#137096)

Compatibility Notes
-------------------
- [Finish changing the internal representation of pasted tokens]
  (rust-lang/rust#124141). Certain invalid
  declarative macros that were previously accepted in obscure
  circumstances are now correctly rejected by the compiler. Use of
  a `tt` fragment specifier can often fix these macros.
- [Fully de-stabilize the `#[bench]` attribute]
  (rust-lang/rust#134273). Usage of `#[bench]`
  without `#![feature(custom_test_frameworks)]` already triggered
  a deny-by-default future-incompatibility lint since Rust 1.77,
  but will now become a hard error.
- [Fix borrow checking some always-true patterns.]
  (rust-lang/rust#139042) The borrow checker
  was overly permissive in some cases, allowing programs that
  shouldn't have compiled.
- [Update the minimum external LLVM to 19.]
  (rust-lang/rust#139275)
- [Make it a hard error to use a vector type with a non-Rust ABI
  without enabling the required target feature.]
  (rust-lang/rust#139309)