Skip to content

Rollup of 15 pull requests#152809

Closed
JonathanBrouwer wants to merge 94 commits intorust-lang:mainfrom
JonathanBrouwer:rollup-rlw2bKe
Closed

Rollup of 15 pull requests#152809
JonathanBrouwer wants to merge 94 commits intorust-lang:mainfrom
JonathanBrouwer:rollup-rlw2bKe

Conversation

@JonathanBrouwer
Copy link
Contributor

Successful merges:

r? @ghost

Create a similar rollup

BoxyUwU and others added 30 commits December 23, 2025 13:54
MGCA: Support struct expressions without intermediary anon consts

r? oli-obk

tracking issue: rust-lang#132980

Fixes rust-lang#127972
Fixes rust-lang#137888
Fixes rust-lang#140275

due to delaying a bug instead of ICEing in HIR ty lowering.

### High level goal

Under `feature(min_generic_const_args)` this PR adds another kind of const argument. A struct/variant construction const arg kind. We represent the values of the fields as themselves being const arguments which allows for uses of generic parameters subject to the existing restrictions present in `min_generic_const_args`:
```rust
fn foo<const N: Option<u32>>() {}

trait Trait {
    #[type_const]
    const ASSOC: usize;
}

fn bar<T: Trait, const N: u32>() {
    // the initializer of `_0` is a `N` which is a legal const argument
    // so this is ok.
    foo::<{ Some::<u32> { 0: N } }>();

    // this is allowed as mgca supports uses of assoc consts in the
    // type system. ie `<T as Trait>::ASSOC` is a legal const argument
    foo::<{ Some::<u32> { 0: <T as Trait>::ASSOC } }>();

    // this on the other hand is not allowed as `N + 1` is not a legal
    // const argument
    foo::<{ Some::<u32> { 0: N + 1 } }>();
}
```

This PR does not support uses of const ctors, e.g. `None`. And also does not support tuple constructors, e.g. `Some(N)`. I believe that it would not be difficult to add support for such functionality after this PR lands so have left it out deliberately.

We currently require that all generic parameters on the type being constructed be explicitly specified. I haven't really looked into why that is but it doesn't seem desirable to me as it should be legal to write `Some { ... }` in a const argument inside of a body and have that desugar to `Some::<_> { ... }`. Regardless this can definitely be a follow-up PR and I assume this is some underlying consistency with the way that elided args are handled with type paths elsewhere.

This PRs implementation of supporting struct expressions is somewhat incomplete. We don't handle `Foo { ..expr }` at all and aren't handling privacy/stability. The printing of `ConstArgKind::Struct` HIR nodes doesn't really exist either :')

I've tried to keep the implementation here somewhat deliberately incomplete as I think a number of these issues are actually quite small and self contained after this PR lands and I'm hoping it could be a good set of issues to mentor newer contributors on 🤔 I just wanted the "bare minimum" required to actually demonstrate that the previous changes are "necessary".

### `ValTree` now recurse through `ty::Const`

In order to actually represent struct/variant construction in `ty::Const` without going through an anon const we would need to introduce some new `ConstKind` variant. Let's say some hypothetical `ConstKind::ADT(Ty<'tcx>, List<Const<'tcx>>)`.

This variant would represent things the same way that `ValTree` does with the first element representing the `VariantIdx` of the enum (if its an enum), and then followed by a list of field values in definition order.

This *could* work but there are a few reasons why it's suboptimal.

First it would mean we have a second kind of `Const` that can be normalized. Right now we only have `ConstKind::Unevaluated` which possibly needs normalization. Similarly with `TyKind` we *only* have `TyKind::Alias`. If we introduced `ConstKind::ADT` it would need to be normalized to a `ConstKind::Value` eventually. This feels to me like it has the potential to cause bugs in the long run where only `ConstKind::Unevaluated` is handled by some code paths.

Secondly it would make type equality/inference be kind of... weird... It's desirable for `Some { 0: ?x } eq Some { 0: 1_u32 }` to result in `?x=1_u32`.  I can't see a way for this to work with this `ConstKind::ADT` design under the current architecture for how we represent types/consts and generally do equality operations.

We would need to wholly special case these two variants in type equality and have a custom recursive walker separate from the existing architecture for doing type equality. It would also be somewhat unique in that it's a non-rigid `ty::Const` (it can be normalized more later on in type inference) while also having somewhat "structural" equality behaviour.

Lastly, it's worth noting that its not *actually* `ConstKind::ADT` that we want. It's desirable to extend this setup to also support tuples and arrays, or even references if we wind up supporting those in const generics. Therefore this isn't really `ConstKind::ADT` but a more general `ConstKind::ShallowValue` or something to that effect. It represents at least one "layer" of a types value :')

