-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make dataflow-based const qualification the canonical one #66385
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
8e40d60
to
ebebc65
Compare
ebebc65
to
236b96d
Compare
|
||
impl QualifSet { | ||
fn contains<Q: ?Sized + Qualif>(self) -> bool { | ||
pub const UNPROMOTABLE: Self = QualifSet(1 << Unpromotable::IDX); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we stop using this hack, btw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's only two places it can appear now. One is where you left a comment below, which doesn't seem to break anything. The other is when a const
panics unconditionally, which is just a hack to approximate the existing behavior. I'll try removing it completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed UNPROMOTABLE
. Let's see what happens with CI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We pass all the tests, and I've tried the following example locally and no ICE occurs, just an error pointing to X
saying that const evaluation failed.
#![feature(const_panic)]
#![allow(const_err)]
const X: u32 = panic!();
fn main() {
let x: &'static _ = &X;
}
src/librustc_mir/transform/mod.rs
Outdated
|
||
if body.return_ty().references_error() { | ||
tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors"); | ||
return check_consts::QualifSet::UNPROMOTABLE.into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anything break if you use QualifSet::default()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently not 😃
236b96d
to
059856e
Compare
src/librustc_mir/transform/mod.rs
Outdated
@@ -185,6 +185,41 @@ pub fn run_passes( | |||
body.phase = mir_phase; | |||
} | |||
|
|||
fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A doc comment would be good especially for the return type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can replace it now with:
struct ConstQualif {
has_mut_interior: bool,
needs_drop: bool,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change was made in the latest version.
// These blocks often drop locals that would otherwise be returned from the function. | ||
// | ||
// FIXME: This shouldn't be unsound since a panic at compile time will cause a compiler | ||
// error anyway, but maybe we should do more here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"If you have to ask..."? ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eddyb I was hoping someone could authoritatively tell me we don't need to do anything for cleanup blocks. I'm pretty sure we don't.
@@ -1,6 +1,9 @@ | |||
// compile-flags: -Zunleash-the-miri-inside-of-you | |||
// compile-flags: -Zunleash-the-miri-inside-of-you -Awarnings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer not to do this so that we can see changes in diffs and whatnot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "skipping const checks" annotations were only added last week since they are now mandatory in all UI tests (see #66213). They are unrelated to the actual purpose of the test; they just add noise (to both the test itself and PRs that work on const qualification). Ignoring warnings was explicitly mentioned as an opt-out path for tests like this.
Interestingly, #![allow(warnings)]
did not work for this purpose. Not sure why?
☔ The latest upstream changes (presumably #66233) made this pull request unmergeable. Please resolve the merge conflicts. |
059856e
to
910ae81
Compare
Rebased to fix merge conflicts. The latest version moves |
src/librustc/mir/mod.rs
Outdated
@@ -2769,6 +2769,13 @@ pub struct BorrowCheckResult<'tcx> { | |||
pub used_mut_upvars: SmallVec<[Field; 8]>, | |||
} | |||
|
|||
/// The result of the `mir_const_qualif` query. | |||
#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)] | |||
pub struct QualifSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think "set" is relevant anymore, the bitset was really just an optimization.
ConstQualifs
might be better. Or ValueQualifs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would lean towards ConstQualifs
since IsNotPromotable
is no longer, but either is fine.
#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)] | ||
pub struct QualifSet { | ||
pub has_mut_interior: bool, | ||
pub needs_drop: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if these two fields should have similar doc comments to the HasMutInterior
and NeedsDrop
types in rustc_mir::transform::check_consts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a link to the Qualif
implementers suffice? I don't wanna copy-paste lest they get out of sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I wasn't thinking copy-pasting, maybe a few words and a link (or even just the rustc_mir::...::HasMutInterior
etc. path).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note on ConstQualifs
that points the user to librustc_mir/transform/check_consts/qualifs.rs
. Lemme know if you want something more here.
src/librustc/query/mod.rs
Outdated
@@ -93,7 +93,7 @@ rustc_queries! { | |||
/// Maps DefId's that have an associated `mir::Body` to the result | |||
/// of the MIR qualify_consts pass. The actual meaning of | |||
/// the value isn't known except to the pass itself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doc comment should be updated.
src/librustc_metadata/rmeta/mod.rs
Outdated
@@ -295,7 +295,7 @@ enum EntryKind<'tcx> { | |||
/// Additional data for EntryKind::Const and EntryKind::AssocConst | |||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)] | |||
struct ConstQualif { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's a point in having this newtype.
☔ The latest upstream changes (presumably #66438) made this pull request unmergeable. Please resolve the merge conflicts. |
Unlike the original pass, we check *every* non-cleanup basic block instead of stopping at `SwitchInt`. We use the `is_cfg_cyclic` function to check for loops unlike the original checker which could not differentiate between true cycles and basic blocks with more than two predecessors. The last three functions are all copied verbatim from `qualify_consts`.
Now `mir_const_qualif` must be called for `static`s and `const fn`s as well as `const`s since it is responsible for const-checking. We return the qualifs in the return place for everything, even though they will only be used for `const`s.
I believe this occurs because the old checker stopped processing basic blocks after a `SwitchInt`.
We have a proper type for these now, so the wrapper is no longer necessary.
93eac78
to
a1135cc
Compare
@eddyb I believe I've resolved all your posted concerns. Let me know what else needs to be done. |
@bors r+ |
📌 Commit a1135cc has been approved by |
@bors rollup=never |
Make dataflow-based const qualification the canonical one For over a month, dataflow-based const qualification has been running in parallel with `qualify_consts` to check the bodies of `const` and `static`s. This PR removes the old qualification pass completely in favor of the dataflow-based one. **edit:** This PR also stops checking `QUALIF_ERROR_BIT` during promotion. This check appears to no longer serve a purpose now that the CTFE engine is more robust. As a side-effect, this resolves #66167. r? @eddyb
☀️ Test successful - checks-azure |
Tested on commit rust-lang/rust@0f0c640. Direct link to PR: <rust-lang/rust#66385> 💔 rustc-guide on linux: test-pass → test-fail (cc @amanjeev @spastorino @mark-i-m, @rust-lang/infra).
Enable `if` and `match` in constants behind a feature flag This PR is an initial implementation of #49146. It introduces a `const_if_match` feature flag and does the following if it is enabled: - Allows `Downcast` projections, `SwitchInt` terminators and `FakeRead`s for matched places through the MIR const-checker. - Allows `if` and `match` expressions through the HIR const-checker. - Stops converting `&&` to `&` and `||` to `|` in `const` and `static` items. As a result, the following operations are now allowed in a const context behind the feature flag: - `if` and `match` - short circuiting logic operators (`&&` and `||`) - the `assert` and `debug_assert` macros (if the `const_panic` feature flag is also enabled) However, the following operations remain forbidden: - `while`, `loop` and `for` (see #52000) - the `?` operator (calls `From::from` on its error variant) - the `assert_eq` and `assert_ne` macros, along with their `debug` variants (calls `fmt::Debug`) This PR is possible now that we use dataflow for const qualification (see #64470 and #66385). r? @oli-obk cc @rust-lang/wg-const-eval @eddyb
For over a month, dataflow-based const qualification has been running in parallel with
qualify_consts
to check the bodies ofconst
andstatic
s. This PR removes the old qualification pass completely in favor of the dataflow-based one.edit:
This PR also stops checking
QUALIF_ERROR_BIT
during promotion. This check appears to no longer serve a purpose now that the CTFE engine is more robust.As a side-effect, this resolves #66167.
r? @eddyb