Compare commits

...
Sign in to create a new pull request.

425 commits

Author SHA1 Message Date
bors
c043085801 Auto merge of #152785 - Zalathar:rollup-UGtEsqh, r=Zalathar
Rollup of 20 pull requests

Successful merges:

 - rust-lang/rust#145399 (Unify wording of resolve error)
 - rust-lang/rust#150473 (tail calls: fix copying non-scalar arguments to callee)
 - rust-lang/rust#152637 (Add a note about elided lifetime)
 - rust-lang/rust#152729 (compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness")
 - rust-lang/rust#152751 (Rename dep node "fingerprints" to distinguish key and value hashes)
 - rust-lang/rust#152753 (remove the explicit error for old `rental` versions)
 - rust-lang/rust#152758 (Remove ShallowInitBox.)
 - rust-lang/rust#151530 (Fix invalid `mut T` suggestion for `&mut T` in missing lifetime error)
 - rust-lang/rust#152179 (Add documentation note about signed overflow direction)
 - rust-lang/rust#152474 (Implement opt-bisect-limit for MIR)
 - rust-lang/rust#152509 (tests/ui/test-attrs: add annotations for reference rules)
 - rust-lang/rust#152672 (std: use libc version of `_NSGetArgc`/`_NSGetArgv`)
 - rust-lang/rust#152711 (resolve: Disable an assert that no longer holds)
 - rust-lang/rust#152725 (Rework explanation of CLI lint level flags)
 - rust-lang/rust#152732 (add regression test for 147958)
 - rust-lang/rust#152745 (Fix ICE in `suggest_param_env_shadowing` with incompatible args)
 - rust-lang/rust#152749 (make `rustc_allow_const_fn_unstable` an actual `rustc_attrs` attribute)
 - rust-lang/rust#152756 (Miri: recursive validity: also recurse into Boxes)
 - rust-lang/rust#152770 (carryless_mul: mention the base)
 - rust-lang/rust#152778 (Update tracking issue number for final_associated_functions)
2026-02-18 11:12:36 +00:00
Stuart Cook
8a2c6ea409
Rollup merge of #152778 - mu001999-contrib:fix/final-method, r=fmease
Update tracking issue number for final_associated_functions

From https://github.com/rust-lang/rust/pull/151783#discussion_r2816929026
2026-02-18 17:29:51 +11:00
Stuart Cook
c7db84b0a3
Rollup merge of #152770 - RalfJung:carryless-mul-base, r=scottmcm
carryless_mul: mention the base

Arithmetic operations do not typically care about the base that is used to represent numbers, but this one does. Mentioning that makes it easier to understand the operation, I think.

Cc @folkertdev
2026-02-18 17:29:50 +11:00
Stuart Cook
123611f208
Rollup merge of #152756 - RalfJung:miri-recursive-box, r=Kivooeo
Miri: recursive validity: also recurse into Boxes

Now that https://github.com/rust-lang/rust/issues/97270 is fixed, the recursive validity mode for Miri can recuse into Boxes without exploding everywhere.
2026-02-18 17:29:50 +11:00
Stuart Cook
e53dd52e16
Rollup merge of #152749 - cyrgani:rustc-allow-const, r=jdonszelmann
make `rustc_allow_const_fn_unstable` an actual `rustc_attrs` attribute

It is already named like one, but used to have its own feature gate, which this PR now removes in favor of just using `#![feature(rustc_attrs)]`.

Most of the diff is just the line number changes in `malformed-attrs.stderr`.
2026-02-18 17:29:49 +11:00
Stuart Cook
e8327b0a79
Rollup merge of #152745 - TaKO8Ki:fix-ice-suggest-param-env-shadowing-incompatible-args, r=Kivooeo
Fix ICE in `suggest_param_env_shadowing` with incompatible args

Fixes rust-lang/rust#152684
2026-02-18 17:29:49 +11:00
Stuart Cook
77e29b25d0
Rollup merge of #152732 - Kivooeo:add-regression-test-1, r=TaKO8Ki
add regression test for 147958

fixes rust-lang/rust#147958
2026-02-18 17:29:48 +11:00
Stuart Cook
f7d5a6467d
Rollup merge of #152725 - ehuss:lint-level-cli, r=jieyouxu
Rework explanation of CLI lint level flags

I think the previous wording as either wrong or confusing. I would consider the CLI flags at a *lower* ranking, since source attributes are able to override the CLI flag.
2026-02-18 17:29:48 +11:00
Stuart Cook
8f3bbc1f5a
Rollup merge of #152711 - petrochenkov:globass, r=Kivooeo
resolve: Disable an assert that no longer holds

Fixes https://github.com/rust-lang/rust/issues/152606
Fixes https://github.com/rust-lang/rust/issues/152595
2026-02-18 17:29:47 +11:00
Stuart Cook
9a82b6700a
Rollup merge of #152672 - joboet:apple_args_libc, r=jhpratt
std: use libc version of `_NSGetArgc`/`_NSGetArgv`

These were added to libc in https://github.com/rust-lang/libc/pull/3702.
2026-02-18 17:29:47 +11:00
Stuart Cook
9ac3dcd7c9
Rollup merge of #152509 - DanielEScherzer:test-references-tests, r=ehuss
tests/ui/test-attrs: add annotations for reference rules
2026-02-18 17:29:46 +11:00
Stuart Cook
544462ad8b
Rollup merge of #152474 - sgasho:opt-bisect-limit-mir, r=saethlin
Implement opt-bisect-limit for MIR

closes: rust-lang/rust#150910

Enable bisecting MIR optimization passes to enhance debuggability.

discussions on zulip: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/MIR.20dump.20the.20pass.20names/with/573219207

### Check it works
#### Sample code
```rust
fn abs(num: isize) -> usize {
    if num < 0 { -num as usize } else { num as usize }
}

fn main() {
    println!("{}", abs(-10));
}
```

#### Output

```shell
rustc +mir -Zmir-opt-bisect-limit=30 src/main.rs
BISECT: running pass (1) CheckAlignment on main[89d5]::main
BISECT: running pass (2) CheckNull on main[89d5]::main
BISECT: running pass (3) CheckEnums on main[89d5]::main
BISECT: running pass (4) LowerSliceLenCalls on main[89d5]::main
BISECT: running pass (5) InstSimplify-before-inline on main[89d5]::main
BISECT: running pass (6) ForceInline on main[89d5]::main
BISECT: running pass (7) RemoveStorageMarkers on main[89d5]::main
BISECT: running pass (8) RemoveZsts on main[89d5]::main
BISECT: running pass (9) RemoveUnneededDrops on main[89d5]::main
BISECT: running pass (10) UnreachableEnumBranching on main[89d5]::main
BISECT: running pass (11) SimplifyCfg-after-unreachable-enum-branching on main[89d5]::main
BISECT: running pass (12) InstSimplify-after-simplifycfg on main[89d5]::main
BISECT: running pass (13) SimplifyConstCondition-after-inst-simplify on main[89d5]::main
BISECT: running pass (14) SimplifyLocals-before-const-prop on main[89d5]::main
BISECT: running pass (15) SimplifyLocals-after-value-numbering on main[89d5]::main
BISECT: running pass (16) MatchBranchSimplification on main[89d5]::main
BISECT: running pass (17) SingleUseConsts on main[89d5]::main
BISECT: running pass (18) SimplifyConstCondition-after-const-prop on main[89d5]::main
BISECT: running pass (19) SimplifyConstCondition-final on main[89d5]::main
BISECT: running pass (20) RemoveNoopLandingPads on main[89d5]::main
BISECT: running pass (21) SimplifyCfg-final on main[89d5]::main
BISECT: running pass (22) CopyProp on main[89d5]::main
BISECT: running pass (23) SimplifyLocals-final on main[89d5]::main
BISECT: running pass (24) AddCallGuards on main[89d5]::main
BISECT: running pass (25) PreCodegen on main[89d5]::main
BISECT: running pass (26) CheckAlignment on main[89d5]::abs
BISECT: running pass (27) CheckNull on main[89d5]::abs
BISECT: running pass (28) CheckEnums on main[89d5]::abs
BISECT: running pass (29) LowerSliceLenCalls on main[89d5]::abs
BISECT: running pass (30) InstSimplify-before-inline on main[89d5]::abs
BISECT: NOT running pass (31) ForceInline on main[89d5]::abs
BISECT: NOT running pass (32) RemoveStorageMarkers on main[89d5]::abs
BISECT: NOT running pass (33) RemoveZsts on main[89d5]::abs
BISECT: NOT running pass (34) RemoveUnneededDrops on main[89d5]::abs
BISECT: NOT running pass (35) UnreachableEnumBranching on main[89d5]::abs
BISECT: NOT running pass (36) SimplifyCfg-after-unreachable-enum-branching on main[89d5]::abs
BISECT: NOT running pass (37) InstSimplify-after-simplifycfg on main[89d5]::abs
BISECT: NOT running pass (38) SimplifyConstCondition-after-inst-simplify on main[89d5]::abs
BISECT: NOT running pass (39) SimplifyLocals-before-const-prop on main[89d5]::abs
BISECT: NOT running pass (40) SimplifyLocals-after-value-numbering on main[89d5]::abs
BISECT: NOT running pass (41) MatchBranchSimplification on main[89d5]::abs
BISECT: NOT running pass (42) SingleUseConsts on main[89d5]::abs
BISECT: NOT running pass (43) SimplifyConstCondition-after-const-prop on main[89d5]::abs
BISECT: NOT running pass (44) SimplifyConstCondition-final on main[89d5]::abs
BISECT: NOT running pass (45) RemoveNoopLandingPads on main[89d5]::abs
BISECT: NOT running pass (46) SimplifyCfg-final on main[89d5]::abs
BISECT: NOT running pass (47) CopyProp on main[89d5]::abs
BISECT: NOT running pass (48) SimplifyLocals-final on main[89d5]::abs
BISECT: NOT running pass (49) AddCallGuards on main[89d5]::abs
BISECT: NOT running pass (50) PreCodegen on main[89d5]::abs
```

r? @saethlin
2026-02-18 17:29:46 +11:00
Stuart Cook
ae196c772d
Rollup merge of #152179 - nickkuk:overflow-direction-note, r=jhpratt
Add documentation note about signed overflow direction

In https://github.com/rust-lang/rust/issues/151989#issuecomment-3845282666 I noticed that signed overflow direction can be determined by returned wrapped value. It is not very obvious (especially, assuming additional `carry: bool` summand), but it is important if we want to add new leading (signed) limb to big integer in this case.

Examples for small summands `x, y: i8` with result extension:

| x     | y    | overflow | result as (u8, i8) |
| ----  | ---- | -------- | ------------------ |
| -1    | -128 | true     | (127, -1)          |
| 0     | -1   | false    | (255, -1)          |
| 2     | 2    | false    | (4, 0)             |
| 127   | 1    | true     | (128, 0)           |

Here is general proof.

1. Set $s=2^{N-1}$ and let's say `iN::carrying_add(x, y, c)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x + y + c + 2s,& x + y + c \le -s-1,\\
x+y+c-2s,& x+y+c\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-s+0+2s =0;\qquad
\mathrm{result}=x + y + c + 2s\le -s-1+2s = s - 1,
$$

so we obtain $[0; s-1]$ which is exactly range of non-negative `iN`.

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x+y+c-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 + s-1+1-2s = -1,
$$

that is, $[-s,-1]$ which is exactly range of negative `iN`.

2. Now suppose that `iN::borrowing_sub(x,y,b)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x - y - b + 2s,& x - y - b \le -s-1,\\
x - y - b - 2s,& x - y - b\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-(s-1)-1+2s =0;\qquad
\mathrm{result}=x - y - b + 2s\le -s-1+2s = s - 1.
$$

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x-y-b-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 - (-s) - 0 - 2s = -1.
$$
2026-02-18 17:29:45 +11:00
Stuart Cook
a544b5df98
Rollup merge of #151530 - reddevilmidzy:e0106, r=fee1-dead
Fix invalid `mut T` suggestion for `&mut T` in missing lifetime error

close: rust-lang/rust#150077

When suggesting to return an owned value instead of a borrowed one, the diagnostic was only removing `&` instead of `&mut `, resulting in invalid syntax like `mut T`. This PR fixes the span calculation to properly cover the entire `&mut ` prefix.
2026-02-18 17:29:45 +11:00
Stuart Cook
d5e9f9d67b
Rollup merge of #152758 - cjgillot:noinit-box, r=RalfJung
Remove ShallowInitBox.

All uses of this were removed by https://github.com/rust-lang/rust/pull/148190
Split from https://github.com/rust-lang/rust/pull/147862

r? @RalfJung
2026-02-18 17:29:44 +11:00
Stuart Cook
64087bc8ec
Rollup merge of #152753 - cyrgani:remove-hack, r=petrochenkov
remove the explicit error for old `rental` versions

This was converted to a hard error 20 months ago (in rust-lang/rust#125596). This seems like enough time for anyone still using it to notice, so remove the note entirely now.
In comparison, the explicit note for the more impactful `time` breakage was already removed after 6 months (rust-lang/rust#129343).

Closes rust-lang/rust#73933.
Closes rust-lang/rust#83125.

r? @petrochenkov
2026-02-18 17:29:43 +11:00
Stuart Cook
7312ac389f
Rollup merge of #152751 - Zalathar:fingerprint, r=nnethercote
Rename dep node "fingerprints" to distinguish key and value hashes

In the query system's dependency graph, each node is associated with two *fingerprints*: one that is typically a hash of the query key, and one that is typically a hash of the query's return value when called with that key.

Unfortunately, many identifiers and comments fail to clearly distinguish between these two kinds of fingerprint, which have very different roles in dependency tracking. This is a frequent source of confusion.

This PR therefore tries to establish a clear distinction between:

- **Key fingerprints** that help to uniquely identify a node (along with its `DepKind`), and are typically a hash of the query key
- **Value fingerprints** that help to determine whether a node can be marked green (despite having red dependencies), and are typically a hash of the query value

There should be no change to compiler behaviour.

r? nnethercote (or compiler)
2026-02-18 17:29:43 +11:00
Stuart Cook
dbc2193d37
Rollup merge of #152729 - Enselic:single_use_consts-not-required, r=cjgillot
compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness"

I don't think this MIR pass is required for soundness. The reasons are:
* Something like it was not enabled by default before PR rust-lang/rust#107404 which was the precursor to `SingleUseConsts` (see rust-lang/rust#125910 for the switch).
* By following the advice from https://github.com/rust-lang/rust/pull/128657#discussion_r1705114015 we can conclude it is not required for soundness since it has only ever run on MIR opt level > 0.
* Its [`MirPass::can_be_overridden()`](0ee7d96253/compiler/rustc_mir_transform/src/pass_manager.rs (L98-L102)) is unchanged and thus returns `true`, indicating that it is not a required MIR pass.
* PR CI pass in rust-lang/rust#151426 which stops enabling it by default in non-optimized builds.

As shown in the updated test `tests/mir-opt/optimize_none.rs`, `#[optimize(none)]` functions become even less optimized, as expected and desired.

Unblocks https://github.com/rust-lang/rust/pull/151426.
2026-02-18 17:29:43 +11:00
Stuart Cook
9e38745532
Rollup merge of #152637 - JohnTitor:issue-65866, r=estebank
Add a note about elided lifetime

Fixes rust-lang/rust#65866
r? @estebank
2026-02-18 17:29:42 +11:00
Stuart Cook
b1c72fbb72
Rollup merge of #150473 - RalfJung:interpret-tail-call, r=WaffleLapkin
tail calls: fix copying non-scalar arguments to callee

Alternative to https://github.com/rust-lang/rust/pull/144933: when invoking a tail call with a non-scalar argument, we need to delay freeing the caller's local variables until after the callee is initialized, so that we can copy things from the caller to the callee.

Fixes https://github.com/rust-lang/rust/issues/144820... but as the FIXMEs in the code show, it's not clear to me whether these are the right semantics.
r? @WaffleLapkin
2026-02-18 17:29:42 +11:00
Stuart Cook
efbc8957a6
Rollup merge of #145399 - estebank:resolve-error-wording-2, r=petrochenkov
Unify wording of resolve error

Remove "failed to resolve" from the main error message and use the same format we use in other resolution errors "cannot find `name`":

```
error[E0433]: cannot find `nonexistent` in `existent`
  --> $DIR/custom_attr_multisegment_error.rs:5:13
   |
LL | #[existent::nonexistent]
   |             ^^^^^^^^^^^ could not find `nonexistent` in `existent`
```

The intent behind this is to end up with all resolve errors eventually be on the form of

```
error[ECODE]: cannot find `{NAME}` in {SCOPE}
  --> $DIR/file.rs:5:13
   |
LL | #[existent::nonexistent]
   |             ^^^^^^^^^^^ {SPECIFIC LABEL}
```

A category of errors that is interest are those that involve keywords. For example:

```
error[E0433]: cannot find `Self` in this scope
  --> $DIR/issue-97194.rs:2:35
   |
LL |     fn bget(&self, index: [usize; Self::DIM]) -> bool {
   |                                   ^^^^ `Self` is only available in impls, traits, and type definitions
```
and

```
error[E0433]: cannot find `super` in this scope
  --> $DIR/keyword-super.rs:2:9
   |
LL |     let super: isize;
   |         ^^^^^ there are too many leading `super` keywords
```

For these the label provides the actual help, while the message is less informative beyond telling you "couldn't find `name`".

This is an off-shoot of https://github.com/rust-lang/rust/pull/126810 and https://github.com/rust-lang/rust/pull/128086, a subset of the intended changes there with review comments applied.

r? @petrochenkov
2026-02-18 17:29:41 +11:00
Zalathar
b015d5712a Rename DepNodeKey::recover to try_recover_key 2026-02-18 17:20:32 +11:00
Zalathar
9eaedddb7f Rename dep node "fingerprints" to distinguish key and value hashes 2026-02-18 17:20:32 +11:00
mu001999
d2580fdd58 Update tracking issue number for final_associated_functions 2026-02-18 10:35:02 +08:00
Daniel Scherzer
6e65aba9a3
tests/ui/test-attrs: add annotations for reference rules 2026-02-17 17:38:48 -08:00
Ralf Jung
ad5108eaad tail calls: fix copying non-scalar arguments to callee 2026-02-17 22:17:58 +01:00
Ralf Jung
626de862a5 carryless_mul: mention the base 2026-02-17 21:57:52 +01:00
cyrgani
83ef5059d6 make rustc_allow_const_fn_unstable an actual rustc_attrs attribute 2026-02-17 20:16:29 +00:00
cyrgani
195b849ea7 remove the explicit error for old rental versions 2026-02-17 20:11:01 +00:00
bors
8387095803 Auto merge of #152677 - ehuss:bootstrap-json-target-spec, r=davidtwco,jieyouxu
Support JSON target specs in bootstrap

JSON target specs were destabilized in https://github.com/rust-lang/rust/pull/150151 and https://github.com/rust-lang/rust/pull/151534. However, this broke trying to build rustc itself with a JSON target spec. This is because in a few places bootstrap is manually calling `rustc` without the ability for the user to provide additional flags (primarily, `-Zunstable-options` to enable JSON targets).

There's a few different ways to fix this. One would be to change these calls to `rustc` to include flags provided by the user (such as `RUSTFLAGS_NOT_BOOTSTRAP`). Just to keep things simple, this PR proposes to just unconditionally pass `-Zunstable-options`.

Another consideration here is how maintainable this is. A possible improvement here would be to have a function somewhere (BootstrapCommand, TargetSelection, free function) that would handle appropriately adding the `--target` flag. For example, that's what cargo does in [`CompileKind::add_target_arg`](592058c7ce/src/cargo/core/compiler/compile_kind.rs (L144-L154)).

I have only tested building the compiler and a few tools like rustdoc. I have not tested doing things like building other tools, running tests, etc.

This would be much easier if there was a Docker image for testing the use case of building rustc with a custom target spec (and even better if that ran in CI).