Instead of doing this implementation choice we instead change `ValTree::Branch`:
```rust
enum ValTree<'tcx> {
    Leaf(ScalarInt),
    // Before this PR:
    Branch(Box<[ValTree<'tcx>]>),
    // After this PR
    Branch(Box<[Const<'tcx>]>),
}
```

The representation for so called "shallow values" is now the same as the representation for the *entire* full value. The desired inference/type equality behaviour just falls right out of this. We also don't wind up with these shallow values actually being non-rigid. And `ValTree` *already* supports references/tuples/arrays so we can handle those just fine.

I think in the future it might be worth considering inlining `ValTree` into `ty::ConstKind`. E.g:
```rust
enum ConstKind {
    Scalar(Ty<'tcx>, ScalarInt),
    ShallowValue(Ty<'tcx>, List<Const<'tcx>>),
    Unevaluated(UnevaluatedConst<'tcx>),
    ...
}
```

This would imply that the usage of `ValTree`s in patterns would now be using `ty::Const` but they already kind of are anyway and I think that's probably okay in the long run. It also would mean that the set of things we *could* represent in const patterns is greater which may be desirable in the long run for supporting things such as const patterns of const generic parameters.

Regardless, this PR doesn't actually inline `ValTree` into `ty::ConstKind`, it only changes `Branch` to recurse through `Const`. This change could be split out of this PR if desired.

I'm not sure if there'll be a perf impact from this change. It's somewhat plausible as now all const pattern values that have nesting will be interning a lot more `Ty`s. We shall see :>

### Forbidding generic parameters under mgca

Under mgca we now allow all const arguments to resolve paths to generic parameters. We then *later* actually validate that the const arg should be allowed to access generic parameters if it did wind up resolving to any.

This winds up just being a lot simpler to implement than trying to make name resolution "keep track" of whether we're inside of a non-anon-const const arg and then encounter a `const { ... }` indicating we should now stop allowing resolving to generic parameters.

It's also somewhat in line with what we'll need for a `feature(generic_const_args)` where we'll want to decide whether an anon const should have any generic parameters based off syntactically whether any generic parameters were used. Though that design is entirely hypothetical at this point :)

### Followup Work

- Make HIR ty lowering check whether lowering generic parameters is supported and if not lower to an error type/const. Should make the code cleaner, fix some other bugs, and maybe(?) recover perf since we'll be accessing less queries which I think is part of the perf regression of this PR
- Make the ValTree setup less scuffed. We should find a new name for `ConstKind::Value` and the `Val` part of `ValTree` and `ty::Value` as they no longer correspond to a fully normalized structure. It may also be worth looking into inlining `ValTreeKind` into `ConstKind` or atleast into `ty::Value` or sth 🤔
- Support tuple constructors and const constructors not just struct expressions.
- Reduce code duplication between HIR ty lowering's handling of struct expressions, and HIR typeck's handling of struct expressions
- Try fix perf rust-lang#149114 (comment). Maybe this will clear up once we clean up `ValTree` a bit and stop doing double interning and whatnot
For some reason git-subtree incorrectly synced those changes.
The next Cranelift release will support for CallConv::Cold as it was
already effectively equivalent to the default calling convention.
This saves about 10MB on the dist size and about 240MB on the build dir
size.
…e_diagnostic` throughout the codebase

This PR was mostly made by search&replacing
…fJung

`c_variadic`: impl `va_copy` and `va_end` as Rust intrinsics

tracking issue: rust-lang#44930

Implement `va_copy` as (the rust equivalent of) `memcpy`, which is the behavior of all current LLVM targets. By providing our own implementation, we can guarantee its behavior. These guarantees are important for implementing c-variadics in e.g. const-eval.

Discussed in [#t-compiler/const-eval > c-variadics in const-eval](https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/c-variadics.20in.20const-eval/with/565509704).

I've also updated the comment for `Drop` a bit. The background here is that the C standard requires that `va_end` is used in the same function (and really, in the same scope) as the corresponding `va_start` or `va_copy`. That is because historically `va_start` would start a scope, which `va_end` would then close. e.g.

https://softwarepreservation.computerhistory.org/c_plus_plus/cfront/release_3.0.3/source/incl-master/proto-headers/stdarg.sol

```c
#define         va_start(ap, parmN)     {\
        va_buf  _va;\
        _vastart(ap = (va_list)_va, (char *)&parmN + sizeof parmN)
