Skip to content

Rollup of 6 pull requests - #162487

Merged
rust-bors[bot] merged 19 commits into
rust-lang:mainfrom
JonathanBrouwer:rollup-3MKwguM
Sep 8, 2026
Merged

Rollup of 6 pull requests#162487
rust-bors[bot] merged 19 commits into
rust-lang:mainfrom
JonathanBrouwer:rollup-3MKwguM

Conversation

@JonathanBrouwer

Copy link
Copy Markdown
Member

Successful merges:

r? @ghost

Create a similar rollup

mati865 and others added 19 commits August 14, 2026 18:04
Under `-Zassumptions-on-binders` the next solver stores its region
constraints in the `InferCtxt` instead of registering region
obligations. The canonical type-op path never copied them into
`QueryResponse`, so they were dropped once the query's inference
context went away. Borrowck then saw a type op with no constraints and
lost the outlives error entirely.

`QueryRegionConstraints` now carries the constraint next to the old
style constraints and assumptions. It stays unspanned while passing
through a canonical query and the caller attaches its own origin span
when consuming the response.

Borrowck accumulates these in `MirTypeckRegionConstraints` through
`ConstraintConversion`, the same way it handles everything else, and
destructures them into NLL outlives constraints at the end of MIR type
checking. Implied bound normalization was dropping the same constraint
before lexical regionck, so that path registers it now as well.
…r, r=ZuseZ4

offload: automate manual clang-linker-wrapper step

automate manual clang-linker-wrapper step from https://rustc-dev-guide.rust-lang.org/offload/usage.html
extract bitcode from device.bin and then wraps it into the host module.
needs some refactoring.

r? @ZuseZ4
…ods, r=petrochenkov

delegation: supporting inherent impls

This PR adds support for delegation to inherent impl functions on the delegation side.

Support for inherent impls in delegation consists of two problems: we need to resolve inherent function through `ProbeContext` routine and then we need to generate delegation function knowing the `DefId` of the signature function. The first problem is a fundamental problem given current compiler architecture, and it is not solved in this PR. To imitate working resolution for tests we adopt simple resolution by name only in inherent impls (not trait impls, which would work if we implement fair resolution through `ProbeContext`). A `resolve_type_relative_delegations` query was created which tries to resolve unresolved delegations after resolve stage. In future, when we will be able to fairly resolve delegations through `ProbeContext` contents of this query can be changed and all other logic implemented in this pull request will work.

## Free to inherent impl

Unlike free to trait delegation where we generated explicit `Self` param, here we just use default parameter.

```rust
struct X<'a, T, const B: bool>(...);
impl<'a, T, const B: bool> X<'a, T, B> {
  fn foo<'b, U, const X: usize>(&self) { ... }
}

reuse X::<'static, (), false>::foo as foo1;
reuse X::<'static, (), false,>::foo::<'static, (), 123> as foo3;

//Desugaring:
#[attr = Inline(Hint)]
fn foo1<'b, U, const X: _>(self: _) -> _ where
    'b:'b { X<'static, (), false>::foo::<'b, U, X>(self) }

#[attr = Inline(Hint)]
fn foo3(self: _) -> _ { X<'static, (), false>::foo::<'static, (), 123>(self) }
```

## Trait to inherent impl

In trait to inherent impl delegation we replace the type of self parameter from impl's type to `Self` generic param (if the signature function is a method).

```rust
trait Trait {
    reuse X::<'static, (), false>::foo as foo1;
    reuse X::<'static, (), false,>::foo::<'static, (), true> as foo3;
}

// Desugaring:
trait Trait {
    #[attr = Inline(Hint)]
    fn foo1<'b, U, const X: _>(self: _) -> _ where
        'b:'b { X<'static, (), false>::foo::<'b, U, X>(self) }

    #[attr = Inline(Hint)]
    fn foo3(self: _)
        -> _ { X<'static, (), false>::foo::<'static, (), 123>(self) }
}
```

Note that we didn't specified target expression, so we would get errors like:
```rust
error[E0308]: mismatched types
  --> $DIR/xd.rs:10:14
   |
LL | trait Trait {
   | ----------- found this type parameter
LL |     reuse X::foo;
   |              ^^^
   |              |
   |              expected `&X<'_, T, B>`, found `&Self`
   |              arguments to this function are incorrect
   |
   = note: expected reference `&X<'_, T, B>`
              found reference `&Self`
