1383 Commits

Author SHA1 Message Date
Jacob Pratt fa82155e54 Rollup merge of #155680 - Amanieu:call-arg-move-index, r=cjgillot
Handle index projections in call destinations in DSE

Since call destinations are evaluated after call arguments, we can't turn copy arguments into moves if the same local is later used as an index projection in the call destination.

DSE call arg optimization: rust-lang/rust#113758

r? @cjgillot
cc @RalfJung
2026-04-25 01:21:52 -04:00
Amanieu d'Antras b15544d52f Handle index projections in call destinations in DSE
Since call destinations are evaluated after call arguments, we can't
turn copy arguments into moves if the same local is later used as an
index projection in the call destination.
2026-04-23 11:17:22 +01:00
Jonathan Brouwer 610bfadb9b Rollup merge of #155630 - Zalathar:skip-filecheck, r=jieyouxu
Make `//@ skip-filecheck` a normal compiletest directive

The `skip-filecheck` directive is currently used by mir-opt tests, to suppress the default behaviour of running LLVM's `FileCheck` tool to check MIR output against FileCheck rules in the test file.

The `skip-filecheck` directive was not included in the big migration to `//@` directive syntax (https://github.com/rust-lang/rust/pull/121370), perhaps because it was parsed and processed in the *miropt-test-tools* helper crate, not in compiletest itself.

Recently I noticed that a small number of *codegen-llvm* tests were using the `//@ build-pass` directive, which has the non-obvious effect of skipping FileCheck in codegen tests. That's quite confusing, so I decided to have the mir-opt tests migrate over to a proper `//@ skip-filecheck` directive, which could then be used by codegen tests as well.

(I also added skip-filecheck support to assembly tests, which are very similar to codegen tests, though there are currently no assembly tests that actually use `//@ skip-filecheck`.)

---

Support for using `//@ build-pass` in codegen tests to skip FileCheck was introduced in https://github.com/rust-lang/rust/pull/113603. With hindsight, I think doing things that way was pretty clearly a  mistake, and we'll be better off with `//@ skip-filecheck`.

r? jieyouxu
2026-04-23 09:38:24 +02:00
Folkert de Vries 84cd23b3c8 c-variadic: rename VaList::arg to VaList::next_arg 2026-04-22 16:02:11 +02:00
Zalathar eb6eed4ba7 Make //@ skip-filecheck a normal compiletest directive 2026-04-22 19:55:11 +10:00
Ohad Ravid 5632001f83 Improve copy_prop and GVN mir-opt passes to remove fewer storage calls 2026-04-17 16:55:43 +03:00
bors 338dff3e3a Auto merge of #136006 - oli-obk:push-tzonluoyuwkq, r=wesleywiser
Start using pattern types in libcore



cc rust-lang/rust#135996

Replaces the innards of `NonNull` with `*const T is !null`.

This does affect LLVM's optimizations, as now reading the field preserves the metadata that the field is not null, and transmuting to another type (e.g. just a raw pointer), will also preserve that information for optimizations. This can cause LLVM opts to do more work, but it's not guaranteed to produce better machine code.

Once we also remove all uses of rustc_layout_scalar_range_start from rustc itself, we can remove the support for that attribute entirely and handle all such needs via pattern types
2026-04-13 21:54:46 +00:00
Oli Scherer 834137afd7 Use !null pattern type in libcore 2026-04-13 17:23:03 +02:00
Jacob Pratt d83352b491 Rollup merge of #155084 - scottmcm:add-transmute-prefix, r=Mark-Simulacrum
Initial functions to start on transmute v2

For context, see https://github.com/rust-lang/rfcs/pull/3844 and https://github.com/rust-lang/libs-team/issues/772

*Experimental* still, tracked under https://github.com/rust-lang/rust/issues/155079

This is just library functions.  A future PR will do compiler changes for things like lints.
2026-04-11 21:12:19 -04:00
Scott McMurray 63d7f8e7ae Initial methods to start on transmute v2 2026-04-10 01:58:56 -07:00
Waffle Lapkin fa73f032b8 don't try to remove drop_in_place calls in RemoveUnneededDrops 2026-04-10 09:32:35 +02:00
Jynn Nelson e61842d378 Update mir-opt 64-bit panic-abort tests for Alignment rename
These seem to have been missed when the PR originally merged.
2026-03-30 10:56:57 +00:00
Ralf Jung 767d71fcb2 EnumSizeOpt test: show actual bytes of new allocation 2026-03-28 11:41:55 +01:00
Pavel Grigorenko ba1e06a722 core::mem::Alignemnt: rename as_nonzero to as_nonzero_usize 2026-03-25 16:18:33 +03:00
Pavel Grigorenko f8d658ab81 core: move Alignment from ptr to mem 2026-03-25 16:18:33 +03:00
dianqk 86da9312dc mir-opt: Drop invalid debuginfos after SingleUseConsts. 2026-03-11 05:40:44 +08:00
Jonathan Brouwer 8120cc4c49 Rollup merge of #153053 - cyrgani:deref-patterns-not-imcomplete, r=fee1-dead,Nadrieril
stop marking `deref_patterns` as an incomplete feature

This PR removes the `incomplete_feature` warning for `deref_patterns`. The reason given for this in the tracking issue (rust-lang/rust#87121) was
> Per policy, the `incomplete_feature` is supposed to stay on until the feature has an accepted RFC. We're slowly working on writing up that RFC so it'll take some more time unfortunately.
>
> I don't know of any compiler crashes it causes today. The feature should be pretty usable.

However, I could not find any evidence of such a policy. The [lint documentation](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features) for `incomplete_features` also only mentions features that are more likely to cause errors.
There are also many other features without an RFC that are not considered incomplete, e.g. `macro_metavar_expr_concat`, `negative_impls` or `yeet_expr`.
The feature does not cause any known ICEs either.

The concrete motivation is to use this feature to replace `box_patterns` in the compiler and pave the way towards removing that legacy feature.
2026-03-09 17:56:15 +01:00
Jonathan Brouwer 83e6dbf9e1 Rollup merge of #151900 - tgross35:num-internal-imp, r=Mark-Simulacrum
num: Separate public API from internal implementations

Currently we have a single `core::num` module that contains both thin wrapper API and higher-complexity numeric routines. Restructure this by moving implementation details to a new `imp` module.

This results in a more clean separation of what is actually user-facing compared to items that have a stability attribute because they are public for testing.

The first commit does the actual change then the second moves a portion back.
2026-03-08 22:51:52 +01:00
Scott McMurray 2c6ec51564 Update __rust_[rd]ealloc to take NonNull<u8> instead of *mut u8
Passing null to it is [already UB](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=8dcd25a549c11de72adc94a668277779) anyway.
2026-02-28 23:49:31 -08:00
bors 3a70d0349f Auto merge of #152702 - oli-obk:nonnulltransmute, r=scottmcm
Prepare NonNull for pattern types



Pull out the changes that affect some tests, but do not require pattern types.

See https://github.com/rust-lang/rust/pull/136006#discussion_r2806740338 for what triggered this PR

r? @scottmcm
2026-02-27 13:04:46 +00:00
cyrgani 06b0bd21d7 stop marking deref_patterns as an incomplete feature 2026-02-24 17:43:06 +00:00
Jonathan Brouwer d447f3d86b Rollup merge of #152888 - ValorZard:async-drop-fix, r=oli-obk
Fix async drop glue MIR bug

Attempted to fix https://github.com/rust-lang/rust/issues/142560
Relevant Zulip (where I talk a lot more about what I did): [#wg-async > is there a way I can help with Async Drop?](https://rust-lang.zulipchat.com/#narrow/channel/187312-wg-async/topic/is.20there.20a.20way.20I.20can.20help.20with.20Async.20Drop.3F/with/572847292)
2026-02-24 14:41:55 +01:00
Oli Scherer 241cd7eeed Prepare NonNull for pattern types 2026-02-24 08:33:15 +00:00
root ce93a5335d Fix Async Drop MIR bug with async_drop_in_place (Squashed) 2026-02-24 00:04:33 -08:00
Camille Gillot a2c3ebf963 Rebase fallout. 2026-02-22 20:02:56 +00:00
Camille Gillot 4953a8bc12 Constants of primitive types are always deterministic. 2026-02-22 19:43:57 +00:00
Camille Gillot 8c907860f7 Try harder to evaluate constants. 2026-02-22 19:43:57 +00:00
bors d8b2222b11 Auto merge of #152737 - scottmcm:box_new_uninit_layout, r=RalfJung
Just pass `Layout` directly to `box_new_uninit`

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

We have a constant for it already (used in `RawVec` for basically the same polymorphization) so let's use it.

This is a simple follow-up to rust-lang/rust#148190 from one of the comments.
2026-02-22 01:21:56 +00:00
Ana Hobden 7c011122e9 Fix copy_and_clone.rs 2026-02-20 13:25:11 -08:00
bors ef70767064 Auto merge of #152689 - scottmcm:also-simplify-of-sized-val-alt, r=cjgillot
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.)
2026-02-19 22:03:50 +00:00
bors 41198cb965 Auto merge of #148034 - dianqk:matchbr-copy, r=cjgillot
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.
2026-02-19 09:56:26 +00:00
Jonathan Brouwer 2f545c4309 Rollup merge of #152787 - scottmcm:alignment-checks-test, r=jieyouxu
Add a mir-opt test for alignment check generation [zero changes outside tests]

I wrote this as part of rust-lang/rust#152641 which it looks like I'm going to just close, so submitting the new test separately since we didn't have any mir-opt testing of this pass that I could find (at least `x test tests/mir-opt` didn't fail when I broke them) so figured it's something that should exist.
2026-02-18 22:19:52 +01:00
Scott McMurray 7585786ecb Add a mir-opt test for alignment check generation 2026-02-17 23:08:08 -08:00
Stuart Cook dbc2193d37 Rollup merge of #152729 - Enselic:single_use_consts-not-required, r=cjgillot
compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness"

I don't think this MIR pass is required for soundness. The reasons are:
* Something like it was not enabled by default before PR rust-lang/rust#107404 which was the precursor to `SingleUseConsts` (see rust-lang/rust#125910 for the switch).
* By following the advice from https://github.com/rust-lang/rust/pull/128657#discussion_r1705114015 we can conclude it is not required for soundness since it has only ever run on MIR opt level > 0.
* Its [`MirPass::can_be_overridden()`](https://github.com/rust-lang/rust/blob/0ee7d96253f92b15115c94a530db8b79cb341b15/compiler/rustc_mir_transform/src/pass_manager.rs#L98-L102) is unchanged and thus returns `true`, indicating that it is not a required MIR pass.
* PR CI pass in rust-lang/rust#151426 which stops enabling it by default in non-optimized builds.

As shown in the updated test `tests/mir-opt/optimize_none.rs`, `#[optimize(none)]` functions become even less optimized, as expected and desired.

Unblocks https://github.com/rust-lang/rust/pull/151426.
2026-02-18 17:29:43 +11:00
Scott McMurray 4b03b97226 What if we discourage mir-inlining of box_new_uninit? 2026-02-17 09:09:48 -08:00
Scott McMurray 1b767bf623 Just pass Layout directly to box_new_uninit
We have a constant for it already (used in `RawVec` for basically the same polymorphization) so let's use it.

Conveniently, it can even be safe that way!
2026-02-17 09:09:35 -08:00
Martin Nordholts 52b19f7dda compiler: Don't mark SingleUseConsts MIR pass as "required for soundness"
Because:
* Something like it did not exist before PR 107404
* That it is not run our mir-opt-level 0 indicates that it is not
  required for soundness
* Its `MirPass::can_be_overridden()` is unchanged and thus returns true,
  indicating that it is not a required MIR pass.
* No test fails in PR 151426 that stops enabling by default in non-optimized builds

As can be seen from the updated test `tests/mir-opt/optimize_none.rs`,
this means that `#[optimize(none)]` functions become even less
optimized. As expected and as desired.
2026-02-17 06:22:39 +01:00
dianqk b4e3de0928 Run MatchBranchSimplification with opt-level 2 2026-02-17 12:38:45 +08:00
dianqk 05f417cc46 Add assume to single target 2026-02-17 10:11:01 +08:00
dianqk adf64bd305 Simplify the canonical enum clone branches to a copy statement 2026-02-17 10:11:00 +08:00
dianqk 50c30220c3 Overhaul MatchBranchSimplification 2026-02-17 10:11:00 +08:00
Ralf Jung 5e65109f21 add write_box_via_move intrinsic and use it for vec!
This allows us to get rid of box_new entirely
2026-02-16 17:27:40 +01:00
Ralf Jung 93d45480aa replace box_new in Box::new with write_via_move
requires lowering write_via_move during MIR building to make it just like an assignment
2026-02-16 08:44:56 +01:00
Scott McMurray 649e027b88 mir-simplify {size,align}_of_val::<impl Sized> 2026-02-15 18:05:30 -08:00
Scott McMurray 61d3b2d046 Add a mir-opt test showing the drop for a box of non-DST 2026-02-15 17:51:26 -08:00
bors 2219766af6 Auto merge of #152605 - scottmcm:box-drop-alignment, r=Mark-Simulacrum
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.
2026-02-15 13:38:45 +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
Scott McMurray 774268afc1 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.
2026-02-14 01:39:16 -08:00
Shoyu Vanilla f5a8b86695 WF check lifetime bounds for locals with type params 2026-02-13 00:33:47 +09:00
Trevor Gross 23e44f65aa num: Separate public API from internal implementations
Currently we have a single `core::num` module that contains both thin
wrapper API and higher-complexity numeric routines. Restructure this by
moving implementation details to a new `imp` module.

This results in a more clean separation of what is actually user-facing
compared to items that have a stability attribute because they are
public for testing.
2026-02-11 17:10:33 -06:00