After the next beta branch, using target JSON specs will become more cumbersome because target specs with the `.json` extension will now require passing `-Zjson-target-spec` (from
https://github.com/rust-lang/cargo/pull/16557). This does not affect target specs without the `.json` extension (such as those from RUST_TARGET_PATH). From my testing, it should be sufficient to pass `CARGOFLAGS_NOT_BOOTSTRAP="-Zjson-target-spec"`. I think that should be fine, since this is not a particularly common use case AFAIK. We could extend bootstrap to auto-detect if the target is a file path, and pass `-Zjson-target-spec` appropriately. I tried something similar in f0bdd35483, which could be adapted if desired.

It would be nice if all of this is documented somewhere. https://rustc-dev-guide.rust-lang.org/building/new-target.html does not really say how to build the compiler with a custom json target.

Fixes https://github.com/rust-lang/rust/issues/151729
2026-02-17 17:35:50 +00:00
Esteban Küber
257a415e05 Make suggestion verbose and fix incorrect suggestion usage 2026-02-17 16:51:53 +00:00
Esteban Küber
c73b3d20c6 Unify wording of resolve error
Remove "failed to resolve" and use the same format we use in other resolution errors "cannot find `name`".

```
error[E0433]: cannot find `nonexistent` in `existent`
  --> $DIR/custom_attr_multisegment_error.rs:5:13
   |
LL | #[existent::nonexistent]
   |             ^^^^^^^^^^^ could not find `nonexistent` in `existent`
```
2026-02-17 16:51:44 +00:00
Ralf Jung
f5421609d6 Miri: recursive validity: also recurse into Boxes 2026-02-17 15:13:58 +01:00
bors
dfbfbf785f Auto merge of #152755 - jdonszelmann:rollup-hcFNB2j, r=jdonszelmann
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#152609 (Install LLVM DLL in the right place on Windows)
 - rust-lang/rust#149904 (`-Znext-solver` Remove the forced ambiguity hack from search graph)
 - rust-lang/rust#152704 (Remove `QueryCtxt` and trait `HasDepContext`)
 - rust-lang/rust#152746 (remove `#![allow(stable_features)]` from most tests)
 - rust-lang/rust#152675 (Improve `VaList` stdlib docs)
 - rust-lang/rust#152748 (Update `sysinfo` version to `0.38.2`)
2026-02-17 13:26:15 +00:00
Jana Dönszelmann
8d26ccc09f
Rollup merge of #152748 - GuillaumeGomez:update-sysinfo, r=GuillaumeGomez
Update `sysinfo` version to `0.38.2`

r? ghost
2026-02-17 14:18:46 +01:00
Jana Dönszelmann
6c38e469b2
Rollup merge of #152675 - folkertdev:va-list-docs, r=tgross35
Improve `VaList` stdlib docs

tracking issue: https://github.com/rust-lang/rust/issues/44930

Some improvements to the `VaList` documentation, at least adding an example. We should link to the reference for c-variadic functions once stable. I've tried to call out explicitly that the type is meant for sending over the FFI boundary.

r? workingjubilee
cc @tgross35
2026-02-17 14:18:46 +01:00
Jana Dönszelmann
76618e7d20
Rollup merge of #152746 - cyrgani:stable-features, r=petrochenkov
remove `#![allow(stable_features)]` from most tests

The only remaining usages are tests that specifically deal with feature gates.
This also deletes the very weird `#![feature(issue_5723_bootstrap)]`, a 13 year old "temporary fix" (rust-lang/rust#5723).
2026-02-17 14:18:45 +01:00
Jana Dönszelmann
47a677d43a
Rollup merge of #152704 - Zalathar:query-ctxt, r=nnethercote
Remove `QueryCtxt` and trait `HasDepContext`

- Follow-up to https://github.com/rust-lang/rust/pull/152636.
- Potentially waiting on https://github.com/rust-lang/rust/pull/152703 to reduce conflicts.
---

With the `QueryContext` trait removed, wrapper struct `QueryCtxt` no longer serves a purpose and can be replaced with `TyCtxt` everywhere.

After that, the only obstacle to removing trait `HasDepContext` is `DepGraph::with_task`, which uses the trait to allow passing both a `TyCtxt` and a query vtable through the context argument. But we can achieve the same result by passing the vtable through the other argument instead, in a tuple alongside the query key.

r? nnethercote
2026-02-17 14:18:44 +01:00
Jana Dönszelmann
c108ad5617
Rollup merge of #149904 - ShoyuVanilla:ns-remove-sg-hack, r=lcnr
`-Znext-solver` Remove the forced ambiguity hack from search graph

As discussed in https://github.com/rust-lang/trait-system-refactor-initiative/issues/257

r? lcnr
2026-02-17 14:18:44 +01:00
Jana Dönszelmann
485f76b835
Rollup merge of #152609 - mati865:gnullvm-llvm-dll, r=bjorn3
Install LLVM DLL in the right place on Windows

Continuation of https://github.com/rust-lang/rust/pull/151795 towards https://github.com/rust-lang/rust/issues/151774.

Unlike other systems, Windows requires runtime libraries to be present in `PATH` or right next to the binary.
So, we copy the library next to the binary as the easier solution.

Tested building `rust-openssl` in debug and release modes, but the difference is within noise margin.
2026-02-17 14:18:43 +01:00
sgasho
28c8d71544 Implement opt-bisect-limit for mir 2026-02-17 21:26:39 +09:00
Camille Gillot
6d4b1b38e7 Remove ShallowInitBox. 2026-02-17 11:25:50 +00:00
cyrgani
609fde8569 remove the issue_5723_bootstrap feature 2026-02-17 10:54:04 +00:00
reddevilmidzy
e0d9d470df Fix invalid mut T suggestion for &mut T in missing lifetime error
* Find ref prefix span for owned suggestions
* Improve missing lifetime suggestions for `&mut str`
2026-02-17 10:18:08 +00:00
Guillaume Gomez
0c8d2b40e3 Update sysinfo version to 0.38.2 2026-02-17 10:57:34 +01:00
bors
3f6250a7bb Auto merge of #152738 - workingjubilee:revert-unsound-ice-patch, r=mati865
Revert "Fix an ICE in the vtable iteration for a trait reference"

The ICE fix appears to be unsound, causing a miscompilation involving `dyn Trait` and `async {}` which induces segfaults in safe Rust code. As the patch only hid an ICE, it does not seem worth the risk.

This addresses the problem in rust-lang/rust#152735 but it may still merit team discussion even if this PR is merged.

This reverts commit 8afd63610b, reversing changes made to 19122c03c7.
2026-02-17 09:36:10 +00:00
cyrgani
28fc413c8f remove #![allow(stable_features)] from most tests 2026-02-17 08:45:08 +00:00
Takayuki Maeda
cbfa215893 fix ICE in suggest_param_env_shadowing with incompatible args
remove comments
2026-02-17 16:48:57 +09:00
Zalathar
25d5cd2eb0 Remove unnecessary trait HasDepContext 2026-02-17 17:30:56 +11:00
Zalathar
db58395a6b Don't use HasDepContext in DepGraph::with_task
The need for a `HasDepContext` impl on tuples can be avoided by passing the
query vtable as part of an argument tuple instead.
2026-02-17 17:30:55 +11:00
Zalathar
fbb34d8c75 Remove wrapper struct QueryCtxt
This struct was only wrapping `TyCtxt` in order to implement traits that
were removed by RUST-152636.

This commit also slightly simplifies the signature of `execute_job_incr`, by
having it call `tcx.dep_graph.data()` internally.
2026-02-17 17:30:55 +11:00
bors
1210e9fa3e Auto merge of #152717 - zetanumbers:fix-152375, r=JonathanBrouwer,petrochenkov,jieyouxu
Fix wrong par_slice implementation

https://github.com/rust-lang/rust/pull/152375#discussion_r2812669219
2026-02-17 06:20:05 +00:00
Martin Nordholts
52b19f7dda compiler: Don't mark SingleUseConsts MIR pass as "required for soundness"
Because:
* Something like it did not exist before PR 107404
* That it is not run our mir-opt-level 0 indicates that it is not
  required for soundness
* Its `MirPass::can_be_overridden()` is unchanged and thus returns true,
  indicating that it is not a required MIR pass.
* No test fails in PR 151426 that stops enabling by default in non-optimized builds

As can be seen from the updated test `tests/mir-opt/optimize_none.rs`,
this means that `#[optimize(none)]` functions become even less
optimized. As expected and as desired.
2026-02-17 06:22:39 +01:00
bors
d1a11b670b Auto merge of #152739 - Zalathar:rollup-8qaJ8F2, r=Zalathar
Rollup of 11 pull requests

Successful merges:

 - rust-lang/rust#152700 (miri subtree update)
 - rust-lang/rust#152715 (`rust-analyzer` subtree update)
 - rust-lang/rust#151783 (Implement RFC 3678: Final trait methods)
 - rust-lang/rust#152512 (core: Implement feature `float_exact_integer_constants`)
 - rust-lang/rust#152661 (Avoid ICE in From/TryFrom diagnostic under -Znext-solver)
 - rust-lang/rust#152703 (Remove `rustc_query_system`)
 - rust-lang/rust#152206 (misc doc improvements)
 - rust-lang/rust#152664 (Fix mis-constructed `file_span` when generating scraped examples)
 - rust-lang/rust#152698 (Suppress unstable-trait notes under `-Zforce-unstable-if-unmarked`)
 - rust-lang/rust#152727 (`probe_op` silence ambiguity errors if tainted)
 - rust-lang/rust#152728 (Port #![default_lib_allocator] to the new attribute parser)
2026-02-17 02:03:25 +00:00
Stuart Cook
f7699054f7
Rollup merge of #152728 - Ozzy1423:default-lib, r=JonathanBrouwer
Port #![default_lib_allocator] to the new attribute parser

Tracking issue: https://github.com/rust-lang/rust/issues/131229

r? @JonathanBrouwer
2026-02-17 13:02:25 +11:00
Stuart Cook
dd27f85cb3
Rollup merge of #152727 - lcnr:method-ambig-err-taint, r=jackh726
`probe_op` silence ambiguity errors if tainted

see the `proc-macro/quote/not-repeatable.rs` test for a case where this is useful

r? types
2026-02-17 13:02:25 +11:00
Stuart Cook
dc77672e9a
Rollup merge of #152698 - Zalathar:zforce, r=jieyouxu
Suppress unstable-trait notes under `-Zforce-unstable-if-unmarked`

- Fixes https://github.com/rust-lang/rust/issues/152692.
---

https://github.com/rust-lang/rust/pull/151036 adds extra diagnostic text (“the nightly-only, unstable trait”) to note when a not-implemented trait is unstable.

However, that extra text is usually unhelpful when building a crate graph with `-Zforce-unstable-if-unmarked` (such as the compiler or stdlib), because *any* trait not explicitly marked stable will be treated as unstable.

(For typical compiler contributors using the stage0 compiler, this fix won't take effect until the next bootstrap beta bump.)
2026-02-17 13:02:24 +11:00
Stuart Cook
7ab22cd1fa
Rollup merge of #152664 - Embers-of-the-Fire:fix-152601, r=GuillaumeGomez
Fix mis-constructed `file_span` when generating scraped examples

Fixes rust-lang/rust#152601. Seemingly relative with rust-lang/rust#147399 but I could not reproduce the original ICE.

This PR removes the `file_span` logic from scraped example generation. The original implementation did not read or write items using `file_span`; it only used it to locate a source file, `context.href_from_span`. However, the span was validated against the wrong file, which could trigger ICEs on inputs such as multibyte characters due to an incorrectly constructed span. Since scraped examples do not use the span and the `url` is already given, the safest and simplest fix is to remove it.

Tested against the crate and MCVE documented in the original issue.

P.S. there seems to be some bug when rendering call sites, but since fixing mis-behavior is a change rather than a bug-fix that would be implemented in another PR.
2026-02-17 13:02:24 +11:00
Stuart Cook
910d4f4c09
Rollup merge of #152206 - tshepang:misc, r=davidtwco
misc doc improvements

These are things I collected as I was looking at code and docs
2026-02-17 13:02:23 +11:00
Stuart Cook
e28a33ad72
Rollup merge of #152703 - nnethercote:rm-rustc_query_system, r=Zalathar
Remove `rustc_query_system`

The end point of the PR sequence rust-lang/rust#152160, rust-lang/rust#152419, rust-lang/rust#152516.

r? @Zalathar
2026-02-17 13:02:23 +11:00
Stuart Cook
572b53fdaf
Rollup merge of #152661 - BartSimpson001:fix-next-solver-from-ice, r=petrochenkov
Avoid ICE in From/TryFrom diagnostic under -Znext-solver

Fixes rust-lang/rust#152518.

Under `-Znext-solver=globally`, `trait_ref.args` may contain fewer
elements than expected. The diagnostic logic in
`fulfillment_errors.rs` assumed at least two elements and
unconditionally called `type_at(1)`, which could lead to an
index out-of-bounds panic during error reporting.

This change adds a defensive check before accessing the second
argument to avoid the ICE. A UI regression test has been added.
2026-02-17 13:02:22 +11:00
Stuart Cook
331a785f81
Rollup merge of #152512 - okaneco:exact_integer, r=tgross35
core: Implement feature `float_exact_integer_constants`

Accepted ACP - https://github.com/rust-lang/libs-team/issues/713#issuecomment-3880122239
Tracking issue - https://github.com/rust-lang/rust/issues/152466

Implement accepted ACP for `MAX_EXACT_INTEGER` and `MIN_EXACT_INTEGER` on `f16`, `f32`, `f64`, and `f128`
Add tests to `coretests/tests/floats/mod.rs`
2026-02-17 13:02:22 +11:00
Stuart Cook
1367126837
Rollup merge of #151783 - mu001999-contrib:impl/final-method, r=fee1-dead
Implement RFC 3678: Final trait methods

Tracking: https://github.com/rust-lang/rust/issues/131179

This PR is based on rust-lang/rust#130802, with some minor changes and conflict resolution.

Futhermore, this PR excludes final methods from the vtable of a dyn Trait.

And some excerpt from the original PR description:
> Implements the surface part of https://github.com/rust-lang/rfcs/pull/3678.
>
> I'm using the word "method" in the title, but in the diagnostics and the feature gate I used "associated function", since that's more accurate.

cc @joshtriplett
2026-02-17 13:02:21 +11:00
Stuart Cook
118df884b9
Rollup merge of #152715 - lnicola:sync-from-ra, r=lnicola
`rust-analyzer` subtree update

Subtree update of `rust-analyzer` to c97b011f91.

Created using https://github.com/rust-lang/josh-sync.

r? @ghost
2026-02-17 13:02:21 +11:00
Stuart Cook
476a6308f1
Rollup merge of #152700 - RalfJung:miri, r=RalfJung
miri subtree update

Subtree update of `miri` to ef30e906aa.

Created using https://github.com/rust-lang/josh-sync.

r? @ghost
2026-02-17 13:02:20 +11:00
Jubilee Young
18a707fc8e Revert "Fix an ICE in the vtable iteration for a trait reference"
The ICE fix appears to be unsound, causing a miscompilation involving
`dyn Trait` and `async {}` which induces segfaults in safe Rust code.
As the patch only hid an ICE, it does not seem worth the risk.

This reverts commit 8afd63610b, reversing
changes made to 19122c03c7.
2026-02-16 17:52:06 -08:00
Kivooeo
e8b0e6b990 add regression test 2026-02-16 22:39:22 +00:00
okaneco
7be024fc06 [cg_clif]: Fix codegen of f128 to i128 casts
Correct name for intrinsic that converts f128 to u128
Use `to_signed` instead of `from_signed` to ensure proper intrinsic
selected for u128/i128
2026-02-16 16:29:36 -05:00
okaneco
67799c9739 core: Implement feature float_exact_integer_constants
Implement accepted ACP for `MAX_EXACT_INTEGER` and `MIN_EXACT_INTEGER`
on `f16`, `f32`, `f64`, and `f128`
Add tests to `coretests/tests/floats/mod.rs`
Disable doc tests for i586 since float<->int casts return incorrect
results
2026-02-16 16:29:31 -05:00
Oscar Bray
8081e86c94 Port #![default_lib_allocator] to the new attribute parser 2026-02-16 19:42:12 +00:00
lcnr
7e14260fd1 probe_op silence ambiguity errors if tainted
see the `proc-macro/quote/not-repeatable.rs` test for a case where this is useful
2026-02-16 19:36:09 +00:00
Eric Huss
3099121bb5 Rework explanation of CLI lint level flags
I think the previous wording as either wrong or confusing. I would
consider the CLI flags at a *lower* ranking, since source attributes are
able to override the CLI flag.
2026-02-16 10:47:35 -08:00
bors
3c9faa0d03 Auto merge of #148190 - RalfJung:box_new, r=RalfJung
replace box_new with lower-level intrinsics

The `box_new` intrinsic is super special: during THIR construction it turns into an `ExprKind::Box` (formerly known as the `box` keyword), which then during MIR building turns into a special instruction sequence that invokes the exchange_malloc lang item (which has a name from a different time) and a special MIR statement to represent a shallowly-initialized `Box` (which raises [interesting opsem questions](https://github.com/rust-lang/rust/issues/97270)).

This PR is the n-th attempt to get rid of `box_new`. That's non-trivial because it usually causes a perf regression: replacing `box_new` by naive unsafe code will incur extra copies in debug builds, making the resulting binaries a lot slower, and will generate a lot more MIR, making compilation measurably slower. Furthermore, `vec!` is a macro, so the exact code it expands to is highly relevant for borrow checking, type inference, and temporary scopes.

To avoid those problems, this PR does its best to make the MIR almost exactly the same as what it was before. `box_new` is used in two places, `Box::new` and `vec!`:
- For `Box::new` that is fairly easy: the `move_by_value` intrinsic is basically all we need. However, to avoid the extra copy that would usually be generated for the argument of a function call, we need to special-case this intrinsic during MIR building. That's what the first commit does.
- `vec!` is a lot more tricky. As a macro, its details leak to stable code, so almost every variant I tried broke either type inference or the lifetimes of temporaries in some ui test or ended up accepting unsound code due to the borrow checker not enforcing all the constraints I hoped it would enforce. I ended up with a variant that involves a new intrinsic, `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, x: T) -> Box<MaybeUninit<T>>`, that writes a value into a `Box<MaybeUninit<T>>` and returns that box again. In exchange we can get rid of somewhat similar code in the lowering for `ExprKind::Box`, and the `exchange_malloc` lang item. (We can also get rid of `Rvalue::ShallowInitBox`; I didn't include that in this PR -- I think @cjgillot has a commit for this somewhere [around here](https://github.com/rust-lang/rust/pull/147862/commits).)

See [here](https://github.com/rust-lang/rust/pull/148190#issuecomment-3457454814) for the latest perf numbers. Most of the regressions are in deep-vector which consists entirely of an invocation of `vec!`, so any change to that macro affects this benchmark disproportionally.

This is my first time even looking at MIR building code, so I am very low confidence in that part of the patch, in particular when it comes to scopes and drops and things like that.

I also had do nerf some clippy tests because clippy gets confused by the new expansion of `vec!` so it makes fewer suggestions when `vec!` is involved.

### `vec!` FAQ

- Why does `write_box_via_move` return the `Box` again? Because we need to expand `vec!` to a bunch of method invocations without any blocks or let-statements, or else the temporary scopes (and type inference) don't work out.
- Why is `box_assume_init_into_vec_unsafe` (unsoundly!) a safe function? Because we can't use an unsafe block in `vec!` as that would necessarily also include the `$x` (due to it all being one big method invocation) and therefore interpret the user's code as being inside `unsafe`, which would be bad (and 10 years later, we still don't have safe blocks for macros like this).
- Why does `write_box_via_move` use `Box` as input/output type, and not, say, raw pointers? Because that is the only way to get the correct behavior when `$x` panics or has control effects: we need the `Box` to be dropped in that case. (As a nice side-effect this also makes the intrinsic safe, which is imported as explained in the previous bullet.)
- Can't we make it safe by having `write_box_via_move` return `Box<T>`? Yes we could, but there's no easy way for the intrinsic to convert its `Box<MaybeUninit<T>>` to a `Box<T>`. Transmuting would be unsound as the borrow checker would no longer properly enforce that lifetimes involved in a `vec!` invocation behave correctly.
- Is this macro truly cursed? Yes, yes it is.
2026-02-16 18:46:10 +00:00
Eric Huss
b4e645fe5a Support JSON target specs in bootstrap
JSON target specs were destabilized in
https://github.com/rust-lang/rust/pull/150151 and
https://github.com/rust-lang/rust/pull/151534. However, this broke
trying to build rustc itself with a JSON target spec. This is because in
a few places bootstrap is manually calling `rustc` without the ability
for the user to provide additional flags (primarily,
`-Zunstable-options` to enable JSON targets).

There's a few different ways to fix this. One would be to change these
calls to `rustc` to include flags provided by the user (such as
`RUSTFLAGS_NOT_BOOTSTRAP`). Just to keep things simple, this PR proposes
to just unconditionally pass `-Zunstable-options`.

Another consideration here is how maintainable this is. A possible
improvement here would be to have a function somewhere
(BootstrapCommand, TargetSelection, free function) that would handle
appropriately adding the `--target` flag. For example, that's what cargo
does in
[`CompileKind::add_target_arg`](592058c7ce/src/cargo/core/compiler/compile_kind.rs (L144-L154)).

I have only tested building the compiler and a few tools like rustdoc. I
have not tested doing things like building other tools, running tests,
etc.

This would be much easier if there was a Docker image for testing the
use case of building rustc with a custom target spec (and even better if
that ran in CI).

After the next beta branch, using target JSON specs will become more
cumbersome because target specs with the `.json` extension will now
require passing `-Zjson-target-spec` (from
https://github.com/rust-lang/cargo/pull/16557). This does not affect
target specs without the `.json` extension (such as those from
RUST_TARGET_PATH). From my testing, it should be sufficient to pass
`CARGOFLAGS_NOT_BOOTSTRAP="-Zjson-target-spec"`. I think that should be
fine, since this is not a particularly common use case AFAIK. We could
extend bootstrap to auto-detect if the target is a file path, and pass
`-Zjson-target-spec` appropriately. I tried something similar in
f0bdd35483,
which could be adapted if desired.

It would be nice if all of this is documented somewhere.
https://rustc-dev-guide.rust-lang.org/building/new-target.html does not
really say how to build the compiler with a custom json target.

Fixes https://github.com/rust-lang/rust/issues/151729
2026-02-16 08:31:00 -08:00
Ralf Jung
0df1764e60 add helper to project to a field of a place 2026-02-16 17:27:40 +01:00
Ralf Jung
e5ed8643b6 adjust clippy to fix some of the issues 2026-02-16 17:27:40 +01:00
Ralf Jung
5e65109f21 add write_box_via_move intrinsic and use it for vec!
This allows us to get rid of box_new entirely
2026-02-16 17:27:40 +01:00
Daria Sukhonina
33a8dc10cf Fix wrong par_slice implementation 2026-02-16 17:49:42 +03:00
Folkert de Vries
3b5874e570
Improve VaList stdlib docs 2026-02-16 14:50:14 +01:00
Mateusz Mikuła
1d1280aae1 Build shared LLVM lib for windows-gnullvm 2026-02-16 14:26:14 +01:00
Mateusz Mikuła
8e9a79091f Add LLVM lib location to the linker search paths 2026-02-16 14:26:14 +01:00
Vadim Petrochenkov
b541f1b198 resolve: Disable an assert that no longer holds 2026-02-16 16:07:08 +03:00
Nicholas Nethercote
e9288e7e90 Remove last remnants of rustc_query_system.
At this point module `ich` is the only thing left.
2026-02-16 22:56:47 +11:00
Nicholas Nethercote
47ed4526d9 Remove DEP_NODE_DEBUG.
Like the previous commit, it's no longer needed.
2026-02-16 22:48:58 +11:00
Nicholas Nethercote
74dd36a934 Remove DEP_KIND_DEBUG.
It's plumbing to work around lack of access to `rustc_middle`, which is
no longer a problem.
2026-02-16 22:48:58 +11:00
Laurențiu Nicola
e52ed9c1ba
Merge pull request #21643 from Shourya742/2026-02-13-migrate-generate-impl-to-use-astnodeedit
migrate generate_impl assist to use AstNodeEdit
2026-02-16 11:11:40 +00:00
Ralf Jung
6a3a3d4f98 try to make cargo-miri work with bootstrap cargo 2026-02-16 11:47:55 +01:00
bors
71e00273c0 Auto merge of #152701 - jhpratt:rollup-clRaY9x, r=jhpratt
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#148206 (Deduplicated float tests and unified in floats/mod.rs)
 - rust-lang/rust#150601 (support c-variadic functions in `rustc_const_eval`)
 - rust-lang/rust#152103 (Consider captures to be used by closures that unwind)
 - rust-lang/rust#152296 (Port `rust_nonnull_optimization_guaranteed` and `rustc_do_not_const_check` to the new attribute parser)
 - rust-lang/rust#152648 (Remove timing assertion from `oneshot::send_before_recv_timeout`)
 - rust-lang/rust#152686 (bootstrap: Inline the `is_tool` check for setting `-Zforce-unstable-if-unmarked`)

Failed merges:

 - rust-lang/rust#152512 (core: Implement feature `float_exact_integer_constants`)
2026-02-16 09:55:35 +00:00
Jacob Pratt
84c522a6b4
Rollup merge of #152686 - Zalathar:force-unstable, r=jieyouxu
bootstrap: Inline the `is_tool` check for setting `-Zforce-unstable-if-unmarked`

`Mode::is_tool` is the sort of method that looks general-purpose, but is only actually used for a very specific purpose, to control the setting of `-Zforce-unstable-if-unmarked`.

It is therefore clearer to inline the mode check, which makes it easier to see how the condition affects the result.

I have tried to add some comments explaining why we set that flag, but they are based on my own recent investigations, so I'm not 100% confident that they're accurate.
2026-02-16 04:28:59 -05:00
Jacob Pratt
1dd933c37e
Rollup merge of #152648 - JonathanBrouwer:debug_spurious, r=jhpratt
Remove timing assertion from `oneshot::send_before_recv_timeout`

This test regularly spuriously fails in CI, such as https://github.com/rust-lang/rust/pull/152632#issuecomment-3902778366
We can just remove the assertion but I'd like to understand why, so I'm adding more information to the assert
2026-02-16 04:28:58 -05:00
Jacob Pratt
d1f3c9eea8
Rollup merge of #152296 - jdonszelmann:port-rust-nonnull-guaranteed, r=jonathanbrouwer
Port `rust_nonnull_optimization_guaranteed` and `rustc_do_not_const_check` to the new attribute parser

r? @JonathanBrouwer another two of them :)
2026-02-16 04:28:57 -05:00
Jacob Pratt
c9a7f8afa9
Rollup merge of #152103 - eggyal:caught-divergence-not-unused, r=cjgillot
Consider captures to be used by closures that unwind

Assignments to a captured variable within a diverging closure should not be considered unused if the divergence is caught.

This patch considers such assignments/captures to be used by diverging closures irrespective of whether the divergence is caught, but better a false negative unused lint than a false positive one (the latter having caused a stable-to-stable regression).

Fixes rust-lang/rust#152079
r? compiler
2026-02-16 04:28:57 -05:00
Jacob Pratt
494c6da389
Rollup merge of #150601 - folkertdev:c-variadic-const-eval, r=RalfJung
support c-variadic functions in `rustc_const_eval`

tracking issue: https://github.com/rust-lang/rust/issues/44930

The new `GlobalAlloc::VaList` is used to create an `AllocId` that represents the variable argument list of a frame. The allocation itself does not store any data, all we need is the unique identifier.

The actual variable argument list is stored in `Memory`, and keyed by the `AllocId`. The `Frame` also stores this `AllocId`, so that when a frame is popped, it can deallocate the variable arguments.

At "runtime" a `VaList` value stores a pointer to the global allocation in its first bytes. The provenance on this pointer can be used to retrieve its `AllocId`, and the offset of the pointer is used to store the index of the next argument to read from the variable argument list.

Miri does not yet support `va_arg`, but I think that can be done separetely?

r? @RalfJung
cc @workingjubilee
2026-02-16 04:28:56 -05:00
Jacob Pratt
bff3e9edcc
Rollup merge of #148206 - xonx4l:deduplicate-float-tests, r=tgross35
Deduplicated float tests and unified in floats/mod.rs

In this PR Float tests are deduplicated and are unified in floats/mod.rs, as discussed in https://github.com/rust-lang/rust/issues/141726.

The moved float tests are:

-> test_powf
-> test_exp
-> test_exp2
-> test_ln
-> test_log_generic
-> test_log2
-> test_log10
-> test_asinh
-> test_acosh
-> test_atanh
-> test_gamma
-> test_ln_gamma

Closes: https://github.com/rust-lang/rust/issues/141726
2026-02-16 04:28:55 -05:00
Nicholas Nethercote
8d56cfe4c3 Move QuerySideEffect.
From `rustc_query_system` to `rustc_middle.` I put it in `graph.rs`,
it's one of two files that uses `QuerySideEffect` and seemed as good as
anywhere else.
2026-02-16 20:04:55 +11:00
Laurențiu Nicola
71c9411b19
Merge pull request #21653 from rust-lang/rustc-pull
minor: Rustc pull update
2026-02-16 09:03:05 +00:00
Nicholas Nethercote
72c7d8640f Remove rustc_query_system README file.
It's identical to the one in `rustc_query_impl`.
2026-02-16 19:58:18 +11:00
Jana Dönszelmann
12e6628977
Port rustc_nonnull_optimization_guaranteed to the new attribute parser 2026-02-16 09:46:04 +01:00
Jana Dönszelmann
47ca78040a
Port rustc_do_not_const_check to the new attribute parser 2026-02-16 09:38:31 +01:00
Ralf Jung
93d45480aa replace box_new in Box::new with write_via_move
requires lowering write_via_move during MIR building to make it just like an assignment
2026-02-16 08:44:56 +01:00
Zalathar
125e69e862 Suppress unstable-trait notes under -Zforce-unstable-if-unmarked 2026-02-16 17:19:05 +11:00
Zalathar
0f5c2215ad Regression test for "unstable" traits in force-unstable builds 2026-02-16 17:13:47 +11:00
The rustc-josh-sync Cronjob Bot
1fb6fc177f Merge ref '139651428d' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@139651428d
Filtered ref: rust-lang/rust-analyzer@3efb0c2db4
Upstream diff: ba284f468c...139651428d

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-16 04:54:45 +00:00
The rustc-josh-sync Cronjob Bot
2ef5156751 Prepare for merging from rust-lang/rust
This updates the rust-version file to 139651428d.
2026-02-16 04:49:19 +00:00
bors
fef627b1eb Auto merge of #152636 - nnethercote:big-cleanups, r=Zalathar
Big query system cleanups

Recent PRs have moved a lot of code from `rustc_query_system` to `rustc_middle` and `rustc_query_impl`, where this code now has access to `TyCtxt`, e.g. rust-lang/rust#152419, rust-lang/rust#152516. As a result, a lot of abstraction and indirection that existed to work around this limitation is no longer necessary. This PR removes a lot of it.

r? @Zalathar
2026-02-16 04:20:25 +00:00
Zalathar
f1664acfbf Inline the is_tool check for setting -Zforce-unstable-if-unmarked 2026-02-16 12:35:00 +11:00
bors
139651428d Auto merge of #152452 - ShE3py:overruled-lint, r=BoxyUwU
feat: show what lint was overruled

We can't `#[allow]` a whole lint group if any of its members is forbidden, but the offending member is not currently shown if it was forbidden from the command line.

Before/after:
```diff
 $ rustc -F dead_code - <<< '#![allow(unused)]'
 error[E0453]: allow(unused) incompatible with previous forbid
  --> <anon>:1:10
   |
 1 | #![allow(unused)]
   |          ^^^^^^ overruled by previous forbid
   |
-  = note: `forbid` lint level was set on command line
+  = note: `forbid` lint level was set on command line (`-F dead_code`)
 
 error: aborting due to 1 previous error
```

@rustbot label +A-diagnostics +A-lints +D-terse
2026-02-15 20:05:05 +00:00
Folkert de Vries
981dacc34f
feature-gate c-variadic definitions and calls in const contexts 2026-02-15 19:54:25 +01:00
Trevor Gross
83794755b7 clif: Only set has_reliable_f128_math with glibc
New float tests in core are failing on clif with issues like the
following:

    Undefined symbols for architecture arm64:
        "_coshf128", referenced from:
            __RNvMNtCshY0fR2o0hOA_3std4f128C4f1284coshCs5TKtJxXQNGL_9coretests in coretests-e38519c0cc90db54.coretests.44b6247a565e10d1-cgu.10.rcgu.o
                "_exp2f128", referenced from:
            __RNvMNtCshY0fR2o0hOA_3std4f128C4f1284exp2Cs5TKtJxXQNGL_9coretests in coretests-e38519c0cc90db54.coretests.44b6247a565e10d1-cgu.10.rcgu.o
        ...

Disable f128 math unless the symbols are known to be available, which
for now is only glibc targets. This matches the LLVM backend.
2026-02-15 18:00:54 +00:00
xonx
2c1d605f21 unify and deduplicate floats 2026-02-15 18:00:41 +00:00
Ralf Jung
1f39d1f74f
Merge pull request #4859 from rust-lang/rustup-2026-02-15
Automatic Rustup
2026-02-15 17:52:14 +00:00
The Miri Cronjob Bot
702793191f fmt 2026-02-15 18:20:47 +01:00
bors
873b4beb0c Auto merge of #152671 - JonathanBrouwer:rollup-4Ov19Nw, r=JonathanBrouwer
Rollup of 4 pull requests

Successful merges:

 - rust-lang/rust#152566 (Remove code for ThinLTO from cg_gcc)
 - rust-lang/rust#152278 (Fix const normalization for generic const items with trait assoc consts)
 - rust-lang/rust#152604 (Relocate some tests)
 - rust-lang/rust#152625 (Provide all lint group names to Clippy)
2026-02-15 16:52:45 +00:00
Chayim Refael Friedman
23a3e642d7
Merge pull request #21648 from alexanderkjall/borsh-error-compilation-failure
fix smol_str compilation error
2026-02-15 16:42:02 +00:00
joboet
bd523647a4
std: use libc version of _NSGetArgc/_NSGetArgv 2026-02-15 17:06:36 +01:00
Jonathan Brouwer
ee17e8cb7c
Rollup merge of #152625 - Alexendoo:lint-group-names, r=Kivooeo
Provide all lint group names to Clippy

Unblocks https://github.com/rust-lang/rust-clippy/pull/14689
2026-02-15 16:37:38 +01:00
Jonathan Brouwer
c5a12fbd0d
Rollup merge of #152604 - reddevilmidzy:refactor, r=Zalathar
Relocate some tests

`dynamically-sized-types` -> `dst`
`underscore-imports` -> `imports/underscore-imports`
`btreemap`, `hashmap` -> `collections/btreemap`, `collections/hashmap`
`higher-ranked-trait-bounds` -> `higher-ranked/trait-bounds`
`meta` -> `compiletest-self-test`, `bootstrap`

After the review, I'll squash.
2026-02-15 16:37:37 +01:00
Jonathan Brouwer
8b3ef9e0c7
Rollup merge of #152278 - lapla-cogito:type_const_nested, r=BoxyUwU
Fix const normalization for generic const items with trait assoc consts

In `try_fold_free_or_assoc`, the check for whether the normalization result needs further normalization only considered types, not constants. This caused generic const items marked with `#[type_const]` that reference trait associated consts to only partially normalize—the outer const would be expanded, but the inner associated const would remain unevaluated, resulting in an ICE in borrowck.

close rust-lang/rust#151647

r? BoxyUwU
(Based on git blame)
2026-02-15 16:37:37 +01:00
Jonathan Brouwer
4a4ea14148
Rollup merge of #152566 - bjorn3:cg_gcc_no_thin_lto, r=antoyo
Remove code for ThinLTO from cg_gcc

It was just a dummy implementation to workarround the fact that thin local lto is the default in rustc. By adding a thin_lto_supported thin local lto can be automatically disabled for cg_gcc, removing the need for this dummy implementation. This makes improvements to the LTO handling on the cg_ssa side a lot easier.

cc [#rustc-codegen-gcc > thin LTO implementation](https://rust-lang.zulipchat.com/#narrow/channel/386786-rustc-codegen-gcc/topic/thin.20LTO.20implementation/with/573625132)
This should make the work on https://github.com/rust-lang/compiler-team/issues/908 easier.

r? rust-lang/wg-gcc-backend
2026-02-15 16:37:36 +01:00
Lieselotte
d12923346c
feat: show what lint was overruled 2026-02-15 15:40:13 +01:00
Embers-of-the-Fire
d13828b2c7
fix: re-format the changes 2026-02-15 22:34:53 +08:00
Embers-of-the-Fire
a8bbacd270
fix: remove unused import 2026-02-15 22:26:54 +08:00
Chayim Refael Friedman
5ad533b09c
Merge pull request #21649 from Albab-Hasan/fix/assignment-rhs-never-coercion
fix: use `ExprIsRead::Yes` for rhs of ordinary assignments
2026-02-15 14:16:24 +00:00
Embers-of-the-Fire
40a3ca1189
fix: remove unused source span 2026-02-15 22:01:01 +08:00
bors
2219766af6 Auto merge of #152605 - scottmcm:box-drop-alignment, r=Mark-Simulacrum
Pass alignments through the shim as `Alignment` (not `usize`)

We're using `Layout` on both sides, so might as well skip the transmutes back and forth to `usize`.

The mir-opt test shows that doing so allows simplifying the boxed-slice drop slightly, for example.
2026-02-15 13:38:45 +00:00
THARUN
b55673bd76 Avoid ICE in From/TryFrom diagnostic under -Znext-solver 2026-02-15 19:02:44 +05:30
lapla
88f0ac34dc
Fix const normalization for generic const items with trait assoc consts 2026-02-15 22:05:27 +09:00
Mateusz Mikuła
b022e16e2a Install LLVM DLL in the right place on Windows
Unlike other systems, Windows requires runtime libraries to be present
in `PATH` or right next to the binary.

So, we copy the library next to the binary as the easier solution.
2026-02-15 13:13:27 +01:00
Albab-Hasan
7733f65ff9 fix: use ExprIsRead::Yes for rhs of ordinary assignments
the rhs of an ordinary assignment `x = *never_ptr` was inferred with
`ExprIsRead::No`, which prevented `NeverToAny` coercion for place
expressions of type `!`. this caused false type mismatches and missing
divergence detection. the destructuring assignment path and let binding
path both correctly use `ExprIsRead::Yes` for the rhs value, since the
value is always consumed (read). this makes the ordinary assignment path
consistent with both.
2026-02-15 17:37:51 +06:00
Chayim Refael Friedman
721edae2f9
Merge pull request #21647 from Albab-Hasan/fix/contains-explicit-ref-binding-missing-refmut
fix: handle `ref mut` bindings in `contains_explicit_ref_binding`
2026-02-15 11:36:30 +00:00
Jonathan Brouwer
dab350a3ed
Remove timing assertion from oneshot::send_before_recv_timeout 2026-02-15 12:32:17 +01:00
bjorn3
fa753a46c1 Remove code for ThinLTO from cg_gcc
It was just a dummy implementation to workarround the fact that thin
local lto is the default in rustc. By adding a thin_lto_supported thin
local lto can be automatically disabled for cg_gcc, removing the need
for this dummy implementation. This makes improvements to the LTO
handling on the cg_ssa side a lot easier.
2026-02-15 10:05:48 +00:00
bors
4c37f6d78c Auto merge of #152375 - Zoxc:rayon-scope-loops, r=jieyouxu,lqd
Use `scope` for `par_slice` instead of `join`

This uses `scope` instead of nested `join`s in `par_slice` so that each group of items are independent and do not end up blocking on another.
2026-02-15 09:55:40 +00:00
Alexander Kjäll
8d3b9f4a81
gate borsh tests on std also, as they depend on both 2026-02-15 10:28:47 +01:00
bors
ce0bf0b22b Auto merge of #152639 - jhpratt:rollup-sIUYGho, r=jhpratt
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#150424 (diagnostics: add note when param-env shadows global impl)
 - rust-lang/rust#152132 (implement `carryless_mul`)
 - rust-lang/rust#152508 (Improve write! and writeln! error when called without destination)
 - rust-lang/rust#152534 (Test(lib/win/net): Skip UDS tests when under Win7)
 - rust-lang/rust#152578 (ci: Lock cross toolchain version and update docs)
 - rust-lang/rust#152188 (Include `library/stdarch` for `CURRENT_RUSTC_VERSION` updates)
 - rust-lang/rust#152402 (Add regression test for rust-lang/rust#141738)
 - rust-lang/rust#152472 (unwind/wasm: fix compile error by wrapping wasm_throw in unsafe block)
 - rust-lang/rust#152610 (Exchange js_lint message between bless and non-bless)
2026-02-15 06:20:35 +00:00
The Miri Cronjob Bot
0f8640376d Merge ref '7bee525095' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@7bee525095
Filtered ref: rust-lang/miri@c878532787
Upstream diff: 47611e1604...7bee525095

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-15 05:26:41 +00:00
The Miri Cronjob Bot
d888b1c108 Prepare for merging from rust-lang/rust
This updates the rust-version file to 7bee525095.
2026-02-15 05:18:09 +00:00
reddevilmidzy
c92f384eb1 Move meta tests to compiletest-self-test, bootstrap dir 2026-02-15 04:43:02 +00:00
reddevilmidzy
86f1affe5a Move higher-ranked-trait-bounds tests into higher-ranked subdir 2026-02-15 04:39:21 +00:00
reddevilmidzy
863caf8b6b Move btreemap, hashmap tests into collections subdir 2026-02-15 04:39:13 +00:00
reddevilmidzy
1612988310 Move underscore-imports tests into imports subdir 2026-02-15 04:38:55 +00:00
reddevilmidzy
abca0d5f74 Move dynamically-sized-types tests into dst dir 2026-02-15 04:38:12 +00:00
Jacob Pratt
12755aa52c
Rollup merge of #152610 - Shunpoco:fix-js-lint-bless-message, r=clubby789
Exchange js_lint message between bless and non-bless

The message `applying suggestions` should be emitted when bless is enabled.
2026-02-14 23:17:41 -05:00
Jacob Pratt
5d2a033b85
Rollup merge of #152472 - lizan:wasm, r=Mark-Simulacrum
unwind/wasm: fix compile error by wrapping wasm_throw in unsafe block

This fix rust-std compile error on wasm32-unknown-unknown with panic=unwind because of `#![deny(unsafe_op_in_unsafe_fn)]`
2026-02-14 23:17:41 -05:00
Jacob Pratt
9369cfff04
Rollup merge of #152402 - AprilNEA:test/issue-141738-struct-ctor-array-len, r=BoxyUwU
Add regression test for #141738

Closes rust-lang/rust#141738

- Add a regression test for rust-lang/rust#141738
- Using a struct constructor (`DefKind::Ctor(Struct, Const)`) as an array repeat count with `#![feature(min_generic_const_args)]` used to ICE in const alias normalization
- Fixed by rust-lang/rust#150704, which added const constructor support for mGCA. This test covers the **error path** (struct ctor where `usize` is expected), which was not covered by the tests in rust-lang/rust#150704
2026-02-14 23:17:40 -05:00
Jacob Pratt
ef776c603c
Rollup merge of #152188 - cuviper:placeholder-stdarch, r=Mark-Simulacrum
Include `library/stdarch` for `CURRENT_RUSTC_VERSION` updates

Our tool `replace-version-placeholder` uses the `tidy` file walker and its
directory filter, but that skips `library/stdarch` which we do need for public
stability markers. This PR adds a local filter function that explicitly allows
that path.

The commit for 1.94 `stdarch` updates is coming from beta rust-lang/rust#152187.
2026-02-14 23:17:40 -05:00
Jacob Pratt
9f0b29be99
Rollup merge of #152578 - heiher:ci-crosstool, r=Mark-Simulacrum
ci: Lock cross toolchain version and update docs

This PR locks the cross-toolchain component version to avoid unexpected changes when bumping crosstool-ng, and updates the toolchain configuration in the docs to match the actual setup.

try-job: dist-arm-linux-musl
try-job: dist-loongarch64-linux
try-job: dist-loongarch64-musl
try-job: dist-powerpc64-linux-musl
try-job: dist-powerpc64le-linux-gnu
try-job: dist-powerpc64le-linux-musl
2026-02-14 23:17:39 -05:00
Jacob Pratt
3ce7fb6607
Rollup merge of #152534 - PaulDance:patches/remove-win7-uds, r=Mark-Simulacrum
Test(lib/win/net): Skip UDS tests when under Win7

Unix Domain Socket support has only been added to Windows since Windows 10 Insider Preview Build 17063. Thus, it has no chance of ever being supported under Windows 7, making current tests fail. This therefore adds the necessary in order to make the tests dynamically skip when run under Windows 7, 8, and early 10, as it does not trigger linker errors.

cc rust-lang/rust#150487 @roblabla

@rustbot label T-libs A-io O-windows-7
2026-02-14 23:17:32 -05:00
Jacob Pratt
8075b89aa6
Rollup merge of #152508 - arferreira:improve-write-macro-diagnostic, r=Mark-Simulacrum
Improve write! and writeln! error when called without destination

Fixes rust-lang/rust#152493

Adds catch-all arms to `write!` and `writeln!` macros so that calling them without a destination (e.g., `write!("S")` instead of `write!(f, "S")`) gives a clear error instead of the cryptic "unexpected end of macro invocation" pointing at macro internals.

r? @estebank
2026-02-14 23:17:31 -05:00
Jacob Pratt
f065c9dab1
Rollup merge of #152132 - folkertdev:carryless-mul, r=Mark-Simulacrum
implement `carryless_mul`

tracking issue: https://github.com/rust-lang/rust/issues/152080
ACP: https://github.com/rust-lang/libs-team/issues/738

This defers to LLVM's `llvm.clmul` when available, and otherwise falls back to a method from the `polyval` crate ([link](https://github.com/RustCrypto/universal-hashes/blob/master/polyval/src/field_element/soft/soft64.rs)).

Some things are missing, which I think we can defer:

- the ACP has some discussion about additional methods, but I'm not sure exactly what is wanted or how to implement it efficiently
- the SIMD intrinsic is not yet `const` (I think I ran into a bootstrapping issue). That is fine for now, I think in `stdarch` we can't really use this intrinsic at the moment, we'd only want the scalar version to replace some riscv intrinsics.
- the SIMD intrinsic is not implemented for the gcc and cranelift backends. That should be reasonably straightforward once we have a const eval implementation though.
2026-02-14 23:17:31 -05:00
Jacob Pratt
79adcd1375
Rollup merge of #150424 - xonx4l:suggest_param_env_shadowing, r=lcnr
diagnostics: add note when param-env shadows global impl

 This PR adds a diagnostics note when param-env shadows global impl as discussed in https://github.com/rust-lang/rust/issues/149910

It adds a note explaining that the definition is hidden by the generic bound.

r?lcnr
2026-02-14 23:17:30 -05:00
bors
75b9d89c68 Auto merge of #151380 - ShoyuVanilla:shallow-resolve-to-root-var, r=lcnr
Shallow resolve ty and const vars to their root vars

Continuation of https://github.com/rust-lang/rust/pull/147193
2026-02-15 03:04:28 +00:00
Yuki Okushi
71dff62449 Add a note about elided lifetime 2026-02-15 11:32:46 +09:00
Nicholas Nethercote
fcea886c1a Break up DepsType.
By moving most of it into `DepKind`, and changing two methods into free
functions.
2026-02-15 13:07:41 +11:00
Nicholas Nethercote
7c877d994b Remove DepContext.
It's no longer needed now that we can access `TyCtxt` directly.
2026-02-15 13:07:40 +11:00
Nicholas Nethercote
414be2e6ff Remove Deps.
It's no longer needed.
2026-02-15 13:07:39 +11:00
Nicholas Nethercote
1d83208683 De-genericize the dep graph.
By removing the generic `D` parameter from `DepGraph`, `DepGraphData`,
`CurrentDepGraph`, `SerializedDepGraph`, `SerializedNodeHeader`, and
`EncoderState`.
2026-02-15 13:07:37 +11:00
Nicholas Nethercote
32e6a1a0ab Remove QueryContext.
`rustc_query_system` has been reduced so much that it's no longer
needed. This avoids a lot of indirection and abstraction.
2026-02-15 13:07:35 +11:00
Alex Macleod
54875f6835 Provide all lint group names to Clippy
Unblocks https://github.com/rust-lang/rust-clippy/pull/14689
2026-02-15 00:32:37 +00:00
Ben Kimock
e542472c92
Merge pull request #4858 from saethlin/typos-redux
src/concurrency/weak_memory.rs made -> marked
2026-02-15 00:10:27 +00:00
bors
7bee525095 Auto merge of #152632 - JonathanBrouwer:rollup-hVWecYA, r=JonathanBrouwer
Rollup of 7 pull requests

Successful merges:

 - rust-lang/rust#152622 (Update GCC subtree)
 - rust-lang/rust#145024 (Optimize indexing slices and strs with inclusive ranges)
 - rust-lang/rust#151365 (UnsafePinned: implement opsem effects of UnsafeUnpin)
 - rust-lang/rust#152381 (Do not require `'static` for obtaining reflection information.)
 - rust-lang/rust#143575 (Remove named lifetimes in some `PartialOrd` & `PartialEq` `impl`s)
 - rust-lang/rust#152404 (tests: adapt align-offset.rs for InstCombine improvements in LLVM 23)
 - rust-lang/rust#152582 (rustc_query_impl: Use `ControlFlow` in `visit_waiters` instead of nested options)
2026-02-14 23:32:04 +00:00
Ben Kimock
1c21e60964 made -> marked 2026-02-14 17:54:44 -05:00
Albab-Hasan
646418838f fix: handle ref mut bindings in contains_explicit_ref_binding
the standalone `contains_explicit_ref_binding` function only checked for
`BindingAnnotation::Ref`, missing `BindingAnnotation::RefMut`. this caused
`let ref mut x = expr` to incorrectly take the coercion path instead of
preserving the exact type of the rhs expression. the method version used
for match arms already handles both `Ref` and `RefMut` correctly.
2026-02-15 04:21:34 +06:00
Folkert de Vries
f5bf3353e6
move va_list operations into InterpCx 2026-02-14 22:55:26 +01:00
xonx
1be41648d4 move and add comment 2026-02-14 21:32:57 +00:00
Folkert de Vries
ca3d1a3211
add c-variadic miri test 2026-02-14 22:27:41 +01:00
Folkert de Vries
02c4af397e
c-variadic functions in rustc_const_eval 2026-02-14 22:27:39 +01:00
Folkert de Vries
ce693807f6
make Va::arg and VaList::drop const fns 2026-02-14 22:26:24 +01:00
Folkert de Vries
a7888c1342
allow const fn to be c-variadic
however `Drop` for `VaList` is not yet available in const fn
2026-02-14 22:26:23 +01:00
Jonathan Brouwer
7c36d152b4
Rollup merge of #152582 - petrochenkov:waitvisit, r=TaKO8Ki
rustc_query_impl: Use `ControlFlow` in `visit_waiters` instead of nested options

Noticed when reviewing https://github.com/rust-lang/rust/pull/152229.
2026-02-14 22:11:55 +01:00
Jonathan Brouwer
e6ca590153
Rollup merge of #152404 - durin42:llvm-23-instcombine-shrink-constant, r=Mark-Simulacrum
tests: adapt align-offset.rs for InstCombine improvements in LLVM 23

Upstream [has improved InstCombine](8d2078332c) so that it can shrink added constants using known zeroes, which caused a little bit of change in this test. As far as I can tell either output is fine, so we just accept both.

@rustbot label: +llvm-main
2026-02-14 22:11:54 +01:00
Jonathan Brouwer
96066cb5b5
Rollup merge of #143575 - GrigorenkoPV:unused_lifetimes, r=Mark-Simulacrum
Remove named lifetimes in some `PartialOrd` & `PartialEq` `impl`s

Makes [the docs](https://doc.rust-lang.org/1.88.0/std/cmp/trait.PartialOrd.html#impl-PartialOrd%3CPathBuf%3E-for-Cow%3C'a,+Path%3E) way easier to look at, gets rid of a few `#[allow(unused_lifetimes)]`, and AFAICT is completely equivalent.
2026-02-14 22:11:54 +01:00
Jonathan Brouwer
16da3ab2ea
Rollup merge of #152381 - oli-obk:non_static_reflection, r=Mark-Simulacrum
Do not require `'static` for obtaining reflection information.

tracking issue rust-lang/rust#142577

This does not affect the stable `TypeId::of`, as that has its own `'static` bound.

But it will allow obtaining `TypeId`s for non-static types via the reflection API. To obtain such a `TypeId` for any type, just use `Type::of::<(T,)>().kind` to extract the first field of a tuple.

This effectively reintroduces rust-lang/rust#41875, which @rust-lang/lang decided against allowing back in 2018 due to lack of sound use cases. We will thus need to have a T-lang meeting specifically about `TypeId` for non-static types before *stabilizing* any part of reflection (in addition to T-lang meetings about reflection in general). I'm adding an explicit point about this to the tracking issue.

cc @scottmcm @joshtriplett @9SonSteroids @SpriteOvO @izagawd @BD103
2026-02-14 22:11:53 +01:00
Jonathan Brouwer
33c2a6eba9
Rollup merge of #151365 - RalfJung:unsafe-unpin-opsem, r=BoxyUwU
UnsafePinned: implement opsem effects of UnsafeUnpin

This implements the next step for https://github.com/rust-lang/rust/issues/125735: actually making `UnsafePinned` have special opsem effects by suppressing the `noalias` *even if* the type is wrapped in an `Unpin` wrapper.

For backwards compatibility we also still keep the `Unpin` hack, i.e. a type must be both `Unpin` and `UnsafeUnpin` to get `noalias`.
2026-02-14 22:11:53 +01:00
Jonathan Brouwer
6d625cc074
Rollup merge of #145024 - Kmeakin:km/optimize-slice-index/v3, r=Mark-Simulacrum
Optimize indexing slices and strs with inclusive ranges

Instead of separately checking for `end == usize::MAX` and `end + 1 > slice.len()`, we can check for `end >= slice.len()`. Also consolidate all the str indexing related panic functions into a single function which reports the correct error depending on the arguments, as the slice indexing code already does.

The downside of all this is that the panic message is slightly less specific when trying to index with `[..=usize::MAX]`: instead of saying "attempted to index str up to maximum usize" it just says "end byte index {end} out of bounds". But this is a rare enough case that I think it is acceptable
2026-02-14 22:11:52 +01:00
Jonathan Brouwer
0318407e30
Rollup merge of #152622 - GuillaumeGomez:subtree-update_cg_gcc_2026-02-14, r=GuillaumeGomez
Update GCC subtree

cc @antoyo
r? ghost
2026-02-14 22:11:52 +01:00
Folkert de Vries
b935f379b4
implement carryless_mul 2026-02-14 21:23:30 +01:00
Alexander Kjäll
d15d7149b1
fix smol_str compilation error
the command 'cargo build --no-default-features --features borsh' failed with:
error[E0599]: no function or associated item named 'other' found for struct 'borsh::io::Error' in the current scope
   --> lib/smol_str/src/borsh.rs:33:39
    |
 33 |                 .ok_or_else(|| Error::other("u8::vec_from_reader unexpectedly returned None"))?;
    |                                       ^^^^^ function or associated item not found in 'borsh::io::Error'
    |
2026-02-14 21:06:34 +01:00
AprilNEA
8d96e26684
Add regression test for struct ctor used as array repeat count under mGCA
Using a struct constructor (DefKind::Ctor(Struct, Const)) as an array
repeat count with `#![feature(min_generic_const_args)]` used to trigger
an ICE in const alias normalization. Add a regression test to ensure
the compiler produces a proper type error instead of panicking.
2026-02-14 19:44:50 +00:00
Ben Kimock
0b1003c20d
Merge pull request #4850 from hsqStephenZhang/chore/typos
chore: fix typos suggested by typos-cli
2026-02-14 18:30:01 +00:00
Guillaume Gomez
1f94802603 Fix libgccjit version 2026-02-14 17:12:51 +01:00
Guillaume Gomez
27d5b14aef Update GCC submodule 2026-02-14 16:59:09 +01:00
Guillaume Gomez
6ea369cfee Merge commit '70ae207ff5' into subtree-update_cg_gcc_2026-02-14 2026-02-14 16:45:12 +01:00
antoyo
70ae207ff5
Merge pull request #852 from rust-lang/sync_from_rust_2026_02_13
Sync from rust 2026/02/13
2026-02-14 08:11:41 -05:00
Ralf Jung
3d2786f69c
Merge pull request #4847 from hsqStephenZhang/feat/aarch64_intrinsics
Feat: aarch64 intrinsics to make MIRI work on chacha20
2026-02-14 13:05:41 +00:00
Antoni Boucher
3fdb366140 Fix clippy warning 2026-02-14 07:47:54 -05:00
Antoni Boucher
d29c931c9d Update to nightly-2026-02-14 2026-02-14 07:43:15 -05:00
Ralf Jung
59329154b7 minor tweaks 2026-02-14 13:41:50 +01:00
hsqStephenZhang
921667859d feat: vtbl1_u8 intrinsic on aarch64
needed for chacha20
2026-02-14 13:34:15 +01:00
Ralf Jung
c78baebe4b
Merge pull request #4851 from royAmmerschuber/feature/simplyfy-exposing
Simplify wildcard datastructure.
2026-02-14 11:37:51 +00:00
Roy Ammerschuber
42479673c5 simplify wildcard datastructure 2026-02-14 12:14:15 +01:00
Shunpoco
98975ffb79 exchange js_lint message between bless and non-bless 2026-02-14 10:42:40 +00:00
Scott McMurray
774268afc1 Pass alignments through the shim as Alignment (not usize)
We're using `Layout` on both sides, so might as well skip the transmutes back and forth to `usize`.

The mir-opt test shows that doing so allows simplifying the boxed-slice drop slightly, for example.
2026-02-14 01:39:16 -08:00
Lukas Wirth
deaae4956d
Merge pull request #21639 from rust-lang/dependabot/npm_and_yarn/editors/code/qs-6.14.2
build(deps): bump qs from 6.14.1 to 6.14.2 in /editors/code
2026-02-14 07:55:56 +00:00
Paul Mabileau
c22301b099
Test(lib/win/net): Skip UDS tests when under Win7
Unix Domain Socket support has only been added to Windows since Windows
10 Insider Preview Build 17063. Thus, it has no chance of ever being
supported under Windows 7, making current tests fail. This therefore
adds the necessary in order to make the tests dynamically skip when run
under Windows 7, 8, and early 10, as it does not trigger linker errors.

Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr>
2026-02-14 01:28:50 +01:00
Pavel Grigorenko
cd314dead1 Remove named lifetimes in some PartialOrd & PartialEq impls 2026-02-14 00:13:46 +03:00
Antoni Boucher
b2a2e18c48 Merge branch 'master' into sync_from_rust_2026_02_13 2026-02-13 15:57:19 -05:00
Lukas Wirth
81b72755bd
Merge pull request #21644 from Veykril/push-zrzoswxlqlqq
Revert "fix: Stale diagnostics with rust-project.json and rustc JSON"
2026-02-13 18:28:52 +00:00
Lukas Wirth
a9cc42e576 Revert "fix: Stale diagnostics with rust-project.json and rustc JSON"
This reverts commit 2cefe47e6d55c186b68687bf677bf0d5eb65a922.
2026-02-13 19:19:26 +01:00
bit-aloo
7ce98394cc
migrate generate_impl to use AstNodeEdit 2026-02-13 22:58:11 +05:30
Vadim Petrochenkov
2ee28ca538 rustc_query_impl: Use ControlFlow in visit_waiters instead of nested options 2026-02-13 20:20:02 +03:00
antoyo
1920fb1d35
Merge pull request #851 from rust-lang/sync_from_rust_2026_02_12
Sync from rust 2026/02/12
2026-02-13 12:13:29 -05:00
Antoni Boucher
c5cb56957a Add cast from f16 to non-native integer 2026-02-13 11:45:40 -05:00
Antoni Boucher
4a6f0bebfb Add missing -Zjson-target-spec for m68k sysroot build 2026-02-13 10:39:24 -05:00
Antoni Boucher
ec2996cfba Add cast from f128 to non-native integer 2026-02-13 10:39:02 -05:00
Lukas Wirth
ca35562cd3
Merge pull request #21640 from Veykril/push-rutrqvxousks
minor: Remove incorrect warning log
2026-02-13 15:33:46 +00:00
Lukas Wirth
da9ff14a13 Remove incorrect warning log 2026-02-13 16:24:28 +01:00
xonx
34981bf3cd add comments to tests 2026-02-13 14:44:40 +00:00
WANG Rui
df798ad68e ci: Lock cross toolchain version and update docs 2026-02-13 22:11:43 +08:00
WANG Rui
e37374b1ac ci: dist-arm-linux: Cleanup unused crosstool-ng 2026-02-13 22:11:42 +08:00
WANG Rui
c0c3c59b83 ci: Drop outdated toolchain configuration: aarch64-linux-gnu.defconfig 2026-02-13 22:11:42 +08:00
Antoni Boucher
e373b93b0b Fix formatting 2026-02-13 08:35:12 -05:00
Antoni Boucher
27e25ff6d8 Add failing tests 2026-02-13 08:27:31 -05:00
Antoni Boucher
5577bd7ac4 Add missing -Zjson-target-spec for m68k test 2026-02-13 08:13:29 -05:00
Antoni Boucher
458adbd66a Implement fptoint_sat for f16 and f128 2026-02-13 08:12:59 -05:00
Antoni Boucher
c2b8abd810 Update to nightly-2026-02-13 2026-02-13 07:49:27 -05:00
dependabot[bot]
c2c7d5d7ef
build(deps): bump qs from 6.14.1 to 6.14.2 in /editors/code
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.14.1...v6.14.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-13 11:43:39 +00:00
Lukas Wirth
4b5b181935
Merge pull request #21609 from Veykril/push-qknzslvkmtyt
internal: Use rayon for proc-macro loading
2026-02-13 11:33:11 +00:00
Lukas Wirth
b132beb7e0 internal: Use rayon for proc-macro loading 2026-02-13 12:24:47 +01:00
Shoyu Vanilla (Flint)
f931a79a2a
Merge pull request #21633 from ChayimFriedman2/proc-macro-is-not-fn
fix: Do not resolve proc macros in value ns (as functions), only in macro ns, outside their defining crate
2026-02-13 08:47:17 +00:00
Shoyu Vanilla (Flint)
6040177bfb
Merge pull request #21636 from Shourya742/2026-02-13-remove-edit-in-place-in-migrated-handlers
Remove mutable edit in place with edit::AstNodeEdit in migrated  assist handlers
2026-02-13 08:45:05 +00:00
bit-aloo
c6b1f8ad9a
remove edit_in_place from generate_new assist with edit::AstNodeEdit 2026-02-13 13:14:06 +05:30
bit-aloo
85e0c3209e
remove edit_in_place from convert_bool_to_enum assist with edit::AstNodeEdit 2026-02-13 13:11:46 +05:30
bit-aloo
140a039fb7
remove edit_in_place from generate_trait_from_impl assist with edit::AstNodeEdit 2026-02-13 13:09:27 +05:30
bit-aloo
c8e284bf01
remove edit_in_place from replace_if_let_with_match assist with edit::AstNodeEdit 2026-02-13 13:01:50 +05:30
Ralf Jung
884126770c
Merge pull request #4856 from rust-lang/rustup-2026-02-13
Automatic Rustup
2026-02-13 07:24:46 +00:00
bit-aloo
96d6a3e077
remove edit_in_place from convert_let_else_to_match assist with edit::AstNodeEdit 2026-02-13 12:20:42 +05:30
bit-aloo
34eee0c30a
remove edit_in_place from generate_getter_or_setter assist with edit::AstNodeEdit 2026-02-13 12:16:50 +05:30
bit-aloo
5de304e2a4
remove edit_in_place from generate_mut_trait_impl assist with edit::AstNodeEdit 2026-02-13 12:15:47 +05:30
bit-aloo
6221b39591
remove edit_in_place from bind_unused_param assist with edit::AstNodeEdit 2026-02-13 12:13:35 +05:30
bit-aloo
28bf2dbb13
remove edit_in_place from move_const_to_impl assist with edit::AstNodeEdit 2026-02-13 12:11:19 +05:30
bit-aloo
3a202c4736
remove edit_in_place from replace_let_with_if_let assist with edit::AstNodeEdit 2026-02-13 12:07:01 +05:30
xonx
7a7d48ea62 add tests 2026-02-13 05:32:55 +00:00
The Miri Cronjob Bot
dce9791ba7 Merge ref '47611e1604' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@47611e1604
Filtered ref: rust-lang/miri@9e16c92d15
Upstream diff: f889772d65...47611e1604

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-13 05:26:53 +00:00
The Miri Cronjob Bot
1911d670fb Prepare for merging from rust-lang/rust
This updates the rust-version file to 47611e1604.
2026-02-13 05:18:33 +00:00
Chayim Refael Friedman
b76642de15 Cleanup unnecessary code 2026-02-13 00:31:51 +02:00
Chayim Refael Friedman
4fc780d97c Do not resolve proc macros in value ns (as functions), only in macro ns, outside their defining crate
The main impact is that syntax highlighting will show it as a macro and not a function.
2026-02-13 00:26:49 +02:00
Shoyu Vanilla (Flint)
b214aac14c
Merge pull request #21632 from ChayimFriedman2/extern-fn-pat
fix: Don't assume `extern fn`s parameters are patterns
2026-02-12 22:14:37 +00:00
Antoni Boucher
5b2cfe3e75 Merge branch 'master' into sync_from_rust_2026_02_12 2026-02-12 16:19:00 -05:00
Chayim Refael Friedman
61df37fafa Don't assume extern fns parameters are patterns
Unlike normal fns, they should be bare identifiers.
2026-02-12 23:17:55 +02:00
Chayim Refael Friedman
15e661ce61
Merge pull request #21381 from A4-Tacks/inline-call-generic-args
Fix incorrect Self path expand for inline_call
2026-02-12 20:57:11 +00:00
Chayim Refael Friedman
88d951e251
Merge pull request #21402 from A4-Tacks/no-semicolon-array
Fix complete semicolon in array expression
2026-02-12 20:10:46 +00:00
Chayim Refael Friedman
860469f758
Merge pull request #21591 from A4-Tacks/hover-fmt-long-param
feat: Improve hover too long parameter list
2026-02-12 19:58:33 +00:00
bjorn3
293e950620 Remove SelfProfilerRef from CodegenContext
It can't be serialized to a file.
2026-02-12 12:44:14 +00:00
xonx
7a2f2fe754 fix tidy 2026-02-12 12:20:36 +00:00
xonx
1eddc17989 fix GATs logic 2026-02-12 12:10:08 +00:00
Shoyu Vanilla (Flint)
5bbd3e65dc
Merge pull request #21619 from Shourya742/2026-02-10-migrate-convert-tuple-return-type-to-struct
migrate covert_tuple_return_type to struct  assist to syntax editor
2026-02-12 09:31:47 +00:00
Chayim Refael Friedman
c991d070bd
Merge pull request #21627 from rust-lang/revert-21380-push-nolvxuourwru
Revert "feat: Implement fine grained client side request cancellation support"
2026-02-12 09:29:22 +00:00
bit-aloo
9c468be363
move to edit::AstNodeEdit from edit_in_place::Indent 2026-02-12 14:52:48 +05:30
bit-aloo
87feb37bc7
migrate covert_tuple_return_type to struct to syntax editor 2026-02-12 14:52:48 +05:30
Chayim Refael Friedman
8b27b45bbd Revert "feat: Implement fine grained client side request cancellation support" 2026-02-12 11:20:27 +02:00
Chayim Refael Friedman
d32a47377e
Merge pull request #21628 from Shourya742/2026-02-12-pin-nightly-for-miri-workflow
Pin nightly for miri workflow
2026-02-12 09:08:22 +00:00
bit-aloo
11ce0a5655
pin nightly for miri workflow 2026-02-12 14:03:22 +05:30
Ralf Jung
0cbe1cc992 try to work around rustdoc bug, and other rustdoc adjustments 2026-02-12 09:09:35 +01:00
Ralf Jung
590c1c9966 UnsafePinned: implement opsem effects of UnsafeUnpin 2026-02-12 09:09:35 +01:00
mu001999
8c77b6c025 Exclude final methods from dyn-compat check and vtable 2026-02-12 15:18:15 +08:00
mu001999
2e0ff1fb1e Fix clippy ast utils
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:18:15 +08:00
mu001999
f0a019bf90 Render final associated functions correctly in rustdoc
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:18:15 +08:00
mu001999
f0e1c8f416 Fix rustfmt
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:18:15 +08:00
mu001999
3572d482a0 Validate no override impl definitions
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:18:15 +08:00
mu001999
460cda8c95 Validate final usages in AST
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:18:09 +08:00
mu001999
7077797f52 Parse and lower final for methods
Co-authored-by: Michael Goulet <michael@errs.io>
2026-02-12 15:12:29 +08:00
Jacob Pratt
d0b2d841e7 Rollup merge of #152478 - bjorn3:lto_refactors10, r=wesleywiser
Remove tm_factory field from CodegenContext

This is necessary to support serializing the `CodegenContext` to a `.rlink` file in the future for moving LTO to the `-Zlink-only` step.

Follow up to https://github.com/rust-lang/rust/pull/149209
Part of https://github.com/rust-lang/compiler-team/issues/908
2026-02-12 00:41:08 -05:00
Jacob Pratt
4e244c7cd5 Rollup merge of #150768 - bjorn3:llvm_intrinsic_no_fn_abi, r=wesleywiser
Don't compute FnAbi for LLVM intrinsics in backends

~~This removes support for `extern "unadjusted"` for anything other than LLVM intrinsics. It only makes sense in the context of calling LLVM intrinsics anyway as it exposes the way the LLVM backend internally represents types. Perhaps it should be renamed to `extern "llvm-intrinsic"`?~~

Follow up to https://github.com/rust-lang/rust/pull/148533
2026-02-12 00:41:06 -05:00
arferreira
0bcec37604 Improve write! and writeln! error when called without destination 2026-02-11 20:37:45 -05:00
antoyo
740a55f641
Merge pull request #849 from him2him2/fix-typos
Fix typos across documentation
2026-02-11 18:02:05 -05:00
ron
dd1b72a0d8
Fix typos and grammar in documentation
- Readme.md: add missing "you" ("If don't" → "If you don't")
- Readme.md: fix wrong preposition ("without this backend" → "with this backend")
- Readme.md: fix double space
- doc/errors.md: fix transposed letters ("libgccijt" → "libgccjit")
- doc/debugging.md: remove extra word ("Run do the command" → "Run the command")
- doc/debugging.md: fix past participle ("cannot be ran" → "cannot be run")
- doc/tips.md: add missing verb ("won't a chance" → "won't have a chance")
- doc/gimple.md: fix preposition ("interested into" → "interested in")
2026-02-11 17:38:07 -05:00
antoyo
30bd49283c
Merge pull request #844 from rust-lang/sync_from_rust_2026_01_28
Sync from rust 2026/01/28
2026-02-11 17:33:53 -05:00
Ralf Jung
940ebdaa9b
Merge pull request #4854 from RalfJung/test-unused
align_strange_enum_discriminant_offset: fix accidentally unused variable
2026-02-11 22:16:29 +00:00
Ralf Jung
ecc243b378 remove an unused allow(unused) 2026-02-11 22:49:03 +01:00
Ralf Jung
fcb881244b align_strange_enum_discriminant_offset: fix accidentally unused variable 2026-02-11 22:44:28 +01:00
Antoni Boucher
809af1f635 Fix clippy warnings 2026-02-11 16:23:56 -05:00
Lukas Wirth
eb05ff6068
Merge pull request #21581 from Wilfred/clippy_in_ci
internal: Run clippy as a separate CI step
2026-02-11 16:57:18 +00:00
bjorn3
a75ff82177 Remove tm_factory field from CodegenContext
This is necessary to support serializing the CodegenContext to a .rlink
file in the future for moving LTO to the -Zlink-only step.
2026-02-11 12:18:04 +00:00
bjorn3
14527b257f Move target machine factory error reporting into codegen backend 2026-02-11 10:53:38 +00:00
Shoyu Vanilla (Flint)
49228dc09f
Merge pull request #21618 from Shourya742/2026-02-10-migrate-destructure-tuple-binding-to-syntaxeditor
Migrate destructure tuple binding assist to syntaxEditor
2026-02-11 10:07:04 +00:00
Shoyu Vanilla (Flint)
751508a968
Merge pull request #21507 from Shourya742/2026-01-17-migrate-named-lifetime
migrate introduce_named_lifetime assist to SyntaxEditor
2026-02-11 10:01:45 +00:00
bit-aloo
9c7cc62406
make generate_unique_lifetime_param_name return Option<SmolStr> 2026-02-11 15:23:09 +05:30
Shoyu Vanilla
8062bee9e3 Bless tests 2026-02-11 18:08:18 +09:00
Shoyu Vanilla
955f7750c1 Remove redundant shallow_resolve call 2026-02-11 18:08:14 +09:00
Shoyu Vanilla
13a83cb639 Shallow resolve ty and const vars to their root vars 2026-02-11 17:38:34 +09:00
bit-aloo
78c8ab35e8
migrate destructure tuple binding to new syntaxEditor 2026-02-11 13:39:13 +05:30
Shoyu Vanilla
1f53258660 Bump ena 2026-02-11 17:05:50 +09:00
Karl Meakin
f8cf68f35a Give into_range more consistent name
Rename `into_range` to `try_into_slice_range`:
- Prepend `try_` to show that it returns `None` on error, like `try_range`
- add `_slice` to make it consistent with `into_slice_range`
2026-02-10 23:19:01 +00:00
Karl Meakin
94ff542ff5 Make panic message less confusing
The panic message when slicing a string with a negative length range (eg
`"abcdef"[4..3]`) is confusing: it gives the condition that failed to hold,
whilst all the other panic messages give the condition that did hold.

Before:
begin <= end (4 <= 3) when slicing `abcdef`

After:
begin > end (4 > 3) when slicing `abcdef`
2026-02-10 23:19:01 +00:00
Karl Meakin
262cd76333 Optimize SliceIndex<str> for RangeInclusive
Replace `self.end() == usize::MAX` and `self.end() + 1 > slice.len()`
with `self.end() >= slice.len()`. Same reasoning as previous commit.

Also consolidate the str panicking functions into function.
2026-02-10 23:19:01 +00:00
Karl Meakin
625b18027d Optimize SliceIndex::get impl for RangeInclusive
The checks for `self.end() == usize::MAX` and `self.end() + 1 > slice.len()`
can be replaced with `self.end() >= slice.len()`, since
`self.end() < slice.len()` implies both
`self.end() <= slice.len()` and
`self.end() < usize::MAX`.
2026-02-10 20:29:45 +00:00
Karl Meakin
d74b276d1d Precommit tests for SliceIndex method codegen
Add a `codegen-llvm` test to check the number of `icmp` instrucitons
generated for each `SliceIndex` method on the various range types. This
will be updated in the next commit when `SliceIndex::get` is optimized
for `RangeInclusive`.
2026-02-10 20:29:45 +00:00
xonx
6b3c42592e update tests 2026-02-10 19:23:10 +00:00
xonx
071d0cd9f2 rewording note and refer issue 2026-02-10 18:42:52 +00:00
xonx
c576dc55b8 delete middle check.
Co-authored-by: lcnr <rust@lcnr.de>
2026-02-10 18:42:51 +00:00
xonx
a873a3fe77 add suggested changes 2026-02-10 18:42:50 +00:00
xonx4l
5b1070b040 Add note for param-env shadowing 2026-02-10 18:42:50 +00:00
Lizan Zhou
78dc744e93 unwind/wasm: fix compile error by wrapping wasm_throw in unsafe block 2026-02-10 22:20:02 +09:00
Shoyu Vanilla (Flint)
c53e819a2c
Merge pull request #21583 from A4-Tacks/derive-manual-assoc-bounds
fix: Fix loses associated bounds for replace_derive_with_manual_impl
2026-02-10 05:56:14 +00:00
Augie Fackler
aefb9a9ae2 tests: adapt align-offset.rs for InstCombine improvements in LLVM 23
Upstream has improved InstCombine so that it can shrink added constants
using known zeroes, which caused a little bit of change in this test. As
far as I can tell either output is fine, so we just accept both.
2026-02-09 15:53:38 -05:00
Chayim Refael Friedman
68f2f3cd7f
Merge pull request #21611 from ShoyuVanilla/issue-21605
fix: Sync `allow_normalization` to rustc
2026-02-09 20:14:10 +00:00
A4-Tacks
5a721a117f
Improve variable name 2026-02-10 04:14:09 +08:00
Chayim Refael Friedman
a3b7fa9d21
Merge pull request #21584 from regexident/def-with-body-types
Add `expression_types()`, `pattern_types()`, `binding_types()` to `DefWithBody`
2026-02-09 20:13:16 +00:00
Shoyu Vanilla
6494dabc33 fix: Sync allow_normalize to rustc 2026-02-10 00:57:41 +09:00
Wilfred Hughes
e7855f5bfa internal: Run clippy as a separate CI step
Currently clippy is run in CI as part of the macOS build. This is a
little confusing, because clippy failures just show as
"Rust (macos-latest)" which make it look like a macOS build failure.

Instead, treat clippy as a separate build step, like miri and rustfmt.

This should also make CI a little faster, because it reduces macOS
runner usage (which tend to be slower than Linux on GitHub actions),
and it reduces the number of steps where we need to install clippy.
2026-02-09 14:18:15 +00:00
Shoyu Vanilla (Flint)
7d521a2cd9
Merge pull request #21574 from ChayimFriedman2/autoimport-after
feat: When autoimporting a segment followed by other segments, only consider items that will resolve with the after segments
2026-02-09 14:08:56 +00:00
Shoyu Vanilla (Flint)
23f6d7474b
Merge pull request #21606 from Shourya742/2026-02-09-migrate-getters-and-setters-handler
migrate getters and setters handler to SyntaxEditor
2026-02-09 13:33:24 +00:00
Lukas Wirth
c4eaf24499
Merge pull request #21608 from Veykril/push-kknkruwvyltp
fix: Fix `set_top_subtree_delimiter_span` using wrong index for close span
2026-02-09 11:54:08 +00:00
Lukas Wirth
ae24fdaccc fix: Fix set_top_subtree_delimiter_span using wrong index for close span 2026-02-09 12:45:01 +01:00
Oli Scherer
3339b061af Do not require 'static for obtaining reflection information. 2026-02-09 09:30:09 +00:00
John Kåre Alsaker
91a6126208 Use scope for par_slice instead of join 2026-02-09 07:59:18 +01:00
Vincent Esche
59111f7a73 Add expression_types(), pattern_types(), binding_types() to DefWithBody 2026-02-08 21:57:53 +01:00
bit-aloo
fa31e1759a
migrate generate_getter_or_setter to syntaxeditor api 2026-02-08 22:14:30 +05:30
bit-aloo
f605c0ab7c
self_param and impl_ implementation in syntax_factory 2026-02-08 22:14:06 +05:30
Tshepang Mbambo
3be2843107 make docs render better by separating intro from rest of paragraph 2026-02-07 04:25:02 +02:00
Tshepang Mbambo
84741ed8ce add reading pauses in doc comment 2026-02-07 04:25:02 +02:00
Tshepang Mbambo
638d23ce42 E0570: improve text 2026-02-07 04:25:02 +02:00
Tshepang Mbambo
6bb8cc619e obsolete comment
`since` is now a field of one of the parameters
2026-02-07 04:25:02 +02:00
Tshepang Mbambo
5b68138797 add trailing commas 2026-02-07 04:25:02 +02:00
Josh Stone
001d710747 Replace a stale clippy CURRENT_RUSTC_VERSION 2026-02-06 09:03:59 -08:00
Oli Scherer
b1e033649c
Merge pull request #4852 from rust-lang/rustup-2026-02-06
Automatic Rustup
2026-02-06 07:21:45 +00:00
The Miri Cronjob Bot
13ebd31ecd Merge ref 'f889772d65' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@f889772d65
Filtered ref: rust-lang/miri@1fa28eb9ac
Upstream diff: 9f4b56a5ae...f889772d65

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-06 05:23:58 +00:00
The Miri Cronjob Bot
85f4694b7d Prepare for merging from rust-lang/rust
This updates the rust-version file to f889772d65.
2026-02-06 05:15:37 +00:00
Tshepang Mbambo
193bc70101 missing word 2026-02-06 05:26:53 +02:00
Tshepang Mbambo
2a6b9e6bef inline the binding 2026-02-06 05:26:53 +02:00
Josh Stone
dd322a0425 Include library/stdarch for CURRENT_RUSTC_VERSION updates 2026-02-05 13:42:06 -08:00
Josh Stone
ec3de4bac5 Replace stdarch version placeholders with 1.94
(cherry picked from commit b90149755a)
2026-02-05 13:41:19 -08:00
Ralf Jung
4d946a972b
Merge pull request #4849 from RalfJung/rustup
Rustup
2026-02-05 19:21:10 +00:00
Ralf Jung
ba33e03f9c pass -Zunstable-options to tests 2026-02-05 19:51:30 +01:00
Nikolai Kuklin
689e8c2099
Add documentation note about signed overflow direction 2026-02-05 16:34:54 +01:00
hsqStephenZhang
40857fcd00 chore: fix typos suggested by typos-cli 2026-02-05 12:53:45 +01:00
Ralf Jung
edc1ad4675 Merge ref '9f4b56a5ae' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 9f4b56a5ae
Filtered ref: 4370958f4e8d5ec5d34e22d989f45c7784038f42
Upstream diff: 1d05e3c131...9f4b56a5ae

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-05 08:52:51 +01:00
Ralf Jung
94fa522956 Prepare for merging from rust-lang/rust
This updates the rust-version file to 9f4b56a5ae.
2026-02-05 08:52:39 +01:00
A4-Tacks
4b68f80a4e
feat: Improve hover too long parameter list
Example
---
```rust
fn fn_$0(
    attrs: impl IntoIterator<Item = ast::Attr>,
    visibility: Option<ast::Visibility>,
    fn_name: ast::Name,
    type_params: Option<ast::GenericParamList>,
    where_clause: Option<ast::WhereClause>,
    params: ast::ParamList,
    body: ast::BlockExpr,
    ret_type: Option<ast::RetType>,
    is_async: bool,
    is_const: bool,
    is_unsafe: bool,
    is_gen: bool,
) -> ast::Fn {}
```

**Before this PR**

```rust
fn fn_(attrs: impl IntoIterator<Item = ast::Attr>, visibility: Option<ast::Visibility>, fn_name: ast::Name, type_params: Option<ast::GenericParamList>, where_clause: Option<ast::WhereClause>, params: ast::ParamList, body: ast::BlockExpr, ret_type: Option<ast::RetType>, is_async: bool, is_const: bool, is_unsafe: bool, is_gen: bool) -> ast::Fn
```

**After this PR**

```rust
fn fn_(
    attrs: impl IntoIterator<Item = ast::Attr>,
    visibility: Option<ast::Visibility>,
    fn_name: ast::Name,
    type_params: Option<ast::GenericParamList>,
    where_clause: Option<ast::WhereClause>,
    params: ast::ParamList,
    body: ast::BlockExpr,
    ret_type: Option<ast::RetType>,
    is_async: bool,
    is_const: bool,
    is_unsafe: bool,
    is_gen: bool
) -> ast::Fn
```
2026-02-05 14:23:09 +08:00
Ralf Jung
bd0d19f0e8
Merge pull request #4848 from rust-lang/dependabot/cargo/git2-0.20.4
Bump git2 from 0.20.2 to 0.20.4
2026-02-04 21:15:25 +00:00
dependabot[bot]
5009ac3094
Bump git2 from 0.20.2 to 0.20.4
Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.20.2 to 0.20.4.
- [Changelog](https://github.com/rust-lang/git2-rs/blob/git2-0.20.4/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.20.2...git2-0.20.4)

---
updated-dependencies:
- dependency-name: git2
  dependency-version: 0.20.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-04 20:44:47 +00:00
bjorn3
e4e725aec6 Convert to inline diagnostics in all codegen backends 2026-02-04 13:12:49 +00:00
Alan Egerton
58292e2a53
Consider captures to be used by closures that unwind
Assignments to a captured variable within a diverging closure should not
be considered unused if the divergence is caught.

This patch considers such assignments/captures to be used by diverging
closures irrespective of whether the divergence is caught, but better a
false negative unused lint than a false positive one (the latter having
caused a stable-to-stable regression).
2026-02-04 12:35:34 +00:00
Ralf Jung
aace5bb00b
Merge pull request #4805 from meithecatte/uninhabited-enum-validity
Add a validity testcase for uninhabited variants
2026-02-04 09:01:54 +00:00
Ralf Jung
1f73d3f30b
Merge pull request #4846 from rust-lang/rustup-2026-02-04
Automatic Rustup
2026-02-04 07:27:42 +00:00
The Miri Cronjob Bot
99f8340f19 Merge ref '1d05e3c131' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@1d05e3c131
Filtered ref: rust-lang/miri@c06e02d53d
Upstream diff: 878374e07f...1d05e3c131

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-04 05:21:27 +00:00
The Miri Cronjob Bot
a3d848be47 Prepare for merging from rust-lang/rust
This updates the rust-version file to 1d05e3c131.
2026-02-04 05:13:19 +00:00
A4-Tacks
9a84e66021
fix: Fix loses associated bounds for replace_derive_with_manual_impl
Example
---
```rust
#[derive(Clo$0ne)]
struct Foo<T: core::ops::Deref>(T::Target);
```

**Before this PR**

```rust
struct Foo<T: core::ops::Deref>(T::Target);

impl<T: core::ops::Deref + Clone> Clone for Foo<T> {
    $0fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}
```

**After this PR**

```rust
struct Foo<T: core::ops::Deref>(T::Target);

impl<T: core::ops::Deref + Clone> Clone for Foo<T>
where T::Target: Clone
{
    $0fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}
```
2026-02-04 12:24:15 +08:00
Ralf Jung
35f6c7509a
Merge pull request #4845 from rust-lang/dependabot/cargo/tests/deps/bytes-1.11.1
Bump bytes from 1.10.1 to 1.11.1 in /tests/deps
2026-02-03 21:47:27 +00:00
dependabot[bot]
510af14aa0
Bump bytes from 1.10.1 to 1.11.1 in /tests/deps
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.10.1 to 1.11.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.1...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-03 19:31:36 +00:00
Maja Kądziołka
2159eaf578
Add a validity testcase for uninhabited variants 2026-02-03 17:13:05 +01:00
Ralf Jung
fd1b7c19b4
Merge pull request #4844 from RalfJung/ci
re-balance CI
2026-02-03 10:14:19 +00:00
Ralf Jung
477f93e390
Merge pull request #4843 from hsqStephenZhang/fix/capstone_features
chore: limit capstone to x86 and arm
2026-02-03 09:46:40 +00:00
Ralf Jung
dcb608d818 re-balance CI 2026-02-03 10:42:22 +01:00
Ralf Jung
d17eefa90f
Merge pull request #4842 from RalfJung/miri-run
`./miri run --dep`: do not run Miri during the dependency build
2026-02-03 09:37:01 +00:00
hsqStephenZhang
3eabab29a2 chore: configure capstone for x86 and clean up arm64 stub 2026-02-03 10:07:43 +01:00
Chayim Refael Friedman
ab29d8285e When autoimporting a segment followed by other segments, only consider items that will resolve with the after segments 2026-02-03 03:35:21 +02:00
Ralf Jung
1044241d38 do not forward run flags to dependency build 2026-02-02 20:51:15 +01:00
Ralf Jung
c89a88ed1b do not run miri for the dependency build
and reset MIRIFLAGS as well just to be safe
2026-02-02 19:44:45 +01:00
Ralf Jung
62d518190e
Merge pull request #4839 from RalfJung/rustup
Rustup
2026-02-01 21:28:28 +00:00
Ralf Jung
070102bb1b fix building sysroot for JSON targets 2026-02-01 22:00:20 +01:00
Ralf Jung
0f4176d682 Merge ref '878374e07f' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 878374e07f
Filtered ref: a46a01d9de0d6a8cb834a0cc04b9156d61493c39
Upstream diff: 35a31ba763...878374e07f

This merge was created using https://github.com/rust-lang/josh-sync.
2026-02-01 12:44:32 +01:00
Ralf Jung
1af122276e Prepare for merging from rust-lang/rust
This updates the rust-version file to 878374e07f.
2026-02-01 12:44:13 +01:00
Ralf Jung
c18e790051
Merge pull request #4838 from RalfJung/oneshot-trophy
trophy case: oneshot data race
2026-01-31 10:30:14 +00:00
Ralf Jung
455172fd0e trophy case: oneshot data race 2026-01-31 11:06:30 +01:00
Antoni Boucher
e4b746486c Ignore test when 128-bit integers are disabled 2026-01-30 11:49:52 -05:00
Antoni Boucher
a04934421f Switch to new_array_type_u64 2026-01-30 11:16:35 -05:00
Antoni Boucher
fb32a3f52e Update GCC version 2026-01-30 11:16:35 -05:00
Antoni Boucher
e8282659f9 Update to nightly-2026-01-30 2026-01-30 11:16:35 -05:00
Antoni Boucher
dffd4ab825 Ignore failing UI test 2026-01-30 11:16:35 -05:00
Antoni Boucher
d299dce03a Fix the name of failing UI tests 2026-01-30 11:16:35 -05:00
Antoni Boucher
ff4db77564 Fix spelling mistake 2026-01-30 11:16:35 -05:00
Antoni Boucher
ee9967bac0 Fix clippy warning 2026-01-30 11:16:35 -05:00
Oli Scherer
ca86fb5aa9
Merge pull request #4837 from rust-lang/rustup-2026-01-30
Automatic Rustup
2026-01-30 06:55:44 +00:00
The Miri Cronjob Bot
f15548f72c Merge ref '35a31ba763' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@35a31ba763
Filtered ref: rust-lang/miri@b43664625b
Upstream diff: e96bb7e44f...35a31ba763

This merge was created using https://github.com/rust-lang/josh-sync.
2026-01-30 05:21:06 +00:00
The Miri Cronjob Bot
ce7c03d96d Prepare for merging from rust-lang/rust
This updates the rust-version file to 35a31ba763.
2026-01-30 05:13:08 +00:00
Antoni Boucher
bd71a5f4b0 Implement new f16/f128 intrinsics and implement dummy va_end 2026-01-28 17:02:09 -05:00
Antoni Boucher
49c9b0a7bf Update to nightly-2026-01-28 2026-01-28 17:01:51 -05:00
Antoni Boucher
7db4614d46 Merge branch 'master' into sync_from_rust_2026_01_28 2026-01-28 15:45:16 -05:00
antoyo
48a52d9c0c
Merge pull request #843 from rust-lang/fix/debuginfo-lang-filename
Set gcc language name and compilation unit name
2026-01-28 14:54:27 -05:00
Antoni Boucher
4a6325de8d Set gcc language name and compilation unit name 2026-01-28 14:13:44 -05:00
Ralf Jung
85134745cb
Merge pull request #4835 from rust-lang/rustup-2026-01-28
Automatic Rustup
2026-01-28 11:06:04 +00:00
Ralf Jung
f67f5d910f bless android tests 2026-01-28 11:23:55 +01:00
Ralf Jung
9fc995034c
Merge pull request #4836 from joboet/vecdeque-trophy
add a bug to the trophy shelf
2026-01-28 10:22:42 +00:00
joboet
71294125ea
add a bug to the trophy shelf 2026-01-28 10:39:10 +01:00
The Miri Cronjob Bot
db1d1abba1 Merge ref 'e96bb7e44f' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@e96bb7e44f
Filtered ref: rust-lang/miri@4304ab0a87
Upstream diff: 873d4682c7...e96bb7e44f

This merge was created using https://github.com/rust-lang/josh-sync.
2026-01-28 05:11:39 +00:00
The Miri Cronjob Bot
db8f27619a Prepare for merging from rust-lang/rust
This updates the rust-version file to e96bb7e44f.
2026-01-28 05:03:07 +00:00
antoyo
94e2af7a16
Merge pull request #841 from GuillaumeGomez/more-mapping
Add two new target-specific intrinsics mapping
2026-01-27 08:41:23 -05:00
xtqqczze
b7728f072e Omit standard copyright notice
Remove copyright notices for files licensed under the standard terms (MIT OR Apache-2.0).
2026-01-26 17:31:34 +00:00
Guillaume Gomez
436ae1e0a0 Add regression test for llvm.sqrt.v4f64 and llvm.smax.v4i32 mapping 2026-01-26 18:25:25 +01:00
Guillaume Gomez
25234f8652 Add two new target-specific intrinsics mapping 2026-01-26 18:24:52 +01:00
Ralf Jung
5f2d232e5f
Merge pull request #4834 from rust-lang/rustup-2026-01-26
Automatic Rustup
2026-01-26 08:15:36 +00:00
The Miri Cronjob Bot
58f38eb01d Merge ref '873d4682c7' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@873d4682c7
Filtered ref: rust-lang/miri@57f1e8b76f
Upstream diff: 5a07626f4b...873d4682c7

This merge was created using https://github.com/rust-lang/josh-sync.
2026-01-26 05:15:06 +00:00
The Miri Cronjob Bot
20c31e0d00 Prepare for merging from rust-lang/rust
This updates the rust-version file to 873d4682c7.
2026-01-26 05:07:09 +00:00
antoyo
774c8a2912
Merge pull request #840 from GuillaumeGomez/sqrt-f32-intrinsic
Add missing intrinsic translation for `llvm.sqrt.f32`
2026-01-25 21:19:19 -05:00
Guillaume Gomez
d3df4bdba5 Add regression test for <https://github.com/rust-lang/rustc_codegen_gcc/issues/288> 2026-01-25 21:09:22 +01:00
Guillaume Gomez
81acbae770 Add missing intrinsic translation for llvm.sqrt.f32 2026-01-25 21:02:34 +01:00
Ralf Jung
be79f4711d
Merge pull request #4767 from RalfJung/shim-scope
document guidelines for which shims have a place in Miri
2026-01-25 19:00:51 +00:00
Ralf Jung
a109785719
Merge pull request #4832 from rust-lang/rustup-2026-01-25
Automatic Rustup
2026-01-25 09:05:57 +00:00
The Miri Cronjob Bot
3d87f9ce4e Merge ref '5a07626f4b' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: rust-lang/rust@5a07626f4b
Filtered ref: rust-lang/miri@cc208624ef
Upstream diff: d10ac47c20...5a07626f4b

This merge was created using https://github.com/rust-lang/josh-sync.
2026-01-25 05:13:36 +00:00
The Miri Cronjob Bot
ed44659973 Prepare for merging from rust-lang/rust
This updates the rust-version file to 5a07626f4b.
2026-01-25 05:05:35 +00:00
bors
d8306375a7 Auto merge of #151065 - nagisa:add-preserve-none-abi, r=petrochenkov
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?)
2026-01-25 02:49:32 +00:00
Matthias Krüger
87c0c90ac0 Rollup merge of #151346 - folkertdev:simd-splat, r=workingjubilee
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:

- https://github.com/rust-lang/rust/issues/60637
- https://github.com/rust-lang/rust/issues/137407
- https://github.com/rust-lang/rust/issues/122623
- https://github.com/rust-lang/rust/issues/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.
2026-01-24 21:04:15 +01:00
antoyo
bcb24ceaba
Merge pull request #834 from rust-lang/fix/unreachable-segfault
Fix segfault related to __builtin_unreachable with inline asm
2026-01-24 13:26:20 -05:00
Antoni Boucher
58156c5cab Fix segfault related to __builtin_unreachable with inline asm 2026-01-24 12:30:39 -05:00
Simonas Kazlauskas
0cb56dc92c 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?)
2026-01-24 19:23:17 +02:00
bit-aloo
0e6d6033b5
migrate introduce_named_lifetime to SyntaxEditor 2026-01-22 19:04:36 +05:30
Jacob Pratt
56d32942a5 Rollup merge of #149209 - lto_refactors8, r=jackh726
Move LTO to OngoingCodegen::join

This will make it easier to in the future move all this code to link_binary.

Follow up to https://github.com/rust-lang/rust/pull/147810
Part of https://github.com/rust-lang/compiler-team/issues/908
2026-01-21 02:04:01 -05:00
Folkert de Vries
012c4603b7 c_variadic: use Clone instead of LLVM va_copy 2026-01-20 18:38:50 +01:00
Folkert de Vries
e0b87e4dd5 simd_splat: custom error in gcc backend for invalid element type 2026-01-19 16:56:20 +01:00
Folkert de Vries
f11abba641 add simd_splat intrinsic 2026-01-19 16:48:28 +01:00
Ralf Jung
d6362e6d0f document guidelines for which shims have a place in Miri 2026-01-18 15:52:45 +01:00
Guillaume Gomez
9b2d8e5c91
Merge pull request #824 from GuillaumeGomez/regen-intrinsics
Regenerate intrinsics
2026-01-16 22:32:07 +01:00
Guillaume Gomez
2177aa9ac7 Manually include intrinsic conversion that is not present in LLVM files 2026-01-16 18:55:09 +01:00
Guillaume Gomez
4f59819c26 Regenerate intrinsics 2026-01-16 17:46:34 +01:00
Guillaume Gomez
40973efd1c
Merge pull request #823 from GuillaumeGomez/simplify-intrinsics-generation
Simplify intrinsics generation
2026-01-16 17:45:40 +01:00
Guillaume Gomez
c848b28a5d Ignore src/intrinsic/old_archs.rs for typo checks 2026-01-16 17:14:09 +01:00
Guillaume Gomez
3dc60d0bf1 Simplify intrinsics translation generation script 2026-01-16 16:52:09 +01:00
Guillaume Gomez
3e789ed576 Stop cloning old llvmint repositories to generate intrinsics 2026-01-16 16:52:09 +01:00
Nicholas Nethercote
c9a063ced9 Remove Deref/DerefMut impl for Providers.
It's described as a "backwards compatibility hack to keep the diff
small". Removing it requires only a modest amount of churn, and the
resulting code is clearer without the invisible derefs.
2026-01-14 15:55:59 +11:00
Martin Nordholts
fe0facf0f6 Finish transition from semitransparent to semiopaque for rustc_macro_transparency 2026-01-08 19:14:45 +01:00
bjorn3
e90414f622 Don't compute FnAbi for LLVM intrinsics in backends 2026-01-08 10:47:29 +00:00
bjorn3
f004b3eb19 Reduce usage of FnAbi in codegen_llvm_intrinsic_call 2026-01-08 10:45:43 +00:00
A4-Tacks
f091a8acad
Fix complete semicolon in array expression
Example
---
```rust
fn foo() {}
fn bar() {
    let _ = [fo$0];
}
```

**Before this PR**

```rust
fn foo() {}
fn bar() {
    let _ = [foo();$0];
}
```

**After this PR**

```rust
fn foo() {}
fn bar() {
    let _ = [foo()$0];
}
```
2026-01-04 20:54:59 +08:00
A4-Tacks
e79fef4086
Fix incorrect Self path expand for inline_call
Example
---
```rust
trait Trait {
    fn f() -> Self;
}
struct Foo<'a>(&'a ());
impl<'a> Trait for Foo<'a> {
    fn f() -> Self { Self(&()) }
}
impl Foo<'_> {
    fn new() -> Self {
        Self::$0f()
    }
}
```

**Before this PR**

```rust
trait Trait {
    fn f() -> Self;
}
struct Foo<'a>(&'a ());
impl<'a> Trait for Foo<'a> {
    fn f() -> Self { Self(&()) }
}
impl Foo<'_> {
    fn new() -> Self {
        Foo<'a>(&())
    }
}
```

**After this PR**

```rust
trait Trait {
    fn f() -> Self;
}
struct Foo<'a>(&'a ());
impl<'a> Trait for Foo<'a> {
    fn f() -> Self { Self(&()) }
}
impl Foo<'_> {
    fn new() -> Self {
        Foo(&())
    }
}
```
2026-01-01 22:21:57 +08:00
bjorn3
ea8f037c76 Fix compilation of cg_gcc with master feature disabled 2025-12-27 18:41:14 +00:00
bjorn3
5bcd472b86 Partially inline get_fn_addr/get_fn in codegen_llvm_intrinsic_call
This moves all LLVM intrinsic handling out of the regular call path for
cg_gcc and makes it easier to hook into this code for future cg_llvm
changes.
2025-12-27 17:46:26 +00:00
bjorn3
56be08eb45 Pass Function to Builder::function_call in cg_gcc 2025-12-27 17:46:26 +00:00
bjorn3
0462ce9934 Don't assume get_fn is only called from codegen_mir in cg_gcc 2025-12-27 17:46:26 +00:00
bjorn3
9ba3ed5423 Move llvm intrinsic call to backend 2025-12-27 17:46:25 +00:00
Guillaume Gomez
bf5283cf6f Merge commit '02f889aec5' 2025-12-21 00:13:38 +01:00
Shoyu Vanilla
9e63845522 -Znext-solver Remove the forced ambiguity hack from search graph 2025-12-12 18:26:44 +09:00
bjorn3
385590e9dc Remove SharedEmitter from CodegenContext 2025-11-23 10:33:52 +00:00
bjorn3
67c61cefaf Remove opts field from CodegenContext 2025-11-23 10:33:52 +00:00
1054 changed files with 14747 additions and 11090 deletions

View file

@ -1298,9 +1298,9 @@ dependencies = [
[[package]]
name = "ena"
version = "0.14.3"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1"
dependencies = [
"log",
]
@ -2652,9 +2652,9 @@ dependencies = [
[[package]]
name = "objc2-core-foundation"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags",
]
@ -2667,9 +2667,9 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
[[package]]
name = "objc2-io-kit"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a"
dependencies = [
"libc",
"objc2-core-foundation",
@ -3640,7 +3640,6 @@ dependencies = [
"rustc_macros",
"rustc_metadata",
"rustc_middle",
"rustc_query_system",
"rustc_sanitizers",
"rustc_session",
"rustc_span",
@ -4243,7 +4242,6 @@ dependencies = [
"rustc_index",
"rustc_lint_defs",
"rustc_macros",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
@ -4500,7 +4498,6 @@ dependencies = [
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
@ -4508,23 +4505,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_query_system"
version = "0.0.0"
dependencies = [
"rustc_abi",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_hir",
"rustc_macros",
"rustc_serialize",
"rustc_session",
"rustc_span",
"smallvec",
]
[[package]]
name = "rustc_resolve"
version = "0.0.0"
@ -5374,9 +5354,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.38.0"
version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe840c5b1afe259a5657392a4dbb74473a14c8db999c3ec2f4ae812e028a94da"
checksum = "1efc19935b4b66baa6f654ac7924c192f55b175c00a7ab72410fc24284dacda8"
dependencies = [
"libc",
"objc2-core-foundation",

View file

@ -3131,8 +3131,16 @@ pub enum Const {
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, Walkable)]
pub enum Defaultness {
/// Item is unmarked. Implicitly determined based off of position.
/// For impls, this is `final`; for traits, this is `default`.
///
/// If you're expanding an item in a built-in macro or parsing an item
/// by hand, you probably want to use this.
Implicit,
/// `default`
Default(Span),
Final,
/// `final`; per RFC 3678, only trait items may be *explicitly* marked final.
Final(Span),
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic, Walkable)]
@ -4140,7 +4148,7 @@ impl AssocItemKind {
| Self::Fn(box Fn { defaultness, .. })
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
Defaultness::Final
Defaultness::Implicit
}
}
}

View file

@ -939,7 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let trait_item_def_id = hir_id.expect_owner();
let (ident, generics, kind, has_default) = match &i.kind {
let (ident, generics, kind, has_value) = match &i.kind {
AssocItemKind::Const(box ConstItem {
ident,
generics,
@ -1088,13 +1088,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value, || {
hir::Defaultness::Default { has_value }
});
let item = hir::TraitItem {
owner_id: trait_item_def_id,
ident: self.lower_ident(ident),
generics,
kind,
span: self.lower_span(i.span),
defaultness: hir::Defaultness::Default { has_value: has_default },
defaultness,
has_delayed_lints: !self.delayed_lints.is_empty(),
};
self.arena.alloc(item)
@ -1122,7 +1126,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
// to not cause an assertion failure inside the `lower_defaultness` function.
let has_val = true;
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
let (defaultness, defaultness_span) =
self.lower_defaultness(defaultness, has_val, || hir::Defaultness::Final);
let modifiers = TraitBoundModifiers {
constness: BoundConstness::Never,
asyncness: BoundAsyncness::Normal,
@ -1151,7 +1156,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> &'hir hir::ImplItem<'hir> {
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let (defaultness, _) =
self.lower_defaultness(i.kind.defaultness(), has_value, || hir::Defaultness::Final);
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(
hir_id,
@ -1304,15 +1310,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
&self,
d: Defaultness,
has_value: bool,
implicit: impl FnOnce() -> hir::Defaultness,
) -> (hir::Defaultness, Option<Span>) {
match d {
Defaultness::Implicit => (implicit(), None),
Defaultness::Default(sp) => {
(hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
}
Defaultness::Final => {
assert!(has_value);
(hir::Defaultness::Final, None)
}
Defaultness::Final(sp) => (hir::Defaultness::Final, Some(self.lower_span(sp))),
}
}

View file

@ -65,6 +65,28 @@ impl TraitOrImpl {
}
}
enum AllowDefault {
Yes,
No,
}
impl AllowDefault {
fn when(b: bool) -> Self {
if b { Self::Yes } else { Self::No }
}
}
enum AllowFinal {
Yes,
No,
}
impl AllowFinal {
fn when(b: bool) -> Self {
if b { Self::Yes } else { Self::No }
}
}
struct AstValidator<'a> {
sess: &'a Session,
features: &'a Features,
@ -563,11 +585,33 @@ impl<'a> AstValidator<'a> {
}
}
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
if let Defaultness::Default(def_span) = defaultness {
fn check_defaultness(
&self,
span: Span,
defaultness: Defaultness,
allow_default: AllowDefault,
allow_final: AllowFinal,
) {
match defaultness {
Defaultness::Default(def_span) if matches!(allow_default, AllowDefault::No) => {
let span = self.sess.source_map().guess_head_span(span);
self.dcx().emit_err(errors::ForbiddenDefault { span, def_span });
}
Defaultness::Final(def_span) if matches!(allow_final, AllowFinal::No) => {
let span = self.sess.source_map().guess_head_span(span);
self.dcx().emit_err(errors::ForbiddenFinal { span, def_span });
}
_ => (),
}
}
fn check_final_has_body(&self, item: &Item<AssocItemKind>, defaultness: Defaultness) {
if let AssocItemKind::Fn(box Fn { body: None, .. }) = &item.kind
&& let Defaultness::Final(def_span) = defaultness
{
let span = self.sess.source_map().guess_head_span(item.span);
self.dcx().emit_err(errors::ForbiddenFinalWithoutBody { span, def_span });
}
}
/// If `sp` ends with a semicolon, returns it as a `Span`
@ -698,13 +742,11 @@ impl<'a> AstValidator<'a> {
unreachable!("C variable argument list cannot be used in closures")
};
// C-variadics are not yet implemented in const evaluation.
if let Const::Yes(const_span) = sig.header.constness {
self.dcx().emit_err(errors::ConstAndCVariadic {
spans: vec![const_span, variadic_param.span],
const_span,
variadic_span: variadic_param.span,
});
if let Const::Yes(_) = sig.header.constness
&& !self.features.enabled(sym::const_c_variadic)
{
let msg = format!("c-variadic const function definitions are unstable");
feature_err(&self.sess, sym::const_c_variadic, sig.span, msg).emit();
}
if let Some(coroutine_kind) = sig.header.coroutine_kind {
@ -1192,7 +1234,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
},
) => {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.check_defaultness(item.span, *defaultness);
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
for EiiImpl { eii_macro_path, .. } in eii_impls {
self.visit_path(eii_macro_path);
@ -1362,7 +1404,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}
ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => {
self.check_defaultness(item.span, *defaultness);
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
if !rhs_kind.has_expr() {
self.dcx().emit_err(errors::ConstWithoutBody {
span: item.span,
@ -1400,7 +1442,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ItemKind::TyAlias(
ty_alias @ box TyAlias { defaultness, bounds, after_where_clause, ty, .. },
) => {
self.check_defaultness(item.span, *defaultness);
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
if ty.is_none() {
self.dcx().emit_err(errors::TyAliasWithoutBody {
span: item.span,
@ -1430,7 +1472,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
match &fi.kind {
ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
self.check_defaultness(fi.span, *defaultness);
self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
self.check_foreign_fn_bodyless(*ident, body.as_deref());
self.check_foreign_fn_headerless(sig.header);
self.check_foreign_item_ascii_only(*ident);
@ -1450,7 +1492,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ty,
..
}) => {
self.check_defaultness(fi.span, *defaultness);
self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics, after_where_clause);
@ -1709,9 +1751,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_nomangle_item_asciionly(ident, item.span);
}
if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
self.check_defaultness(item.span, item.kind.defaultness());
}
let defaultness = item.kind.defaultness();
self.check_defaultness(
item.span,
defaultness,
// `default` is allowed on all associated items in impls.
AllowDefault::when(matches!(ctxt, AssocCtxt::Impl { .. })),
// `final` is allowed on all associated *functions* in traits.
AllowFinal::when(
ctxt == AssocCtxt::Trait && matches!(item.kind, AssocItemKind::Fn(..)),
),
);
self.check_final_has_body(item, defaultness);
if let AssocCtxt::Impl { .. } = ctxt {
match &item.kind {

View file

@ -159,6 +159,24 @@ pub(crate) struct ForbiddenDefault {
pub def_span: Span,
}
#[derive(Diagnostic)]
#[diag("`final` is only allowed on associated functions in traits")]
pub(crate) struct ForbiddenFinal {
#[primary_span]
pub span: Span,
#[label("`final` because of this")]
pub def_span: Span,
}
#[derive(Diagnostic)]
#[diag("`final` is only allowed on associated functions if they have a body")]
pub(crate) struct ForbiddenFinalWithoutBody {
#[primary_span]
pub span: Span,
#[label("`final` because of this")]
pub def_span: Span,
}
#[derive(Diagnostic)]
#[diag("associated constant in `impl` without body")]
pub(crate) struct AssocConstWithoutBody {
@ -823,17 +841,6 @@ pub(crate) struct ConstAndCoroutine {
pub coroutine_kind: &'static str,
}
#[derive(Diagnostic)]
#[diag("functions cannot be both `const` and C-variadic")]
pub(crate) struct ConstAndCVariadic {
#[primary_span]
pub spans: Vec<Span>,
#[label("`const` because of this")]
pub const_span: Span,
#[label("C-variadic because of this")]
pub variadic_span: Span,
}
#[derive(Diagnostic)]
#[diag("functions cannot be both `{$coroutine_kind}` and C-variadic")]
pub(crate) struct CoroutineAndCVariadic {

View file

@ -580,6 +580,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(frontmatter, "frontmatters are experimental");
gate_all!(coroutines, "coroutine syntax is experimental");
gate_all!(const_block_items, "const block items are experimental");
gate_all!(final_associated_functions, "`final` on trait functions is experimental");
if !visitor.features.never_patterns() {
if let Some(spans) = spans.get(&sym::never_patterns) {

View file

@ -51,7 +51,7 @@ impl<'a> State<'a> {
expr.as_deref(),
vis,
*safety,
ast::Defaultness::Final,
ast::Defaultness::Implicit,
define_opaque.as_deref(),
),
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
@ -201,7 +201,7 @@ impl<'a> State<'a> {
body.as_deref(),
&item.vis,
ast::Safety::Default,
ast::Defaultness::Final,
ast::Defaultness::Implicit,
define_opaque.as_deref(),
);
}

View file

@ -292,3 +292,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitBoundsParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds;
}
pub(crate) struct DefaultLibAllocatorParser;
impl<S: Stage> NoArgsAttributeParser<S> for DefaultLibAllocatorParser {
const PATH: &[Symbol] = &[sym::default_lib_allocator];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator;
}

View file

@ -1178,6 +1178,30 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
}
}
pub(crate) struct RustcDoNotConstCheckParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDoNotConstCheckParser {
const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::Method(MethodKind::Trait { body: false })),
Allow(Target::Method(MethodKind::Trait { body: true })),
]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
}
pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonnullOptimizationGuaranteedParser {
const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
}
pub(crate) struct RustcSymbolName;
impl<S: Stage> SingleAttributeParser<S> for RustcSymbolName {

View file

@ -235,6 +235,7 @@ attribute_parsers!(
Single<WithoutArgs<ConstContinueParser>>,
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<CoroutineParser>>,
Single<WithoutArgs<DefaultLibAllocatorParser>>,
Single<WithoutArgs<DenyExplicitImplParser>>,
Single<WithoutArgs<DynIncompatibleTraitParser>>,
Single<WithoutArgs<EiiForeignItemParser>>,
@ -274,6 +275,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcConversionSuggestionParser>>,
Single<WithoutArgs<RustcDeallocatorParser>>,
Single<WithoutArgs<RustcDelayedBugFromInsideQueryParser>>,
Single<WithoutArgs<RustcDoNotConstCheckParser>>,
Single<WithoutArgs<RustcDumpDefParentsParser>>,
Single<WithoutArgs<RustcDumpItemBoundsParser>>,
Single<WithoutArgs<RustcDumpPredicatesParser>>,
@ -295,6 +297,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
Single<WithoutArgs<RustcNoMirInlineParser>>,
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
Single<WithoutArgs<RustcNounwindParser>>,
Single<WithoutArgs<RustcObjectLifetimeDefaultParser>>,
Single<WithoutArgs<RustcOffloadKernelParser>>,

View file

@ -1544,8 +1544,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, operand)
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => {
self.consume_operand(location, (operand, span), state)
}

View file

@ -297,8 +297,9 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, operand)
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => {
self.consume_operand(location, operand)
}
&Rvalue::Discriminant(place) => {
self.access_place(

View file

@ -1004,17 +1004,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
Rvalue::ShallowInitBox(_operand, ty) => {
let trait_ref =
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]);
self.prove_trait_ref(
trait_ref,
location.to_locations(),
ConstraintCategory::SizedBound,
);
}
Rvalue::Cast(cast_kind, op, ty) => {
match *cast_kind {
CastKind::PointerCoercion(
@ -2231,7 +2220,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| Rvalue::Ref(..)
| Rvalue::RawPtr(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)
| Rvalue::CopyForDeref(..)
| Rvalue::UnaryOp(..)

View file

@ -83,7 +83,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let body = Some(cx.block_expr(call));
let kind = ItemKind::Fn(Box::new(Fn {
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
sig,
ident: Ident::from_str_and_span(&global_fn_name(ALLOC_ERROR_HANDLER), span),
generics: Generics::default(),

View file

@ -334,7 +334,7 @@ mod llvm_enzyme {
// The first element of it is the name of the function to be generated
let d_fn = Box::new(ast::Fn {
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
sig: d_sig,
ident: first_ident(&meta_item_vec[0]),
generics,

View file

@ -136,7 +136,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
of_trait: Some(Box::new(ast::TraitImplHeader {
safety: ast::Safety::Default,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
trait_ref,
})),
constness: ast::Const::No,
@ -159,7 +159,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
of_trait: Some(Box::new(ast::TraitImplHeader {
safety: ast::Safety::Default,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
trait_ref,
})),
constness: ast::Const::No,

View file

@ -614,7 +614,7 @@ impl<'a> TraitDef<'a> {
},
attrs: ast::AttrVec::new(),
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
ident,
generics: Generics::default(),
after_where_clause: ast::WhereClause::default(),
@ -851,7 +851,7 @@ impl<'a> TraitDef<'a> {
of_trait: Some(Box::new(ast::TraitImplHeader {
safety: self.safety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
trait_ref,
})),
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
@ -1073,7 +1073,7 @@ impl<'a> MethodDef<'a> {
let trait_lo_sp = span.shrink_to_lo();
let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span };
let defaultness = ast::Defaultness::Final;
let defaultness = ast::Defaultness::Implicit;
// Create the method.
Box::new(ast::AssocItem {

View file

@ -77,7 +77,7 @@ impl AllocFnFactory<'_, '_> {
let sig = FnSig { decl, header, span: self.span };
let body = Some(self.cx.block_expr(result));
let kind = ItemKind::Fn(Box::new(Fn {
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
sig,
ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span),
generics: Generics::default(),
@ -128,11 +128,15 @@ impl AllocFnFactory<'_, '_> {
let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
let ty_usize = self.cx.ty_path(usize);
args.push(self.cx.param(self.span, size, ty_usize.clone()));
args.push(self.cx.param(self.span, align, ty_usize));
args.push(self.cx.param(self.span, size, ty_usize));
let ty_align = self.ptr_alignment();
args.push(self.cx.param(self.span, align, ty_align));
let layout_new =
self.cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]);
let layout_new = self.cx.std_path(&[
sym::alloc,
sym::Layout,
sym::from_size_alignment_unchecked,
]);
let layout_new = self.cx.expr_path(self.cx.path(self.span, layout_new));
let size = self.cx.expr_ident(self.span, size);
let align = self.cx.expr_ident(self.span, align);
@ -175,6 +179,12 @@ impl AllocFnFactory<'_, '_> {
self.cx.ty_path(usize)
}
fn ptr_alignment(&self) -> Box<Ty> {
let path = self.cx.std_path(&[sym::ptr, sym::Alignment]);
let path = self.cx.path(self.span, path);
self.cx.ty_path(path)
}
fn ptr_u8(&self) -> Box<Ty> {
let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
let ty_u8 = self.cx.ty_path(u8);

View file

@ -283,7 +283,7 @@ pub(crate) fn expand_test_or_bench(
// const $ident: test::TestDescAndFn =
ast::ItemKind::Const(
ast::ConstItem {
defaultness: ast::Defaultness::Final,
defaultness: ast::Defaultness::Implicit,
ident: Ident::new(fn_.ident.name, sp),
generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),

View file

@ -330,7 +330,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
let defaultness = ast::Defaultness::Final;
let defaultness = ast::Defaultness::Implicit;
// Honor the reexport_test_harness_main attribute
let main_ident = match cx.reexport_test_harness_main {

View file

@ -622,11 +622,6 @@ impl<T: ?Sized> Deref for Box<T> {
}
}
#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
unsafe { libc::malloc(size) }
}
#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);

View file

@ -0,0 +1,133 @@
From 285d5716fcfa6d43a3516d899b73bc85da322c25 Mon Sep 17 00:00:00 2001
From: xonx <119700621+xonx4l@users.noreply.github.com>
Date: Sun, 15 Feb 2026 14:06:49 +0000
Subject: [PATCH] Disable f16 math tests for cranelift
---
coretests/tests/floats/mod.rs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/coretests/tests/floats/mod.rs b/coretests/tests/floats/mod.rs
index c61961f8584..d7b4fa20322 100644
--- a/coretests/tests/floats/mod.rs
+++ b/coretests/tests/floats/mod.rs
@@ -1534,7 +1534,7 @@ fn s_nan() -> Float {
name: powf,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1557,7 +1557,7 @@ fn s_nan() -> Float {
name: exp,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1578,7 +1578,7 @@ fn s_nan() -> Float {
name: exp2,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1598,7 +1598,7 @@ fn s_nan() -> Float {
name: ln,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1620,7 +1620,7 @@ fn s_nan() -> Float {
name: log,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1645,7 +1645,7 @@ fn s_nan() -> Float {
name: log2,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1668,7 +1668,7 @@ fn s_nan() -> Float {
name: log10,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1692,7 +1692,7 @@ fn s_nan() -> Float {
name: asinh,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1725,7 +1725,7 @@ fn s_nan() -> Float {
name: acosh,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1753,7 +1753,7 @@ fn s_nan() -> Float {
name: atanh,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1779,7 +1779,7 @@ fn s_nan() -> Float {
name: gamma,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -1814,7 +1814,7 @@ fn s_nan() -> Float {
name: ln_gamma,
attrs: {
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
@@ -2027,7 +2027,7 @@ fn s_nan() -> Float {
attrs: {
// FIXME(f16_f128): add math tests when available
const: #[cfg(false)],
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
--
2.50.1

View file

@ -902,7 +902,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
lval.write_cvalue_transmute(fx, operand);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
}
}
StatementKind::StorageLive(_)

View file

@ -208,7 +208,7 @@ pub(crate) fn codegen_cast(
let ret_ty = if to_ty.bits() < 32 { types::I32 } else { to_ty };
let name = format!(
"__fix{sign}tf{size}i",
sign = if from_signed { "" } else { "un" },
sign = if to_signed { "" } else { "uns" },
size = match ret_ty {
types::I32 => 's',
types::I64 => 'd',

View file

@ -180,6 +180,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
&& sess.target.env == Env::Gnu
&& sess.target.abi != Abi::Llvm);
// FIXME(f128): f128 math operations need f128 math symbols, which currently aren't always
// filled in by compiler-builtins. The only libc that provides these currently is glibc.
let has_reliable_f128_math = has_reliable_f16_f128 && sess.target.env == Env::Gnu;
TargetConfig {
target_features,
unstable_target_features,
@ -188,7 +192,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
has_reliable_f16: has_reliable_f16_f128,
has_reliable_f16_math: has_reliable_f16_f128,
has_reliable_f128: has_reliable_f16_f128,
has_reliable_f128_math: has_reliable_f16_f128,
has_reliable_f128_math,
}
}

View file

@ -18,6 +18,7 @@
],
"ignorePaths": [
"src/intrinsic/archs.rs",
"src/intrinsic/old_archs.rs",
"src/intrinsic/llvm.rs"
],
"ignoreRegExpList": [

View file

@ -113,6 +113,10 @@ jobs:
git config --global user.name "User"
./y.sh prepare
- name: Add more failing tests for GCC without 128-bit integers support
if: ${{ matrix.libgccjit_version.gcc == 'gcc-15-without-int128.deb' }}
run: cat tests/failing-ui-tests-without-128bit-integers.txt >> tests/failing-ui-tests.txt
- name: Run tests
run: |
./y.sh test --release --clean --build-sysroot ${{ matrix.commands }}

View file

@ -83,7 +83,7 @@ jobs:
run: |
./y.sh prepare --only-libcore --cross
./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build -Zjson-target-spec --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
./y.sh clean all
- name: Build

View file

@ -56,18 +56,18 @@ dependencies = [
[[package]]
name = "gccjit"
version = "3.1.1"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683"
checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
version = "1.1.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f81d901767ddba371a619fa9bba657066a4d3c5607ee69bbb557c1c5ba9bf85"
checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15"
dependencies = [
"libc",
]

View file

@ -24,7 +24,7 @@ default = ["master"]
[dependencies]
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
tempfile = "3.20"
gccjit = { version = "3.1.1", features = ["dlopen"] }
gccjit = { version = "3.3.0", features = ["dlopen"] }
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] }
# Local copy.

View file

@ -45,12 +45,12 @@ The default configuration (see below in the [Quick start](#quick-start) section)
./y.sh test --release
```
If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should
If you don't need to test GCC patches you wrote in our GCC fork, then the default configuration should
be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC.
### Building with your own GCC version
If you wrote a patch for GCC and want to test it without this backend, you will need
If you wrote a patch for GCC and want to test it with this backend, you will need
to do a few more things.
To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):

View file

@ -6,4 +6,4 @@ seh = "seh"
typ = "typ"
[files]
extend-exclude = ["src/intrinsic/archs.rs"]
extend-exclude = ["src/intrinsic/archs.rs", "src/intrinsic/old_archs.rs"]

View file

@ -141,6 +141,10 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
}
let mut args: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"build", &"--target", &config.target];
if config.target.ends_with(".json") {
args.push(&"-Zjson-target-spec");
}
for feature in &config.features {
args.push(&"--features");
args.push(feature);

View file

@ -679,10 +679,10 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
create_dir(projects_path)?;
let nb_parts = args.nb_parts.unwrap_or(0);
if nb_parts > 0 {
if let Some(count) = projects.len().checked_div(nb_parts) {
// We increment the number of tests by one because if this is an odd number, we would skip
// one test.
let count = projects.len() / nb_parts + 1;
let count = count + 1;
let current_part = args.current_part.unwrap();
let start = current_part * count;
// We remove the projects we don't want to test.

View file

@ -2,9 +2,9 @@
## How to debug GCC LTO
Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger.
Run the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger.
## How to debug stdarch tests that cannot be ran locally
## How to debug stdarch tests that cannot be run locally
First, run the tests normally:

View file

@ -15,7 +15,7 @@ That can be caused by the fact that you try to compile with `lto = "fat"`, but y
### ld: cannot find crtbegin.o
When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors:
When compiling an executable with libgccjit, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors:
```
ld: cannot find crtbegin.o: No such file or directory

View file

@ -3,7 +3,7 @@
You can see the full documentation about what GIMPLE is [here](https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html). In this document we will explain how to generate it.
First, we'll copy the content from `gcc/gcc/testsuite/jit.dg/test-const-attribute.c` into a
file named `local.c` and remove the content we're not interested into:
file named `local.c` and remove the content we're not interested in:
```diff
- /* { dg-do compile { target x86_64-*-* } } */

View file

@ -53,7 +53,7 @@ If you wish to build a custom sysroot, pass the path of your sysroot source to `
### How to use [mem-trace](https://github.com/antoyo/mem-trace)
`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't have a chance to intercept the calls to `malloc`.
### How to generate GIMPLE

View file

@ -628,11 +628,6 @@ impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
}
}
#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
libc::malloc(size)
}
#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);

View file

@ -1 +1 @@
0081ca6631abdfa02bf42bc85aaf507b8a0e6beb
efdd0a7290c22f5438d7c5380105d353ee3e8518

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-12-20"
channel = "nightly-2026-02-14"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -575,9 +575,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
}
if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) {
let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
let builtin_unreachable: RValue<'gcc> =
unsafe { std::mem::transmute(builtin_unreachable) };
self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None);
self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[]));
}
// Write results to outputs.

View file

@ -17,15 +17,13 @@
// /usr/bin/ld: warning: type of symbol `_RNvNvNvNvNtNtNtCsAj5i4SGTR7_3std4sync4mpmc5waker17current_thread_id5DUMMY7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o
// /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization
// cSpell:enable
use std::ffi::{CStr, CString};
use std::ffi::CString;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::Ordering;
use gccjit::{Context, OutputKind};
use gccjit::OutputKind;
use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::lto::SerializedModule;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
@ -33,15 +31,12 @@ use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_errors::{DiagCtxt, DiagCtxtHandle};
use rustc_log::tracing::info;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config::Lto;
use rustc_target::spec::RelocModel;
use tempfile::{TempDir, tempdir};
use crate::back::write::save_temp_bitcode;
use crate::errors::LtoBitcodeFromRlib;
use crate::{GccCodegenBackend, GccContext, LTO_SUPPORTED, LtoMode, SyncContext, to_gcc_opt_level};
use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level};
struct LtoData {
// TODO(antoyo): use symbols_below_threshold.
@ -281,385 +276,3 @@ impl ModuleBufferMethods for ModuleBuffer {
&[]
}
}
/// Performs thin LTO by performing necessary global analysis and returning two
/// lists, one of the modules that need optimization and another for modules that
/// can simply be copied over from the incr. comp. cache.
pub(crate) fn run_thin(
cgcx: &CodegenContext,
prof: &SelfProfilerRef,
dcx: DiagCtxtHandle<'_>,
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
if cgcx.use_linker_plugin_lto {
unreachable!(
"We should never reach this case if the LTO step \
is deferred to the linker"
);
}
thin_lto(
cgcx,
prof,
dcx,
modules,
lto_data.upstream_modules,
lto_data.tmp_path,
cached_modules,
//&lto_data.symbols_below_threshold,
)
}
pub(crate) fn prepare_thin(module: ModuleCodegen<GccContext>) -> (String, ThinBuffer) {
let name = module.name;
//let buffer = ThinBuffer::new(module.module_llvm.context, true);
let buffer = ThinBuffer::new(&module.module_llvm.context);
(name, buffer)
}
/// Prepare "thin" LTO to get run on these modules.
///
/// The general structure of ThinLTO is quite different from the structure of
/// "fat" LTO above. With "fat" LTO all LLVM modules in question are merged into
/// one giant LLVM module, and then we run more optimization passes over this
/// big module after internalizing most symbols. Thin LTO, on the other hand,
/// avoid this large bottleneck through more targeted optimization.
///
/// At a high level Thin LTO looks like:
///
/// 1. Prepare a "summary" of each LLVM module in question which describes
/// the values inside, cost of the values, etc.
/// 2. Merge the summaries of all modules in question into one "index"
/// 3. Perform some global analysis on this index
/// 4. For each module, use the index and analysis calculated previously to
/// perform local transformations on the module, for example inlining
/// small functions from other modules.
/// 5. Run thin-specific optimization passes over each module, and then code
/// generate everything at the end.
///
/// The summary for each module is intended to be quite cheap, and the global
/// index is relatively quite cheap to create as well. As a result, the goal of
/// ThinLTO is to reduce the bottleneck on LTO and enable LTO to be used in more
/// situations. For example one cheap optimization is that we can parallelize
/// all codegen modules, easily making use of all the cores on a machine.
///
/// With all that in mind, the function here is designed at specifically just
/// calculating the *index* for ThinLTO. This index will then be shared amongst
/// all of the `LtoModuleCodegen` units returned below and destroyed once
/// they all go out of scope.
fn thin_lto(
_cgcx: &CodegenContext,
prof: &SelfProfilerRef,
_dcx: DiagCtxtHandle<'_>,
modules: Vec<(String, ThinBuffer)>,
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
tmp_path: TempDir,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
//_symbols_below_threshold: &[String],
) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
let _timer = prof.generic_activity("LLVM_thin_lto_global_analysis");
info!("going for that thin, thin LTO");
/*let green_modules: FxHashMap<_, _> =
cached_modules.iter().map(|(_, wp)| (wp.cgu_name.clone(), wp.clone())).collect();*/
let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len();
let mut thin_buffers = Vec::with_capacity(modules.len());
let mut module_names = Vec::with_capacity(full_scope_len);
//let mut thin_modules = Vec::with_capacity(full_scope_len);
for (i, (name, buffer)) in modules.into_iter().enumerate() {
info!("local module: {} - {}", i, name);
let cname = CString::new(name.as_bytes()).unwrap();
/*thin_modules.push(llvm::ThinLTOModule {
identifier: cname.as_ptr(),
data: buffer.data().as_ptr(),
len: buffer.data().len(),
});*/
thin_buffers.push(buffer);
module_names.push(cname);
}
// FIXME: All upstream crates are deserialized internally in the
// function below to extract their summary and modules. Note that
// unlike the loop above we *must* decode and/or read something
// here as these are all just serialized files on disk. An
// improvement, however, to make here would be to store the
// module summary separately from the actual module itself. Right
// now this is store in one large bitcode file, and the entire
// file is deflate-compressed. We could try to bypass some of the
// decompression by storing the index uncompressed and only
// lazily decompressing the bytecode if necessary.
//
// Note that truly taking advantage of this optimization will
// likely be further down the road. We'd have to implement
// incremental ThinLTO first where we could actually avoid
// looking at upstream modules entirely sometimes (the contents,
// we must always unconditionally look at the index).
let mut serialized = Vec::with_capacity(serialized_modules.len() + cached_modules.len());
let cached_modules =
cached_modules.into_iter().map(|(sm, wp)| (sm, CString::new(wp.cgu_name).unwrap()));
for (module, name) in serialized_modules.into_iter().chain(cached_modules) {
info!("upstream or cached module {:?}", name);
/*thin_modules.push(llvm::ThinLTOModule {
identifier: name.as_ptr(),
data: module.data().as_ptr(),
len: module.data().len(),
});*/
match module {
SerializedModule::Local(_) => {
//let path = module_buffer.0.to_str().expect("path");
//let my_path = PathBuf::from(path);
//let exists = my_path.exists();
/*module.module_llvm.should_combine_object_files = true;
module
.module_llvm
.context
.add_driver_option(module_buffer.0.to_str().expect("path"));*/
}
SerializedModule::FromRlib(_) => unimplemented!("from rlib"),
SerializedModule::FromUncompressedFile(_) => {
unimplemented!("from uncompressed file")
}
}
serialized.push(module);
module_names.push(name);
}
// Sanity check
//assert_eq!(thin_modules.len(), module_names.len());
// Delegate to the C++ bindings to create some data here. Once this is a
// tried-and-true interface we may wish to try to upstream some of this
// to LLVM itself, right now we reimplement a lot of what they do
// upstream...
/*let data = llvm::LLVMRustCreateThinLTOData(
thin_modules.as_ptr(),
thin_modules.len() as u32,
symbols_below_threshold.as_ptr(),
symbols_below_threshold.len() as u32,
)
.ok_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext))?;
*/
let data = ThinData; //(Arc::new(tmp_path))/*(data)*/;
info!("thin LTO data created");
/*let (key_map_path, prev_key_map, curr_key_map) =
if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir {
let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME);
// If the previous file was deleted, or we get an IO error
// reading the file, then we'll just use `None` as the
// prev_key_map, which will force the code to be recompiled.
let prev =
if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None };
let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names);
(Some(path), prev, curr)
}
else {
// If we don't compile incrementally, we don't need to load the
// import data from LLVM.
assert!(green_modules.is_empty());
let curr = ThinLTOKeysMap::default();
(None, None, curr)
};
info!("thin LTO cache key map loaded");
info!("prev_key_map: {:#?}", prev_key_map);
info!("curr_key_map: {:#?}", curr_key_map);*/
// Throw our data in an `Arc` as we'll be sharing it across threads. We
// also put all memory referenced by the C++ data (buffers, ids, etc)
// into the arc as well. After this we'll create a thin module
// codegen per module in this data.
let shared =
Arc::new(ThinShared { data, thin_buffers, serialized_modules: serialized, module_names });
let copy_jobs = vec![];
let mut opt_jobs = vec![];
info!("checking which modules can be-reused and which have to be re-optimized.");
for (module_index, module_name) in shared.module_names.iter().enumerate() {
let module_name = module_name_to_str(module_name);
/*if let (Some(prev_key_map), true) =
(prev_key_map.as_ref(), green_modules.contains_key(module_name))
{
assert!(cgcx.incr_comp_session_dir.is_some());
// If a module exists in both the current and the previous session,
// and has the same LTO cache key in both sessions, then we can re-use it
if prev_key_map.keys.get(module_name) == curr_key_map.keys.get(module_name) {
let work_product = green_modules[module_name].clone();
copy_jobs.push(work_product);
info!(" - {}: re-used", module_name);
assert!(cgcx.incr_comp_session_dir.is_some());
continue;
}
}*/
info!(" - {}: re-compiled", module_name);
opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index });
}
// Save the current ThinLTO import information for the next compilation
// session, overwriting the previous serialized data (if any).
/*if let Some(path) = key_map_path {
if let Err(err) = curr_key_map.save_to_file(&path) {
return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }));
}
}*/
// NOTE: save the temporary directory used by LTO so that it gets deleted after linking instead
// of now.
//module.module_llvm.temp_dir = Some(tmp_path);
// TODO: save the directory so that it gets deleted later.
std::mem::forget(tmp_path);
(opt_jobs, copy_jobs)
}
pub fn optimize_thin_module(
thin_module: ThinModule<GccCodegenBackend>,
_cgcx: &CodegenContext,
) -> ModuleCodegen<GccContext> {
//let module_name = &thin_module.shared.module_names[thin_module.idx];
// Right now the implementation we've got only works over serialized
// modules, so we create a fresh new LLVM context and parse the module
// into that context. One day, however, we may do this for upstream
// crates but for locally codegened modules we may be able to reuse
// that LLVM Context and Module.
//let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
//let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &dcx)? as *const _;
let mut lto_mode = LtoMode::None;
let context = match thin_module.shared.thin_buffers.get(thin_module.idx) {
Some(thin_buffer) => Arc::clone(&thin_buffer.context),
None => {
let context = Context::default();
let len = thin_module.shared.thin_buffers.len();
let module = &thin_module.shared.serialized_modules[thin_module.idx - len];
match *module {
SerializedModule::Local(ref module_buffer) => {
let path = module_buffer.0.to_str().expect("path");
context.add_driver_option(path);
lto_mode = LtoMode::Thin;
/*module.module_llvm.should_combine_object_files = true;
module
.module_llvm
.context
.add_driver_option(module_buffer.0.to_str().expect("path"));*/
}
SerializedModule::FromRlib(_) => unimplemented!("from rlib"),
SerializedModule::FromUncompressedFile(_) => {
unimplemented!("from uncompressed file")
}
}
Arc::new(SyncContext::new(context))
}
};
let lto_supported = LTO_SUPPORTED.load(Ordering::SeqCst);
let module = ModuleCodegen::new_regular(
thin_module.name().to_string(),
GccContext {
context,
lto_mode,
lto_supported,
// TODO(antoyo): use the correct relocation model here.
relocation_model: RelocModel::Pic,
temp_dir: None,
},
);
/*{
let target = &*module.module_llvm.tm;
let llmod = module.module_llvm.llmod();
save_temp_bitcode(cgcx, &module, "thin-lto-input");
// Up next comes the per-module local analyses that we do for Thin LTO.
// Each of these functions is basically copied from the LLVM
// implementation and then tailored to suit this implementation. Ideally
// each of these would be supported by upstream LLVM but that's perhaps
// a patch for another day!
//
// You can find some more comments about these functions in the LLVM
// bindings we've got (currently `PassWrapper.cpp`)
{
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
unsafe { llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) };
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
}
{
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
}
{
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
}
{
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
}
// Alright now that we've done everything related to the ThinLTO
// analysis it's time to run some optimizations! Here we use the same
// `run_pass_manager` as the "fat" LTO above except that we tell it to
// populate a thin-specific pass manager, which presumably LLVM treats a
// little differently.
{
info!("running thin lto passes over {}", module.name);
run_pass_manager(cgcx, &dcx, &mut module, true)?;
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
}
}*/
// FIXME: switch to #[expect] when the clippy bug is fixed.
#[allow(clippy::let_and_return)]
module
}
pub struct ThinBuffer {
context: Arc<SyncContext>,
}
impl ThinBuffer {
pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
Self { context: Arc::clone(context) }
}
}
impl ThinBufferMethods for ThinBuffer {
fn data(&self) -> &[u8] {
&[]
}
}
pub struct ThinData; //(Arc<TempDir>);
fn module_name_to_str(c_str: &CStr) -> &str {
c_str.to_str().unwrap_or_else(|e| {
bug!("Encountered non-utf8 GCC module name `{}`: {}", c_str.to_string_lossy(), e)
})
}

View file

@ -1495,6 +1495,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
#[cfg(not(feature = "master"))]
fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
use crate::context::new_array_type;
let vector_type = vec
.get_type()
.unqualified()
@ -1503,7 +1505,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
let element_type = vector_type.get_element_type();
let vec_num_units = vector_type.get_num_units();
let array_type =
self.context.new_array_type(self.location, element_type, vec_num_units as u64);
new_array_type(self.context, self.location, element_type, vec_num_units as u64);
let array = self.context.new_bitcast(self.location, vec, array_type).to_rvalue();
self.context.new_array_access(self.location, array, idx).to_rvalue()
}
@ -1871,32 +1873,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
// On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
let int_max = |signed: bool, int_width: u64| -> u128 {
fn int_max(signed: bool, int_width: u64) -> u128 {
let shift_amount = 128 - int_width;
if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
};
let int_min = |signed: bool, int_width: u64| -> i128 {
}
fn int_min(signed: bool, int_width: u64) -> i128 {
if signed { i128::MIN >> (128 - int_width) } else { 0 }
};
}
let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
// TODO: rewrite using a generic function with <F: Float>.
let compute_clamp_bounds_half = |signed: bool, int_width: u64| -> (u128, u128) {
let rounded_min =
ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
ieee::Half::from_i128_r(int_min(signed, int_width), Round::TowardZero);
//assert_eq!(rounded_min.status, Status::OK);
let rounded_max =
ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero);
ieee::Half::from_u128_r(int_max(signed, int_width), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) {
let rounded_min =
ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero);
fn compute_clamp_bounds<F: Float>(signed: bool, int_width: u64) -> (u128, u128) {
let rounded_min = F::from_i128_r(int_min(signed, int_width), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max =
ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero);
let rounded_max = F::from_u128_r(int_max(signed, int_width), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
}
// To implement saturation, we perform the following steps:
//
// 1. Cast val to an integer with fpto[su]i. This may result in undef.
@ -1926,15 +1927,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let float_bits_to_llval = |bx: &mut Self, bits| {
let bits_llval = match float_width {
16 => bx.cx().const_u16(bits as u16),
32 => bx.cx().const_u32(bits as u32),
64 => bx.cx().const_u64(bits as u64),
128 => bx.cx().const_u128(bits),
n => bug!("unsupported float width {}", n),
};
bx.bitcast(bits_llval, float_ty)
};
let (f_min, f_max) = match float_width {
32 => compute_clamp_bounds_single(signed, int_width),
64 => compute_clamp_bounds_double(signed, int_width),
16 => compute_clamp_bounds_half(signed, int_width),
32 => compute_clamp_bounds::<ieee::Single>(signed, int_width),
64 => compute_clamp_bounds::<ieee::Double>(signed, int_width),
128 => compute_clamp_bounds::<ieee::Quad>(signed, int_width),
n => bug!("unsupported float width {}", n),
};
let f_min = float_bits_to_llval(self, f_min);

View file

@ -8,7 +8,7 @@ use rustc_middle::mir::Mutability;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, PointerArithmetic, Scalar};
use rustc_middle::ty::layout::LayoutOf;
use crate::context::CodegenCx;
use crate::context::{CodegenCx, new_array_type};
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -20,6 +20,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
bytes_in_context(self, bytes)
}
pub fn const_u16(&self, i: u16) -> RValue<'gcc> {
self.const_uint(self.type_u16(), i as u64)
}
fn global_string(&self, string: &str) -> LValue<'gcc> {
// TODO(antoyo): handle non-null-terminated strings.
let string = self.context.new_string_literal(string);
@ -55,7 +59,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
0 => {
let context = &cx.context;
let byte_type = context.new_type::<u64>();
let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 8);
let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8);
let elements: Vec<_> = bytes
.chunks_exact(8)
.map(|arr| {
@ -76,7 +80,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
4 => {
let context = &cx.context;
let byte_type = context.new_type::<u32>();
let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 4);
let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4);
let elements: Vec<_> = bytes
.chunks_exact(4)
.map(|arr| {
@ -95,7 +99,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
_ => {
let context = cx.context;
let byte_type = context.new_type::<u8>();
let typ = context.new_array_type(None, byte_type, bytes.len() as u64);
let typ = new_array_type(context, None, byte_type, bytes.len() as u64);
let elements: Vec<_> = bytes
.iter()
.map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))

View file

@ -19,6 +19,8 @@ use rustc_middle::ty::layout::{
};
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
use rustc_session::Session;
#[cfg(feature = "master")]
use rustc_session::config::DebugInfo;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi};
@ -145,6 +147,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
supports_f64_type: bool,
supports_f128_type: bool,
) -> Self {
#[cfg(feature = "master")]
if tcx.sess.opts.debuginfo != DebugInfo::None {
context.set_filename(codegen_unit.name().as_str());
}
let create_type = |ctype, rust_type| {
let layout = tcx
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
@ -194,8 +201,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
// TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
// gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
let i128_type = new_array_type(context, None, i64_type, 2)/*.get_aligned(i128_align)*/;
let u128_type = new_array_type(context, None, u64_type, 2)/*.get_aligned(u128_align)*/;
(i128_type, u128_type)
};
@ -601,3 +608,17 @@ fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel {
TlsModel::Emulated => gccjit::TlsModel::GlobalDynamic,
}
}
pub fn new_array_type<'gcc>(
context: &'gcc Context<'gcc>,
location: Option<Location<'gcc>>,
typ: Type<'gcc>,
size: u64,
) -> Type<'gcc> {
#[cfg(feature = "master")]
{
context.new_array_type_u64(location, typ, size)
}
#[cfg(not(feature = "master"))]
context.new_array_type(location, typ, size)
}

View file

@ -942,7 +942,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
fn float_to_int_cast(
&self,
signed: bool,
value: RValue<'gcc>,
mut value: RValue<'gcc>,
dest_typ: Type<'gcc>,
) -> RValue<'gcc> {
let value_type = value.get_type();
@ -951,16 +951,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
debug_assert!(dest_typ.dyncast_array().is_some());
let (dest_type, param_type) = match self.type_kind(value_type) {
TypeKind::Half => (Some(self.float_type), self.float_type),
_ => (None, value_type),
};
let name_suffix = match self.type_kind(value_type) {
// cSpell:disable
TypeKind::Float => "sfti",
// Since we will cast Half to a float, we use sfti for both.
TypeKind::Half | TypeKind::Float => "sfti",
TypeKind::Double => "dfti",
TypeKind::FP128 => "tfti",
// cSpell:enable
kind => panic!("cannot cast a {:?} to non-native integer", kind),
};
let sign = if signed { "" } else { "uns" };
let func_name = format!("__fix{}{}", sign, name_suffix);
let param = self.context.new_parameter(None, value_type, "n");
let param = self.context.new_parameter(None, param_type, "n");
let func = self.context.new_function(
None,
FunctionType::Extern,
@ -969,6 +975,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
func_name,
false,
);
if let Some(dest_type) = dest_type {
value = self.context.new_cast(None, value, dest_type);
}
self.context.new_call(None, func, &[value])
}

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue,
use rustc_codegen_ssa::traits::BuilderMethods;
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::context::{CodegenCx, new_array_type};
fn encode_key_128_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
@ -585,7 +585,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
"__builtin_ia32_encodekey128_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 6);
let array_type = new_array_type(builder.context, None, m128i, 6);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
@ -593,7 +593,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
"__builtin_ia32_encodekey256_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 7);
let array_type = new_array_type(builder.context, None, m128i, 7);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
@ -620,7 +620,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let first_value = old_args.swap_remove(0);
let element_type = first_value.get_type();
let array_type = builder.context.new_array_type(None, element_type, 8);
let array_type = new_array_type(builder.context, None, element_type, 8);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
@ -869,7 +869,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 6);
let array_type = new_array_type(builder.context, None, field2_type, 6);
let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
@ -891,7 +891,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 7);
let array_type = new_array_type(builder.context, None, field2_type, 7);
let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
@ -937,7 +937,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 8);
let array_type = new_array_type(builder.context, None, field2_type, 8);
let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
@ -1061,7 +1061,18 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.x86.xgetbv" => "__builtin_ia32_xgetbv",
// NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html
// FIXME: Should handle other targets than `ia32`.
"llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd",
// FIXME: Should handle other targets than `ia32`.
"llvm.sqrt.v4f32" => "__builtin_ia32_sqrtps",
"llvm.sqrt.f32" => {
let gcc_name = "__builtin_sqrtf";
let func = cx.context.get_builtin_function(gcc_name);
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
return func;
}
// FIXME: Should handle other targets than `ia32`.
"llvm.smax.v4i32" => "__builtin_ia32_pmaxsd128",
"llvm.x86.avx512.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask",
"llvm.x86.avx512.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask",
"llvm.x86.avx512.max.ps.512" => "__builtin_ia32_maxps512_mask",
@ -1604,5 +1615,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
func
}
#[cfg(feature = "master")]
include!("old_archs.rs");
#[cfg(feature = "master")]
include!("archs.rs");

View file

@ -208,6 +208,7 @@ fn get_simple_function_f128<'gcc, 'tcx>(
let f128_type = cx.type_f128();
let func_name = match name {
sym::ceilf128 => "ceilf128",
sym::fabsf128 => "fabsf128",
sym::floorf128 => "floorf128",
sym::truncf128 => "truncf128",
sym::roundf128 => "roundf128",
@ -262,6 +263,7 @@ fn f16_builtin<'gcc, 'tcx>(
let builtin_name = match name {
sym::ceilf16 => "__builtin_ceilf",
sym::copysignf16 => "__builtin_copysignf",
sym::fabsf16 => "fabsf",
sym::floorf16 => "__builtin_floorf",
sym::fmaf16 => "fmaf",
sym::maxnumf16 => "__builtin_fmaxf",
@ -328,6 +330,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}
sym::ceilf16
| sym::copysignf16
| sym::fabsf16
| sym::floorf16
| sym::fmaf16
| sym::maxnumf16
@ -648,15 +651,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let fn_ptr = func.get_address(None);
let fn_ty = fn_ptr.get_type();
let mut llargs = vec![];
let mut call_args = vec![];
for arg in args {
match arg.val {
OperandValue::ZeroSized => {}
OperandValue::Immediate(_) => llargs.push(arg.immediate()),
OperandValue::Immediate(_) => call_args.push(arg.immediate()),
OperandValue::Pair(a, b) => {
llargs.push(a);
llargs.push(b);
call_args.push(a);
call_args.push(b);
}
OperandValue::Ref(op_place_val) => {
let mut llval = op_place_val.llval;
@ -673,13 +676,13 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
// We store bools as `i8` so we need to truncate to `i1`.
llval = self.to_immediate_scalar(llval, scalar);
}
llargs.push(llval);
call_args.push(llval);
}
}
}
// FIXME directly use the llvm intrinsic adjustment functions here
let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None);
let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None);
if is_cleanup {
self.apply_attrs_to_cleanup_callsite(llret);
}
@ -720,7 +723,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}
fn va_end(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> {
unimplemented!();
// TODO(antoyo): implement.
self.context.new_rvalue_from_int(self.int_type, 0)
}
}

File diff suppressed because it is too large Load diff

View file

@ -76,7 +76,6 @@ use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use back::lto::{ThinBuffer, ThinData};
use gccjit::{CType, Context, OptimizationLevel};
#[cfg(feature = "master")]
use gccjit::{TargetInfo, Version};
@ -87,7 +86,9 @@ use rustc_codegen_ssa::back::write::{
};
use rustc_codegen_ssa::base::codegen_crate;
use rustc_codegen_ssa::target_features::cfg_target_feature;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
use rustc_codegen_ssa::traits::{
CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods,
};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::profiling::SelfProfilerRef;
@ -177,8 +178,6 @@ pub struct GccCodegenBackend {
lto_supported: Arc<AtomicBool>,
}
static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false);
fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) {
if gccjit::is_loaded() {
// Do not load a libgccjit second time.
@ -234,6 +233,8 @@ impl CodegenBackend for GccCodegenBackend {
#[cfg(feature = "master")]
{
gccjit::set_lang_name(c"GNU Rust");
let target_cpu = target_cpu(sess);
// Get the second TargetInfo with the correct CPU features by setting the arch.
@ -249,7 +250,6 @@ impl CodegenBackend for GccCodegenBackend {
#[cfg(feature = "master")]
{
let lto_supported = gccjit::is_lto_supported();
LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst);
self.lto_supported.store(lto_supported, Ordering::SeqCst);
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
@ -279,6 +279,10 @@ impl CodegenBackend for GccCodegenBackend {
}
}
fn thin_lto_supported(&self) -> bool {
false
}
fn provide(&self, providers: &mut Providers) {
providers.queries.global_backend_features =
|tcx, ()| gcc_util::global_gcc_features(tcx.sess)
@ -419,11 +423,19 @@ unsafe impl Send for SyncContext {}
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
unsafe impl Sync for SyncContext {}
pub struct ThinBuffer;
impl ThinBufferMethods for ThinBuffer {
fn data(&self) -> &[u8] {
&[]
}
}
impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext;
type TargetMachine = ();
type ModuleBuffer = ModuleBuffer;
type ThinData = ThinData;
type ThinData = ();
type ThinBuffer = ThinBuffer;
fn run_and_optimize_fat_lto(
@ -440,16 +452,16 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn run_thin_lto(
cgcx: &CodegenContext,
prof: &SelfProfilerRef,
dcx: DiagCtxtHandle<'_>,
_cgcx: &CodegenContext,
_prof: &SelfProfilerRef,
_dcx: DiagCtxtHandle<'_>,
// FIXME(bjorn3): Limit LTO exports to these symbols
_exported_symbols_for_lto: &[String],
each_linked_rlib_for_lto: &[PathBuf],
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
_each_linked_rlib_for_lto: &[PathBuf],
_modules: Vec<(String, Self::ThinBuffer)>,
_cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
back::lto::run_thin(cgcx, prof, dcx, each_linked_rlib_for_lto, modules, cached_modules)
unreachable!()
}
fn print_pass_timings(&self) {
@ -471,13 +483,13 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn optimize_thin(
cgcx: &CodegenContext,
_cgcx: &CodegenContext,
_prof: &SelfProfilerRef,
_shared_emitter: &SharedEmitter,
_tm_factory: TargetMachineFactoryFn<Self>,
thin: ThinModule<Self>,
_thin: ThinModule<Self>,
) -> ModuleCodegen<Self::Module> {
back::lto::optimize_thin_module(thin, cgcx)
unreachable!()
}
fn codegen(
@ -490,8 +502,8 @@ impl WriteBackendMethods for GccCodegenBackend {
back::write::codegen(cgcx, prof, shared_emitter, module, config)
}
fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
back::lto::prepare_thin(module)
fn prepare_thin(_module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
unreachable!()
}
fn serialize_module(_module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {

View file

@ -13,7 +13,7 @@ use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, ty};
use crate::common::TypeReflection;
use crate::context::CodegenCx;
use crate::context::{CodegenCx, new_array_type};
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -311,7 +311,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
len = 0;
}
self.context.new_array_type(None, ty, len)
new_array_type(self.context, None, ty, len)
}
}

View file

@ -11,4 +11,4 @@ tests/run-make/foreign-exceptions/
tests/run-make/glibc-staticlib-args/
tests/run-make/lto-smoke-c/
tests/run-make/return-non-c-like-enum/
tests/run-make/short-ice

View file

@ -0,0 +1 @@
tests/ui/simd/intrinsic/splat.rs

View file

@ -89,11 +89,13 @@ tests/ui/thir-print/offset_of.rs
tests/ui/iterators/rangefrom-overflow-debug.rs
tests/ui/iterators/rangefrom-overflow-overflow-checks.rs
tests/ui/iterators/iter-filter-count-debug-check.rs
tests/ui/eii/codegen_single_crate.rs
tests/ui/eii/codegen_cross_crate.rs
tests/ui/eii/linking/codegen_single_crate.rs
tests/ui/eii/linking/codegen_cross_crate.rs
tests/ui/eii/default/local_crate.rs
tests/ui/eii/multiple_impls.rs
tests/ui/eii/duplicate/multiple_impls.rs
tests/ui/eii/default/call_default.rs
tests/ui/eii/same-symbol.rs
tests/ui/eii/linking/same-symbol.rs
tests/ui/eii/privacy1.rs
tests/ui/eii/default/call_impl.rs
tests/ui/c-variadic/copy.rs
tests/ui/asm/x86_64/global_asm_escape.rs

View file

@ -0,0 +1,38 @@
// Compiler:
//
// Run-time:
// status: 0
// FIXME: Remove this test once rustc's `./tests/codegen/riscv-abi/call-llvm-intrinsics.rs`
// stops ignoring GCC backend.
#![feature(link_llvm_intrinsics)]
#![allow(internal_features)]
struct A;
impl Drop for A {
fn drop(&mut self) {
println!("A");
}
}
extern "C" {
#[link_name = "llvm.sqrt.f32"]
fn sqrt(x: f32) -> f32;
}
pub fn do_call() {
let _a = A;
unsafe {
// Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
// CHECK: store float 4.000000e+00, float* %{{.}}, align 4
// CHECK: call float @llvm.sqrt.f32(float %{{.}}
sqrt(4.0);
}
}
fn main() {
do_call();
}

View file

@ -0,0 +1,102 @@
// Compiler:
//
// Run-time:
// status: 0
// FIXME: Remove this test once <tests/run-make/simd-ffi/simd.rs> stops
// ignoring GCC backend.
#![allow(internal_features, non_camel_case_types)]
// we can compile to a variety of platforms, because we don't need
// cross-compiled standard libraries.
#![feature(no_core, auto_traits)]
#![no_core]
#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
#[derive(Copy)]
#[repr(simd)]
pub struct f32x4([f32; 4]);
extern "C" {
#[link_name = "llvm.sqrt.v4f32"]
fn vsqrt(x: f32x4) -> f32x4;
}
pub fn foo(x: f32x4) -> f32x4 {
unsafe { vsqrt(x) }
}
#[derive(Copy)]
#[repr(simd)]
pub struct i32x4([i32; 4]);
extern "C" {
// _mm_sll_epi32
#[cfg(all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"))]
#[link_name = "llvm.x86.sse2.psll.d"]
fn integer(a: i32x4, b: i32x4) -> i32x4;
// vmaxq_s32
#[cfg(target_arch = "arm")]
#[link_name = "llvm.arm.neon.vmaxs.v4i32"]
fn integer(a: i32x4, b: i32x4) -> i32x4;
// vmaxq_s32
#[cfg(target_arch = "aarch64")]
#[link_name = "llvm.aarch64.neon.maxs.v4i32"]
fn integer(a: i32x4, b: i32x4) -> i32x4;
// Use a generic LLVM intrinsic to do type checking on other platforms
#[cfg(not(any(
all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"),
target_arch = "arm",
target_arch = "aarch64"
)))]
#[link_name = "llvm.smax.v4i32"]
fn integer(a: i32x4, b: i32x4) -> i32x4;
}
pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
unsafe { integer(a, b) }
}
#[lang = "pointee_sized"]
pub trait PointeeSized {}
#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}
#[lang = "sized"]
pub trait Sized: MetaSized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for f32 {}
impl Copy for i32 {}
impl Copy for [f32; 4] {}
impl Copy for [i32; 4] {}
pub mod marker {
pub use Copy;
}
#[lang = "freeze"]
auto trait Freeze {}
#[macro_export]
#[rustc_builtin_macro]
macro_rules! Copy {
() => {};
}
#[macro_export]
#[rustc_builtin_macro]
macro_rules! derive {
() => {};
}
#[lang = "start"]
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
0
}
fn main() {}

View file

@ -0,0 +1,27 @@
// Compiler:
//
// Run-time:
// status: 0
use std::arch::asm;
fn exit_syscall(status: i32) -> ! {
#[cfg(target_arch = "x86_64")]
unsafe {
asm!(
"syscall",
in("rax") 60,
in("rdi") status,
options(noreturn)
);
}
#[cfg(not(target_arch = "x86_64"))]
std::process::exit(status);
}
fn main() {
// Used to crash with rustc_codegen_gcc.
exit_syscall(0);
std::process::exit(1);
}

View file

@ -12,7 +12,7 @@ def run_command(command, cwd=None):
sys.exit(1)
def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None):
def clone_repository(repo_name, path, repo_url, sub_paths):
if os.path.exists(path):
while True:
choice = input("There is already a `{}` folder, do you want to update it? [y/N]".format(path))
@ -21,14 +21,11 @@ def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None)
return
elif choice.lower() == "y":
print("Updating repository...")
run_command(["git", "pull", "origin", branch], cwd=path)
run_command(["git", "pull", "origin", "main"], cwd=path)
return
else:
print("Didn't understand answer...")
print("Cloning {} repository...".format(repo_name))
if sub_paths is None:
run_command(["git", "clone", repo_url, "--depth", "1", path])
else:
run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path])
run_command(["git", "sparse-checkout", "init"], cwd=path)
run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path)
@ -45,31 +42,22 @@ def convert_to_string(content):
return content
def extract_intrinsics_from_llvm(llvm_path, intrinsics):
command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"]
def extract_intrinsics_from_llvm(llvm_path):
intrinsics = {}
command = ["llvm-tblgen", "llvm/IR/Intrinsics.td", "--dump-json"]
cwd = os.path.join(llvm_path, "llvm/include")
print("=> Running command `{}` from `{}`".format(command, cwd))
p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE)
output, err = p.communicate()
lines = convert_to_string(output).splitlines()
pos = 0
while pos < len(lines):
line = lines[pos]
if not line.startswith("def "):
pos += 1
content = json.loads(convert_to_string(output))
for intrinsic in content:
data = content[intrinsic]
if not isinstance(data, dict):
continue
current_arch = data.get("TargetPrefix")
builtin_name = data.get("ClangBuiltinName")
if current_arch is None or current_arch == "" or builtin_name is None:
continue
intrinsic = line.split(" ")[1].strip()
content = line
while pos < len(lines):
line = lines[pos].split(" // ")[0].strip()
content += line
pos += 1
if line == "}":
break
entries = re.findall('string ClangBuiltinName = "(\\w+)";', content)
current_arch = re.findall('string TargetPrefix = "(\\w+)";', content)
if len(entries) == 1 and len(current_arch) == 1:
current_arch = current_arch[0]
intrinsic = intrinsic.split("_")
if len(intrinsic) < 2 or intrinsic[0] != "int":
continue
@ -77,89 +65,13 @@ def extract_intrinsics_from_llvm(llvm_path, intrinsics):
intrinsic = ".".join(intrinsic)
if current_arch not in intrinsics:
intrinsics[current_arch] = []
append_intrinsic(intrinsics[current_arch], intrinsic, entries[0])
append_intrinsic(intrinsics[current_arch], intrinsic, builtin_name)
return intrinsics
def append_translation(json_data, p, array):
it = json_data["index"][p]
content = it["docs"].split('`')
if len(content) != 5:
return
append_intrinsic(array, content[1], content[3])
def extract_intrinsics_from_llvmint(llvmint, intrinsics):
archs = [
"AMDGPU",
"aarch64",
"arm",
"cuda",
"hexagon",
"mips",
"nvvm",
"ppc",
"ptx",
"x86",
"xcore",
]
json_file = os.path.join(llvmint, "target/doc/llvmint.json")
# We need to regenerate the documentation!
run_command(
["cargo", "rustdoc", "--", "-Zunstable-options", "--output-format", "json"],
cwd=llvmint,
)
with open(json_file, "r", encoding="utf8") as f:
json_data = json.loads(f.read())
for p in json_data["paths"]:
it = json_data["paths"][p]
if it["crate_id"] != 0:
# This is from an external crate.
continue
if it["kind"] != "function":
# We're only looking for functions.
continue
# if len(it["path"]) == 2:
# # This is a "general" intrinsic, not bound to a specific arch.
# append_translation(json_data, p, general)
# continue
if len(it["path"]) != 3 or it["path"][1] not in archs:
continue
arch = it["path"][1]
if arch not in intrinsics:
intrinsics[arch] = []
append_translation(json_data, p, intrinsics[arch])
def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics):
for arch in from_intrinsics:
if arch not in intrinsics:
intrinsics[arch] = []
for entry in from_intrinsics[arch]:
if entry[0] in all_intrinsics:
if all_intrinsics[entry[0]] == entry[1]:
# This is a "full" duplicate, both the LLVM instruction and the GCC
# translation are the same.
continue
intrinsics[arch].append((entry[0], entry[1], True))
else:
intrinsics[arch].append((entry[0], entry[1], False))
all_intrinsics[entry[0]] = entry[1]
def update_intrinsics(llvm_path, llvmint, llvmint2):
intrinsics_llvm = {}
intrinsics_llvmint = {}
all_intrinsics = {}
extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm)
extract_intrinsics_from_llvmint(llvmint, intrinsics_llvmint)
extract_intrinsics_from_llvmint(llvmint2, intrinsics_llvmint)
intrinsics = {}
# We give priority to translations from LLVM over the ones from llvmint.
fill_intrinsics(intrinsics, intrinsics_llvm, all_intrinsics)
fill_intrinsics(intrinsics, intrinsics_llvmint, all_intrinsics)
def update_intrinsics(llvm_path):
intrinsics = extract_intrinsics_from_llvm(llvm_path)
archs = [arch for arch in intrinsics]
archs.sort()
@ -173,33 +85,41 @@ def update_intrinsics(llvm_path, llvmint, llvmint2):
# Since all intrinsic names start with "llvm.", we skip that prefix.
print("Updating content of `{}`...".format(output_file))
with open(output_file, "w", encoding="utf8") as out:
out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n")
out.write("// DO NOT EDIT IT!\n")
out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n")
out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n")
out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n')
out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n')
out.write("match arch {\n")
out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`
// DO NOT EDIT IT!
/// Translate a given LLVM intrinsic name to an equivalent GCC one.
fn map_arch_intrinsic(full_name:&str)-> &'static str {
let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };
let Some((arch, name)) = name.split_once('.') else { unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) };
let old_arch_res = old_archs(arch, name);
if let ArchCheckResult::Ok(res) = old_arch_res {
return res;
}
match arch {""")
for arch in archs:
if len(intrinsics[arch]) == 0:
continue
attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else ""
out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch))
intrinsics[arch].sort(key=lambda x: (x[0], x[2]))
intrinsics[arch].sort(key=lambda x: (x[0], x[1]))
out.write(' // {}\n'.format(arch))
for entry in intrinsics[arch]:
llvm_name = entry[0].removeprefix("llvm.");
llvm_name = llvm_name.removeprefix(arch);
llvm_name = llvm_name.removeprefix(".");
if entry[2] is True: # if it is a duplicate
out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(llvm_name, entry[1]))
elif "_round_mask" in entry[1]:
if "_round_mask" in entry[1]:
out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1]))
else:
out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1]))
out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n')
out.write("}} }} {}(name,full_name) }}\n,".format(arch))
out.write(' _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n')
out.write(""" _ => {
match old_arch_res {
ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"),
ArchCheckResult::Ok(_) => unreachable!(),
}
}""")
out.write("}\n}")
subprocess.call(["rustfmt", output_file])
print("Done!")
@ -210,35 +130,21 @@ def main():
os.path.dirname(os.path.abspath(__file__)),
"llvm-project",
)
llvmint_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"llvmint",
)
llvmint2_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"llvmint-2",
)
# First, we clone the LLVM repository if it's not already here.
clone_repository(
"llvm-project",
llvm_path,
"https://github.com/llvm/llvm-project",
branch="main",
sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"],
["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"],
)
clone_repository(
"llvmint",
llvmint_path,
"https://github.com/GuillaumeGomez/llvmint",
)
clone_repository(
"llvmint2",
llvmint2_path,
"https://github.com/antoyo/llvmint",
)
update_intrinsics(llvm_path, llvmint_path, llvmint2_path)
update_intrinsics(llvm_path)
# llvm-tblgen can be built with:
#
# mkdir llvm-tblgen-build && cd llvm-tblgen-build
# cmake -G Ninja -DLLVM_ENABLE_PROJECTS="llvm" -DCMAKE_BUILD_TYPE=Release ../llvm
# ninja llvm-tblgen
if __name__ == "__main__":
sys.exit(main())

View file

@ -31,7 +31,6 @@ rustc_llvm = { path = "../rustc_llvm" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_middle = { path = "../rustc_middle" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_sanitizers = { path = "../rustc_sanitizers" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }

View file

@ -387,6 +387,27 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
let pair = self.insert_value(pair, high, 1);
pair
}
// FIXME move into the branch below when LLVM 22 is the lowest version we support.
sym::carryless_mul if crate::llvm_util::get_version() >= (22, 0, 0) => {
let ty = args[0].layout.ty;
if !ty.is_integral() {
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
span,
name,
ty,
});
return Ok(());
}
let (size, _) = ty.int_size_and_signed(self.tcx);
let width = size.bits();
let llty = self.type_ix(width);
let lhs = args[0].immediate();
let rhs = args[1].immediate();
self.call_intrinsic("llvm.clmul", &[llty], &[lhs, rhs])
}
sym::ctlz
| sym::ctlz_nonzero
| sym::cttz
@ -2784,6 +2805,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
| sym::simd_ctlz
| sym::simd_ctpop
| sym::simd_cttz
| sym::simd_carryless_mul
| sym::simd_funnel_shl
| sym::simd_funnel_shr
) {
@ -2808,6 +2830,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
sym::simd_cttz => "llvm.cttz",
sym::simd_funnel_shl => "llvm.fshl",
sym::simd_funnel_shr => "llvm.fshr",
sym::simd_carryless_mul => "llvm.clmul",
_ => unreachable!(),
};
let int_size = in_elem.int_size_and_signed(bx.tcx()).0.bits();
@ -2833,6 +2856,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
&[vec_ty],
&[args[0].immediate(), args[1].immediate(), args[2].immediate()],
)),
sym::simd_carryless_mul => {
if crate::llvm_util::get_version() >= (22, 0, 0) {
Ok(bx.call_intrinsic(
llvm_intrinsic,
&[vec_ty],
&[args[0].immediate(), args[1].immediate()],
))
} else {
span_bug!(span, "`simd_carryless_mul` needs LLVM 22 or higher");
}
}
_ => unreachable!(),
};
}

View file

@ -354,7 +354,14 @@ impl CodegenBackend for LlvmCodegenBackend {
}
fn replaced_intrinsics(&self) -> Vec<Symbol> {
vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add]
let mut will_not_use_fallback =
vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add];
if llvm_util::get_version() >= (22, 0, 0) {
will_not_use_fallback.push(sym::carryless_mul);
}
will_not_use_fallback
}
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {

View file

@ -710,7 +710,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandRef { val: operand.val, layout, move_annotation: None }
}
mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
mir::Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
}
}

View file

@ -80,6 +80,11 @@ pub trait CodegenBackend {
vec![]
}
/// Is ThinLTO supported by this backend?
fn thin_lto_supported(&self) -> bool {
true
}
/// Value printed by `--print=backend-has-zstd`.
///
/// Used by compiletest to determine whether tests involving zstd compression

View file

@ -7,9 +7,10 @@ use std::ops::Deref;
use rustc_data_structures::assert_matches;
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_hir::{self as hir, LangItem, find_attr};
use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::visit::Visitor;
@ -215,7 +216,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
return;
}
if !tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
if !find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcDoNotConstCheck) {
self.visit_body(body);
}
@ -645,8 +646,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::Cast(_, _, _) => {}
Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(op, operand) => {
let ty = operand.ty(self.body, self.tcx);
match op {
@ -815,6 +814,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
});
}
if self.tcx.fn_sig(callee).skip_binder().c_variadic() {
self.check_op(ops::FnCallCVariadic)
}
// At this point, we are calling a function, `callee`, whose `DefId` is known...
// `begin_panic` and `panic_display` functions accept generic
@ -845,13 +848,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}
// This can be called on stable via the `vec!` macro.
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
self.check_op(ops::HeapAllocation);
// Allow this call, skip all the checks below.
return;
}
// Intrinsics are language primitives, not regular calls, so treat them separately.
if let Some(intrinsic) = tcx.intrinsic(callee) {
if !tcx.is_const_fn(callee) {

View file

@ -75,6 +75,27 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
}
}
/// A c-variadic function call.
#[derive(Debug)]
pub(crate) struct FnCallCVariadic;
impl<'tcx> NonConstOp<'tcx> for FnCallCVariadic {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable {
gate: sym::const_c_variadic,
gate_already_checked: false,
safe_to_expose_on_stable: false,
is_function_call: true,
}
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.tcx.sess.create_feature_err(
errors::NonConstCVariadicCall { span, kind: ccx.const_kind() },
sym::const_c_variadic,
)
}
}
/// A call to a function that is in a trait, or has trait bounds that make it conditionally-const.
#[derive(Debug)]
pub(crate) struct ConditionallyConstCall<'tcx> {
@ -540,18 +561,6 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
}
}
#[derive(Debug)]
pub(crate) struct HeapAllocation;
impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.dcx().create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0010),
})
}
}
#[derive(Debug)]
pub(crate) struct InlineAsm;
impl<'tcx> NonConstOp<'tcx> for InlineAsm {

View file

@ -1,3 +1,5 @@
use rustc_hir::attrs::AttributeKind;
use rustc_hir::find_attr;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
@ -34,7 +36,7 @@ pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
return;
}
if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) {
if find_attr!(tcx.get_all_attrs(body.source.def_id()), AttributeKind::RustcDoNotConstCheck) {
return;
}

View file

@ -237,8 +237,7 @@ where
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_, operand)
| Rvalue::Cast(_, operand, _)
| Rvalue::ShallowInitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
| Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
Rvalue::BinaryOp(_, box (lhs, rhs)) => {
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)

View file

@ -192,7 +192,6 @@ where
}
mir::Rvalue::Cast(..)
| mir::Rvalue::ShallowInitBox(..)
| mir::Rvalue::Use(..)
| mir::Rvalue::CopyForDeref(..)
| mir::Rvalue::ThreadLocalRef(..)

View file

@ -6,10 +6,11 @@ use rustc_abi::{Align, Size};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_errors::msg;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem, find_attr};
use rustc_middle::mir::AssertMessage;
use rustc_middle::mir::interpret::{Pointer, ReportedErrorInfo};
use rustc_middle::mir::interpret::ReportedErrorInfo;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout, ValidityRequirement};
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -22,7 +23,7 @@ use super::error::*;
use crate::errors::{LongRunning, LongRunningWarn};
use crate::interpret::{
self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar,
GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar,
compile_time_machine, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub,
throw_ub_custom, throw_unsup, throw_unsup_format,
};
@ -235,7 +236,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
if self.tcx.is_lang_item(def_id, LangItem::PanicDisplay)
|| self.tcx.is_lang_item(def_id, LangItem::BeginPanic)
{
let args = self.copy_fn_args(args);
let args = Self::copy_fn_args(args);
// &str or &&str
assert!(args.len() == 1);
@ -440,7 +441,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
// sensitive check here. But we can at least rule out functions that are not const at
// all. That said, we have to allow calling functions inside a `const trait`. These
// *are* const-checked!
if !ecx.tcx.is_const_fn(def) || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check) {
if !ecx.tcx.is_const_fn(def)
|| find_attr!(ecx.tcx.get_all_attrs(def), AttributeKind::RustcDoNotConstCheck)
{
// We certainly do *not* want to actually call the fn
// though, so be sure we return here.
throw_unsup_format!("calling non-const function `{}`", instance)

View file

@ -289,31 +289,6 @@ pub(crate) struct UnallowedOpInConstContext {
pub msg: String,
}
#[derive(Diagnostic)]
#[diag(r#"allocations are not allowed in {$kind ->
[const] constant
[static] static
[const_fn] constant function
*[other] {""}
}s"#, code = E0010)]
pub(crate) struct UnallowedHeapAllocations {
#[primary_span]
#[label(
r#"allocation not allowed in {$kind ->
[const] constant
[static] static
[const_fn] constant function
*[other] {""}
}s"#
)]
pub span: Span,
pub kind: ConstContext,
#[note(
"the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created"
)]
pub teach: bool,
}
#[derive(Diagnostic)]
#[diag(r#"inline assembly is not allowed in {$kind ->
[const] constant
@ -531,6 +506,19 @@ pub struct NonConstClosure {
pub non_or_conditionally: &'static str,
}
#[derive(Diagnostic)]
#[diag(r#"calling const c-variadic functions is unstable in {$kind ->
[const] constant
[static] static
[const_fn] constant function
*[other] {""}
}s"#, code = E0015)]
pub struct NonConstCVariadicCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
#[derive(Subdiagnostic)]
pub enum NonConstClosureNote {
#[note("function defined here, but it is not `const`")]
@ -757,11 +745,13 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
WriteToReadOnly(_) => msg!("writing to {$allocation} which is read-only"),
DerefFunctionPointer(_) => msg!("accessing {$allocation} which contains a function"),
DerefVTablePointer(_) => msg!("accessing {$allocation} which contains a vtable"),
DerefVaListPointer(_) => msg!("accessing {$allocation} which contains a variable argument list"),
DerefTypeIdPointer(_) => msg!("accessing {$allocation} which contains a `TypeId`"),
InvalidBool(_) => msg!("interpreting an invalid 8-bit value as a bool: 0x{$value}"),
InvalidChar(_) => msg!("interpreting an invalid 32-bit value as a char: 0x{$value}"),
InvalidTag(_) => msg!("enum value has invalid tag: {$tag}"),
InvalidFunctionPointer(_) => msg!("using {$pointer} as function pointer but it does not point to a function"),
InvalidVaListPointer(_) => msg!("using {$pointer} as variable argument list pointer but it does not point to a variable argument list"),
InvalidVTablePointer(_) => msg!("using {$pointer} as vtable pointer but it does not point to a vtable"),
InvalidVTableTrait { .. } => msg!("using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected"),
InvalidStr(_) => msg!("this string is not valid UTF-8: {$err}"),
@ -776,6 +766,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
}
AbiMismatchArgument { .. } => msg!("calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty}"),
AbiMismatchReturn { .. } => msg!("calling a function with return type {$callee_ty} passing return place of type {$caller_ty}"),
VaArgOutOfBounds => "more C-variadic arguments read than were passed".into(),
CVariadicMismatch { ..} => "calling a function where the caller and callee disagree on whether the function is C-variadic".into(),
CVariadicFixedCountMismatch { .. } => msg!("calling a C-variadic function with {$caller} fixed arguments, but the function expects {$callee}"),
}
}
@ -800,6 +793,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
| InvalidMeta(InvalidMetaKind::TooBig)
| InvalidUninitBytes(None)
| DeadLocal
| VaArgOutOfBounds
| UninhabitedEnumVariantWritten(_)
| UninhabitedEnumVariantRead(_) => {}
@ -820,7 +814,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
diag.arg("len", len);
diag.arg("index", index);
}
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
UnterminatedCString(ptr)
| InvalidFunctionPointer(ptr)
| InvalidVaListPointer(ptr)
| InvalidVTablePointer(ptr) => {
diag.arg("pointer", ptr);
}
InvalidVTableTrait { expected_dyn_type, vtable_dyn_type } => {
@ -874,6 +871,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
WriteToReadOnly(alloc)
| DerefFunctionPointer(alloc)
| DerefVTablePointer(alloc)
| DerefVaListPointer(alloc)
| DerefTypeIdPointer(alloc) => {
diag.arg("allocation", alloc);
}
@ -910,6 +908,14 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
diag.arg("caller_ty", caller_ty);
diag.arg("callee_ty", callee_ty);
}
CVariadicMismatch { caller_is_c_variadic, callee_is_c_variadic } => {
diag.arg("caller_is_c_variadic", caller_is_c_variadic);
diag.arg("callee_is_c_variadic", callee_is_c_variadic);
}
CVariadicFixedCountMismatch { caller, callee } => {
diag.arg("caller", caller);
diag.arg("callee", callee);
}
}
}
}

View file

@ -7,19 +7,20 @@ use either::{Left, Right};
use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx};
use rustc_data_structures::assert_matches;
use rustc_errors::msg;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::DefId;
use rustc_hir::find_attr;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::sym;
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use tracing::field::Empty;
use tracing::{info, instrument, trace};
use super::{
CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy,
Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, StackPopInfo, interp_ok,
throw_ub, throw_ub_custom, throw_unsup_format,
Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, interp_ok, throw_ub,
throw_ub_custom,
};
use crate::enter_trace_span;
use crate::interpret::EnteredTraceSpan;
@ -42,25 +43,22 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
FnArg::InPlace(mplace) => &mplace.layout,
}
}
}
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
/// original memory occurs.
pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
match arg {
pub fn copy_fn_arg(&self) -> OpTy<'tcx, Prov> {
match self {
FnArg::Copy(op) => op.clone(),
FnArg::InPlace(mplace) => mplace.clone().into(),
}
}
}
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Make a copy of the given fn_args. Any `InPlace` are degenerated to copies, no protection of the
/// original memory occurs.
pub fn copy_fn_args(
&self,
args: &[FnArg<'tcx, M::Provenance>],
) -> Vec<OpTy<'tcx, M::Provenance>> {
args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
pub fn copy_fn_args(args: &[FnArg<'tcx, M::Provenance>]) -> Vec<OpTy<'tcx, M::Provenance>> {
args.iter().map(|fn_arg| fn_arg.copy_fn_arg()).collect()
}
/// Helper function for argument untupling.
@ -145,7 +143,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Check if the inner type is one of the NPO-guaranteed ones.
// For that we first unpeel transparent *structs* (but not unions).
let is_npo = |def: AdtDef<'tcx>| {
self.tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed)
find_attr!(
self.tcx.get_all_attrs(def.did()),
AttributeKind::RustcNonnullOptimizationGuaranteed
)
};
let inner = self.unfold_transparent(inner, /* may_unfold */ |def| {
// Stop at NPO types so that we don't miss that attribute in the check below!
@ -315,7 +316,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// We work with a copy of the argument for now; if this is in-place argument passing, we
// will later protect the source it comes from. This means the callee cannot observe if we
// did in-place of by-copy argument passing, except for pointer equality tests.
let caller_arg_copy = self.copy_fn_arg(caller_arg);
let caller_arg_copy = caller_arg.copy_fn_arg();
if !already_live {
let local = callee_arg.as_local().unwrap();
let meta = caller_arg_copy.meta();
@ -354,13 +355,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
) -> InterpResult<'tcx> {
let _trace = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty);
// Compute callee information.
// FIXME: for variadic support, do we have to somehow determine callee's extra_args?
let callee_fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
if callee_fn_abi.c_variadic || caller_fn_abi.c_variadic {
throw_unsup_format!("calling a c-variadic function is not supported");
}
// The first order of business is to figure out the callee signature.
// However, that requires the list of variadic arguments.
// We use the *caller* information to determine where to split the list of arguments,
// and then later check that the callee indeed has the same number of fixed arguments.
let extra_tys = if caller_fn_abi.c_variadic {
let fixed_count = usize::try_from(caller_fn_abi.fixed_count).unwrap();
let extra_tys = args[fixed_count..].iter().map(|arg| arg.layout().ty);
self.tcx.mk_type_list_from_iter(extra_tys)
} else {
ty::List::empty()
};
let callee_fn_abi = self.fn_abi_of_instance(instance, extra_tys)?;
if caller_fn_abi.conv != callee_fn_abi.conv {
throw_ub_custom!(
@ -372,6 +378,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
)
}
if caller_fn_abi.c_variadic != callee_fn_abi.c_variadic {
throw_ub!(CVariadicMismatch {
caller_is_c_variadic: caller_fn_abi.c_variadic,
callee_is_c_variadic: callee_fn_abi.c_variadic,
});
}
if caller_fn_abi.c_variadic && caller_fn_abi.fixed_count != callee_fn_abi.fixed_count {
throw_ub!(CVariadicFixedCountMismatch {
caller: caller_fn_abi.fixed_count,
callee: callee_fn_abi.fixed_count,
});
}
// Check that all target features required by the callee (i.e., from
// the attribute `#[target_feature(enable = ...)]`) are enabled at
// compile time.
@ -444,6 +463,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// `pass_argument` would be the loop body. It takes care to
// not advance `caller_iter` for ignored arguments.
let mut callee_args_abis = callee_fn_abi.args.iter().enumerate();
// Determine whether there is a special VaList argument. This is always the
// last argument, and since arguments start at index 1 that's `arg_count`.
let va_list_arg =
callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count));
for local in body.args_iter() {
// Construct the destination place for this argument. At this point all
// locals are still dead, so we cannot construct a `PlaceTy`.
@ -452,7 +475,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// type, but the result gets cached so this avoids calling the instantiation
// query *again* the next time this local is accessed.
let ty = self.layout_of_local(self.frame(), local, None)?.ty;
if Some(local) == body.spread_arg {
if Some(local) == va_list_arg {
// This is the last callee-side argument of a variadic function.
// This argument is a VaList holding the remaining caller-side arguments.
self.storage_live(local)?;
let place = self.eval_place(dest)?;
let mplace = self.force_allocation(&place)?;
// Consume the remaining arguments by putting them into the variable argument
// list.
let varargs = self.allocate_varargs(&mut caller_args, &mut callee_args_abis)?;
// When the frame is dropped, these variable arguments are deallocated.
self.frame_mut().va_list = varargs.clone();
let key = self.va_list_ptr(varargs.into());
// Zero the VaList, so it is fully initialized.
self.write_bytes_ptr(
mplace.ptr(),
(0..mplace.layout.size.bytes()).map(|_| 0u8),
)?;
// Store the "key" pointer in the right field.
let key_mplace = self.va_list_key_field(&mplace)?;
self.write_pointer(key, &key_mplace)?;
} else if Some(local) == body.spread_arg {
// Make the local live once, then fill in the value field by field.
self.storage_live(local)?;
// Must be a tuple
@ -491,7 +538,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
if instance.def.requires_caller_location(*self.tcx) {
callee_args_abis.next().unwrap();
}
// Now we should have no more caller args or callee arg ABIs
// Now we should have no more caller args or callee arg ABIs.
assert!(
callee_args_abis.next().is_none(),
"mismatch between callee ABI and callee body arguments"
@ -566,7 +613,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
if let Some(fallback) = M::call_intrinsic(
self,
instance,
&self.copy_fn_args(args),
&Self::copy_fn_args(args),
destination,
target,
unwind,
@ -653,7 +700,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// An `InPlace` does nothing here, we keep the original receiver intact. We can't
// really pass the argument in-place anyway, and we are constructing a new
// `Immediate` receiver.
let mut receiver = self.copy_fn_arg(&args[0]);
let mut receiver = args[0].copy_fn_arg();
let receiver_place = loop {
match receiver.layout.ty.kind() {
ty::Ref(..) | ty::RawPtr(..) => {
@ -774,41 +821,50 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
with_caller_location: bool,
) -> InterpResult<'tcx> {
trace!("init_fn_tail_call: {:#?}", fn_val);
// This is the "canonical" implementation of tails calls,
// a pop of the current stack frame, followed by a normal call
// which pushes a new stack frame, with the return address from
// the popped stack frame.
//
// Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`,
// as the latter "executes" the goto to the return block, but we don't want to,
// Note that we cannot use `return_from_current_stack_frame`,
// as that "executes" the goto to the return block, but we don't want to,
// only the tail called function should return to the current return block.
let StackPopInfo { return_action, return_cont, return_place } =
self.pop_stack_frame_raw(false, |_this, _return_place| {
// This function's return value is just discarded, the tail-callee will fill in the return place instead.
interp_ok(())
})?;
assert_eq!(return_action, ReturnAction::Normal);
// Take the "stack pop cleanup" info, and use that to initiate the next call.
let ReturnContinuation::Goto { ret, unwind } = return_cont else {
bug!("can't tailcall as root");
// The arguments need to all be copied since the current stack frame will be removed
// before the callee even starts executing.
// FIXME(explicit_tail_calls,#144855): does this match what codegen does?
let args = args.iter().map(|fn_arg| FnArg::Copy(fn_arg.copy_fn_arg())).collect::<Vec<_>>();
// Remove the frame from the stack.
let frame = self.pop_stack_frame_raw()?;
// Remember where this frame would have returned to.
let ReturnContinuation::Goto { ret, unwind } = frame.return_cont() else {
bug!("can't tailcall as root of the stack");
};
// There's no return value to deal with! Instead, we forward the old return place
// to the new function.
// FIXME(explicit_tail_calls):
// we should check if both caller&callee can/n't unwind,
// see <https://github.com/rust-lang/rust/pull/113128#issuecomment-1614979803>
// Now push the new stack frame.
self.init_fn_call(
fn_val,
(caller_abi, caller_fn_abi),
args,
&*args,
with_caller_location,
&return_place,
frame.return_place(),
ret,
unwind,
)
)?;
// Finally, clear the local variables. Has to be done after pushing to support
// non-scalar arguments.
// FIXME(explicit_tail_calls,#144855): revisit this once codegen supports indirect
// arguments, to ensure the semantics are compatible.
let return_action = self.cleanup_stack_frame(/* unwinding */ false, frame)?;
assert_eq!(return_action, ReturnAction::Normal);
interp_ok(())
}
pub(super) fn init_drop_in_place_call(
@ -903,14 +959,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// local's value out.
let return_op =
self.local_to_op(mir::RETURN_PLACE, None).expect("return place should always be live");
// Do the actual pop + copy.
let stack_pop_info = self.pop_stack_frame_raw(unwinding, |this, return_place| {
this.copy_op_allow_transmute(&return_op, return_place)?;
trace!("return value: {:?}", this.dump_place(return_place));
interp_ok(())
})?;
match stack_pop_info.return_action {
// Remove the frame from the stack.
let frame = self.pop_stack_frame_raw()?;
// Copy the return value and remember the return continuation.
if !unwinding {
self.copy_op_allow_transmute(&return_op, frame.return_place())?;
trace!("return value: {:?}", self.dump_place(frame.return_place()));
}
let return_cont = frame.return_cont();
// Finish popping the stack frame.
let return_action = self.cleanup_stack_frame(unwinding, frame)?;
// Jump to the next block.
match return_action {
ReturnAction::Normal => {}
ReturnAction::NoJump => {
// The hook already did everything.
@ -928,7 +988,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Normal return, figure out where to jump.
if unwinding {
// Follow the unwind edge.
match stack_pop_info.return_cont {
match return_cont {
ReturnContinuation::Goto { unwind, .. } => {
// This must be the very last thing that happens, since it can in fact push a new stack frame.
self.unwind_to_block(unwind)
@ -939,7 +999,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
} else {
// Follow the normal return edge.
match stack_pop_info.return_cont {
match return_cont {
ReturnContinuation::Goto { ret, .. } => self.return_to_block(ret),
ReturnContinuation::Stop { .. } => {
assert!(

View file

@ -23,8 +23,8 @@ use super::memory::MemoryKind;
use super::util::ensure_monomorphic_enough;
use super::{
AllocId, CheckInAllocMsg, ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Pointer,
PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok, throw_inval,
throw_ub_custom, throw_ub_format,
PointerArithmetic, Projectable, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok,
throw_inval, throw_ub, throw_ub_custom, throw_ub_format, throw_unsup_format,
};
use crate::interpret::Writeable;
@ -750,6 +750,57 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.float_muladd_intrinsic::<Quad>(args, dest, MulAddType::Nondeterministic)?
}
sym::va_copy => {
let va_list = self.deref_pointer(&args[0])?;
let key_mplace = self.va_list_key_field(&va_list)?;
let key = self.read_pointer(&key_mplace)?;
let varargs = self.get_ptr_va_list(key)?;
let copy_key = self.va_list_ptr(varargs.clone());
let copy_key_mplace = self.va_list_key_field(dest)?;
self.write_pointer(copy_key, &copy_key_mplace)?;
}
sym::va_end => {
let va_list = self.deref_pointer(&args[0])?;
let key_mplace = self.va_list_key_field(&va_list)?;
let key = self.read_pointer(&key_mplace)?;
self.deallocate_va_list(key)?;
}
sym::va_arg => {
let va_list = self.deref_pointer(&args[0])?;
let key_mplace = self.va_list_key_field(&va_list)?;
let key = self.read_pointer(&key_mplace)?;
// Invalidate the old list and get its content. We'll recreate the
// new list (one element shorter) below.
let mut varargs = self.deallocate_va_list(key)?;
let Some(arg_mplace) = varargs.pop_front() else {
throw_ub!(VaArgOutOfBounds);
};
// NOTE: In C some type conversions are allowed (e.g. casting between signed and
// unsigned integers). For now we require c-variadic arguments to be read with the
// exact type they were passed as.
if arg_mplace.layout.ty != dest.layout.ty {
throw_unsup_format!(
"va_arg type mismatch: requested `{}`, but next argument is `{}`",
dest.layout.ty,
arg_mplace.layout.ty
);
}
// Copy the argument.
self.copy_op(&arg_mplace, dest)?;
// Update the VaList pointer.
let new_key = self.va_list_ptr(varargs);
self.write_pointer(new_key, &key_mplace)?;
}
// Unsupported intrinsic: skip the return_to_block below.
_ => return interp_ok(false),
}
@ -1230,4 +1281,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
interp_ok(Some(ImmTy::from_scalar(val, cast_to)))
}
}
/// Get the MPlace of the key from the place storing the VaList.
pub(super) fn va_list_key_field<P: Projectable<'tcx, M::Provenance>>(
&self,
va_list: &P,
) -> InterpResult<'tcx, P> {
// The struct wrapped by VaList.
let va_list_inner = self.project_field(va_list, FieldIdx::ZERO)?;
// Find the first pointer field in this struct. The exact index is target-specific.
let ty::Adt(adt, substs) = va_list_inner.layout().ty.kind() else {
bug!("invalid VaListImpl layout");
};
for (i, field) in adt.non_enum_variant().fields.iter().enumerate() {
if field.ty(*self.tcx, substs).is_raw_ptr() {
return self.project_field(&va_list_inner, FieldIdx::from_usize(i));
}
}
bug!("no VaListImpl field is a pointer");
}
}

View file

@ -23,8 +23,8 @@ use tracing::{debug, instrument, trace};
use super::{
AllocBytes, AllocId, AllocInit, AllocMap, AllocRange, Allocation, CheckAlignMsg,
CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak,
Misalignment, Pointer, PointerArithmetic, Provenance, Scalar, alloc_range, err_ub,
CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine,
MayLeak, Misalignment, Pointer, PointerArithmetic, Provenance, Scalar, alloc_range, err_ub,
err_ub_custom, interp_ok, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format,
};
use crate::const_eval::ConstEvalErrKind;
@ -67,6 +67,8 @@ pub enum AllocKind {
LiveData,
/// A function allocation (that fn ptrs point to).
Function,
/// A variable argument list allocation (used by c-variadic functions).
VaList,
/// A vtable allocation.
VTable,
/// A TypeId allocation.
@ -126,6 +128,9 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
/// Map for "extra" function pointers.
extra_fn_ptr_map: FxIndexMap<AllocId, M::ExtraFnVal>,
/// Map storing variable argument lists.
va_list_map: FxIndexMap<AllocId, VecDeque<MPlaceTy<'tcx, M::Provenance>>>,
/// To be able to compare pointers with null, and to check alignment for accesses
/// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
/// that do not exist any more.
@ -161,6 +166,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
Memory {
alloc_map: M::MemoryMap::default(),
extra_fn_ptr_map: FxIndexMap::default(),
va_list_map: FxIndexMap::default(),
dead_alloc_map: FxIndexMap::default(),
validation_in_progress: Cell::new(false),
}
@ -199,9 +205,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return M::extern_static_pointer(self, def_id);
}
None => {
let is_fn_ptr = self.memory.extra_fn_ptr_map.contains_key(&alloc_id);
let is_va_list = self.memory.va_list_map.contains_key(&alloc_id);
assert!(
self.memory.extra_fn_ptr_map.contains_key(&alloc_id),
"{alloc_id:?} is neither global nor a function pointer"
is_fn_ptr || is_va_list,
"{alloc_id:?} is neither global, va_list nor a function pointer"
);
}
_ => {}
@ -229,6 +237,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.global_root_pointer(Pointer::from(id)).unwrap()
}
/// Insert a new variable argument list in the global map of variable argument lists.
pub fn va_list_ptr(
&mut self,
varargs: VecDeque<MPlaceTy<'tcx, M::Provenance>>,
) -> Pointer<M::Provenance> {
let id = self.tcx.reserve_alloc_id();
let old = self.memory.va_list_map.insert(id, varargs);
assert!(old.is_none());
// Variable argument lists are global allocations, so make sure we get the right root
// pointer. We know this is not an `extern static` so this cannot fail.
self.global_root_pointer(Pointer::from(id)).unwrap()
}
pub fn allocate_ptr(
&mut self,
size: Size,
@ -956,6 +977,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn is_alloc_live(&self, id: AllocId) -> bool {
self.memory.alloc_map.contains_key_ref(&id)
|| self.memory.extra_fn_ptr_map.contains_key(&id)
|| self.memory.va_list_map.contains_key(&id)
// We check `tcx` last as that has to acquire a lock in `many-seeds` mode.
// This also matches the order in `get_alloc_info`.
|| self.tcx.try_get_global_alloc(id).is_some()
@ -995,6 +1017,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not);
}
// # Variable argument lists
if self.memory.va_list_map.contains_key(&id) {
return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::VaList, Mutability::Not);
}
// # Global allocations
if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
// NOTE: `static` alignment from attributes has already been applied to the allocation.
@ -1069,6 +1096,43 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
.into()
}
pub fn get_ptr_va_list(
&self,
ptr: Pointer<Option<M::Provenance>>,
) -> InterpResult<'tcx, &VecDeque<MPlaceTy<'tcx, M::Provenance>>> {
trace!("get_ptr_va_list({:?})", ptr);
let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
if offset.bytes() != 0 {
throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
}
let Some(va_list) = self.memory.va_list_map.get(&alloc_id) else {
throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
};
interp_ok(va_list)
}
/// Removes this VaList from the global map of variable argument lists. This does not deallocate
/// the VaList elements, that happens when the Frame is popped.
pub fn deallocate_va_list(
&mut self,
ptr: Pointer<Option<M::Provenance>>,
) -> InterpResult<'tcx, VecDeque<MPlaceTy<'tcx, M::Provenance>>> {
trace!("deallocate_va_list({:?})", ptr);
let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
if offset.bytes() != 0 {
throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
}
let Some(va_list) = self.memory.va_list_map.swap_remove(&alloc_id) else {
throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
};
self.memory.dead_alloc_map.insert(alloc_id, (Size::ZERO, Align::ONE));
interp_ok(va_list)
}
/// Get the dynamic type of the given vtable pointer.
/// If `expected_trait` is `Some`, it must be a vtable for the given trait.
pub fn get_ptr_vtable_ty(

View file

@ -36,7 +36,7 @@ pub use self::operand::{ImmTy, Immediate, OpTy};
pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
use self::place::{MemPlace, Place};
pub use self::projection::{OffsetMode, Projectable};
pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo};
pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation};
pub use self::util::EnteredTraceSpan;
pub(crate) use self::util::create_static_alloc;
pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};

View file

@ -12,13 +12,14 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_mir_dataflow::impls::always_storage_live_locals;
use rustc_span::Span;
use rustc_target::callconv::ArgAbi;
use tracing::field::Empty;
use tracing::{info_span, instrument, trace};
use super::{
AllocId, CtfeProvenance, Immediate, InterpCx, InterpResult, Machine, MemPlace, MemPlaceMeta,
MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar, from_known_layout,
interp_ok, throw_ub, throw_unsup,
AllocId, CtfeProvenance, FnArg, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace,
MemPlaceMeta, MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar,
from_known_layout, interp_ok, throw_ub, throw_unsup,
};
use crate::{enter_trace_span, errors};
@ -80,7 +81,7 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
/// and its layout in the caller. This place is to be interpreted relative to the
/// *caller's* stack frame. We use a `PlaceTy` instead of an `MPlaceTy` since this
/// avoids having to move *all* return places into Miri's memory.
pub return_place: PlaceTy<'tcx, Prov>,
return_place: PlaceTy<'tcx, Prov>,
/// The list of locals for this stack frame, stored in order as
/// `[return_ptr, arguments..., variables..., temporaries...]`.
@ -91,6 +92,10 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
/// Do *not* access this directly; always go through the machine hook!
pub locals: IndexVec<mir::Local, LocalState<'tcx, Prov>>,
/// The complete variable argument list of this frame. Its elements must be dropped when the
/// frame is popped.
pub(super) va_list: Vec<MPlaceTy<'tcx, Prov>>,
/// The span of the `tracing` crate is stored here.
/// When the guard is dropped, the span is exited. This gives us
/// a full stack trace on all tracing statements.
@ -122,19 +127,6 @@ pub enum ReturnContinuation {
Stop { cleanup: bool },
}
/// Return type of [`InterpCx::pop_stack_frame_raw`].
pub struct StackPopInfo<'tcx, Prov: Provenance> {
/// Additional information about the action to be performed when returning from the popped
/// stack frame.
pub return_action: ReturnAction,
/// [`return_cont`](Frame::return_cont) of the popped stack frame.
pub return_cont: ReturnContinuation,
/// [`return_place`](Frame::return_place) of the popped stack frame.
pub return_place: PlaceTy<'tcx, Prov>,
}
/// State of a local variable including a memoized layout
#[derive(Clone)]
pub struct LocalState<'tcx, Prov: Provenance = CtfeProvenance> {
@ -259,6 +251,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
return_cont: self.return_cont,
return_place: self.return_place,
locals: self.locals,
va_list: self.va_list,
loc: self.loc,
extra,
tracing_span: self.tracing_span,
@ -286,6 +279,14 @@ impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
self.instance
}
pub fn return_place(&self) -> &PlaceTy<'tcx, Prov> {
&self.return_place
}
pub fn return_cont(&self) -> ReturnContinuation {
self.return_cont
}
/// Return the `SourceInfo` of the current instruction.
pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
self.loc.left().map(|loc| self.body.source_info(loc))
@ -377,6 +378,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return_cont,
return_place: return_place.clone(),
locals,
va_list: vec![],
instance,
tracing_span: SpanGuard::new(),
extra: (),
@ -410,35 +412,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
interp_ok(())
}
/// Low-level helper that pops a stack frame from the stack and returns some information about
/// it.
///
/// This also deallocates locals, if necessary.
/// `copy_ret_val` gets called after the frame has been taken from the stack but before the locals have been deallocated.
///
/// [`M::before_stack_pop`] and [`M::after_stack_pop`] are called by this function
/// automatically.
///
/// The high-level version of this is `return_from_current_stack_frame`.
///
/// [`M::before_stack_pop`]: Machine::before_stack_pop
/// [`M::after_stack_pop`]: Machine::after_stack_pop
/// Low-level helper that pops a stack frame from the stack without any cleanup.
/// This invokes `before_stack_pop`.
/// After calling this function, you need to deal with the return value, and then
/// invoke `cleanup_stack_frame`.
pub(super) fn pop_stack_frame_raw(
&mut self,
unwinding: bool,
copy_ret_val: impl FnOnce(&mut Self, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx>,
) -> InterpResult<'tcx, StackPopInfo<'tcx, M::Provenance>> {
) -> InterpResult<'tcx, Frame<'tcx, M::Provenance, M::FrameExtra>> {
M::before_stack_pop(self)?;
let frame =
self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
// Copy return value (unless we are unwinding).
if !unwinding {
copy_ret_val(self, &frame.return_place)?;
interp_ok(frame)
}
/// Deallocate local variables in the stack frame, and invoke `after_stack_pop`.
pub(super) fn cleanup_stack_frame(
&mut self,
unwinding: bool,
frame: Frame<'tcx, M::Provenance, M::FrameExtra>,
) -> InterpResult<'tcx, ReturnAction> {
let return_cont = frame.return_cont;
let return_place = frame.return_place.clone();
// Cleanup: deallocate locals.
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
@ -448,22 +441,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ReturnContinuation::Stop { cleanup, .. } => cleanup,
};
let return_action = if cleanup {
// We need to take the locals out, since we need to mutate while iterating.
if cleanup {
for local in &frame.locals {
self.deallocate_local(local.value)?;
}
// Deallocate any c-variadic arguments.
self.deallocate_varargs(&frame.va_list)?;
// Call the machine hook, which determines the next steps.
let return_action = M::after_stack_pop(self, frame, unwinding)?;
assert_ne!(return_action, ReturnAction::NoCleanup);
return_action
interp_ok(return_action)
} else {
// We also skip the machine hook when there's no cleanup. This not a real "pop" anyway.
ReturnAction::NoCleanup
};
interp_ok(StackPopInfo { return_action, return_cont, return_place })
interp_ok(ReturnAction::NoCleanup)
}
}
/// In the current stack frame, mark all locals as live that are not arguments and don't have
@ -626,6 +619,58 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}
impl<'a, 'tcx: 'a, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Consume the arguments provided by the iterator and store them as a list
/// of variadic arguments. Return a list of the places that hold those arguments.
pub(crate) fn allocate_varargs<I, J>(
&mut self,
caller_args: &mut I,
callee_abis: &mut J,
) -> InterpResult<'tcx, Vec<MPlaceTy<'tcx, M::Provenance>>>
where
I: Iterator<Item = (&'a FnArg<'tcx, M::Provenance>, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
J: Iterator<Item = (usize, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
{
// Consume the remaining arguments and store them in fresh allocations.
let mut varargs = Vec::new();
for (fn_arg, caller_abi) in caller_args {
// The callee ABI is entirely computed based on which arguments the caller has
// provided so it should not be possible to get a mismatch here.
let (_idx, callee_abi) = callee_abis.next().unwrap();
assert!(self.check_argument_compat(caller_abi, callee_abi)?);
// FIXME: do we have to worry about in-place argument passing?
let op = fn_arg.copy_fn_arg();
let mplace = self.allocate(op.layout, MemoryKind::Stack)?;
self.copy_op(&op, &mplace)?;
varargs.push(mplace);
}
assert!(callee_abis.next().is_none());
interp_ok(varargs)
}
/// Deallocate the variadic arguments in the list (that must have been created with `allocate_varargs`).
fn deallocate_varargs(
&mut self,
varargs: &[MPlaceTy<'tcx, M::Provenance>],
) -> InterpResult<'tcx> {
for vararg in varargs {
let ptr = vararg.ptr();
trace!(
"deallocating vararg {:?}: {:?}",
vararg,
// Locals always have a `alloc_id` (they are never the result of a int2ptr).
self.dump_alloc(ptr.provenance.unwrap().get_alloc_id().unwrap())
);
self.deallocate_ptr(ptr, None, MemoryKind::Stack)?;
}
interp_ok(())
}
}
impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
pub(super) fn print(
&self,

View file

@ -249,12 +249,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.write_immediate(*val, &dest)?;
}
ShallowInitBox(ref operand, _) => {
let src = self.eval_operand(operand, None)?;
let v = self.read_immediate(&src)?;
self.write_immediate(*v, &dest)?;
}
Cast(cast_kind, ref operand, cast_ty) => {
let src = self.eval_operand(operand, None)?;
let cast_ty =

View file

@ -647,13 +647,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
}
} else {
// This is not CTFE, so it's Miri with recursive checking.
// FIXME: we do *not* check behind boxes, since creating a new box first creates it uninitialized
// and then puts the value in there, so briefly we have a box with uninit contents.
// FIXME: should we also skip `UnsafeCell` behind shared references? Currently that is not
// FIXME: should we also `UnsafeCell` behind shared references? Currently that is not
// needed since validation reads bypass Stacked Borrows and data race checks.
if matches!(ptr_kind, PointerKind::Box) {
return interp_ok(());
}
}
let path = &self.path;
ref_tracking.track(place, || {

View file

@ -9,7 +9,7 @@ arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
either = "1.0"
elsa = "1.11.0"
ena = "0.14.3"
ena = "0.14.4"
indexmap = "2.12.1"
jobserver_crate = { version = "0.1.28", package = "jobserver" }
measureme = "12.0.1"

View file

@ -128,34 +128,21 @@ fn par_slice<I: DynSend>(
guard: &ParallelGuard,
for_each: impl Fn(&mut I) + DynSync + DynSend,
) {
struct State<'a, F> {
for_each: FromDyn<F>,
guard: &'a ParallelGuard,
group: usize,
let for_each = FromDyn::from(for_each);
let mut items = for_each.derive(items);
rustc_thread_pool::scope(|s| {
let proof = items.derive(());
let group_size = std::cmp::max(items.len() / 128, 1);
for group in items.chunks_mut(group_size) {
let group = proof.derive(group);
s.spawn(|_| {
let mut group = group;
for i in group.iter_mut() {
guard.run(|| for_each(i));
}
fn par_rec<I: DynSend, F: Fn(&mut I) + DynSync + DynSend>(
items: &mut [I],
state: &State<'_, F>,
) {
if items.len() <= state.group {
for item in items {
state.guard.run(|| (state.for_each)(item));
});
}
} else {
let (left, right) = items.split_at_mut(items.len() / 2);
let mut left = state.for_each.derive(left);
let mut right = state.for_each.derive(right);
rustc_thread_pool::join(move || par_rec(*left, state), move || par_rec(*right, state));
}
}
let state = State {
for_each: FromDyn::from(for_each),
guard,
group: std::cmp::max(items.len() / 128, 1),
};
par_rec(items, &state)
});
}
pub fn par_for_each_in<I: DynSend, T: IntoIterator<Item = I>>(

View file

@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler.
The value of statics and constants must be known at compile time, and they live
for the entire lifetime of a program. Creating a boxed value allocates memory on
the heap at runtime, and therefore cannot be done at compile time.
Erroneous code example:
```compile_fail,E0010
```ignore (no longer emitted)
const CON : Vec<i32> = vec![1, 2, 3];
```

View file

@ -1,7 +1,7 @@
The requested ABI is unsupported by the current target.
The rust compiler maintains for each target a list of unsupported ABIs on
that target. If an ABI is present in such a list this usually means that the
The Rust compiler maintains a list of unsupported ABIs for each target.
If an ABI is present in such a list, this usually means that the
target / ABI combination is currently unsupported by llvm.
If necessary, you can circumvent this check using custom target specifications.

View file

@ -20,7 +20,8 @@
//
// Do *not* remove entries from this list. Instead, just add a note to the corresponding markdown
// file saying that this error is not emitted by the compiler any more (see E0001.md for an
// example), and remove all code examples that do not build any more.
// example), and remove all code examples that do not build any more by marking them
// with `ignore (no longer emitted)`.
#[macro_export]
#[rustfmt::skip]
macro_rules! error_codes {

View file

@ -2,12 +2,11 @@ use std::any::Any;
use std::default::Default;
use std::iter;
use std::path::Component::Prefix;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use rustc_ast::attr::MarkedAttrs;
use rustc_ast::token::MetaVarKind;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{AssocCtxt, Visitor};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind, Safety};
@ -22,14 +21,14 @@ use rustc_hir::limit::Limit;
use rustc_hir::{Stability, find_attr};
use rustc_lint_defs::RegisteredTools;
use rustc_parse::MACRO_ARGUMENTS;
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
use rustc_parse::parser::Parser;
use rustc_session::Session;
use rustc_session::parse::ParseSess;
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
use rustc_span::source_map::SourceMap;
use rustc_span::{DUMMY_SP, FileName, Ident, Span, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
use smallvec::{SmallVec, smallvec};
use thin_vec::ThinVec;
@ -1421,80 +1420,3 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
}
}
}
/// If this item looks like a specific enums from `rental`, emit a fatal error.
/// See #73345 and #83125 for more details.
/// FIXME(#73933): Remove this eventually.
fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind
&& ident.name == sym::ProceduralMasqueradeDummyType
&& let [variant] = &*enum_def.variants
&& variant.ident.name == sym::Input
&& let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
&& let Some(c) = real
.local_path()
.unwrap_or(Path::new(""))
.components()
.flat_map(|c| c.as_os_str().to_str())
.find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
{
let crate_matches = if c.starts_with("allsorts-rental") {
true
} else {
let mut version = c.trim_start_matches("rental-").split('.');
version.next() == Some("0")
&& version.next() == Some("5")
&& version.next().and_then(|c| c.parse::<u32>().ok()).is_some_and(|v| v < 6)
};
if crate_matches {
psess.dcx().emit_fatal(errors::ProcMacroBackCompat {
crate_name: "rental".to_string(),
fixed_version: "0.5.6".to_string(),
});
}
}
}
pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: &ParseSess) {
let item = match ann {
Annotatable::Item(item) => item,
Annotatable::Stmt(stmt) => match &stmt.kind {
ast::StmtKind::Item(item) => item,
_ => return,
},
_ => return,
};
pretty_printing_compatibility_hack(item, psess)
}
pub(crate) fn stream_pretty_printing_compatibility_hack(
kind: MetaVarKind,
stream: &TokenStream,
psess: &ParseSess,
) {
let item = match kind {
MetaVarKind::Item => {
let mut parser = Parser::new(psess, stream.clone(), None);
// No need to collect tokens for this simple check.
parser
.parse_item(ForceCollect::No, AllowConstBlockItems::No)
.expect("failed to reparse item")
.expect("an actual item")
}
MetaVarKind::Stmt => {
let mut parser = Parser::new(psess, stream.clone(), None);
// No need to collect tokens for this simple check.
let stmt = parser
.parse_stmt(ForceCollect::No)
.expect("failed to reparse")
.expect("an actual stmt");
match &stmt.kind {
ast::StmtKind::Item(item) => item.clone(),
_ => return,
}
}
_ => return,
};
pretty_printing_compatibility_hack(&item, psess)
}

View file

@ -729,7 +729,7 @@ impl<'a> ExtCtxt<'a> {
ty: Box<ast::Ty>,
rhs_kind: ast::ConstItemRhsKind,
) -> Box<ast::Item> {
let defaultness = ast::Defaultness::Final;
let defaultness = ast::Defaultness::Implicit;
self.item(
span,
AttrVec::new(),

View file

@ -86,8 +86,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name == f.feature.name) {
let pull_note = if let Some(pull) = f.pull {
format!(
"; see <https://github.com/rust-lang/rust/pull/{}> for more information",
pull
"; see <https://github.com/rust-lang/rust/pull/{pull}> for more information",
)
} else {
"".to_owned()
@ -123,7 +122,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
// If the enabled feature is unstable, record it.
if UNSTABLE_LANG_FEATURES.iter().find(|f| name == f.name).is_some() {
// When the ICE comes a standard library crate, there's a chance that the person
// When the ICE comes from a standard library crate, there's a chance that the person
// hitting the ICE may be using -Zbuild-std or similar with an untested target.
// The bug is probably in the standard library and not the compiler in that case,
// but that doesn't really matter - we want a bug report.

View file

@ -446,18 +446,6 @@ pub(crate) struct GlobDelegationTraitlessQpath {
pub span: Span,
}
// This used to be the `proc_macro_back_compat` lint (#83125). It was later
// turned into a hard error.
#[derive(Diagnostic)]
#[diag("using an old version of `{$crate_name}`")]
#[note(
"older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives"
)]
pub(crate) struct ProcMacroBackCompat {
pub crate_name: String,
pub fixed_version: String,
}
pub(crate) use metavar_exprs::*;
mod metavar_exprs {
use super::*;

View file

@ -105,11 +105,6 @@ impl MultiItemModifier for DeriveProcMacro {
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
let is_stmt = matches!(item, Annotatable::Stmt(..));
// We used to have an alternative behaviour for crates that needed it.
// We had a lint for a long time, but now we just emit a hard error.
// Eventually we might remove the special case hard error check
// altogether. See #73345.
crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.psess);
let input = item.to_tokens();
let invoc_id = ecx.current_expansion.id;

View file

@ -103,8 +103,8 @@ impl ToInternal<token::LitKind> for LitKind {
}
}
impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStream, Span, Symbol>> {
fn from_internal((stream, rustc): (TokenStream, &mut Rustc<'_, '_>)) -> Self {
impl FromInternal<TokenStream> for Vec<TokenTree<TokenStream, Span, Symbol>> {
fn from_internal(stream: TokenStream) -> Self {
use rustc_ast::token::*;
// Estimate the capacity as `stream.len()` rounded up to the next power
@ -115,22 +115,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
while let Some(tree) = iter.next() {
let (Token { kind, span }, joint) = match tree.clone() {
tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => {
// We used to have an alternative behaviour for crates that
// needed it: a hack used to pass AST fragments to
// attribute and derive macros as a single nonterminal
// token instead of a token stream. Such token needs to be
// "unwrapped" and not represented as a delimited group. We
// had a lint for a long time, but now we just emit a hard
// error. Eventually we might remove the special case hard
// error check altogether. See #73345.
if let Delimiter::Invisible(InvisibleOrigin::MetaVar(kind)) = delim {
crate::base::stream_pretty_printing_compatibility_hack(
kind,
&stream,
rustc.psess(),
);
}
// In `mk_delimited` we avoid nesting invisible delimited
// of the same `MetaVarKind`. Here we do the same but
// ignore the `MetaVarKind` because it is discarded when we
@ -687,7 +671,7 @@ impl server::Server for Rustc<'_, '_> {
&mut self,
stream: Self::TokenStream,
) -> Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
FromInternal::from_internal((stream, self))
FromInternal::from_internal(stream)
}
fn span_debug(&mut self, span: Self::Span) -> String {

View file

@ -25,9 +25,6 @@ declare_features! (
// feature-group-start: for testing purposes
// -------------------------------------------------------------------------
/// A temporary feature gate used to enable parser extensions needed
/// to bootstrap fix for #5723.
(accepted, issue_5723_bootstrap, "1.0.0", None),
/// These are used to test this portion of the compiler,
/// they don't actually mean anything.
(accepted, test_accepted_feature, "1.0.0", None),

View file

@ -1208,7 +1208,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_intrinsic_const_stable_indirect, Normal,
template!(Word), WarnFollowing, EncodeCrossCrate::No, "this is an internal implementation detail",
),
gated!(
rustc_attr!(
rustc_allow_const_fn_unstable, Normal,
template!(Word, List: &["feat1, feat2, ..."]), DuplicatesOk, EncodeCrossCrate::No,
"rustc_allow_const_fn_unstable side-steps feature gating and stability checks"

View file

@ -172,6 +172,9 @@ declare_features! (
/// Allow anonymous constants from an inline `const` block in pattern position
(removed, inline_const_pat, "1.88.0", Some(76001),
Some("removed due to implementation concerns as it requires significant refactorings"), 138492),
/// A temporary feature gate used to enable parser extensions needed
/// to bootstrap fix for #5723.
(removed, issue_5723_bootstrap, "CURRENT_RUSTC_VERSION", None, None),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.56.0", Some(72219), Some("superseded by `generic_const_exprs`"), 88369),
/// Changes `impl Trait` to capture all lifetimes in scope.

View file

@ -64,8 +64,6 @@ pub struct EnabledLibFeature {
}
impl Features {
/// `since` should be set for stable features that are nevertheless enabled with a `#[feature]`
/// attribute, indicating since when they are stable.
pub fn set_enabled_lang_feature(&mut self, lang_feat: EnabledLangFeature) {
self.enabled_lang_features.push(lang_feat);
self.enabled_features.insert(lang_feat.gate_name);
@ -289,10 +287,6 @@ declare_features! (
(internal, panic_runtime, "1.10.0", Some(32837)),
/// Allows using pattern types.
(internal, pattern_types, "1.79.0", Some(123646)),
/// Allows using `#[rustc_allow_const_fn_unstable]`.
/// This is an attribute on `const fn` for the same
/// purpose as `#[allow_internal_unstable]`.
(internal, rustc_allow_const_fn_unstable, "1.49.0", Some(69399)),
/// Allows using compiler's own crates.
(unstable, rustc_private, "1.0.0", Some(27812)),
/// Allows using internal rustdoc features like `doc(keyword)`.
@ -420,6 +414,8 @@ declare_features! (
(unstable, const_async_blocks, "1.53.0", Some(85368)),
/// Allows `const { ... }` as a shorthand for `const _: () = const { ... };` for module items.
(unstable, const_block_items, "CURRENT_RUSTC_VERSION", Some(149226)),
/// Allows defining and calling c-variadic functions in const contexts.
(unstable, const_c_variadic, "CURRENT_RUSTC_VERSION", Some(151787)),
/// Allows `const || {}` closures in const contexts.
(incomplete, const_closures, "1.68.0", Some(106003)),
/// Allows using `[const] Destruct` bounds and calling drop impls in const contexts.
@ -492,6 +488,8 @@ declare_features! (
(unstable, ffi_const, "1.45.0", Some(58328)),
/// Allows the use of `#[ffi_pure]` on foreign functions.
(unstable, ffi_pure, "1.45.0", Some(58329)),
/// Allows marking trait functions as `final` to prevent overriding impls
(unstable, final_associated_functions, "CURRENT_RUSTC_VERSION", Some(131179)),
/// Controlling the behavior of fmt::Debug
(unstable, fmt_debug, "1.82.0", Some(129709)),
/// Allows using `#[align(...)]` on function items
@ -777,8 +775,9 @@ impl Features {
}
}
/// Some features are not allowed to be used together at the same time, if
/// the two are present, produce an error.
/// Some features are not allowed to be used together at the same time.
///
/// If the two are present, produce an error.
pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[
// Experimental match ergonomics rulesets are incompatible with each other, to simplify the
// boolean logic required to tell which typing rules to use.

View file

@ -897,6 +897,9 @@ pub enum AttributeKind {
/// Represents `#[debugger_visualizer]`.
DebuggerVisualizer(ThinVec<DebugVisualizer>),
/// Represents `#![default_lib_allocator]`
DefaultLibAllocator,
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
Deprecation { deprecation: Deprecation, span: Span },
@ -1163,6 +1166,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_diagnostic_item]`
RustcDiagnosticItem(Symbol),
/// Represents `#[rustc_do_not_const_check]`
RustcDoNotConstCheck,
/// Represents `#[rustc_dummy]`.
RustcDummy,
@ -1265,6 +1271,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_non_const_trait_method]`.
RustcNonConstTraitMethod,
/// Represents `#[rustc_nonnull_optimization_guaranteed]`.
RustcNonnullOptimizationGuaranteed,
/// Represents `#[rustc_nounwind]`
RustcNounwind,

View file

@ -35,6 +35,7 @@ impl AttributeKind {
CrateType(_) => No,
CustomMir(_, _, _) => Yes,
DebuggerVisualizer(..) => No,
DefaultLibAllocator => No,
Deprecation { .. } => Yes,
DoNotRecommend { .. } => Yes,
Doc(_) => Yes,
@ -115,6 +116,7 @@ impl AttributeKind {
RustcDenyExplicitImpl(..) => No,
RustcDeprecatedSafe2024 { .. } => Yes,
RustcDiagnosticItem(..) => Yes,
RustcDoNotConstCheck => Yes,
RustcDummy => No,
RustcDumpDefParents => No,
RustcDumpItemBounds => No,
@ -148,6 +150,7 @@ impl AttributeKind {
RustcNoImplicitBounds => No,
RustcNoMirInline => Yes,
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
RustcNonnullOptimizationGuaranteed => Yes,
RustcNounwind => No,
RustcObjcClass { .. } => No,
RustcObjcSelector { .. } => No,

View file

@ -320,7 +320,6 @@ language_item_table! {
FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;

View file

@ -1175,13 +1175,35 @@ pub(super) fn check_specialization_validity<'tcx>(
if let Err(parent_impl) = result {
if !tcx.is_impl_trait_in_trait(impl_item) {
report_forbidden_specialization(tcx, impl_item, parent_impl);
let span = tcx.def_span(impl_item);
let ident = tcx.item_ident(impl_item);
let err = match tcx.span_of_impl(parent_impl) {
Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname },
};
tcx.dcx().emit_err(err);
} else {
tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
}
}
}
fn check_overriding_final_trait_item<'tcx>(
tcx: TyCtxt<'tcx>,
trait_item: ty::AssocItem,
impl_item: ty::AssocItem,
) {
if trait_item.defaultness(tcx).is_final() {
tcx.dcx().emit_err(errors::OverridingFinalTraitFunction {
impl_span: tcx.def_span(impl_item.def_id),
trait_span: tcx.def_span(trait_item.def_id),
ident: tcx.item_ident(impl_item.def_id),
});
}
}
fn check_impl_items_against_trait<'tcx>(
tcx: TyCtxt<'tcx>,
impl_id: LocalDefId,
@ -1259,6 +1281,8 @@ fn check_impl_items_against_trait<'tcx>(
impl_id.to_def_id(),
impl_item,
);
check_overriding_final_trait_item(tcx, ty_trait_item, ty_impl_item);
}
if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {

View file

@ -77,11 +77,11 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::autodiff
| sym::bitreverse
| sym::black_box
| sym::box_new
| sym::breakpoint
| sym::bswap
| sym::caller_location
| sym::carrying_mul_add
| sym::carryless_mul
| sym::ceilf16
| sym::ceilf32
| sym::ceilf64
@ -222,6 +222,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::wrapping_add
| sym::wrapping_mul
| sym::wrapping_sub
| sym::write_box_via_move
// tidy-alphabetical-end
=> hir::Safety::Safe,
_ => hir::Safety::Unsafe,
@ -564,6 +565,7 @@ pub(crate) fn check_intrinsic_type(
(1, 0, vec![param(0), param(0)], param(0))
}
sym::saturating_add | sym::saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
sym::carryless_mul => (1, 0, vec![param(0), param(0)], param(0)),
sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
(1, 0, vec![param(0), param(0)], param(0))
}
@ -582,6 +584,13 @@ pub(crate) fn check_intrinsic_type(
sym::write_via_move => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
}
sym::write_box_via_move => {
let t = param(0);
let maybe_uninit_t = Ty::new_maybe_uninit(tcx, t);
let box_mu_t = Ty::new_box(tcx, maybe_uninit_t);
(1, 0, vec![box_mu_t, param(0)], box_mu_t)
}
sym::typed_swap_nonoverlapping => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit)
@ -687,8 +696,6 @@ pub(crate) fn check_intrinsic_type(
sym::ub_checks | sym::overflow_checks => (0, 0, Vec::new(), tcx.types.bool),
sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))),
// contract_check_requires::<C>(C) -> bool, where C: impl Fn() -> bool
sym::contract_check_requires => (1, 0, vec![param(0)], tcx.types.unit),
sym::contract_check_ensures => {
@ -711,7 +718,8 @@ pub(crate) fn check_intrinsic_type(
| sym::simd_fmin
| sym::simd_fmax
| sym::simd_saturating_add
| sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
| sym::simd_saturating_sub
| sym::simd_carryless_mul => (1, 0, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
sym::simd_neg
| sym::simd_bswap

View file

@ -197,18 +197,6 @@ pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDef
}
}
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
let span = tcx.def_span(impl_item);
let ident = tcx.item_ident(impl_item);
let err = match tcx.span_of_impl(parent_impl) {
Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname },
};
tcx.dcx().emit_err(err);
}
fn missing_items_err(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,

Some files were not shown because too many files have changed in this diff Show more