```

## Trait impl to inherent impl

Here the resolution should look signature in trait as in other cases where we delegate from trait impl. We generate function whose signature matches the resolved function in trait. We propagate only child generics if they are not specified.

```rust
trait Trait {
    fn foo<A, B, C>(&self) { }
    fn foo1<T, U, V>(&self) { }
    fn foo2<'a, T, U, V>(&self) where 'a:'a { }
    fn foo3(&self) { }
}

impl Trait for X {
    reuse X::<'static, (), false>::foo as foo1;
    reuse X::<'static, (), false,>::foo::<'static, (), 123> as foo3;
}

// Desugaring:
impl Trait for X<'_> {
    #[attr = Inline(Hint)]
    fn foo1<T, U, V>(self: _)
        -> _ { X<'static, (), false>::foo::<T, U, V>(self) }

    #[attr = Inline(Hint)]
    fn foo3(self: _)
        -> _ { X<'static, (), false>::foo::<'static, (), 123>(self) }
}
```

## Inherent impl to inherent impl

In inherent impl to inherent impl delegation we replace signature self type with delegation parent self type in case of methods.
```rust
trait Trait {
    fn foo<A, B, C>(&self) { }
    fn foo1<T, U, V>(&self) { }
    fn foo2<'a, T, U, V>(&self) where 'a:'a { }
    fn foo3(&self) { }
}

struct Y;

impl Trait for Y {
    reuse X::<'static, (), false>::foo as foo1;
    reuse X::<'static, (), false,>::foo::<'static, (), 123> as foo3;
}

impl Trait for Y {
    #[attr = Inline(Hint)]
    fn foo1<T, U, V>(self: _)
        -> _ { X<'static, (), false>::foo::<T, U, V>(self) }

    #[attr = Inline(Hint)]
    fn foo3(self: _)
        -> _ { X<'static, (), false>::foo::<'static, (), 123>(self) }
}
```

We did not specify target expression so we would get errors like:
```rust
error[E0308]: mismatched types
  --> $DIR/xd.rs:12:14
   |
LL |     reuse X::foo;
   |              ^^^
   |              |
   |              expected `&X<'_, T, B>`, found `Y`
   |              arguments to this function are incorrect
   |
   = note: expected reference `&X<'_, T, B>`
                 found struct `Y`
```

## Generics

After some experiments I think that we should force user to always specify generics for parent segment of delegation to inherent impls. Consider the following example and imagine that we can use fair resolution through `ProbeContext`:

```rust
trait M1 {}
trait M2 {}

struct S1;
struct S2;

impl M1 for S1 {}
impl M2 for S2 {}

struct X<T, U>(T, U);

impl<T: M1> X<T, ()> {
    fn foo() {}
}

impl<T: M2> X<T, usize> {
    fn foo() {}
}

reuse X::foo;
```

How to resolve `X::foo`? If we generate parent generics (`fn foo<T, U>() { X::<T, U>::foo() }`) which clauses should we inherit? It is impossible to determine which function to reuse, and despite the fact that there may be some cases where it is possible, I don't think that we should write heuristics for that. So always specifying parent generics seems to be a good option. Also I think we should ban infers in parent segment too.

One implementation aspect of how we map generic args for signature and predicates inheritance, as we inherit predicates not from the ADT declaration but from the impl block we need to take generic args from this impl, not from the declaration. So indices of generic args are taken from the impl block and then they are used in mapping and future instantiation:

```rust
struct S<'a, A, const C: usize> {
    xd: &'a [A; C],
}

// index of A = 3
// index of C = 4
impl<'a, 'b, 'c, A, const C: usize> S<A, C> {
    fn foo_self<'d: 'd, 'e, T, const B: bool>(self) {}
}

trait Trait<'a, AA, BB> where Self: Sized {
    reuse S::<(), ()>::foo_self;
    // Args: [Self/#0, 'a/rust-lang#1, AA/rust-lang#2, BB/rust-lang#3, '{region error}, 'd/rust-lang#4, (), {const error}, T/rust-lang#5, B/rust-lang#6]
    // Mapping: {0: 0, 7: 9, 5: 5, 3: 6, 6: 8, 4: 7}, A (index 3) is mapped into index 6 (`()`), C (index 4) mapped into index 7 (const error)
}
```

## Other concerns

### Glob and list delegations

List delegations are supported, glob delegations are not supported:

```rust
struct X;

impl X {
    fn foo(&self) {}
    fn foo2(&self) {}
}

struct Y;

impl Y {
    reuse X::{foo, foo2} { X }
}

