Commit graph

2600 commits

Author SHA1 Message Date
Ralf Jung
0df1764e60 add helper to project to a field of a place 2026-02-16 17:27:40 +01: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
Jonathan Brouwer
38cc50b6e4
Rollup merge of #152612 - JonathanBrouwer:rename_to_msg, r=jdonszelmann
Rename `inline_fluent!` to `msg!`

This was the most popular name for the macro as voted in [#t-compiler > Bikeshed the new `inline_fluent!` macro @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Bikeshed.20the.20new.20.60inline_fluent!.60.20macro/near/572751863)
2026-02-14 18:55:38 +01:00
Jonathan Brouwer
5ae6bb3faf
Rollup merge of #152001 - reddevilmidzy:mgca-i, r=BoxyUwU
mGCA: Validate const literal against expected type

close: rust-lang/rust#151625
close: rust-lang/rust#150983

also fix: https://github.com/rust-lang/rust/issues/133966 (moved crashes test)
2026-02-14 18:55:35 +01: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
Jonathan Brouwer
018a5efcf7
Rename inline_fluent! to msg! 2026-02-14 13:47:52 +01:00
reddevilmidzy
01d48c62a5 Move LitToConstInput into ty::consts
Relocate LitToConstInput and const_lit_matches_ty from mir::interpret
to ty::consts::lit
2026-02-14 04:12:46 +00:00
reddevilmidzy
8af02e230a mGCA: Validate const literal against expected type
Co-authored-by: Boxy <rust@boxyuwu.dev>
2026-02-14 04:12:40 +00:00
Lukas Bergdoll
2f3b952349 Stabilize assert_matches 2026-02-11 14:13:44 +01:00
Jana Dönszelmann
9cc2924959
Port rustc_deprecated_safe_2024 to the new attribute parser 2026-02-10 10:10:38 +01:00
bors
381e9ef09e Auto merge of #152324 - Keith-Cancel:mgca4, r=BoxyUwU
Update mgca to use `type const` syntax instead of the `#[type_const]` attribute. 

This PR changes the `#[type_const]` attribute to the `type const` syntax for  https://github.com/rust-lang/rust/issues/132980.

This will fixes https://github.com/rust-lang/rust/issues/151273 and similar issues, since we need to check `type const` of items before expansion. The move to add a syntax was mentioned here: https://github.com/rust-lang/rust/pull/151289#issuecomment-3765241397

The first part of this PR adds support by allowing `type const <IDENT>: <TYPE> { = <EXPR> };` syntax in `rustc_parse/src/parser/item.rs`.

The next part since the AST item does not contain enough information to determine if we have a `type const` was rework `ConstItemRhs` into `ConstItemRhsKind` to store the information since we no longer have the attribute acting as a source of extra data/metadata. 

The hir node `ConstItemRhsKind` current shape mostly works, except in the case of `TraitItemKind` where it is an option. I initially went about giving `hir::ConstItemRhsKind` a similar form the AST, but it touches a lot more lines of code and files so because of that, the less invasive option was to add a simple boolean flag to `TraitItemKind`. 

The forth part of this PR includes adding a query I called `is_rhs_type_const` so that we can handle both local and foreign def_ids. 

The fifth aspect of the PR is adding a `mgca_type_const_syntax` feature gate that is checked before expansion. The standard mgca feature gate is ran after expansion. This feature gate allows for conditional compilation (e.g #[cfg(..)]) of the `type const` syntax  in nightly without `min_generic_const_args` being enabled. 

The last bit is updating all the the tests that used the `#[type_const]` attribute to use the new syntax that failed because of the changes. This is the bulk of touched/edited files in the PR. 

r? @BoxyUwU 
@rustbot label +F-associated_const_equality +F-min_generic_const_args
2026-02-09 22:37:29 +00:00
Keith-Cancel
73a991fb9d Allow provisional mgca syntax of type const <IDENT> = <EXPR> to be reconized.
Revert, but without type const.

Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those.

Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added.

Fix for tidyfmt and some errors when manually resolving a merge conflicts.

Update these tests to use update error messages and type const syntax.

Update comments and error message to use new syntax instead of old type_const attribute.

Remove the type_const attribute

update some more tests to use the new syntax.

Update these test cases.

update feature gate test

Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled.

Create a new feature gate that checks for the feature before expansion.

Make rustfmt handle the `type const` syntax correctly.

Add a convience method to check if a RhsKind is type const.

Rename `Const` discriminant to `Body` for `ConstItemRhsKind`

Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for.

Update formatting for these match statements.

Update clippy test to use type const syntax.

Update test to use type const syntax.

update rustfmt to match ast items.

Update clippy to match ast and hir items.

Few more test cases that used old attribute, instead of 'type const'

Update to match the output from the feature gate checks.

tidyfmt adjustments.

Update the is_type_const, so I can constrain record!(..) in encoder.rs

Update conditional compilation test.

Move the feature gate to after expansion to allow for cfg(...) to work.

Update some more tests to use the new syntax.

Update type const tests in associated-const-bindings to use new syntax.

Don't check based off the attribute, but the item here.

Update some tests outside of the const_generics folder that were using #[type_const]

update the tests in associated consts that use #[type_const] to use type const

Update these mgca tests with the type const syntax.

Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code.

Don't need into for these now that it's a query.

Add is_type_const query to handle foreign def ids.

update this test to use type const syntax.

Fix logic here, we only want to lower if there is expression in this case.

Update built-in macros to use ConstItemRhsKind

Update more instance of the old ConstItemRhs.

Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion.

Update lower to use ConstItemKind

Add an other helper method to check if the rhs kinda has an expr.

Update item parse to use ConstItemKind enum.

Felt the field name could a be little clear when editing a few other things.

Change the ConstItem struct see know if we have a type const or regular const.

Make sure this syntax is properly feature gated.
2026-02-09 07:59:24 -08:00
Jonathan Brouwer
99c6009c45
Reformat existing messages 2026-02-08 23:07:58 +01:00
Jonathan Brouwer
0d9b0ab620
Rollup merge of #152328 - JonathanBrouwer:fix_diags, r=JonathanBrouwer
Fix a few diagnostics

When working on the inline diagnostics conversion (https://github.com/rust-lang/rust/issues/151366), I noticed that my script sometimes took the wrong message.
Because it didn't happen very often, I just fixed it manually when a uitest fails.

However I got paranoid that the script changed messages that were not covered by uitests, so I checked for all messages in the previous `messages.ftl` files, whether they occured at least once in the codebase. I found 3 messages that indeed were wrongly replaced by my script, fixed them, and added uitests to make sure this doesn't happen again :)

r? @jdonszelmann (Anyone else, also feel free to review, just assigning to Jana because she's been reviewing the other PRs)
2026-02-08 19:15:26 +01:00
Jonathan Brouwer
8aa0e905f4
Fix suggestion on CallToDeprecatedSafeFnRequiresUnsafe diagnostic 2026-02-08 17:02:40 +01:00
Stuart Cook
68f4a99963
Rollup merge of #151887 - scottmcm:homogeneous-try-in-compiler, r=jackh726
Remove some unnecessary `try`-related type annotations

I left a few, like
```rust
let result: Result<_, ModError<'_>> = try {
```
where it felt like seeing it might still be useful for the reader.

Feel free to push back on any of these changes if you think they should be left alone.
2026-02-08 16:58:23 +11:00
Zalathar
cc3fdc637a Avoid a bogus THIR span for let x = offset_of!(..) 2026-02-07 23:41:24 +11:00
Jonathan Brouwer
edd43c9e1f
Fix existing messages in the diag structs 2026-02-07 09:11:34 +01:00
Guillaume Gomez
885a8081c4 Convert to inline diagnostics in rustc_mir_build 2026-02-06 22:21:27 +01:00
Frank King
996425b295 refactor: add an enum DerefAdjustKind in favor of Option<OverloadedDeref> 2026-01-31 16:25:32 +08:00
Scott McMurray
f7931c8050 Remove some unnecessary try-related type annotations
I left a few, like
```rust
let result: Result<_, ModError<'_>> = try {
```
where it felt like seeing it might still be useful for the reader.

Feel free to push back on any of these changes if you think seeing the type would be better.
2026-01-30 18:21:19 -08:00
Zalathar
566c23de41 THIR patterns: Explicitly distinguish &pin from plain &/&mut 2026-01-20 13:41:32 +11:00
Jonathan Brouwer
b41e8f0897
Rollup merge of #151295 - const-to-pat, r=BoxyUwU
THIR patterns: Use `ty::Value` in more places throughout `const_to_pat`

This PR changes `ConstToPat::valtree_to_pat` to take a `ty::Value` instead of separate type and valtree arguments, and propagates that change throughout other parts of the overall `const_to_pat` implementation.

The biggest under-the-hood change is that instead of combining valtrees from the constant with child types from the parent type, we now just rely on the types already embedded in children of the valtree.

I'm not *entirely* sure that this is correct, but it doesn't seem to cause any failures in the test suite, and from what I can tell the old way was a holdover from a time when the types weren't readily available from the value side.

---

My ulterior motive for this cleanup is that I'm hoping to eventually add some extra data to `thir::PatKind::Const`, which will be a little easier if creation of that `PatKind::Const` doesn't have to assemble a `ty::Value` from component parts.
2026-01-19 20:53:24 +01:00
Jonathan Brouwer
be69cc22a1
Rollup merge of #151045 - wrapping-neg, r=lcnr
Simplify some literal-value negations with `u128::wrapping_neg`

- Calling `overflowing_neg` and then discarding the overflow bit is the same as just calling `wrapping_neg`.
- Casting to `u128` to `i128`, negating, and then casting back produces the same result as just performing an unsigned `wrapping_neg`.

There should be no actual change to compiler behaviour.
2026-01-19 20:53:22 +01:00
Jonathan Brouwer
0ee7d96253
Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase
This PR was mostly made by search&replacing
2026-01-19 17:39:49 +01:00
Zalathar
7ec34defe9 Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
Zalathar
97603c0df0 Use ty::Value in more places throughout const_to_pat 2026-01-18 21:55:10 +11:00
Keith-Cancel
4c93efae2b Fix ICE: When Trying to check visibility of a #[type_const], check RHS instead.
We want to evaluate the rhs of a type_const.

Also added an early return/guard in eval_in_interpreter which is used in functions like `eval_to_allocation_raw_provider`

Lastly add a debug assert to `thir_body()` if we have gotten there with a type_const something as gone wrong.

Get rid of a call to is_type_const() and instead use a match arm.

Change this is_type_const() check to a debug_assert!()

Change to use an if else statment instead.

Update type_const-pub.rs

Fix formatting.

Noticed that this is the same check as is_type_const() centralize it.

Add test case for pub type_const.
2026-01-16 20:30:58 -08:00
Alex Celeste
1f691f7dbd Add missing closing brackets to THIR output.
Closing brackets were missing on AdtDef, the field_types list in FruInfo, and InlineAsmExpr, breaking folding in some editors;
Fields were incorrectly (?) indexed in the list for functional update syntax, showing the (implicit, irrelevant) iteration index instead of the field index;
also spurious colon after Pat.
2026-01-16 14:44:58 +00:00
Zalathar
e673bf57c2 Also remove pat_ty from TestKind::ScalarEq 2026-01-16 12:21:48 +11:00
Zalathar
066eb6d2ea THIR patterns: Always use type str for string-constant-value nodes 2026-01-16 12:17:48 +11:00
Maja Kądziołka
af302a67fd discriminant reads: make semantics independent of module/crate 2026-01-15 19:12:13 +01:00
Stuart Cook
69f0a498ba
Rollup merge of #151103 - array-pat-len, r=Nadrieril,petrochenkov
mir_build: Simplify length-determination and indexing for array/slice patterns

The existing length-determination code in `prefix_slice_suffix` has ended up overly complicated, partly because it doesn't know in advance whether the pattern is supposed to be an array pattern or a slice pattern.

Pulling most of that step out into the `PatKind::Array` arm makes the whole thing a bit nicer overall.

There should (hopefully) be no change to compiler output. The biggest “functional” change is that we now discard the subpatterns of an array pattern of unknowable length, instead of treating it as a slice pattern. I'm not aware of any way for this to make an observable difference, and it can only occur when compilation is already doomed to fail.
2026-01-15 21:39:03 +11:00
Stuart Cook
eafe40e05c
Rollup merge of #150846 - thir-hir-id, r=lcnr
include `HirId`s directly in the THIR, not wrapped in `LintLevel`s

Occurrences of `LintLevel` in the THIR were always `LintLevel::Explicit`, containing a `HirId`, so we don't need to make it possible to put `LintLevel::Inherited` there. Removing the unused case where `HirId`s aren't present in the THIR slightly simplifies diagnostics/lints/tools that want to map from the THIR back to the HIR, e.g. rust-lang/rust#145569.

Since `LintLevel` is no longer present in the THIR, I've moved it in the second commit to live in `rustc_mir_build`; that's where it's actually used. I'm not sure exactly where exactly it should live there, but I put it in the `builder::scope` module since it's used by `Builder::in_scope` for determining when to introduce source scopes.

r? lcnr as the reviewer of rust-lang/rust#145569, since this was discussed there
2026-01-15 21:39:02 +11:00
dianne
8868b479a8 move LintLevel to rustc_mir_build 2026-01-14 14:25:21 -08:00
dianne
36d37fd11b THIR: directly contain HirIds, not LintLevels 2026-01-14 14:25:21 -08:00
Zalathar
a72083f739 Avoid some more usize-to-u64 casts in prefix_slice_suffix 2026-01-14 18:10:55 +11:00
Zalathar
a9ce7503d5 Pull array length determination out of prefix_slice_suffix 2026-01-14 18:10:55 +11:00
Nicholas Nethercote
3aa31788b5 Remove Deref/DerefMut impl for Providers.
It's described as a "backwards compatibility hack to keep the diff
small". Removing it requires only a modest amount of churn, and the
resulting code is clearer without the invisible derefs.
2026-01-14 15:55:59 +11:00
Zalathar
02333ad8a2 Simplify some literal-value negations with u128::wrapping_neg 2026-01-13 14:16:25 +11:00
Matthias Krüger
12b1f3f145
Rollup merge of #150920 - hook-build-mir, r=tiif
Use a hook to decouple `rustc_mir_transform` from `rustc_mir_build`

I noticed that the only point of direct contact between the `rustc_mir_transform` and `rustc_mir_build` crates is a single `build_mir` function, which could easily be changed to a hook function instead.

By making that function a hook, we can make `rustc_mir_transform` no longer have a dependency on `rustc_mir_build`, allowing them to be built/rebuilt independently. That should hopefully allow slightly more parallelism in clean builds and incremental rebuilds of the compiler.
2026-01-12 13:32:09 +01:00
Stuart Cook
e25d7a898a
Rollup merge of #150799 - mcga, r=BoxyUwU
Fix ICE: can't type-check body of DefId  for issue #148729

This commit fixes https://github.com/rust-lang/rust/issues/148729 for min_const_generic_args https://github.com/rust-lang/rust/issues/132980.

It's pretty small PR. The first commit makes sure that the `type_const`s are made into normal consts in const expressions.

The next one just handles the case https://github.com/rust-lang/rust/issues/148729 of where the type of the const was omitted at which point it was trying to treat a `type_const` again as a regular const. That obviously will fail since a type_const does not have a body.

@rustbot label +F-associated_const_equality +F-min_generic_const_args +I-ICE
2026-01-11 14:27:56 +11:00
Zalathar
539e855008 Use a hook to decouple rustc_mir_transform from rustc_mir_build 2026-01-10 22:14:35 +11:00
Keith-Cancel
f982bc6a2d Fix ICE: can't type-check body of DefId, since type_consts don't have a body.
Handling for inherent associated consts is missing elsewhere, remove so it can be handled later in that handling.

Diagnostic not always be emitted on associated constant

Add a test case and Fix for a different ICE I encountered.

I noticed when trying various permuations of the test case code to see if I could find anymore ICEs. I did, but not one that I expected. So in the instances of the a named const not having any args, insantiate it directly. Since it is likely an inherent assocaiated const.

Added tests.

Centralize the is_type_const() logic.

I also noticed basically the exact same check in other part the code.

Const blocks can't be a type_const, therefore this check is uneeded.

Fix comment spelling error.

get_all_attrs is not valid to call for all DefIds it seems.

Make sure that if the type is omitted for a type_const that we don't ICE.

Co-Authored-By: Boxy <rust@boxyuwu.dev>
2026-01-09 14:45:33 -08:00
Zalathar
8516c64115 Replace AscribeUserType and ExpandedConstant with per-node data 2026-01-09 16:46:08 +11:00
Zalathar
bd77048303 Initial plumbing for thir::PatExtra 2026-01-09 16:32:23 +11:00
Zalathar
f85b898c45 Prefer to return Box<thir::Pat> instead of thir::PatKind
This will allow extra data to be attached to the `Pat` before it is returned.
2026-01-09 16:32:23 +11:00
Zalathar
0495a73474 Prepare for thir::Pat nodes having multiple user-type ascriptions 2026-01-09 16:32:23 +11:00
Jonathan Brouwer
ce42a619a2
Rollup merge of #150670 - Zalathar:let-ty, r=Nadrieril
THIR pattern building: Move all `thir::Pat` creation into `rustc_mir_build::thir::pattern`

The code in `thir::cx::block` was the only code outside of `thir::pattern` that created `thir::Pat` nodes.

Moving it makes the signature of `pat_from_hir` a bit messier, but ensures that all `thir::Pat` creation occurs in one module. That will be useful when trying to change `thir::Pat`, e.g. by adding fields to remove the need for wrapper nodes.

There should be no change to compiler output.
2026-01-06 16:19:41 +01:00