Implement simple CopyPropagation based on SSA analysis
This PR extracts the "copy propagation" logic from https://github.com/rust-lang/rust/pull/106285.
MIR may produce chains of assignment between locals, like `_x = move? _y`.
This PR attempts to remove such chains by unifying locals.
The current implementation is a bit overzealous in turning moves into copies, and in removing storage statements.
Skip possible where_clause_object_safety lints when checking `multiple_supertrait_upcastable`
Fix#106247
To achieve this, I lifted the `WhereClauseReferencesSelf` out from `object_safety_violations` and move it into `is_object_safe` (which is changed to a new query).
cc `@dtolnay`
r? `@compiler-errors`
Rollup of 8 pull requests
Successful merges:
- #106618 (Disable `linux_ext` in wasm32 and fortanix rustdoc builds.)
- #107097 (Fix def-use dominance check)
- #107154 (library/std/sys_common: Define MIN_ALIGN for m68k-unknown-linux-gnu)
- #107397 (Gracefully exit if --keep-stage flag is used on a clean source tree)
- #107401 (remove the usize field from CandidateSource::AliasBound)
- #107413 (make more pleasant to read)
- #107422 (Also erase substs for new infcx in pin move error)
- #107425 (Check for missing space between fat arrow and range pattern)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Check for missing space between fat arrow and range pattern
Fixes#107420
Ideally we wouldn't emit an error about expecting `=>` etc., but I'm not sure how to recover from this.
`@rustbot` label +A-diagnostics
Also erase substs for new infcx in pin move error
The code originally correctly erased the regions of the type it passed to the newly created infcx. But after the `fn_sig` query was made to return an `EarlyBinder<T>`, some substs that were around were substituted there without erasing their regions. They were then passed into the newly cerated infcx, which caused the ICE.
Fixes#107419
r? compiler-errors who reviewed the original PR adding this diagnostic
Fix def-use dominance check
A definition does not dominate a use in the same statement. For example
in MIR generated for compound assignment x += a (when overflow checks
are disabled).
Use stable metric for const eval limit instead of current terminator-based logic
This patch adds a `MirPass` that inserts a new MIR instruction `ConstEvalCounter` to any loops and function calls in the CFG. This instruction is used during Const Eval to count against the `const_eval_limit`, and emit the `StepLimitReached` error, replacing the current logic which uses Terminators only.
The new method of counting loops and function calls should be more stable across compiler versions (i.e., not cause crates that compiled successfully before, to no longer compile when changes to the MIR generation/optimization are made).
Also see: #103877
Special-case deriving `PartialOrd` for enums with dataless variants
I was able to get slightly better codegen by flipping the derived `PartialOrd` logic for two-variant enums. I also tried to document the implementation of the derive macro to make the special-case logic a little clearer.
```rs
#[derive(PartialEq, PartialOrd)]
pub enum A<T> {
A,
B(T)
}
```
```diff
impl<T: ::core::cmp::PartialOrd> ::core::cmp::PartialOrd for A<T> {
#[inline]
fn partial_cmp(
&self,
other: &A<T>,
) -> ::core::option::Option<::core::cmp::Ordering> {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) => {
- match (self, other) {
- (A::B(__self_0), A::B(__arg1_0)) => {
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
- }
- _ => ::core::option::Option::Some(::core::cmp::Ordering::Equal),
- }
+ match (self, other) {
+ (A::B(__self_0), A::B(__arg1_0)) => {
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
}
- cmp => cmp,
+ _ => ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag),
}
}
}
```
Godbolt: [Current](https://godbolt.org/z/GYjEzG1T8), [New](https://godbolt.org/z/GoK78qx15)
I'm not sure how common a case comparing two enums like this (such as `Option`) is, and if it's worth the slowdown of adding a special case to the derive. If it causes overall regressions it might be worth just manually implementing this for `Option`.
The code originally correctly erased the regions of the type it passed
to the newly created infcx. But after the `fn_sig` query was made to
return an `EarlyBinder<T>`, some substs that were around were
substituted there without erasing their regions. They were then passed
into the newly cerated infcx, which caused the ICE.
Remove HirId -> LocalDefId map from HIR.
Having this map in HIR prevents the creating of new definitions after HIR has been built.
Thankfully, we do not need it.
Based on https://github.com/rust-lang/rust/pull/103902
Remove `ControlFlow::{BREAK, CONTINUE}`
Libs-API decided to remove these in #102697.
Follow-up to #107023, which removed them from `compiler/`, but a couple new ones showed up since that was merged.
r? libs
Use `FallibleTypeFolder` for `ConstInferUnifier` not `TypeRelation`
I am not sure why this was using a `TypeRelation`, maybe it predates the ability to have fallible type folders
Detect references to non-existant messages in Fluent resources
Should help with cases like #107091, where `{variable}` (a message reference) is accidentally typed, rather than `{$variable}` (a variable reference)
Fixes#107370
```@rustbot``` label +A-translation
Improve unexpected close and mismatch delimiter hint in TokenTreesReader
Fixes#103882Fixes#68987Fixes#69259
The inner indentation mismatching will be covered by outer block, the new added function `report_error_prone_delim_block` will find out the error prone candidates for reporting.
Remove overlapping parts of multipart suggestions
This PR adds a debug assertion that the parts of a single substitution cannot overlap, fixes a overlapping substitution from the testsuite, and fixes https://github.com/rust-lang/rust/issues/106870.
Note that a single suggestion can still have multiple overlapping substitutions / possible edits, we just don't suggest overlapping replacements in a single edit anymore.
I've also included a fix for an unrelated bug where rustfix for `explicit_outlives_requirements` would produce multiple trailing commas for a where clause.
Rollup of 8 pull requests
Successful merges:
- #107022 (Implement `SpecOptionPartialEq` for `cmp::Ordering`)
- #107100 (Use proper `InferCtxt` when probing for associated types in astconv)
- #107103 (Use new solver in `evaluate_obligation` query (when new solver is enabled))
- #107190 (Recover from more const arguments that are not wrapped in curly braces)
- #107306 (Correct suggestions for closure arguments that need a borrow)
- #107339 (internally change regions to be covariant)
- #107344 (Minor tweaks in the new solver)
- #107373 (Don't merge vtables when full debuginfo is enabled.)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Don't merge vtables when full debuginfo is enabled.
This PR makes the compiler not emit the `unnamed_addr` attribute for vtables when full debuginfo is enabled, so that they don't get merged even if they have the same contents. This allows debuggers to more reliably map from a dyn pointer to the self-type of a trait object by looking at the vtable's debuginfo.
The PR only changes the behavior of the LLVM backend as other backends don't emit vtable debuginfo (as far as I can tell).
The performance impact of this change should be small as [measured](https://github.com/rust-lang/rust/pull/103514#issuecomment-1290833854) in a previous PR.
Minor tweaks in the new solver
1. `InferCtxt::probe` is not needed in `compute_subtype_goal` and `compute_well_formed_goal`.
2. Add a handful of comments.
3. Add a micro-optimization in `consider_assumption` where we check the def-ids of the assumption and goal match before instantiating any binders.
r? ``@lcnr``
internally change regions to be covariant
Surprisingly, we consider the reference type `&'a T` to be contravaraint in its lifetime parameter. This is confusing and conflicts with the documentation we have in the reference, rustnomicon, and rustc-dev-guide. This also arguably not the correct use of terminology since we can use `&'static u8` in a place where `&' a u8` is expected, this implies that `&'static u8 <: &' a u8` and consequently `'static <: ' a`, hence covariance.
Because of this, when relating two types, we used to switch the argument positions in a confusing way:
`Subtype(&'a u8 <: &'b u8) => Subtype('b <: 'a) => Outlives('a: 'b) => RegionSubRegion('b <= 'a)`
The reason for the current behavior is probably that we wanted `Subtype('b <: 'a)` and `RegionSubRegion('b <= 'a)` to be equivalent, but I don' t think this is a good reason since these relations are sufficiently different in that the first is a relation in the subtyping lattice and is intrinsic to the type-systems, while the the second relation is an implementation detail of regionck.
This PR changes this behavior to use covariance, so..
`Subtype(&'a u8 <: &'b u8) => Subtype('a <: 'b) => Outlives('a: 'b) => RegionSubRegion('b <= 'a) `
Resolves#103676
r? `@lcnr`
Correct suggestions for closure arguments that need a borrow
Fixes#107301 by dealing with binders correctly
Fixes another issue where we were suggesting adding just `&` when we expected `&mut _` in a closure arg
Recover from more const arguments that are not wrapped in curly braces
Recover from some array, borrow, tuple & arithmetic expressions in const argument positions that lack curly braces and provide a suggestion to fix the issue continuing where #92884 left off. Examples of such expressions: `[]`, `[0]`, `[1, 2]`, `[0; 0xff]`, `&9`, `("", 0)` and `(1 + 2) * 3` (we previously did not recover from them).
I am not entirely happy with my current solution because the code that recovers from `[0]` (coinciding with a malformed slice type) and `[0; 0]` (coinciding with a malformed array type) is quite fragile as the aforementioned snippets are actually successfully parsed as types by `parse_ty` since it itself already recovers from them (returning `[⟨error⟩]` and `[⟨error⟩; 0]` respectively) meaning I have to manually look for `TyKind::Err`s and construct a separate diagnostic for the suggestion to attach to (thereby emitting two diagnostics in total).
Fixes#81698.
`@rustbot` label A-diagnostics
r? diagnostics
Use new solver in `evaluate_obligation` query (when new solver is enabled)
(only when `-Ztrait-solver=next`, of course)
... Does this make sense? It seems to me like it should be reasonable, but maybe there's some reason why this is a bad idea.
r? ``@lcnr``
Needs a perf run because I guess this `solver == TraitSolver::Next` check is on a hot path.
Libs-API decided to remove these in #102697.
Follow-up to #107023, which removed them from `compiler/`, but a couple new ones showed up since that was merged.
Compute generator saved locals on MIR
Generators are currently type-checked by introducing a `witness` type variable, which is unified with a `GeneratorWitness(captured types)` whose purpose is to ensure that the auto traits correctly migrate from the captured types to the `witness` type. This requires computing the captured types on HIR during type-checking, only to re-do it on MIR later.
This PR proposes to drop the HIR-based computation, and only keep the MIR one. This is done in 3 steps.
1. During type-checking, the `witness` type variable is never unified. This allows to stall all the obligations that depend on it until the end of type-checking. Then, the stalled obligations are marked as successful, and saved into the typeck results for later verification.
2. At type-checking writeback, `witness` is replaced by `GeneratorWitnessMIR(def_id, substs)`. From this point on, all trait selection involving `GeneratorWitnessMIR` will fetch the MIR-computed locals, similar to what opaque types do. There is no lifetime to be preserved here: we consider all the lifetimes appearing in this witness type to be higher-ranked.
3. After borrowck, the stashed obligations are verified against the actually computed types, in the `check_generator_obligations` query. If any obligation was wrongly marked as fulfilled in step 1, it should be reported here.
There are still many issues:
- ~I am not too happy having to filter out some locals from the checked bounds, I think this is MIR building that introduces raw pointers polluting the analysis;~ solved by a check specific to static variables.
- the diagnostics for captured types don't show where they are used/dropped;
- I do not attempt to support chalk.
cc `@eholk` `@jyn514` for the drop-tracking work
r? `@oli-obk` as you warned me of potential unsoundness