impl Y {
    reuse X::*;
    //~^ ERROR: expected trait, found struct `X`
}
```

### Self type adjustments and target expression deletion

Adjustments for receiver are applied, adjustments for other parameters whose types contain `Self` are not applied as `Self` acts as a type alias to the struct, not a generic param which will can get replaced. The deletion of target expression should work as before.

```rust
enum X {
   ...
}

impl X {
    fn static_f() {}
    fn by_value(self) {}
    fn by_ref(&self) {}
    fn by_mut_ref(&mut self) {}
}

struct Y;

impl Y {
    fn get_x(&self) -> X { X }
    reuse X::{static_f, by_value, by_ref, by_mut_ref} { self.get_x() }
}

impl Y {
    fn get_x(&self) -> X { X }

    #[attr = Inline(Hint)]
    fn static_f() -> _ { X::static_f() }

    #[attr = Inline(Hint)]
    fn by_value(self: _) -> _ { X::by_value(self.get_x()) }

    #[attr = Inline(Hint)]
    fn by_ref(self: _) -> _ { X::by_ref(self.get_x()) }

    #[attr = Inline(Hint)]
    fn by_mut_ref(self: _) -> _ { X::by_mut_ref(self.get_x()) }
}

fn main() {
    let y = Y;
    y.by_ref();
    y.by_mut_ref();
    //~^ ERROR: cannot borrow `y` as mutable, as it is not declared as mutable
    y.by_value();

    let y = &Y;
    y.by_value();
    //~^ ERROR: cannot move out of `*y` which is behind a shared reference
    y.by_ref();
    y.by_mut_ref();
    //~^ ERROR: cannot borrow `*y` as mutable, as it is behind a `&` reference

    let y = &mut Y;
    y.by_value();
    //~^ ERROR: cannot move out of `*y` which is behind a mutable reference
    y.by_ref();
    y.by_mut_ref();
}
```

### Recursive delegations

Works as before, we just check the resolution chain and we do not care whether it came from resolution at resolve stage or from resolution of type relative delegations.

r? @petrochenkov
…r=petrochenkov

windows-gnullvm: always link libunwind statically

Previously shared library was used by default, meaning that programs and libraries couldn't be loaded if `libunwind.dll` was missing from the PATH. Using Wine (on Linux) because it better shows the problem (and is more convenient):
```
❯ cargo new hello &> /dev/null