#define         va_end(ap)      }
#define         va_arg(ap, mode)        *((mode *)_vaarg(ap, sizeof (mode)))
```

The C standard still has to consider such implementations, but for Rust they are irrelevant. Hence we can use `Clone` for `va_copy` and `Drop` for `va_end`.
* Fix CI disk space issue for abi-cafe tests

Port disk space cleanup script from rust-lang/rust to free space on
GitHub Actions runners before running abi-cafe tests.

* ci: update free-disk-space.sh to match rust-lang/rust@d29e478

* ci: set RUNNER_ENVIRONMENT=github-hosted for free-disk-space script

* Revert indentation change

---------

Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com>
This is the conceptual opposite of the rust-cold calling convention and
is particularly useful in combination with the new `explicit_tail_calls`
feature.

For relatively tight loops implemented with tail calling (`become`) each
of the function with the regular calling convention is still responsible
for restoring the initial value of the preserved registers. So it is not
unusual to end up with a situation where each step in the tail call loop
is spilling and reloading registers, along the lines of:

    foo:
        push r12
        ; do things
        pop r12
        jmp next_step

This adds up quickly, especially when most of the clobberable registers
are already used to pass arguments or other uses.

I was thinking of making the name of this ABI a little less LLVM-derived
and more like a conceptual inverse of `rust-cold`, but could not come
with a great name (`rust-cold` is itself not a great name: cold in what
context? from which perspective? is it supposed to mean that the
function is rarely called?)
…bilee

add `simd_splat` intrinsic

Add `simd_splat` which lowers to the LLVM canonical splat sequence.

```llvm
insertelement <N x elem> poison, elem %x, i32 0
shufflevector <N x elem> v0, <N x elem> poison, <N x i32> zeroinitializer
```

Right now we try to fake it using one of

```rust
fn splat(x: u32) -> u32x8 {
    u32x8::from_array([x; 8])
}
```

or (in `stdarch`)

```rust
fn splat(value: $elem_type) -> $name {
    #[derive(Copy, Clone)]
    #[repr(simd)]
    struct JustOne([$elem_type; 1]);
    let one = JustOne([value]);
    // SAFETY: 0 is always in-bounds because we're shuffling
    // a simd type with exactly one element.
    unsafe { simd_shuffle!(one, one, [0; $len]) }
}
```

Both of these can confuse the LLVM optimizer, producing sub-par code. Some examples:

- rust-lang#60637
- rust-lang#137407
- rust-lang#122623
- rust-lang#97804

---

As far as I can tell there is no way to provide a fallback implementation for this intrinsic, because there is no `const` way of evaluating the number of elements (there might be issues beyond that, too). So, I added implementations for all 4 backends.

Both GCC and const-eval appear to have some issues with simd vectors containing pointers. I have a workaround for GCC, but haven't yet been able to make const-eval work. See the comments below.

Currently this just adds the intrinsic, it does not actually use it anywhere yet.
…ochenkov

abi: add a rust-preserve-none calling convention

This is the conceptual opposite of the rust-cold calling convention and is particularly useful in combination with the new `explicit_tail_calls` feature.

For relatively tight loops implemented with tail calling (`become`) each of the function with the regular calling convention is still responsible for restoring the initial value of the preserved registers. So it is not unusual to end up with a situation where each step in the tail call loop is spilling and reloading registers, along the lines of:

    foo:
        push r12
        ; do things
        pop r12
        jmp next_step

This adds up quickly, especially when most of the clobberable registers are already used to pass arguments or other uses.

I was thinking of making the name of this ABI a little less LLVM-derived and more like a conceptual inverse of `rust-cold`, but could not come with a great name (`rust-cold` is itself not a great name: cold in what context? from which perspective? is it supposed to mean that the function is rarely called?)
bjorn3 and others added 20 commits February 18, 2026 14:52
- Implement handling of FnPtr TypeKind in const-eval, including:
  - Unsafety flag (safe vs unsafe fn)
  - ABI variants (Rust, Named(C), Named(custom))
  - Input and output types
  - Variadic function pointers
- Add const-eval tests covering:
  - Basic Rust fn() pointers
  - Unsafe fn() pointers
  - Extern C and custom ABI pointers
  - Functions with multiple inputs and output types
  - Variadic functions
- Use const TypeId checks to verify correctness of inputs, outputs, and payloads
…bjorn3

Subtree sync for rustc_codegen_cranelift

The highlight this time is a Cranelift update.

r? @ghost

@rustbot label +A-codegen +A-cranelift +T-compiler
…range_end_end, r=davidtwco

Stop using rustc_layout_scalar_valid_range_* in rustc

Another step towards rust-lang#135996

Required some manual impls, but we already do many manual impls for the newtype_index types, so it's not really a new maintenance burden.
x86: support passing `u128`/`i128` to inline assembly

tracking issue: rust-lang#133416

Seems like an oversight. LLVM has supported this since 2019, see llvm/llvm-project#42502. I've put this under `asm_experimental_reg`.

cc @taiki-e
r? @Amanieu
…obzol

Respect the `--ci` flag in more places in bootstrap

### Motivation
Currently, the way of checking CI environment in bootstrap is not unified. Sometimes `--ci` flag is respected, but in other cases only GITHUB_ACTIONS env var is checked.

### Change
This PR modifies the way of treating the flag in bootstrap. If `--ci` (or `--ci=true`) is added, bootstrap's config set ci_env as `CiEnv::GithubActions`. This PR also modifies some lines in bootstrap to respect the config's CiEnv instance.

### Note
I haven't touched anything in tidy, because I want to raise another PR for introducing --ci flag in tidy. In the PR, I will need to change how tidy treats CI information. So currently I leave it as it is.
…mann

Fix ICE in transmutability error reporting when type aliases are normalized

Fixes rust-lang#151462

Transmutability error reporting hit an ICE when type aliases were normalized for diagnostics. For example, when type
 `JustUnit = ()` normalizes to `()`, the check passes unexpectedly even though the original check with `JustUnit` failed.

Fixed by adding a retry in the `Answer::Yes` arm that checks with the root obligation's types before panicking. The retry only occurs when the root obligation differs and is a Transmute trait predicate.

Also added a test that reproduces the original ICE.
…li-obk

Reflection TypeKind::FnPtr

This is for rust-lang#146922.

Const-eval currently lacks full support for function pointer (fn) types. We should implement handling of FnPtr TypeKind, covering safe and unsafe functions, Rust and custom ABIs, input and output types, higher-ranked lifetimes, and variadic functions.
…nwhite

Remove unnecessary closure.

The comments that says it's necessary is wrong.

r? @adwinwhite
…eyouxu

tests: rustc_public: Check const allocation for all variables (1 of 11 was missing)

In the test `tests/ui-fulldeps/rustc_public/check_allocation.rs` there is a check for constant allocations of local variables of this function:

    fn other_consts() {{
        let _max_u128 = u128::MAX;
        let _min_i128 = i128::MIN;
        let _max_i8 = i8::MAX;
        let _char = 'x';
        let _false = false;
        let _true = true;
        let _ptr = &BAR;
        let _null_ptr: *const u8 = NULL;
        let _tuple = TUPLE;
        let _char_id = const {{ type_id::<char>() }};
        let _bool_id = const {{ type_id::<bool>() }};
    }}

The current test only finds 10 out of 11 allocations. The constant allocation for

    let _ptr = &BAR;

is not checked, because the `SingleUseConsts` MIR pass does not optimize away that assignment. Add code to also collect constant allocation from assignment rvalues to find the constant allocation for that last variable.

Not only does this change make sense on its own, it also makes the test pass both with and without the `SingleUseConsts` pass.

Discovered while investigating ways to avoid [this tests/ui-fulldeps/rustc_public/check_allocation.rs](Enselic@d7fffab#diff-c4a926f9e8ba22bcfb1e6f2491b79b80608ab018641f85f66d6718d7f3716a5e) hack from rust-lang#151426 which wants to stop running `SingleUseConsts` for non-optimized builds.
…ieyouxu

compiletest: normalize stderr before SVG rendering

Element position is hardcoded in the rendered SVG. This means that any change in element length (for instance, when substituting the path with the `rust` checkout with `$DIR`) would not change the position and result in buggy SVG being generated. Normalizing before SVG rendering allows us to keep a consistent element placement.
std::r#try! - avoid link to nightly docs

Use a relative link to the current version of rust-by-example rather than sending people to the nightly version.
Remove some clones in deriving

Just factoring away a few `.clone()`s.
…jieyouxu

Add a mir-opt test for alignment check generation [zero changes outside tests]

I wrote this as part of rust-lang#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.
Fix incorrect target in aarch64-unknown-linux-gnu docs

Very minor thing, but the target should be `-gnu` instead of `-musl`.
…chenkov

Fix an ICE while checking param env shadowing on an erroneous trait impl

Fixes rust-lang#152663
… r=petrochenkov

Do no add -no-pie on Windows

Windows binaries are always position independent and Clang warns when trying to enable or disable that:
```
❯ clang hello.c -pie
clang: warning: argument unused during compilation: '-pie' [-Wunused-command-line-argument]

❯ clang hello.c -no-pie
clang: warning: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument]
```

rust-lang#149937 will turn these warnings into build errors:
```
❯ cargo rustc -- -D linker-messages
   Compiling hello v0.1.0 (E:\tmp\hello)
error: linker stderr: x86_64-w64-mingw32-clang: argument unused during compilation: '-nolibc' [-Wunused-command-line-argument]␍
       x86_64-w64-mingw32-clang: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument]␍

  |
  = note: requested on the command line with `-D linker-messages`

error: could not compile `hello` (bin "hello") due to 1 previous error
```
@rust-bors rust-bors bot added the rollup A PR which is a rollup label Feb 18, 2026
@rustbot rustbot added A-compiletest Area: The compiletest test runner A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 18, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-compiletest Area: The compiletest test runner A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` A-testsuite Area: The testsuite used to check the correctness of rustc rollup A PR which is a rollup T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Comments