This fixes a number of correctness issues from the previous version. Additionally, we use a new
strategy which has much better performance charactersitics and also finds more opportunities to
apply the optimization.
Refine `instruction_set` MIR inline rules
Previously an exact match of the `instruction_set` attribute was required for an MIR inline to be considered. This change checks for an exact match *only* if the callee sets an `instruction_set` in the first place. When the callee does not declare an instruction set then it is considered to be platform agnostic code and it's allowed to be inline'd into the caller.
cc ``@oli-obk``
[Edit] Zulip Context: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/What.20exactly.20does.20the.20MIR.20optimizer.20do.3F
Previously an exact match of the `instruction_set` attribute was required for an MIR inline to be considered. This change checks for an exact match *only* if the callee sets an `instruction_set` in the first place. When the callee does not declare an instruction set then it is considered to be platform agnostic code and it's allowed to be inline'd into the caller.
Make rustc_target usable outside of rustc
I'm working on showing type size in rust-analyzer (https://github.com/rust-lang/rust-analyzer/pull/13490) and I currently copied rustc code inside rust-analyzer, which works, but is bad. With this change, I would become able to use `rustc_target` and `rustc_index` directly in r-a, reducing the amount of copy needed.
This PR contains some feature flag to put nightly features behind them to make crates buildable on the stable compiler + makes layout related types generic over index type + removes interning of nested layouts.
Previously, async constructs would be lowered to "normal" generators,
with an additional `from_generator` / `GenFuture` shim in between to
convert from `Generator` to `Future`.
The compiler will now special-case these generators internally so that
async constructs will *directly* implement `Future` without the need
to go through the `from_generator` / `GenFuture` shim.
The primary motivation for this change was hiding this implementation
detail in stack traces and debuginfo, but it can in theory also help
the optimizer as there is less abstractions to see through.
nll: correctly deal with bivariance
fixes#104409
when in a bivariant context, relating stuff should always trivially succeed. Also changes the mir validator to correctly deal with higher ranked regions.
r? types cc ``@RalfJung``
Record `LocalDefId` in HIR nodes instead of a side table
This is part of an attempt to remove the `HirId -> LocalDefId` table from HIR.
This attempt is a prerequisite to creation of `LocalDefId` after HIR lowering (https://github.com/rust-lang/rust/pull/96840), by controlling how `def_id` information is accessed.
This first part adds the information to HIR nodes themselves instead of a table.
The second part is https://github.com/rust-lang/rust/pull/103902
The third part will be to make `hir::Visitor::visit_fn` take a `LocalDefId` as last parameter.
The fourth part will be to completely remove the side table.
Perform simple scalar replacement of aggregates (SROA) MIR opt
This is a re-open of https://github.com/rust-lang/rust/pull/85796
I copied the debuginfo implementation (first commit) from `@eddyb's` own SROA PR.
This pass replaces plain field accesses by simple locals when possible.
To be eligible, the replaced locals:
- must not be enums or unions;
- must not be used whole;
- must not have their address taken.
The storage and deinit statements are duplicated on each created local.
cc `@tmiasko` who reviewed the former version of this PR.
interpret: support for per-byte provenance
Also factors the provenance map into its own module.
The third commit does the same for the init mask. I can move it in a separate PR if you prefer.
Fixes https://github.com/rust-lang/miri/issues/2181
r? `@oli-obk`
Add new MIR constant propagation based on dataflow analysis
The current constant propagation in `rustc_mir_transform/src/const_prop.rs` fails to handle many cases that would be expected from a constant propagation optimization. For example:
```rust
let x = if true { 0 } else { 0 };
```
This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations.
Closes#80038. Closes#81605.
## Todo
### Essential
- [x] [Writes to inactive enum variants](https://github.com/rust-lang/rust/pull/101168#pullrequestreview-1089493974). Resolved by rejecting the registration of places with downcast projections for now. Could be improved by flooding other variants if mutable access to a variant is observed.
- [X] Handle [`StatementKind::CopyNonOverlapping`](https://github.com/rust-lang/rust/pull/101168#discussion_r957774914). Resolved by flooding the destination.
- [x] Handle `UnsafeCell` / `!Freeze` correctly.
- [X] Overflow propagation of `CheckedBinaryOp`: Decided to not propagate if overflow flag is `true` (`false` will still be propagated)
- [x] More documentation in general.
- [x] Arguments for correctness, documentation of necessary assumptions.
- [x] Better performance, or alternatively, require `-Zmir-opt-level=3` for now.
### Extra
- [x] Add explicit unreachability, i.e. upgrading the lattice from $\mathbb{P} \to \mathbb{V}$ to $\set{\bot} \cup (\mathbb{P} \to \mathbb{V})$.
- [x] Use storage statements to improve precision.
- [ ] Consider opening issue for duplicate diagnostics: https://github.com/rust-lang/rust/pull/101168#issuecomment-1276609950
- [ ] Flood moved-from places with $\bot$ (requires some changes for places with tracked projections).
- [ ] Add downcast projections back in.
- [ ] [Algebraic simplifications](https://github.com/rust-lang/rust/pull/101168#discussion_r957967878) (possibly with a shared API; done by old const prop).
- [ ] Propagation through slices / arrays.
- [ ] Find other optimizations that are done by old `const_prop.rs`, but not by this one.
Add mir building test directory
The first commit renames `mir-map.0` mir dumps to `built.after` dumps. I am happy to drop this commit if someone can explain the origin of the name.
The second commit moves a bunch of mir building tests into their own directory. I did my best to make sure that all of these tests are actually testing mir building, and not just incidentally using `built.after`
r? ``@oli-obk``
indirect immutable freeze by-value function parameters.
Right now, `rustc` only examines function signatures and the platform ABI when
determining the LLVM attributes to apply to parameters. This results in missed
optimizations, because there are some attributes that can be determined via
analysis of the MIR making up the function body. In particular, `readonly`
could be applied to most indirectly-passed by-value function arguments
(specifically, those that are freeze and are observed not to be mutated), but
it currently is not.
This patch introduces the machinery that allows `rustc` to determine those
attributes. It consists of a query, `deduced_param_attrs`, that, when
evaluated, analyzes the MIR of the function to determine supplementary
attributes. The results of this query for each function are written into the
crate metadata so that the deduced parameter attributes can be applied to
cross-crate functions. In this patch, we simply check the parameter for
mutations to determine whether the `readonly` attribute should be applied to
parameters that are indirect immutable freeze by-value. More attributes could
conceivably be deduced in the future: `nocapture` and `noalias` come to mind.
Adding `readonly` to indirect function parameters where applicable enables some
potential optimizations in LLVM that are discussed in [issue 103103] and [PR
103070] around avoiding stack-to-stack memory copies that appear in functions
like `core::fmt::Write::write_fmt` and `core::panicking::assert_failed`. These
functions pass a large structure unchanged by value to a subfunction that also
doesn't mutate it. Since the structure in this case is passed as an indirect
parameter, it's a pointer from LLVM's perspective. As a result, the
intermediate copy of the structure that our codegen emits could be optimized
away by LLVM's MemCpyOptimizer if it knew that the pointer is `readonly
nocapture noalias` in both the caller and callee. We already pass `nocapture
noalias`, but we're missing `readonly`, as we can't determine whether a
by-value parameter is mutated by examining the signature in Rust. I didn't have
much success with having LLVM infer the `readonly` attribute, even with fat
LTO; it seems that deducing it at the MIR level is necessary.
No large benefits should be expected from this optimization *now*; LLVM needs
some changes (discussed in [PR 103070]) to more aggressively use the `noalias
nocapture readonly` combination in its alias analysis. I have some LLVM patches
for these optimizations and have had them looked over. With all the patches
applied locally, I enabled LLVM to remove all the `memcpy`s from the following
code:
```rust
fn main() {
println!("Hello {}", 3);
}
```
which is a significant codegen improvement over the status quo. I expect that
if this optimization kicks in in multiple places even for such a simple
program, then it will apply to Rust code all over the place.
[issue 103103]: https://github.com/rust-lang/rust/issues/103103
[PR 103070]: https://github.com/rust-lang/rust/pull/103070
Fix MIR inlining of asm_unwind
The MIR inlining currently doesn't handle inline asm's unwind edge correctly.
This code will cause ICE:
```rust
struct D;
impl Drop for D {
fn drop(&mut self) {}
}
#[inline(always)]
fn foo() {
let _d = D;
unsafe { std::arch::asm!("", options(may_unwind)) };
}
pub fn main() {
foo();
}
```
This PR fixes this issue. I also take the opportunity to extract common code into a method.
On later stages, the feature is already stable.
Result of running:
rg -l "feature.let_else" compiler/ src/librustdoc/ library/ | xargs sed -s -i "s#\\[feature.let_else#\\[cfg_attr\\(bootstrap, feature\\(let_else\\)#"
Rework definition of MIR phases to more closely reflect semantic concerns
Implements most of rust-lang/compiler-team#522 .
I tried my best to restrict this PR to the "core" parts of the MCP. In other words, this includes just enough changes to make the new definition of `MirPhase` make sense. That means there are a couple of FIXMEs lying around. Depending on what reviewers prefer, I can either fix them in this PR or send follow up PRs. There are also a couple other refactorings of the `rustc_mir_transform/src/lib.rs` file that I want to do in follow ups that I didn't leave explicit FIXMEs for.
Revert let_chains stabilization
This is the revert against master, the beta revert was already done in #100538.
Bumps the stage0 compiler which already has it reverted.
remove an ineffective check in const_prop
Based on https://github.com/rust-lang/rust/pull/100043, only the last two commits are new.
ConstProp has a special check when reading from a local that prevents reading uninit locals. However, if that local flows into `force_allocation`, then no check fires and evaluation proceeds. So this check is not really effective at preventing accesses to uninit locals.
With https://github.com/rust-lang/rust/pull/100043, `read_immediate` and friends always fail when reading uninit locals, so I don't see why ConstProp would need a separate check. Thus I propose we remove it. This is needed to be able to do https://github.com/rust-lang/rust/pull/100085.
Use the declaration's SourceInfo for FnEntry retags, not the outermost
This addresses a long-standing `// FIXME` in the pass that adds retags.
The changes to Miri's UI tests will look like this:
```
--> $DIR/aliasing_mut1.rs:LL:CC
|
LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
< | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
> | ^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
|
```
r? ````@RalfJung````
Replace `Body::basic_blocks()` with field access
Since the refactoring in #98930, it is possible to borrow the basic blocks
independently from other parts of MIR by accessing the `basic_blocks` field
directly.
Replace unnecessary `Body::basic_blocks()` method with a direct field access,
which has an additional benefit of borrowing the basic blocks only.
Elaborate all box dereferences in `ElaborateBoxDerefs`
so that it is the only pass responsible for elaboration, instead of
splitting this responsibility between the `StateTransform` and
`ElaborateBoxDerefs`.
so that it is the only pass responsible for elaboration, instead of
splitting this responsibility between the `StateTransform` and
`ElaborateBoxDerefs`.
Check projection types before inlining MIR
Fixes https://github.com/rust-lang/rust/issues/100550
I'm very unhappy with this solution, having to duplicate MIR validation code, but at least it removes the ICE.
r? `@compiler-errors`
Elide superfluous storage markers
Follow the existing strategy of omitting the storage markers for temporaries
introduced for internal usage when elaborating derefs and deref projections.
Those temporaries are simple scalars which are used immediately after being
defined and never have their address taken. There is no benefit from storage
markers from either liveness analysis or code generation perspective.
It was disabled because of pathological behaviour of LLVM in some
benchmarks. As of #77680, this has been fixed. The problem there was
that it caused pessimizations in some cases. These have now been fixed
as well.
Before, UnreachablePropagation removed all unreachable branches.
This was a pessimization, as it removed information about
reachability that was used later in the optimization pipeline.
For example, this code
```rust
pub enum Two { A, B }
pub fn identity(x: Two) -> Two {
match x {
Two::A => Two::A,
Two::B => Two::B,
}
}
```
basically has `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]` for the match.
This allows it to be transformed into a simple `x`. If we remove the
unreachable branch, the transformation becomes illegal.
never consider unsafe blocks unused if they would be required with deny(unsafe_op_in_unsafe_fn)
Judging from https://github.com/rust-lang/rust/issues/71668#issuecomment-1200317370 the consensus nowadays seems to be that we should never consider an unsafe block unused if it was required with `deny(unsafe_op_in_unsafe_fn)`, no matter whether that lint is actually enabled or not. So let's adjust rustc accordingly.
The first commit does the change, the 2nd does some cleanup.
Remove duplicated temporaries creating during box derefs elaboration
Temporaries created with `MirPatch::new_temp` will be declared after
patch application. Remove manually created duplicate declarations.
Removing duplicates exposes another issue. Visitor elaborates
terminator twice and attempts to access new, but not yet available,
local declarations. Remove duplicated call to `visit_terminator`.
Extracted from #99946.
Temporaries created with `MirPatch::new_temp` will be declared after
patch application. Remove manually created duplicate declarations.
Removing duplicates exposes another issue. Visitor elaborates
terminator twice and attempts to access new, but not yet available,
local declarations. Remove duplicated call to `visit_terminator`.
Some command-line options accessible through `sess.opts` are best
accessed through wrapper functions on `Session`, `TyCtxt` or otherwise,
rather than through field access on the option struct in the `Session`.
Adds a new lint which triggers on those options that should be accessed
through a wrapper function so that this is prohibited. Options are
annotated with a new attribute `rustc_lint_opt_deny_field_access` which
can specify the error message (i.e. "use this other function instead")
to be emitted.
A simpler alternative would be to simply rename the options in the
option type so that it is clear they should not be used, however this
doesn't prevent uses, just discourages them. Another alternative would
be to make the option fields private, and adding accessor functions on
the option types, however the wrapper functions sometimes rely on
additional state from `Session` or `TyCtxt` which wouldn't be available
in an function on the option type, so the accessor would simply make the
field available and its use would be discouraged too.
Signed-off-by: David Wood <david.wood@huawei.com>
Remove erroneous E0133 code from an error message.
This error message is about `derive` and `packed`, but E0133 is for
"Unsafe code was used outside of an unsafe function or block".
r? ``@estebank``
Remove reachable coverage without counters
Remove reachable coverage without counters to maintain invariant that
either there is no coverage at all or there is a live coverage counter
left that provides the function source hash.
The motivating example would be a following closure:
```rust
let f = |x: bool| {
debug_assert!(x);
};
```
Which, with span changes from #93967, with disabled debug assertions,
after the final CFG simplifications but before removal of dead blocks,
gives rise to MIR:
```rust
fn main::{closure#0}(_1: &[closure@a.rs:2:13: 2:22], _2: bool) -> () {
debug x => _2;
let mut _0: ();
bb0: {
Coverage::Expression(4294967295) = 1 - 2;
return;
}
...
}
```
Which also makes the initial instrumentation quite suspect, although
this pull request doesn't attempt to address that aspect directly.
Fixes#98833.
r? ``@wesleywiser`` ``@richkadel``
Simplify some code that depend on Deref
Now that we can assume #97025 works, it's safe to expect Deref is always in the first place of projections. With this, I was able to simplify some code that depended on Deref's place in projections. When we are able to move Derefer before `ElaborateDrops` successfully we will be able to optimize more places.
r? `@oli-obk`
Remove reachable coverage without counters to maintain invariant that
either there is no coverage at all or there is a live coverage counter
left that provides the function source hash.
The motivating example would be a following closure:
```rust
let f = |x: bool| {
debug_assert!(x);
};
```
Which, with span changes from #93967, with disabled debug assertions,
after the final CFG simplifications but before removal of dead blocks,
gives rise to MIR:
```rust
fn main::{closure#0}(_1: &[closure@a.rs:2:13: 2:22], _2: bool) -> () {
debug x => _2;
let mut _0: ();
bb0: {
Coverage::Expression(4294967295) = 1 - 2;
return;
}
...
}
```
Improve error messages involving `derive` and `packed`.
There are two errors involving `derive` and `packed`.
```
`#[derive]` can't be derived on a `#[repr(packed)]` struct with type or const parameters
`#[derive]` can't be derived on a `#[repr(packed)]` struct that does not derive Copy
```
The second one overstates things. It is possible to use derive on a
repr(packed) struct that doesn't derive Copy in two cases.
- If all the fields within the struct meet the required alignment: 1 for
`repr(packed)`, or `N` for `repr(packed(N))`.
- If `Default` is the only trait derived.
This commit improves things in a few ways.
- Changes the errors to say `this trait can't be derived on this ...`.
This is more accurate, because it's just *this* trait and *this*
packed struct that are a problem, not *all* derived traits on *all*
packed structs.
- Adds more details to the "ERROR" lines in the test case, enough to
distinguish between the two error messages.
- Adds more cases to the test case that don't cause errors, e.g. `Default`
derives.
- Uses a wider variety of builtin traits in the test case, for better coverage.
r? `@estebank`
There are two errors involving `derive` and `packed`.
```
`#[derive]` can't be derived on a `#[repr(packed)]` struct with type or const parameters
`#[derive]` can't be derived on a `#[repr(packed)]` struct that does not derive Copy
```
The second one overstates things. It is possible to use derive on a
repr(packed) struct that doesn't derive Copy in two cases.
- If all the fields within the struct meet the required alignment: 1 for
`repr(packed)`, or `N` for `repr(packed(N))`.
- If `Default` is the only trait derived.
This commit improves things in a few ways.
- Changes the errors to say `$TRAIT can't be derived on this ...`.
This is more accurate, because it's just $TRAIT and *this* packed
struct that are a problem, not *all* derived traits on *all* packed
structs.
- Adds more details to the "ERROR" lines in the test case, enough to
distinguish between the two error messages.
- Adds more cases to the test case that don't cause errors, e.g. `Default`
derives.
- Uses a wider variety of builtin traits in the test case, for better coverage.
Fix unreachable coverage generation for inlined functions
To generate a function coverage we need at least one coverage counter,
so a coverage from unreachable blocks is retained only when some live
counters remain.
The previous implementation incorrectly retained unreachable coverage,
because it didn't account for the fact that those live counters can
belong to another function due to inlining.
Fixes#98833.
make vtable pointers entirely opaque
This implements the scheme discussed in https://github.com/rust-lang/unsafe-code-guidelines/issues/338: vtable pointers should be considered entirely opaque and not even readable by Rust code, similar to function pointers.
- We have a new kind of `GlobalAlloc` that symbolically refers to a vtable.
- Miri uses that kind of allocation when generating a vtable.
- The codegen backends, upon encountering such an allocation, call `vtable_allocation` to obtain an actually dataful allocation for this vtable.
- We need new intrinsics to obtain the size and align from a vtable (for some `ptr::metadata` APIs), since direct accesses are UB now.
I had to touch quite a bit of code that I am not very familiar with, so some of this might not make much sense...
r? `@oli-obk`
Remove the unused StableSet and StableMap types from rustc_data_structures.
The current implementation is not "stable" in the same sense that `HashStable` and `StableHasher` are stable, i.e. across compilation sessions. So, in my opinion, it's better to remove those types (which are basically unused anyway) than to give the wrong impression that these are safe for incr. comp.
I plan to provide new "stable" collection types soon that can be used to replace `FxHashMap` and `FxHashSet` in query results (see [draft](69d03ac7a7)). It's unsound that `HashMap` and `HashSet` implement `HashStable` (see https://github.com/rust-lang/rust/issues/98890 for a recent P-critical bug caused by this) -- so we should make some progress there.
interpret: rename Tag/PointerTag to Prov/Provenance
We were pretty inconsistent with calling this the "tag" vs the "provenance" of the pointer; I think we should consistently call it "provenance".
r? `@oli-obk`
Let's avoid using two different terms for the same thing -- let's just call it "provenance" everywhere.
In Miri, provenance consists of an AllocId and an SbTag (Stacked Borrows tag), which made this even more confusing.
interpret: make some large types not Copy
Also remove some unused trait impls (mostly HashStable).
This didn't find any unnecessary copies that I managed to avoid, but it might still be better to require explicit clone for these types? Not sure.
r? `@oli-obk`
Pull Derefer before ElaborateDrops
_Follow up work to #97025#96549#96116#95887 #95649_
This moves `Derefer` before `ElaborateDrops` and creates a new `Rvalue` called `VirtualRef` that allows us to bypass many constraints for `DerefTemp`.
r? `@oli-obk`
Lower let-else in MIR
This MR will switch to lower let-else statements in MIR building instead.
To lower let-else in MIR, we build a mini-switch two branches. One branch leads to the matching case, and the other leads to the `else` block. This arrangement will allow temporary lifetime analysis running as-is so that the temporaries are properly extended according to the same rule applied to regular `let` statements.
cc https://github.com/rust-lang/rust/issues/87335Fix#98672
To generate a function coverage we need at least one coverage counter,
so a coverage from unreachable blocks is retained only when some live
counters remain.
The previous implementation incorrectly retained unreachable coverage,
because it didn't account for the fact that those live counters can
belong to another function due to inlining.
Rollup of 9 pull requests
Successful merges:
- #97917 (Implement ExitCodeExt for Windows)
- #98844 (Reword comments and rename HIR visiting methods.)
- #98979 (interpret: use AllocRange in UninitByteAccess)
- #98986 (Fix missing word in comment)
- #98994 (replace process exit with more detailed exit in src/bootstrap/*.rs)
- #98995 (Add a test for #80471)
- #99002 (suggest adding a derive for #[default] applied to variants)
- #99004 (Add a test for #70408)
- #99017 (Replace boolean argument for print_where_clause with an enum to make code more clear)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Make lowering a query
Split from https://github.com/rust-lang/rust/pull/88186.
This PR refactors the relationship between lowering and the resolver outputs in order to make lowering itself a query.
In a first part, lowering is changed to avoid modifying resolver outputs, by maintaining its own data structures for creating new `NodeId`s and so.
Then, the `TyCtxt` is modified to allow creating new `LocalDefId`s from inside it. This is done by:
- enclosing `Definitions` in a lock, so as to allow modification;
- creating a query `register_def` whose purpose is to declare a `LocalDefId` to the query system.
See `TyCtxt::create_def` and `TyCtxt::iter_local_def_id` for more detailed explanations of the design.
This makes it possible to mutably borrow different fields of the MIR
body without resorting to methods like `basic_blocks_local_decls_mut_and_var_debug_info`.
To preserve validity of control flow graph caches in the presence of
modifications, a new struct `BasicBlocks` wraps together basic blocks
and control flow graph caches.
The `BasicBlocks` dereferences to `IndexVec<BasicBlock, BasicBlockData>`.
On the other hand a mutable access requires explicit `as_mut()` call.
Operand::Uninit is an *allocated* operand that is fully uninitialized.
This lets us lazily allocate the actual backing store of *all* locals (no matter their ABI).
I also reordered things in pop_stack_frame at the same time.
I should probably have made that a separate commit...
macros: `LintDiagnostic` derive
- Move `LintDiagnosticBuilder` into `rustc_errors` so that a diagnostic derive can refer to it.
- Introduce a `DecorateLint` trait, which is equivalent to `SessionDiagnostic` or `AddToDiagnostic` but for lints. Necessary without making more changes to the lint infrastructure as `DecorateLint` takes a `LintDiagnosticBuilder` and re-uses all of the existing logic for determining what type of diagnostic a lint should be emitted as (e.g. error/warning).
- Various refactorings of the diagnostic derive machinery (extracting `build_field_mapping` helper and moving `sess` field out of the `DiagnosticDeriveBuilder`).
- Introduce a `LintDiagnostic` derive macro that works almost exactly like the `SessionDiagnostic` derive macro except that it derives a `DecorateLint` implementation instead. A new derive is necessary for this because `SessionDiagnostic` is intended for when the generated code creates the diagnostic. `AddToDiagnostic` could have been used but it would have required more changes to the lint machinery.
~~At time of opening this pull request, ignore all of the commits from #98624, it's just the last few commits that are new.~~
r? `@oli-obk`
Add method to mutate MIR body without invalidating CFG caches.
In addition to adding this method, a handful of passes are updated to use it. There's still quite a few passes that could in principle make use of this as well, but do not at the moment because they use `VisitorMut` or `MirPatch`, which needs additional support for this.
The method name is slightly unwieldy, but I don't expect anyone to be writing it a lot, and at least it says what it does. If anyone has a suggestion for a better name though, would be happy to rename.
r? rust-lang/mir-opt
Fix FFI-unwind unsoundness with mixed panic mode
UB maybe introduced when an FFI exception happens in a `C-unwind` foreign function and it propagates through a crate compiled with `-C panic=unwind` into a crate compiled with `-C panic=abort` (#96926).
To prevent this unsoundness from happening, we will disallow a crate compiled with `-C panic=unwind` to be linked into `panic-abort` *if* it contains a call to `C-unwind` foreign function or function pointer. If no such call exists, then we continue to allow such mixed panic mode linking because it's sound (and stable). In fact we still need the ability to do mixed panic mode linking for std, because we only compile std once with `-C panic=unwind` and link it regardless panic strategy.
For libraries that wish to remain compile-once-and-linkable-to-both-panic-runtimes, a `ffi_unwind_calls` lint is added (gated under `c_unwind` feature gate) to flag any FFI unwind calls that will cause the linkable panic runtime be restricted.
In summary:
```rust
#![warn(ffi_unwind_calls)]
mod foo {
#[no_mangle]
pub extern "C-unwind" fn foo() {}
}
extern "C-unwind" {
fn foo();
}
fn main() {
// Call to Rust function is fine regardless ABI.
foo::foo();
// Call to foreign function, will cause the crate to be unlinkable to panic-abort if compiled with `-Cpanic=unwind`.
unsafe { foo(); }
//~^ WARNING call to foreign function with FFI-unwind ABI
let ptr: extern "C-unwind" fn() = foo::foo;
// Call to function pointer, will cause the crate to be unlinkable to panic-abort if compiled with `-Cpanic=unwind`.
ptr();
//~^ WARNING call to function pointer with FFI-unwind ABI
}
```
Fix#96926
`@rustbot` label: T-compiler F-c_unwind
Enable MIR inlining
Continuation of https://github.com/rust-lang/rust/pull/82280 by `@wesleywiser.`
#82280 has shown nice compile time wins could be obtained by enabling MIR inlining.
Most of the issues in https://github.com/rust-lang/rust/issues/81567 are now fixed,
except the interaction with polymorphization which is worked around specifically.
I believe we can proceed with enabling MIR inlining in the near future
(preferably just after beta branching, in case we discover new issues).
Steps before merging:
- [x] figure out the interaction with polymorphization;
- [x] figure out how miri should deal with extern types;
- [x] silence the extra arithmetic overflow warnings;
- [x] remove the codegen fulfilment ICE;
- [x] remove the type normalization ICEs while compiling nalgebra;
- [ ] tweak the inlining threshold.
This created unexpected diagnostics while compiling alga:
cannot satisfy `<Self as Module>::Ring == _`
Turns out that we don't need this diagnostic as we disable inlining when
it would trigger an ICE.
Remove dereferencing of Box from codegen
Through #94043, #94414, #94873, and #95328, I've been fixing issues caused by Box being treated like a pointer when it is not a pointer. However, these PRs just introduced special cases for Box. This PR removes those special cases and instead transforms a deref of Box into a deref of the pointer it contains.
Hopefully, this is the end of the Box<T, A> ICEs.
Don't omit comma when suggesting wildcard arm after macro expr
* Also adds `Span::eq_ctxt` to consolidate the various usages of `span.ctxt() == other.ctxt()`
* Also fixes an unhygenic usage of spans which caused the suggestion to render weirdly when we had one arm match in a macro
* Also always suggests a comma (i.e. even after a block) if we're rendering a wildcard arm in a single-line match (looks prettier 🌹)
Fixes#94866
Drop magic value 3 from code
Magic value 3 is used to create state for a yield point. It is in fact
the number of reserved variants.
Lift RESERVED_VARIANTS out to module scope and use it instead.
Magic value 3 is used to create state for a yield point. It is in fact
the number of reserved variants.
Lift RESERVED_VARIANTS out to module scope and use it instead.
once cell renamings
This PR does the renamings proposed in https://github.com/rust-lang/rust/issues/74465#issuecomment-1153703128
- Move/rename `lazy::{OnceCell, Lazy}` to `cell::{OnceCell, LazyCell}`
- Move/rename `lazy::{SyncOnceCell, SyncLazy}` to `sync::{OnceLock, LazyLock}`
(I used `Lazy...` instead of `...Lazy` as it seems to be more consistent, easier to pronounce, etc)
```@rustbot``` label +T-libs-api -T-libs
`BitSet` related perf improvements
This commit makes two changes:
1. Changes `MaybeLiveLocals` to use `ChunkedBitSet`
2. Overrides the `fold` method for the iterator for `ChunkedBitSet`
I have local benchmarks verifying that each of these changes individually yield significant perf improvements to #96451 . I'm hoping this will be true outside of that context too. If that is not the case, I'll try to gate things on where they help as needed
r? `@nnethercote` who I believe was working on closely related things, cc `@tmiasko` because of the destprop pr
And likewise for the `Const::val` method.
Because its type is called `ConstKind`. Also `val` is a confusing name
because `ConstKind` is an enum with seven variants, one of which is
called `Value`. Also, this gives consistency with `TyS` and `PredicateS`
which have `kind` fields.
The commit also renames a few `Const` variables from `val` to `c`, to
avoid confusion with the `ConstKind::Value` variant.
use precise spans for recursive const evaluation
This fixes https://github.com/rust-lang/rust/issues/73283 by using a `TyCtxtAt` with a more precise span when the interpreter recursively calls itself. Hopefully such calls are sufficiently rare that this does not cost us too much performance.
(In theory, cycles can also arise through layout computation, as layout can depend on consts -- but layout computation happens all the time so we'd have to do something to not make this terrible for performance.)
Replace `&Vec<_>`s with `&[_]`s
It's generally preferable to use `&[_]` since it's one less indirection and it can be created from types other that `Vec`.
I've left `&Vec` in some locals where it doesn't really matter, in cases where `TypeFoldable` is expected (`TypeFoldable: Clone` so slice can't implement it) and in cases where it's `&TypeAliasThatIsActiallyVec`. Nothing important, really, I was just a little annoyed by `visit_generic_param_vec` :D
r? `@compiler-errors`
Lifetime variance fixes for rustc
#97287 migrates rustc to a `Ty` type that is invariant over its lifetime `'tcx`, so I need to fix a bunch of places that assume that `Ty<'a>` and `Ty<'b>` can be unified by shortening both to some common lifetime.
This is doable, since many lifetimes are already `'tcx`, so all this PR does is be a bit more explicit that elided lifetimes are actually `'tcx`.
Split out from #97287 so the compiler team can review independently.
move processing of `source_scope_data` into `MutVisitor`'s impl of `Integrator` when inline
This PR fixes the FIXME in the inline mir-opt which moves processing of `source_scope_data` into `MutVisitor`'s impl of `Integrator` when inline
Change `Successors` to `impl Iterator<Item = BasicBlock>`
This PR fixes the FIXME in `compiler\rustc_middle\src\mir\mod.rs`.
This can omit several `&`, `*` or `cloned` operations on Successros' generated elements
Add a query for checking whether a function is an intrinsic.
work towards #93145
This will reduce churn when we add more ways to declare intrinsics
r? `@scottmcm`
Add EarlyBinder
Chalk has no concept of `Param` (e0ade19d13/chalk-ir/src/lib.rs (L579)) or `ReEarlyBound` (e0ade19d13/chalk-ir/src/lib.rs (L1308)). Everything is just "bound" - the equivalent of rustc's late-bound. It's not completely clear yet whether to move everything to the same time of binder in rustc or add `Param` and `ReEarlyBound` in Chalk.
Either way, tracking when we have or haven't already substituted out these in rustc can be helpful.
As a first step, I'm just adding a `EarlyBinder` newtype that is required to call `subst`. I also add a couple "transparent" `bound_*` wrappers around a couple query that are often immediately substituted.
r? `@nikomatsakis`
Initial work on Miri permissive-exposed-provenance
Rustc portion of the changes for portions of a permissive ptr-to-int model for Miri. The main changes here are changing `ptr_get_alloc` and `get_alloc_id` to return an Option, and also making ptr-to-int casts have an expose side effect.
Begin fixing all the broken doctests in `compiler/`
Begins to fix#95994.
All of them pass now but 24 of them I've marked with `ignore HELP (<explanation>)` (asking for help) as I'm unsure how to get them to work / if we should leave them as they are.
There are also a few that I marked `ignore` that could maybe be made to work but seem less important.
Each `ignore` has a rough "reason" for ignoring after it parentheses, with
- `(pseudo-rust)` meaning "mostly rust-like but contains foreign syntax"
- `(illustrative)` a somewhat catchall for either a fragment of rust that doesn't stand on its own (like a lone type), or abbreviated rust with ellipses and undeclared types that would get too cluttered if made compile-worthy.
- `(not-rust)` stuff that isn't rust but benefits from the syntax highlighting, like MIR.
- `(internal)` uses `rustc_*` code which would be difficult to make work with the testing setup.
Those reason notes are a bit inconsistently applied and messy though. If that's important I can go through them again and try a more principled approach. When I run `rg '```ignore \(' .` on the repo, there look to be lots of different conventions other people have used for this sort of thing. I could try unifying them all if that would be helpful.
I'm not sure if there was a better existing way to do this but I wrote my own script to help me run all the doctests and wade through the output. If that would be useful to anyone else, I put it here: https://github.com/Elliot-Roberts/rust_doctest_fixing_tool
interpret/validity: debug-check ScalarPair layout information
This would have caught https://github.com/rust-lang/rust/issues/96158.
I ran the Miri test suite and it still passes.
r? `@oli-obk`
Display function path in unsafety violations - E0133
adds `DefId` to `UnsafetyViolationDetails`
this enables consumers to access the function definition that was reported to be unsafe and also changes the output for some E0133 diagnostics
Implement MIR opt unit tests
This implements rust-lang/compiler-team#502 .
There's not much to say here, this implementation does everything as proposed. I also added the flag to a bunch of existing tests (mostly those to which I could add it without causing huge diffs due to changes in line numbers). Summarizing the changes to test outputs:
- Every time an `MirPatch` is created, it adds a cleanup block to the body if it did not exist already. If this block is unused (as is usually the case), it usually gets removed soon after by some pass calling `SimplifyCFG` for unrelated reasons (in many cases this cycle happens quite a few times for a single body). We now run `SimplifyCFG` less often, so those blocks end up in some of our outputs. I looked at changing `MirPatch` to not do this, but that seemed too complicated for this PR. I may still do that in a follow-up.
- The `InstCombine` test had set `-C opt-level=0` in its flags and so there were no storage markers. I don't really see a good motivation for doing this, so bringing it back in line with what everything else does seems correct.
- One of the `EarlyOtherwiseBranch` tests had `UnreachableProp` running on it. Preventing that kind of thing is the goal of this feature, so this seems fine.
For the remaining tests for which this feature might be useful, we can gradually migrate them as opportunities present themselves.
In terms of documentation, I plan on submitting a PR to the rustc dev guide in the near future documenting this and other recent changes to MIR. If there's any other places to update, do let me know
r? `@nagisa`
Rollup of 7 pull requests
Successful merges:
- #95566 (Avoid duplication of doc comments in `std::char` constants and functions)
- #95784 (Suggest replacing `typeof(...)` with an actual type)
- #95807 (Suggest adding a local for vector to fix borrowck errors)
- #95849 (Check for git submodules in non-git source tree.)
- #95852 (Fix missing space in lossy provenance cast lint)
- #95857 (Allow multiple derefs to be splitted in deref_separator)
- #95868 (rustdoc: Reduce allocations in a `html::markdown` function)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Allow multiple derefs to be splitted in deref_separator
Previously in #95649 only a single deref within projection was supported and multiple derefs caused a bunch of issues, this PR fixes those issues.
```@oli-obk``` helped a ton again ❤️
New mir-opt deref_separator
This adds a new mir-opt that split certain derefs into this form:
`let x = (*a.b).c;` to => `tmp = a.b; let x = (*tmp).c;`
Huge thanks to ``@oli-obk`` for his patient mentoring.
enhance `ConstGoto` mir-opt by moving up `StorageDead` statements
From the `FIXME` in the implementation of `ConstGoto` miropt. We can move `StorageDead` statements up to the predecessor. This can expand the scope of application of this opt.
When encountering an unsatisfied trait bound, if there are no other
suggestions, mention all the types that *do* implement that trait:
```
error[E0277]: the trait bound `f32: Foo` is not satisfied
--> $DIR/impl_wf.rs:22:6
|
LL | impl Baz<f32> for f32 { }
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
|
= help: the following other types implement trait `Foo`:
Option<T>
i32
str
note: required by a bound in `Baz`
--> $DIR/impl_wf.rs:18:31
|
LL | trait Baz<U: ?Sized> where U: Foo { }
| ^^^ required by this bound in `Baz`
```
Mention implementers of traits in `ImplObligation`s.
Do not mention other `impl`s for closures, ranges and `?`.
Spellchecking compiler comments
This PR cleans up the rest of the spelling mistakes in the compiler comments. This PR does not change any literal or code spelling issues.
This allows to compute the `BodyOwnerKind` from `DefKind` only, and
removes a direct dependency of some MIR queries onto HIR.
As a side effect, it also simplifies metadata, since we don't need 4
flavours of `EntryKind::*Static` any more.
Remove `Session::one_time_diagnostic`
This is untracked mutable state, which modified the behaviour of queries.
It was used for 2 things: some full-blown errors, but mostly for lint declaration notes ("the lint level is defined here" notes).
It is replaced by the diagnostic deduplication infra which already exists in the diagnostic emitter.
A new diagnostic level `OnceNote` is introduced specifically for lint notes, to deduplicate subdiagnostics.
As a drive-by, diagnostic emission takes a `&mut` to allow dropping the `SubDiagnostic`s.
Clarify which kinds of MIR are allowed during which phases.
This enhances documentation with these details and extends the validator to check these requirements more thoroughly. Most of these conditions were already being checked.
There was also some disagreement between the `MirPhase` docs and validator as to what it meant for the `body.phase` field to have a certain value. This PR resolves those disagreements in favor of the `MirPhase` docs (which is what the pass manager implemented), adjusting the validator accordingly. The result is now that the `DropLowering` phase begins with the end of the elaborate drops pass, and lasts until the beginning of the generator lowring pass. This doesn't feel entirely natural to me, but as long as it's documented accurately it should be ok.
r? rust-lang/mir-opt
This enhances documentation with these details and extends the validator to check these requirements
more thoroughly. As a part of this, we add a new `Deaggregated` phase, and rename other phases so
that their names more naturally correspond to what they represent.
rename LocalState::Uninitialized to Unallocated
This is to avoid confusion with `Uninit` as in `ScalarMaybeUninit`, which is very different.
r? `@oli-obk`