Miri: unleash all feature gates
IMO it is silly to unleash features that do not even have a feature gate yet, but not unleash features that do. The only thing this achieves is making unleashed mode annoying to use as we have to figure out the feature flags to enable (and not always do the error messages say what that flag is).
Given that the point of `-Z unleash-the-miri-inside-of-you` is to debug the Miri internals, I see no good reason for this extra hurdle. I cannot imagine a situation where we'd use that flag, realize the program also requires some feature gate, and then be like "oh I guess if this feature is unstable I will do something else". Instead, we'll always just add that flag to the code as well, so requiring the flag achieves nothing.
r? @oli-obk @ecstatic-morse
Fixes https://github.com/rust-lang/rust/issues/71630
Allow `Downcast` projections unconditionally in const-checking
`ProjectionElem::Downcast` sounds scary, but it's really just the projection we use to access a particular enum variant. They usually appear in the lowering of a `match` statement, so they have been associated with control flow in const-checking, but they don't do any control flow by themselves. We already have a HIR pass that looks for `if` and `match` (even ones that have 1 or fewer reachable branches). That pass is double-checked by a MIR pass that looks for `SwitchInt`s and `FakeRead`s for match scrutinees. In my opinion, there's no need to look for `Downcast` as well.
r? @oli-obk
MIR dump: print pointers consistently with Miri output
This makes MIR allocation dump pointer printing consistent with Miri output: both use hexadecimal offsets with a `0x` prefix. To save some space, MIR dump replaces the `alloc` prefix by `a` when necessary.
I also made AllocId/Pointer printing more consistent in their Debug/Display handling, and adjusted Display printing for Scalar a bit to avoid using decimal printing when we do not know the sign with which to interpret the value (IMO using decimal then is misleading).
Rename Unique::empty() -> Unique::dangling()
A `FIXME` comment in `src/libcore/ptr/unique.rs` suggested refactoring `Unique::empty()` to `Unique::dangling()` which this PR does.
Miri: better document and fix dynamic const pattern soundness checks
https://github.com/rust-lang/const-eval/issues/42 got me thinking about soundness for consts being used in patterns, and I found a hole in our existing dynamic checks: a const referring to a mutable static *in a different crate* was not caught. This PR fixes that. It also adds some comments that explain which invariants are crucial for soundness of const-patterns.
Curiously, trying to weaponize this soundness hole failed: pattern matching compilation ICEd when encountering the cross-crate static, saying "expected allocation ID alloc0 to point to memory". I don't know why that would happen, statics *should* be entirely normal memory for pattern matching to access.
r? @oli-obk
Cc @rust-lang/wg-const-eval
Const qualification for `StructuralEq`
Furthers #62411. Resolves#62614.
The goal of this PR is to implement the logic in #67088 on the MIR instead of the HIR. It uses the `Qualif` trait to track `StructuralPartialEq`/`StructuralEq` in the final value of a `const`. Then, if we encounter a constant during HAIR lowering whose value may not be structurally matchable, we emit the `indirect_structural_match` lint.
This PR contains all the tests present in #67088 and emits the proper warnings for the corner cases. This PR does not handle #65466, which would require that we be [more aggressive](42abbd8878/src/librustc_mir_build/hair/pattern/const_to_pat.rs (L126-L130)) when checking matched types for `PartialEq`. I think that should be done separately.
Because this works on MIR and uses dataflow, this PR should accept more cases than #67088. Notably, the qualifs in the final value of a const are encoded cross-crate, so matching on a constant whose value is defined in another crate to be `Option::<TyWithCustomEqImpl>::None` should work. Additionally, if a `const` has branching/looping, we will only emit the warning if any possible control flow path could result in a type with a custom `PartialEq` impl ending up as the final value of a `const`. I'm not sure how #67088 handled this.
AFAIK, it's not settled that these are the semantics we actually want: it's just how the `Qualif` framework happens to work. If the cross-crate part is undesirable, it would be quite easy to change the result of `mir_const_qualif().custom_eq` to `true` before encoding it in the crate metadata. This way, other crates would have to assume that all publicly exported constants may not be safe for matching.
r? @pnkfelix
cc @eddyb
[breaking change] Disallow statics initializing themselves
fixes#71078
Self-initialization is unsound because it breaks privacy assumptions that unsafe code can make. In
```rust
pub mod foo {
#[derive(Debug, Copy, Clone)]
pub struct Foo {
x: (),
}
}
pub static FOO: foo::Foo = FOO;
```
unsafe could could expect that ony functions inside the `foo` module were able to create a value of type `Foo`.
Reading from the return place is fine
Const eval thinks that reading from local `_0` is UB, but it isn't. `_0` is just a normal local like any other, and codegen handles it that way too. The only special thing is that the `Return` terminator will read from it.
I've hit these errors while working on an NRVO pass that can merge other locals with `_0` in https://github.com/rust-lang/rust/pull/71003.
r? @oli-obk
Exhaustively match on `{Statement,Terminator}Kind` during const checking
This adds a pre-monomorphization error for inline assembly in a const context as well.
r? @oli-obk
Detect mistyped associated consts in `Instance::resolve`.
*Based on #71049 to prevent redundant/misleading downstream errors.*
Fixes#70942 by refusing to resolve an associated `const` if it doesn't have the same type in the `impl` that it does in the `trait` (which we assume had errored, and `delay_span_bug` guards against bugs).