Catch unwinds from the global ctxt callback to complete queries profiling data in more cases
The driver/compiler interface provides multiple callbacks, and we sometimes catch unwinds to flush diagnostics, ensure ICEs appear, and so on even when fatal errors occur.
When these panics happen, we don't `finish` the `TyCtxt`, and there's a fixme about that. Unfortunately this is where we also allocate the self-profile strings: query events for example start as virtual and are turned into real strings by this finalization process; they are _invalid_ without this step. When fatal errors happen, the in-flight query name will be `<unknown>`, event counts will be inaccurate, etc.
This PR catches panics from another of these callbacks, where the `TyCtxt` is available, to allow for the self-profiling data to be computed before continuing the unwinding process as before. `finish` does more things, that I don't want to introduce here.
I remember seeing this discussed in GH issues in the past, but can't find any open ones now. It may also have been only mentioned while trying to profile existing slowness issues. I stumbled upon this again recently when looking into `tests/ui/try-trait/deep-try-chain-issue-153583.rs`, where the slowest query is `<unknown>`.
```
> rm *.mm_profdata ; rustc +nightly -Zself-profile tests/ui/try-trait/deep-try-chain-issue-153583.rs ; summarize summarize *.mm_profdata | head -n 5
error[E0277]: the `?` operator can only be applied to values that implement `Try`
--> tests/ui/try-trait/deep-try-chain-issue-153583.rs:6:5
|
6 | 0?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????...
| ^^ the `?` operator cannot be applied to type `{integer}`
|
= help: the nightly-only, unstable trait `Try` is not implemented for `{integer}`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.
+------------------------------------------------------+-----------+-----------------+----------+------------+
| Item | Self time | % of total time | Time | Item count |
+------------------------------------------------------+-----------+-----------------+----------+------------+
| <unknown> | 1.55s | 99.416 | 3.21s | 15230 |
+------------------------------------------------------+-----------+-----------------+----------+------------+
```
This PR fixes that case at least. In general, it should fix the invalid profiling records for fatal errors happening while a query is running.
```
+------------------------------------------------------+-----------+-----------------+----------+------------+
| Item | Self time | % of total time | Time | Item count |
+------------------------------------------------------+-----------+-----------------+----------+------------+
| typeck_root | 5.04s | 95.588 | 5.08s | 1 |
+------------------------------------------------------+-----------+-----------------+----------+------------+
```
r? @bjorn3
rustdoc: preserve parent doc cfg for `macro_export` macros
The detached-item context is discovered before `propagate_doc_cfg`, it is carried on the clean item and consumed by the pass.
Closesrust-lang/rust#100916
simplify `ast_fragments!`
The syntax and meaning of this macro are not very intuitive as its just a large dump of function names and has some special cases.
Each commit should be a small improvement that can be evaluated on its own.
Fix: On wasm targets, call `panic_in_cleanup` if panic occurs in cleanup
Relies on https://github.com/rust-lang/llvm-project/pull/194.
Reland of https://github.com/rust-lang/rust/pull/151771.
Previously this was not correctly implemented. Each funclet may need its own terminate block, so this changes the `terminate_block` into a `terminate_blocks` `IndexVec` which can have a terminate_block for each funclet. We key on the first basic block of the funclet -- in particular, this is the start block for the old case of the top level terminate function.
Rather than using a catchswitch/catchpad pair, I used a cleanuppad. The reason for the pair is to avoid catching foreign exceptions on MSVC. On wasm, it seems that the catchswitch/catchpad pair is optimized back into a single cleanuppad and a catch_all instruction is emitted which will catch foreign exceptions. Because the new logic is only used on wasm, it seemed better to take the simpler approach seeing as they do the same thing.
- [ ] Add test for https://github.com/rust-lang/rust/issues/153948
Disentangle AST crates and error crates
Currently the `rustc_ast*` crates and the `rustc_error*` crates (and `rustc_lint_defs`) are quite intertwined. This PR disentangles them. Details in individual commits.
r? @davidtwco
It currently only depends on two things:
- `rustc_ast::AttrId`: this is just a re-export of `rustc_span::AttrId`,
so we can import the original instead.
- `rustc_ast::AttributeExt`: needed only for the `name` and `id`
methods. We can instead pass in the `name` and `id` directly.
`rustc_error_messages` currently depends on
`rustc_ast`/`rustc_ast_pretty`. This is odd, because
`rustc_error_messages` feels like a very low-level module but
`rustc_ast`/`rustc_ast_pretty` do not.
The reason is that a few AST types impl `IntoDiagArg` via
pretty-printing. `rustc_error_messages` can define `IntoDiagArg` and
then impl it for the AST types. But if we invert the dependency we hit
a problem with the orphan rule: `rustc_ast` must impl `IntoDiagArg`
for the AST types, but that requires calling pretty-printing code which
is in `rustc_ast_pretty`, a downstream crate.
This commit avoids this problem by just removing the `IntoDiagArg` impls
for these AST types. There aren't that many of them, and we can just use
`String` in the relevant error structs and use the pretty printer in the
downstream crates that construct the error structs. There are plenty of
existing examples where `String` is used in error structs.
There is now no dependency between `rustc_ast*` and
`rustc_error_messages`.
fatal errors currently abort the compiler process without allocating the self-profile
strings: query events aren't always correctly recorded, and will show up as <unknown>
in the data.
catching the unwinding panic allows us to finalize the self-profiling process correctly
before continuing unwinding as before.
Simplify `HashStable`
This PR:
- Simplifies the `HashStable` trait, by moving its generic parameter from the trait to its single method.
- Eliminates the need for the non-obvious `derive(HashStable)`/`derive(HashStable_Generic)` distinction.
- Reduces the need for, and clarifies, the non-obvious `derive(HashStable)`/`derive(HashStable_NoContext)` distinction.
r? @fee1-dead
Thanks to the `HashStable` trait being simplified,
`HashStable_NoContext` is only needed when a (near) perfect derive is
required. In practice, this means it's only needed for types with a
generic `<I: Interner>` parameter.
This commit replaces `derive(HashStable_NoContext)` with
`derive(HashStable)` for all types that don't have `<I: Interner>`.
`std::hash::Hash` looks like this:
```
pub trait Hash {
fn hash<H>(&self, state: &mut H)
where H: Hasher;
...
}
```
The method is generic.
In contrast, `HashStable` looks like this:
```
pub trait HashStable<Hcx> {
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher);
}
```
and impls look like this (in crates upstream of `rustc_middle`):
```
impl<Hcx: HashStableContext> HashStable<Hcx> for Path {
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
...
}
}
```
or this (in `rustc_middle` and crates downstream of `rustc_middle`):
```
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
...
}
}
```
Differences to `std::hash::Hash`:
- The trait is generic, rather than the method.
- The way impls are written depends their position in the crate graph.
- This explains why we have both `derive(HashStable)` and
`derive(HashStable_Generic)`. The former is for the
downstream-of-`rustc_middle` case, the latter is for the upstream of
`rustc_middle` case.
Why the differences? It all boils down to `HashStable` and
`HashStableContext` being in different crates. But the previous commit
fixed that, which means `HashStable` can be simplified to this, with a
generic method:
```
pub trait HashStable {
fn hash_stable<Hcx: HashStableContext>(&self, hcx: &mut Hcx, hasher: &mut StableHasher);
}
```
and all impls look like this:
```
impl HashStable for Path {
fn hash_stable<Hcx: HashStableContext>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
...
}
}
```
Other consequences:
- `derive(HashStable_Generic)` is no longer needed; `derive(HashStable)`
can be used instead.
- In this commit, `derive(HashStable_Generic` is made a synonym of
`derive(HashStable)`. The next commit will remove this synonym,
because it's a change that touches many lines.
- `#[stable_hash_generic]` is no longer needed (for `newtype_index`);
`#[stable_hash]` can be used instead.
- `#[stable_hash_no_context]` was already a synonym of
`#[stable_hash_generic]`, so it's also removed in favour of just
`#[stable_hash]`.
- The difference between `derive(HashStable)` and
`derive(HashStable_NoContext)` now comes down to the difference
between `synstructure::AddBounds::Generics` and
`synstructure::AddBounds::Fields`, which is basically "vanilla derive"
vs "(near) perfect derive".
- I have improved the comments on `HashStableMode` to better
explaining this subtle difference.
- `rustc_middle/src/ich/impls_syntax.rs` is no longer needed; the
relevant impls can be defined in the crate that defines the relevant
type.
- Occurrences of `for<'a> HashStable<StableHashingContext<'a>>` are
replaced with with `HashStable`, hooray.
- The commit adds a `HashStableContext::hashing_controls` method, which
is no big deal. (It's necessary for `AdtDefData::hash_stable`, which
calls `hashing_controls` and used to have an `hcx` that was a
concrete `StableHashingContext` but now has an `hcx` that is just
`Hcx: HashStableContext`.)
Overall this is a big simplification, removing a lot of confusing
complexity in stable hashing traits.
This puts it in the same crate as the `HashStable` and `ToStableHasher`
traits. This requires introducing three types `RawSpan`, `RawDefId` and
`RawDefPathHash` to work around the fact that `rustc_data_structures`
is upstream of `rustc_span` and so doesn't have access to `Span`,
`DefId`, and `DefPathHash`. This is a bit ugly but is worth it because
moving `HashStableContext` enables big cleanups across many crates in
subsequent commits.
`def_id.to_stable_hash_key(hcx)` calls `hcx.def_path_hash(def_id)`. This
commit replaces various other occurrences of the latter form with the
former form. It's all inlined so there should be no perf effects.
This will make things easier for the next commit, which will change
`DefId::to_stable_hash_key`, among other things.
Rollup of 21 pull requests
Successful merges:
- rust-lang/rust#155966 (miri subtree update)
- rust-lang/rust#154149 (resolve: Extend `ambiguous_import_visibilities` deprecation lint to glob-vs-glob ambiguities)
- rust-lang/rust#155189 (simd_reduce_min/max: remove float support)
- rust-lang/rust#155562 (Add a missing `GenericTypeVisitable`, and avoid having interner traits for `FnSigKind` and `Abi`)
- rust-lang/rust#155608 (rustc_middle: Implement the `partial_cmp` operation for `DefId`s)
- rust-lang/rust#155721 (When archive format is wrong produce an error instead of ICE)
- rust-lang/rust#155794 (privacy: share effective visibility initialization)
- rust-lang/rust#155832 (c-variadic: more precise compatibility check in const-eval)
- rust-lang/rust#155856 (std_detect: support detecting more features on aarch64 Windows)
- rust-lang/rust#155861 (Suggest `[const] Trait` bounds in more places)
- rust-lang/rust#155899 (`dlltool`: Set the working directory to workaround `--temp-prefix` bug)
- rust-lang/rust#155916 (Update with new LLVM 22 target for `wasm32-wali-linux-musl` target)
- rust-lang/rust#155935 (remap OUT_DIR paths to fix build script path leakage in crate metadata. )
- rust-lang/rust#155950 (use the new `//@ needs-asm-mnemonic: ret` more)
- rust-lang/rust#155958 (ci(free-disk-space): remove more tools and fix warnings)
- rust-lang/rust#155711 (bump curl-sys and openssl-sys to support OpenSSL 4.0.x)
- rust-lang/rust#155831 (Add `AcceptContext::expect_key_value`)
- rust-lang/rust#155877 (Avoid misleading return-type note for foreign `Fn` callees)
- rust-lang/rust#155949 (Update `opt_ast_lowering_delayed_lints` query to allow "stealing" lints, allowing to use `FnOnce` instead of `Fn`)
- rust-lang/rust#155951 (Make `FlatMapInPlaceVec` an unsafe trait.)
- rust-lang/rust#155967 (Fix `doc_cfg` feature for extern items)
Fix `doc_cfg` feature for extern items
Part of rust-lang/rust#150268.
It only solves the extern items issue, but not the others listed in the issue. I will need to think about how to fix them nicely.
r? @Urgau
Make `FlatMapInPlaceVec` an unsafe trait.
Because the memory safety of `FlatMapInPlace::flat_map_in_place` depends on `FlatMapInPlaceVec` impls behaving correctly.
r? @chenyukang
Avoid misleading return-type note for foreign `Fn` callees
Fixesrust-lang/rust#155727.
The issue occurred because the code that emitted the `Fn`/`FnMut` suggestion only avoided the return-type fallback when it could point at a local callee argument. The local case from rust-lang/rust#125325 was fixed in rust-lang/rust#126226, but nested cross-crate cases could still suggest changing the enclosing function's return type even though the relevant `Fn` requirement came from the callee argument.
This is also the broader diagnostic shape discussed in rust-lang/rust#119985.
This PR checks the instantiated callee predicates for an exact `Fn` bound
on the closure argument, and extends `wrong-closure-arg-suggestion-125325` with cross-crate function and method cases for that path.
bump curl-sys and openssl-sys to support OpenSSL 4.0.x
The previously pinned versions of openssl-sys and curl-sys are not
compatible with OpenSSL 4.0.x.
- `curl-sys`: 0.4.84+curl-8.17.0 -> 0.4.87+curl-8.19.0
- `openssl-sys`: 0.9.111 -> 0.9.114
r? @mati865
@rustbot label +beta-nominated +stable-nominated
Update with new LLVM 22 target for `wasm32-wali-linux-musl` target
This is a reopening of rust-lang/rust#155654, which was closed abruptly due to changed commit SHAs on my end during merge.
`dlltool`: Set the working directory to workaround `--temp-prefix` bug
dlltool's `--temp-prefix` argument incorrectly splits paths that contain spaces. To workaround this, we pass a relative path to `--temp-prefix` and set the working directory.
fixesrust-lang/rust#155591
Suggest `[const] Trait` bounds in more places
Right now we have some special logic in the const checker for emitting `[const] Trait` suggestions, but I'm trying to handle that similarly to how it is handled for normal `Trait` clauses. This is just a small step in how it will look on the UX side, which should make my follow-up PRs affect tests less and just be a refactoring
std_detect: support detecting more features on aarch64 Windows
Wires `IsProcessorFeaturePresent` calls for the `PF_ARM_*` constants exposed in Windows SDK 26100 (Windows 11 24H2), plus an architectural derivation for `rdm`. All eight feature names have been stable in `is_aarch64_feature_detected!` on Linux/Darwin/BSD since Rust 1.60 — this brings the Windows backend to parity.
| Feature | Source on Windows |
|---|---|
| `fp16` | `PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE` (value 67) |
| `i8mm` | `PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE` (value 66) |
| `bf16` | `PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE` (value 68) |
| `sha3` | `PF_ARM_SHA3` (value 64) **AND** `PF_ARM_SHA512` (value 65) |
| `lse2` | `PF_ARM_LSE2_AVAILABLE` (value 62) |
| `f32mm` | `PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE` (value 58) |
| `f64mm` | `PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE` (value 59) |
| `rdm` | derived from `PF_ARM_V82_DP` (see below) |
`PF_ARM_SVE_F32MM` / `PF_ARM_SVE_F64MM` (values 58 / 59) were already added as commented-out placeholders in rust-lang/stdarch#1749 — they have direct stable Feature mappings (`f32mm`, `f64mm`), unlike their sibling values 52 / 53 / 57 (`SVE_BF16`, `SVE_EBF16`, `SVE_I8MM`) which have no SVE-specific stdarch Feature name and remain commented for that reason.
`sha3` requires both `PF_ARM_SHA3` (FEAT_SHA3) and `PF_ARM_SHA512` (FEAT_SHA512), matching the existing convention from rust-lang/stdarch#1749 where `sve2-aes` is set only when both `PF_ARM_SVE_AES` and `PF_ARM_SVE_PMULL128` are present.
### `rdm` derivation
There is no `PF_ARM_RDM_*` constant; Microsoft has never defined one. We derive it from `PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE` (FEAT_DotProd) via the following architectural chain:
1. FEAT_DotProd is an optional v8.2-A feature, so its presence implies the core implements at least v8.1-A.
2. Per Arm ARM K.a §D17.2.91: *"In an ARMv8.1 implementation, if FEAT_AdvSIMD is implemented, FEAT_RDM is implemented."*
3. AdvSIMD is universally implemented on every Windows-on-ARM SKU.
4. Therefore: DotProd ⇒ v8.1-A baseline + AdvSIMD ⇒ FEAT_RDM.
This is the same derivation .NET 10 uses, with comment cited verbatim ([dotnet/runtime PR 109493](https://github.com/dotnet/runtime/pull/109493), shipped in v10.0.0 at [`src/native/minipal/cpufeatures.c`](https://github.com/dotnet/runtime/blob/v10.0.0/src/native/minipal/cpufeatures.c)):
> *"IsProcessorFeaturePresent does not have a dedicated flag for RDM, so we enable it by implication.
> 1) DP is an optional instruction set for Armv8.2, which may be included only in processors implementing at least Armv8.1.
> 2) Armv8.1 requires RDM when AdvSIMD is implemented, and AdvSIMD is a baseline requirement of .NET.
> Therefore, by documented standard, DP cannot exist here without RDM. In practice, there is only one CPU supported by Windows that includes RDM without DP, so this implication also has little practical chance of a false negative."*
The "one CPU with RDM without DP" trade-off applies equally to us: we accept a possible false negative on that single SKU rather than introducing a more aggressive heuristic.
### Tests
Adds `println!` lines to the existing `aarch64_windows()` test in `library/std_detect/tests/cpu-detection.rs` for each newly-detected feature, mirroring the existing single-line pattern. No structural assertions added.
### Scope
Stable feature names only. The unstable SME family (`sme`, `sme2`, `sme2p1`, `sme_*`, `ssve_fp8*`) and other unstable additions tracked under rust-lang/rust#127764 are intentionally out of scope here to keep this PR minimal — happy to do a follow-up.
### References
- Tracking issue: rust-lang/rust#127764 (`stdarch_aarch64_feature_detection`)
- Precedent: rust-lang/stdarch#1749 (taiki-e, merged 2025-03-24) — added the SVE constants this builds on
- MS docs: [`IsProcessorFeaturePresent`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent) — full PF_ARM_* table
r? @Amanieu
cc @taiki-e (author of rust-lang/stdarch#1749, would appreciate your eyes on the `rdm` inference)
@rustbot label +T-libs +O-windows +O-ARM
c-variadic: more precise compatibility check in const-eval
tracking issue: https://github.com/rust-lang/rust/issues/44930
This came up in the stabilization report discussion https://github.com/rust-lang/rust/pull/155697#discussion_r3139778447.
As a reminder, this is what C says (in section 7.16.1.1 of the [C23 standard](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=302).
> If type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:
>
> - both types are pointers to qualified or unqualified versions of compatible types;
> - one type is compatible with a signed integer type, the other type is compatible with the
> corresponding unsigned integer type, and the value is representable in both types;
> - one type is pointer to qualified or unqualified void and the other is a pointer to a qualified or
> unqualified character type;
> - or, the type of the next argument is `nullptr_t` and type is a pointer type that has the same representation and alignment requirements as a pointer to a character type
I think the last rule is not relevant for us, we don't really have an equivalent of `nullptr_t` as far as I know.
r? RalfJung
cc @tgross35
privacy: share effective visibility initialization
Address one `FIXME` in `EffectiveVisibilities` by sharing the private effective visibility initialization path between `effective_vis_or_private` and `update`.
`update` now mutates the map entry in place instead of copying the effective visibility out and inserting it back at the end. The inserted default value and update logic are unchanged.
Validation:
- `git diff --check`
- `python x.py check compiler/rustc_middle`
When archive format is wrong produce an error instead of ICE
Fixrust-lang/rust#145624. Fixrust-lang/rust#147094. Fixrust-lang/rust#148217.
There are now two-step solutions to replace the original ICE:
Step 1: BSD format archive on a GNU/Linux target should emit a format mismatch warning.
Step 2: Corrupt archive with member offset exceeding file boundary should produce an error, not an ICE.
r? @bjorn3
simd_reduce_min/max: remove float support
LLVM currently doesn't have an intrinsic with the right semantics here (see https://github.com/llvm/llvm-project/issues/185827). The only remaining user of this intrinsic with float types is portable-simd and it's easier to implement a fallback there than here, so I opted for making the intrinsic int-only. I kept around the float support in cranelift and Miri because there it already has the desired semantics (matching scalar min/max).
Fixes https://github.com/rust-lang/rust/issues/153395
~~Blocked on https://github.com/rust-lang/portable-simd/pull/515~~