❯ cargo rustc --target x86_64-pc-windows-gnullvm &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe
...
Import {
  Name: libunwind.dll
  ImportLookupTableRVA: 0x3D308
  ImportAddressTableRVA: 0x3D678
  Symbol: _GCC_specific_handler (0)
  Symbol: _Unwind_DeleteException (0)
  Symbol: _Unwind_GetDataRelBase (0)
  Symbol: _Unwind_GetIPInfo (0)
  Symbol: _Unwind_GetLanguageSpecificData (0)
  Symbol: _Unwind_GetRegionStart (0)
  Symbol: _Unwind_GetTextRelBase (0)
  Symbol: _Unwind_RaiseException (0)
  Symbol: _Unwind_Resume (0)
  Symbol: _Unwind_SetGR (0)
  Symbol: _Unwind_SetIP (0)
}
...
```
Optionally libunwind could be linked statically via `+crt-static`:
```
❯ cargo rustc --target x86_64-pc-windows-gnullvm -- -C target-feature=+crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind
```

After a discussion of approach in rust-lang#159782 with @bjorn3 (thanks BTW!), I changed the proposed approach to always link static libunwind.

I don't have a good solution for rust-lang#121794 that will resurface. I guess the user has three options:
- symlink `libunwind.dll.a` as `libunwind.a`
- add `--unwindlib=none -lunwind` to the linker args
- create linker wrapper
- use self-contained mode which is likely is undesirable

I think the ease of use (not having to deal with additional DLL dependency) outweights the benefit of working with incomplete C toolchain.

The size bloat is also not a problem, sizes (in bytes) of the binary for the literal hello world project:
- debug build:
  - shared libunwind 4194816
  - static libunwind 4323328
- release build:
  - shared libunwind 382464
  - static libunwind 423424

Debug diff +125.5 KiB, release diff: +40 KiB.
Size of `libunwind.dll` that has to be provided when linking shared libunwind: 204288 bytes (199.5 KiB).
…ve_type_op_constraints, r=BoxyUwU

trait_selection: Keep type-op region constraints in borrowck

I ran into this while working on rust-lang#158588. `borrowck_env_fail` still had a FIXME because the function body wasn't reporting the outlives error. The next solver creates the region constraint, but the canonical type-op path doesn't put it in `QueryResponse`. Borrowck never sees it, so the type op looks fine and the error is lost.

With `-Zassumptions-on-binders`, these type ops now run locally on borrowck's `InferCtxt`. The fast path still runs first. That leaves the constraint in the same inference context borrowck reads later.

I prefer this over adding more data to the old canonical response. The next solver already caches its work, and teaching the old query path about these constraints felt like extra machinery for something we can avoid. Running locally is pretty boring, but I think that's a good thing here. The old FIXME is now the regression test.
…te, r=BoxyUwU

limit the api of `fold_predicate` and `visit_predicate`

r? @lcnr or anyone in @rust-lang/initiative-trait-system-refactor

In the future, we may want to start compressing clauses in the `ParamEnv`. One major problem was that we are leaking too many implementation details in `fold_predicate` and `visit_predicate`. Almost no code actually cares about dealing with an actual predicate there. Instead, what really matters is the type flags on a predicate for example. As such, this PR majorly limits the API that is exposed to a folder, hiding the underlying predicate data structure used.

As an example why this matters: in the case of compressed clauses, this will mean we won't need to "decompress" them. Instead, we can just fold over the self type, not telling folders whether the predicate was or was not compressed at all.

> [!NOTE]
> I've not used an LLM for any part of this PR, or any other PR I make. This includes any related work like research.
Fix unsoundness bug on next trait solver for dyn const generics placeholder

This seem to fix the related test, which would compile on next trait solver and should not.
It's related to the linked issue where it'd lead to a segmentation fault.

Closes rust-lang/trait-system-refactor-initiative#296

r? @BoxyUwU
@rust-bors rust-bors Bot added the rollup A PR which is a rollup label Sep 8, 2026
@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Sep 8, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@bors r+ p=5

@rust-bors

rust-bors Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

📌 Commit faf7381 has been approved by JonathanBrouwer

It is now in the queue for this repository.

@rust-bors rust-bors Bot 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 Sep 8, 2026
@rust-bors

This comment has been minimized.

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@bors treeopen

@rust-bors

rust-bors Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Tree is now open for merging.

@rust-bors rust-bors Bot added merged-by-bors This PR was explicitly merged by bors. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 8, 2026
@rust-bors

rust-bors Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

☀️ Test successful - CI
Approved by: JonathanBrouwer
Duration: 3h 19m 19s
Pushing 0b1760a to main...

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor
What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing b505807 (parent) -> 0b1760a (this PR)

Test differences

Show 243 test diffs

Stage 0

  • infer::solver_region_constraints::tests::true_constraint_keeps_query_response_empty: [missing] -> pass (J3)

Stage 1

  • [ui] tests/ui/const-generics/dyn-trait-ill-typed.rs: [missing] -> pass (J1)
  • [ui (polonius)] tests/ui/const-generics/dyn-trait-ill-typed.rs: [missing] -> pass (J2)
  • infer::solver_region_constraints::tests::true_constraint_keeps_query_response_empty: [missing] -> pass (J4)

Stage 2

  • [ui] tests/ui/const-generics/dyn-trait-ill-typed.rs: [missing] -> pass (J0)

Additionally, 238 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard 0b1760a65ab20bb78ca29be1fd951cd6b52ca3dd --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. test-x86_64-gnu-llvm-21-3: 1h 18m -> 2h (+52.9%)
  2. test-x86_64-gnu: 1h 48m -> 2h 40m (+48.3%)
  3. test-x86_64-msvc-ext2: 1h 17m -> 1h 52m (+44.6%)
  4. test-x86_64-gnu-gcc: 59m 52s -> 1h 25m (+42.4%)
  5. dist-powerpc64le-linux-gnu: 1h 15m -> 1h 42m (+35.3%)
  6. test-i686-gnu-2: 1h 22m -> 1h 46m (+29.0%)
  7. dist-arm-linux-gnueabi: 1h 10m -> 1h 30m (+28.5%)
  8. dist-x86_64-msvc-alt: 2h 51m -> 2h 5m (-27.0%)
  9. dist-x86_64-apple: 2h 16m -> 2h 52m (+26.1%)
  10. test-x86_64-gnu-miri: 1h 31m -> 1h 7m (-25.6%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. merged-by-bors This PR was explicitly merged by bors. 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants