Rollup of 7 pull requests - #162486
Closed
JonathanBrouwer wants to merge 21 commits into
Closed
Conversation
…which causes Unable to find target error
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.
…r=Kobzol Make `run-make` testsuite work with other codegen backend than LLVM Needed for rust-lang#159924. Currently, we always run `run-make` testsuite with the codegen backend rustc was compiled with. However, in CI it's compiled with LLVM, so when we want to test with GCC (with `--test-codegen-backend`), it compiles `rmake.rs` with the GCC backend, but when running the test, it doesn't use the GCC backend since it just calls `rustc`. So to get around that, I now pass the codegen backend through the environment and set it in the `rustc` function of `run_make_support`. To be noted that for now it's only for the `rustc` function, no other command uses it. Should I extend it right away for all commands (well, likely only `cargo`) or just `rustc` for now is enough? r? @jieyouxu
…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
Member
Author
Contributor
This comment has been minimized.
This comment has been minimized.
rust-bors Bot
pushed a commit
that referenced
this pull request
Sep 8, 2026
Rollup of 7 pull requests try-job: dist-various-1 try-job: test-various try-job: test-x86_64-gnu-aux try-job: test-x86_64-gnu-llvm-21-3 try-job: test-x86_64-msvc-1 try-job: test-aarch64-apple-1 try-job: test-aarch64-apple-2 try-job: test-x86_64-mingw-1 try-job: test-i686-msvc-1 try-job: test-i686-msvc-2 try-job: test-armhf-gnu
Contributor
|
PR #162482, which is a member of this rollup, was unapproved. This rollup was thus unapproved. |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Successful merges:
run-maketestsuite work with other codegen backend than LLVM #162482 (Makerun-maketestsuite work with other codegen backend than LLVM)fold_predicateandvisit_predicate#162461 (limit the api offold_predicateandvisit_predicate)r? @ghost
Create a similar rollup