Initial support for dynamically linked crates
This PR is an initial implementation of [rust-lang/rfcs#3435](https://github.com/rust-lang/rfcs/pull/3435) proposal.
### component 1: interface generator
Interface generator - a tool for generating a stripped version of crate source code. The interface is like a C header, where all function bodies are omitted. For example, initial crate:
```rust
#[export]
#[repr(C)]
pub struct S {
pub x: i32
}
#[export]
pub extern "C" fn foo(x: S) {
m1::bar(x);
}
pub fn bar(x: crate::S) {
// some computations
}
```
generated interface:
```rust
#[export]
#[repr(C)]
pub struct S {
pub x: i32,
}
#[export]
pub extern "C" fn foo(x: S);
pub fn bar(x: crate::S);
```
The interface generator was implemented as part of the pretty-printer. Ideally interface should only contain exportable items, but here is the first problem:
- pass for determining exportable items relies on privacy information, which is totally available only in HIR
- HIR pretty-printer uses pseudo-code(at least for attributes)
So, the interface generator was implemented in AST. This has led to the fact that non-exportable items cannot be filtered out, but I don't think this is a major issue at the moment.
To emit an interface use a new `sdylib` crate type which is basically the same as `dylib`, but it doesn't contain metadata, and also produces the interface as a second artifact. The current interface name is `lib{crate_name}.rs`.
#### Why was it decided to use a design with an auto-generated interface?
One of the main objectives of this proposal is to allow building the library and the application with different compiler versions. This requires either a metadata format compatible across rustc versions or some form of a source code. The option with a stable metadata format has not been investigated in detail, but it is not part of RFC either. Here is the the related discussion: https://github.com/rust-lang/rfcs/pull/3435#discussion_r1202872373
Original proposal suggests using the source code for the dynamic library and all its dependencies. Metadata is obtained from `cargo check`. I decided to use interface files since it is more or less compatible with the original proposal, but also allows users to hide the source code.
##### Regarding the design with interfaces
in Rust, files generally do not have a special meaning, unlike C++. A translation unit i.e. a crate is not a single file, it consists of modules. Modules, in turn, can be declared either in one file or divided into several. That's why the "interface file" isn't a very coherent concept in Rust. I would like to avoid adding an additional level of complexity for users until it is proven necessary. Therefore, the initial plan was to make the interfaces completely invisible to users i. e. make them auto-generated. I also planned to put them in the dylib, but this has not been done yet. (since the PR is already big enough, I decided to postpone it)
There is one concern, though, which has not yet been investigated(https://github.com/rust-lang/rust/pull/134767#issuecomment-2736471828):
> Compiling the interface as pretty-printed source code doesn't use correct macro hygiene (mostly relevant to macros 2.0, stable macros do not affect item hygiene). I don't have much hope for encoding hygiene data in any stable way, we should rather support a way for the interface file to be provided manually, instead of being auto-generated, if there are any non-trivial requirements.
### component 2: crate loader
When building dynamic dependencies, the crate loader searches for the interface in the file system, builds the interface without codegen and loads it's metadata. Routing rules for interface files are almost the same as for `rlibs` and `dylibs`. Firstly, the compiler checks `extern` options and then tries to deduce the path himself.
Here are the code and commands that corresponds to the compilation process:
```rust
// simple-lib.rs
#![crate_type = "sdylib"]
#[extern]
pub extern "C" fn foo() -> i32 {
42
}
```
```rust
// app.rs
extern crate simple_lib;
fn main() {
assert!(simple_lib::foo(), 42);
}
```
```
// Generate interface, build library.
rustc +toolchain1 lib.rs
// Build app. Perhaps with a different compiler version.
rustc +toolchain2 app.rs -L.
```
P.S. The interface name/format and rules for file system routing can be changed further.
### component 3: exportable items collector
Query for collecting exportable items. Which items are exportable is defined [here](https://github.com/m-ou-se/rfcs/blob/export/text/0000-export.md#the-export-attribute) .
### component 4: "stable" mangling scheme
The mangling scheme proposed in the RFC consists of two parts: a mangled item path and a hash of the signature.
#### mangled item path
For the first part of the symbol it has been decided to reuse the `v0` mangling scheme as it much less dependent on compiler internals compared to the `legacy` scheme.
The exception is disambiguators (https://doc.rust-lang.org/rustc/symbol-mangling/v0.html#disambiguator):
For example, during symbol mangling rustc uses a special index to distinguish between two impls of the same type in the same module(See `DisambiguatedDefPathData`). The calculation of this index may depend on private items, but private items should not affect the ABI. Example:
```rust
#[export]
#[repr(C)]
pub struct S<T>(pub T);
struct S1;
pub struct S2;
impl S<S1> {
extern "C" fn foo() -> i32 {
1
}
}
#[export]
impl S<S2> {
// Different symbol names can be generated for this item
// when compiling the interface and source code.
pub extern "C" fn foo() -> i32 {
2
}
}
```
In order to make disambiguation independent of the compiler version we can assign an id to each impl according to their relative order in the source code.
The second example is `StableCrateId` which is used to disambiguate different crates. `StableCrateId` consists of crate name, `-Cmetadata` arguments and compiler version. At the moment, I have decided to keep only the crate name, but a more consistent approach to crate disambiguation could be added in the future.
Actually, there are more cases where such disambiguation can be used. For instance, when mangling internal rustc symbols, but it also hasn't been investigated in detail yet.
#### hash of the signature
Exportable functions from stable dylibs can be called from safe code. In order to provide type safety, 128 bit hash with relevant type information is appended to the symbol ([description from RFC](https://github.com/m-ou-se/rfcs/blob/export/text/0000-export.md#name-mangling-and-safety)). For now, it includes:
- hash of the type name for primitive types
- for ADT types with public fields the implementation follows [this](https://github.com/m-ou-se/rfcs/blob/export/text/0000-export.md#types-with-public-fields) rules
`#[export(unsafe_stable_abi = "hash")]` syntax for ADT types with private fields is not yet implemented.
Type safety is a subtle thing here. I used the approach from RFC, but there is the ongoing research project about it. [https://rust-lang.github.io/rust-project-goals/2025h1/safe-linking.html](https://rust-lang.github.io/rust-project-goals/2025h1/safe-linking.html)
### Unresolved questions
Interfaces:
1. Move the interface generator to HIR and add an exportable items filter.
2. Compatibility of auto-generated interfaces and macro hygiene.
3. There is an open issue with interface files compilation: https://github.com/rust-lang/rust/pull/134767#issuecomment-2736471828
4. Put an interface into a dylib.
Mangling scheme:
1. Which information is required to ensure type safety and how should it be encoded? ([https://rust-lang.github.io/rust-project-goals/2025h1/safe-linking.html](https://rust-lang.github.io/rust-project-goals/2025h1/safe-linking.html))
2. Determine all other possible cases, where path disambiguation is used. Make it compiler independent.
We also need a semi-stable API to represent types. For example, the order of fields in the `VariantDef` must be stable. Or a semi-stable representation for AST, which ensures that the order of the items in the code is preserved.
There are some others, mentioned in the proposal.
Refactor rustc_on_unimplemented's filter parser
Followup to https://github.com/rust-lang/rust/pull/139091; I plan on moving most of this code into `rustc_attr_parsing` at some point, but want to land this separately first.
I have taken care to preserve the original behavior as much as I could:
- All but one of the new error variants are replacements for the ones originally emitted by the cfg parsing machinery; so these errors are not "new".
- the `InvalidFlag` variant is new, this PR turns this (from being ignored and silently doing nothing) into an error:
```rust
#[rustc_on_unimplemented(on(something, message = "y"))]
//~^ ERROR invalid boolean flag
//~^^ NOTE expected one of `crate_local`, `direct` or `from_desugaring`, not `something`
trait InvalidFlag {}
```
This does not occur anywhere except in this test. I couldn't find a way that I liked to keep allowing this or to do nothing, erroring was the cleanest solution.
- There are a bunch of FIXME throughout this and the previous PR, I plan on addressing those in follow up prs..
Finally, this gets rid of the "longest" dependency in rustc:

Rollup of 6 pull requests
Successful merges:
- #137280 (stabilize ptr::swap_nonoverlapping in const)
- #140457 (Use target-cpu=z13 on s390x codegen const vector test)
- #140619 (Small adjustments to `check_attribute_safety` to make the logic more obvious)
- #140625 (Suggest `retain_mut` over `retain` as `Vec::extract_if` alternative)
- #140627 (Allow linking rustc and rustdoc against the same single tracing crate)
- #140630 (Async drop source info fix for proxy-drop-coroutine)
r? `@ghost`
`@rustbot` modify labels: rollup
Use target-cpu=z13 on s390x codegen const vector test
The default s390x cpu(z10) does not have vector support. Setting target-cpu at least to z13 enables vectorisation for s390x architecture and makes the test pass.
stabilize ptr::swap_nonoverlapping in const
Closes https://github.com/rust-lang/rust/issues/133668
The blocking issue mentioned there is resolved by documentation. We may in the future actually support such code, but that is blocked on https://github.com/rust-lang/const-eval/issues/72 which is non-trivial to implement. Meanwhile, this completes stabilization of all `const fn` in `ptr`. :)
Here's a version of the problematic example to play around with:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6c390452379fb593e109b8f8ee854d2a
Should be FCP'd with both `@rust-lang/libs-api` and `@rust-lang/lang` since `swap_nonoverlapping` is documented to work as an "untyped" operation but due to the limitation mentioned above, that's not entirely true during const evaluation. I expect this limitation will only be hit in niche corner cases, so the benefits of having this function work most of the time outweigh the downsides of users running into this problem. (Note that unsafe code could already hit this limitation before this PR by doing cursed pointer casts, but having it hidden inside `swap_nonoverlapping` feels a bit different.)
compiletest: Support matching on non-json lines in compiler output
and migrate most of remaining `error-pattern`s to it.
Such diagnostics use a new diagnostic kind `RAW`.
Also emit an error for `error-pattern`s that can be replaced with line annotations.
Also remove a number of conditions to check both line annotations and `error-pattern`s in more cases.
Also respect `//@ check-stdout` when collecting "actual errors" for comparing against line annotations.
(A couple of tiny refactorings is also included.)
Continuation of https://github.com/rust-lang/rust/pull/139760.
r? `@jieyouxu`
Don't name variables from external macros in borrow errors.
This came up as part of the expansion of format_args. However, it's a more general problem (and now solution).
I noticed that this does change another test, moving out of fields in derives on packed struct. However, I think this is a better error simply because it used to refer to `other.0` which is an implementation detail which doesn't really make sense.
cc `@m-ou-se`
compiletest: Do not require annotations on empty labels and suggestions
Unlike other empty diagnostics, empty labels (only underlining spans) and empty suggestions (suggestions to remove something) are quite usual and do not require any special attention and annotations.
This effectively reverts a part of https://github.com/rust-lang/rust/pull/139485.
r? `@jieyouxu`
Rollup of 7 pull requests
Successful merges:
- #139675 (Add the AVX10 target features)
- #140286 (Check if format argument is identifier to avoid error err-emit)
- #140456 (Fix test simd/extract-insert-dyn on s390x)
- #140551 (Move some tests out of tests/ui)
- #140588 (Adjust some ui tests re. target-dependent errors)
- #140617 (Report the `unsafe_attr_outside_unsafe` lint at the closest node)
- #140626 (allow `#[rustfmt::skip]` in combination with `#[naked]`)
r? `@ghost`
`@rustbot` modify labels: rollup
allow `#[rustfmt::skip]` in combination with `#[naked]`
fixes https://github.com/rust-lang/rust/issues/140623
We very deliberately use an allowlist to prevent weird interactions with `#[naked]`, hopefully we've now found all of the useful combinations.
cc `@Amanieu`
Report the `unsafe_attr_outside_unsafe` lint at the closest node
This PR have `AstValidation` track a linting node id and then uses it when reporting the `unsafe_attr_outside_unsafe` lint, so that instead of being bound at the crate-root, `#[allow]` of the lint works at any node.
Fixesrust-lang/rust#140602
r? `@jieyouxu`
Adjust some ui tests re. target-dependent errors
Alternatives to optional error annotations in #140586:
- Continue to ignore target-dependent additional errors in `tests/ui/panic-runtime/{two-panic-runtimes.rs,tests/ui/panic-runtime/want-abort-got-unwind.rs,tests/ui/panic-runtime/want-abort-got-unwind2.rs}` -- but explain why some targets have more errors than others.
- Use `-Cpanic=abort` for `tests/ui/cfg/cfg_false_no_std-2.rs`. In that test, the panic strategy does not matter w.r.t. test intention.
- Adjust FIXMEs in `tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs` to track it in #140620.
---
try-job: armhf-gnu
try-job: test-various
try-job: x86_64-msvc-1
try-job: i686-msvc-1
try-job: x86_64-mingw-1
try-job: aarch64-apple
try-job: x86_64-apple-1
Fix test simd/extract-insert-dyn on s390x
Fix the test for s390x by enabling s390x vector extension via `target_feature(enable = "vector")`(#127506). As this is is still gated by `#![feature(s390x_target_feature)]` we need that attribute also.
Check if format argument is identifier to avoid error err-emit
Fixes#139104
When `argument` is not an identifier, it should not be considered a field access. I checked this and if not emit an invalid format string error. I think we could do with a little finer error handling, I'll open an issue to track this down later.
The first commit submits the ui test, the second commits the code and the changes to the test output.
r? compiler
Add the AVX10 target features
Parent #138843
Adds the `avx10_target_feature` feature gate, and `avx10.1` and `avx10.2` target features.
It is confirmed that Intel is dropping AVX10/256 (see [this comment](https://github.com/rust-lang/rust/issues/111137#issuecomment-2795442288)), so this should be safe to implement now.
The LLVM fix for llvm/llvm-project#135394 was merged, and has been backported to LLVM20, and the patch has also been propagated to rustc in #140502
`@rustbot` label O-x86_64 O-x86_32 A-target-feature A-SIMD
Set groundwork for proper const normalization
r? lcnr
Updates a lot of our normalization/alias infrastructure to be setup to handle mgca aliases and normalization once const items are represented more like aliases than bodies. Inherent associated consts are still super busted, I didn't update the assertions that IACs the right arg setup because that winds up being somewhat involved to do *before* proper support for normalizing const aliases is implemented.
I dont *intend* for this to have any effect on stable. We continue normalizing via ctfe on stable and the codepaths in `project` for consts should only be reachable with mgca or ace.
Remove fragile equal-pointers-unequal tests.
Same as https://github.com/rust-lang/rust/pull/139176
---
These tests were added in #127003
These tests stop working when I change implementation details of format_args!(). These tests shouldn't rely on such implementation details.
Do these tests test anything that isn't already covered by other tests? If so, they should be expressed in a less fragile way that doesn't rely on internal details of format_args!().
cc `@GrigorenkoPV,` author of these tests.
organize and extend forbidden target feature tests
In particular this adds some loongarch tests for https://github.com/rust-lang/rust/pull/135015, Cc `@heiher`
Seems like the tests change so much git does not detect the renames; a commit-by-commit review should help.
try-job: `x86_64-gnu-llvm-20-*`
resolve: Support imports of associated types and glob imports from traits
Follow up to https://github.com/rust-lang/rust/pull/134754, part of https://github.com/rust-lang/rust/issues/134691.
This PR also closes https://github.com/rust-lang/rust/issues/138711 now.
Prohibiting `use Trait::AssocType;` at name resolution stage doesn't make sense, the name itself is perfectly resolveable.
It's a type checker's problem that the necessary generic args are not passed when the imported `AssocType` is used, so an error should be reported there.
And since we can import associated trait items now, glob imports from traits can also be allowed.
Fix the test for s390x by enabling s390x vector extension via
`target_feature(enable = "vector")`(#127506). As this is is still
gated by `#![feature(s390x_target_feature)]` we need that attribute
also.
Add regression test for #140545Closes#140545
I am not very knowledgable about the typesystem internals, so I couldn't come up with a good name for the test. But I'm happy to move it to a more appropriate place if there is one (`tests/ui/impl-trait/non-defining-uses` maybe?)
r? types (or reroll as appropriate if this is not actually a T-types issue; i'm clueless)
Emit user type annotations for free consts in pattern position
This previously wasnt done because free consts couldn't have any generic parameters that need to be preserved for borrowck. This is no longer the case with `feature(generic_const_items)`
r? fmease