The types of statics, like all other items, are stored in the tcx
unnormalized. This is necessarily so, because
a) Item types other than statics have generics, which can't be
normalized.
b) Eager normalization causes undesirable on-demand dependencies.
Keeping with the principle that MIR lvalues require no normalization in
order to interpret, this patch stores the normalized type of the statics
in the Lvalue and reads it to get the lvalue type.
Fixes#39367.
This removes another special case of Switch by replacing it with the more general SwitchInt. While
this is more clunky currently, there’s no reason we can’t make it nice (and efficient) to use.
we can't create the target block until *after* we promote the arguments
- otherwise the arguments will be promoted into the target block. oops.
Fixes#38985.
Allow projections to be promoted to constants in MIR.
This employs the `LvalueContext` additions by @pcwalton to properly extend the MIR promotion of temporaries to allow projections (field accesses, indexing and dereferences) on said temporaries.
It's needed both parity with the old constant qualification logic (for current borrowck) and it fixes#38074.
The former is *required for soundness* if we accept the RFC for promoting rvalues to `'static` constants.
That is, until we get MIR borrowck and the same source of truth will be used for both checks and codegen.
Simplify use of mir_opt_level
Remove the unused top level option by the same name, and retain the
debug option.
Use -Zmir-opt-level=1 as default.
One pass is enabled by default but wants to be optional:
- Instcombine requires mir_opt_level > 0
Copy propagation is not used by default, but used to be activated by
explicit -Zmir-opt-level=1. It must move one higher to be off by
default:
- CopyPropagation requires mir_opt_level > 1
Deaggregate is not used by default, and used to be on a different level
than CopyPropagation:
- Deaggreate requires mir_opt_level > 2
Remove the unused top level option by the same name, and retain the
debug option.
Use -Zmir-opt-level=1 as default.
One pass is enabled by default but wants to be optional:
- Instcombine requires mir_opt_level > 0
Copy propagation is not used by default, but used to be activated by
explicit -Zmir-opt-level=1. It must move one higher to be off by
default:
- CopyPropagation requires mir_opt_level > 1
Deaggregate is not used by default, and used to be on a different level
than CopyPropagation:
- Deaggreate requires mir_opt_level > 2
A previous commit must have removed the `while let` loop here by
mistake; for each basic block, it should find and deaggregate multiple
statements in their index order, and the `curr` index tracks the
progress through the block.
This fixes both the case of deaggregating statements in separate
basic blocks (preserving `curr` could prevent that) as well
as multiple times in the same block (missing loop prevented that).
Refactor TraitObject to Slice<ExistentialPredicate>
For reference, the primary types changes in this PR are shown below. They may add in the understanding of what is discussed below, though they should not be required.
We change `TraitObject` into a list of `ExistentialPredicate`s to allow for a couple of things:
- Principal (ExistentialPredicate::Trait) is now optional.
- Region bounds are moved out of `TraitObject` into `TyDynamic`. This permits wrapping only the `ExistentialPredicate` list in `Binder`.
- `BuiltinBounds` and `BuiltinBound` are removed entirely from the codebase, to permit future non-constrained auto traits. These are replaced with `ExistentialPredicate::AutoTrait`, which only requires a `DefId`. For the time being, only `Send` and `Sync` are supported; this constraint can be lifted in a future pull request.
- Binder-related logic is extracted from `ExistentialPredicate` into the parent (`Binder<Slice<EP>>`), so `PolyX`s are inside `TraitObject` are replaced with `X`.
The code requires a sorting order for `ExistentialPredicate`s in the interned `Slice`. The sort order is asserted to be correct during interning, but the slices are not sorted at that point.
1. `ExistentialPredicate::Trait` are defined as always equal; **This may be wrong; should we be comparing them and sorting them in some way?**
1. `ExistentialPredicate::Projection`: Compared by `ExistentialProjection::sort_key`.
1. `ExistentialPredicate::AutoTrait`: Compared by `TraitDef.def_path_hash`.
Construction of `ExistentialPredicate`s is conducted through `TyCtxt::mk_existential_predicates`, which interns a passed iterator as a `Slice`. There are no convenience functions to construct from a set of separate iterators; callers must pass an iterator chain. The lack of convenience functions is primarily due to few uses and the relative difficulty in defining a nice API due to optional parts and difficulty in recognizing which argument goes where. It is also true that the current situation isn't significantly better than 4 arguments to a constructor function; but the extra work is deemed unnecessary as of this time.
```rust
// before this PR
struct TraitObject<'tcx> {
pub principal: PolyExistentialTraitRef<'tcx>,
pub region_bound: &'tcx ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
// after
pub enum ExistentialPredicate<'tcx> {
// e.g. Iterator
Trait(ExistentialTraitRef<'tcx>),
// e.g. Iterator::Item = T
Projection(ExistentialProjection<'tcx>),
// e.g. Send
AutoTrait(DefId),
}
```
Separate impl items from the parent impl
This change separates impl item bodies out of the impl itself. This gives incremental more resolution. In so doing, it refactors how the visitors work, and cleans up a bit of the collect/check logic (mostly by moving things out of collect that didn't really belong there, because they were just checking conditions).
However, this is not as effective as I expected, for a kind of frustrating reason. In particular, when invoking `foo.bar()` you still wind up with dependencies on private items. The problem is that the method resolution code scans that list for methods with the name `bar` -- and this winds up touching *all* the methods, even private ones.
I can imagine two obvious ways to fix this:
- separating fn bodies from fn sigs (#35078, currently being pursued by @flodiebold)
- a more aggressive model of incremental that @michaelwoerister has been advocating, in which we hash the intermediate results (e.g., the outputs of collect) so that we can see that the intermediate result hasn't changed, even if a particular impl item has changed.
So all in all I'm not quite sure whether to land this or not. =) It still seems like it has to be a win in some cases, but not with the test cases we have just now. I can try to gin up some test cases, but I'm not sure if they will be totally realistic. On the other hand, some of the early refactorings to the visitor trait seem worthwhile to me regardless.
cc #36349 -- well, this is basically a fix for that issue, I guess
r? @michaelwoerister
NB: Based atop of @eddyb's PR https://github.com/rust-lang/rust/pull/37402; don't land until that lands.
Refactoring towards region obligation
Two refactorings towards the intermediate goal of propagating region obligations through the `InferOk` structure (which in turn leads to the possibility of lazy normalization).
1. Remove `TypeOrigin` and add `ObligationCause`
- as we converge subtyping and obligations and so forth, the ability to keep these types distinct gets harder
2. Propagate obligations from `InferOk` into the surrounding fulfillment context
After these land, I have a separate branch (which still needs a bit of work) that can make the actual change to stop directly adding subregion edges and instead propagate obligations. (This should also make it easier to fix the unsoundness in specialization around lifetimes.)
r? @eddyb
In general having all these different structs for "origins" is not
great, since equating types can cause obligations and vice-versa. I
think we should gradually collapse these things. We almost certainly
also need to invest a big more energy into the `error_reporting` code to
rationalize it: this PR does kind of the minimal effort in that
direction.