Skip to content
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

Merged
merged 17 commits into from
Nov 17, 2019

Conversation

ecstatic-morse
Copy link
Contributor

@ecstatic-morse ecstatic-morse commented Nov 13, 2019

For over a month, dataflow-based const qualification has been running in parallel with qualify_consts to check the bodies of const and statics. 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

@rust-highfive

This comment has been minimized.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 13, 2019
@ecstatic-morse

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@ecstatic-morse ecstatic-morse marked this pull request as ready for review November 13, 2019 23:25

impl QualifSet {
fn contains<Q: ?Sized + Qualif>(self) -> bool {
pub const UNPROMOTABLE: Self = QualifSet(1 << Unpromotable::IDX);
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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;
}


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();
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently not 😃

@@ -185,6 +185,41 @@ pub fn run_passes(
body.phase = mir_phase;
}

fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
Copy link
Contributor

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.

Copy link
Member

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,
}

Copy link
Contributor Author

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?
Copy link
Contributor

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..."? ;)

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

@ecstatic-morse ecstatic-morse Nov 14, 2019

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?

@bors
Copy link
Contributor

bors commented Nov 14, 2019

☔ The latest upstream changes (presumably #66233) made this pull request unmergeable. Please resolve the merge conflicts.

@ecstatic-morse
Copy link
Contributor Author

Rebased to fix merge conflicts. The latest version moves QualifSet into rustc::mir and uses it everywhere.

@@ -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 {
Copy link
Member

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?

Copy link
Contributor Author

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,
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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).

Copy link
Contributor Author

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.

@@ -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.
Copy link
Member

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.

@@ -295,7 +295,7 @@ enum EntryKind<'tcx> {
/// Additional data for EntryKind::Const and EntryKind::AssocConst
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
struct ConstQualif {
Copy link
Member

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.

@bors
Copy link
Contributor

bors commented Nov 15, 2019

☔ 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.
@ecstatic-morse
Copy link
Contributor Author

@eddyb I believe I've resolved all your posted concerns. Let me know what else needs to be done.

@eddyb
Copy link
Member

eddyb commented Nov 15, 2019

@bors r+

@bors
Copy link
Contributor

bors commented Nov 15, 2019

📌 Commit a1135cc has been approved by eddyb

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 15, 2019
@Centril
Copy link
Contributor

Centril commented Nov 16, 2019

@bors rollup=never

@bors
Copy link
Contributor

bors commented Nov 17, 2019

⌛ Testing commit a1135cc with merge 0f0c640...

bors added a commit that referenced this pull request Nov 17, 2019
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
@bors
Copy link
Contributor

bors commented Nov 17, 2019

☀️ Test successful - checks-azure
Approved by: eddyb
Pushing 0f0c640 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Nov 17, 2019
@bors bors merged commit a1135cc into rust-lang:master Nov 17, 2019
@rust-highfive
Copy link
Collaborator

📣 Toolstate changed by #66385!

Tested on commit 0f0c640.
Direct link to PR: #66385

💔 rustc-guide on linux: test-pass → test-fail (cc @amanjeev @spastorino @mark-i-m, @rust-lang/infra).

rust-highfive added a commit to rust-lang-nursery/rust-toolstate that referenced this pull request Nov 17, 2019
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).
bors added a commit that referenced this pull request Nov 23, 2019
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
@ecstatic-morse ecstatic-morse deleted the check-only-pass2 branch October 6, 2020 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
6 participants