Skip to content

Commit

Permalink
Rollup merge of #90069 - tmiasko:promoted-const-qualif, r=oli-obk
Browse files Browse the repository at this point in the history
Fix const qualification when executed after promotion

The const qualification was so far performed before the promotion and
the implementation assumed that it will never encounter a promoted.

With `const_precise_live_drops` feature, checking for live drops is
delayed until after drop elaboration, which in turn runs after
promotion. so the assumption is no longer true. When evaluating
`NeedsNonConstDrop` it is now possible to encounter promoteds.

Use type base qualification for the promoted. It is a sound
approximation in general, and in the specific case of promoteds and
`NeedsNonConstDrop` it is precise.

Fixes #89938.
  • Loading branch information
JohnTitor committed Oct 22, 2021
2 parents 9ed9025 + 74c6636 commit a656bc5
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
11 changes: 9 additions & 2 deletions compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub trait Qualif {
/// Whether this `Qualif` is cleared when a local is moved from.
const IS_CLEARED_ON_MOVE: bool = false;

/// Whether this `Qualif` might be evaluated after the promotion and can encounter a promoted.
const ALLOW_PROMOTED: bool = false;

/// Extracts the field of `ConstQualifs` that corresponds to this `Qualif`.
fn in_qualifs(qualifs: &ConstQualifs) -> bool;

Expand Down Expand Up @@ -129,6 +132,7 @@ pub struct NeedsNonConstDrop;
impl Qualif for NeedsNonConstDrop {
const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop";
const IS_CLEARED_ON_MOVE: bool = true;
const ALLOW_PROMOTED: bool = true;

fn in_qualifs(qualifs: &ConstQualifs) -> bool {
qualifs.needs_non_const_drop
Expand Down Expand Up @@ -310,9 +314,12 @@ where
// Check the qualifs of the value of `const` items.
if let Some(ct) = constant.literal.const_for_ty() {
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val {
assert!(promoted.is_none());
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
// check performed after the promotion. Verify that with an assertion.
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(def.did).is_none() {
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/consts/precise-drop-with-promoted.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Regression test for issue #89938.
// check-pass
// compile-flags: --crate-type=lib
#![feature(const_precise_live_drops)]

pub const fn f() {
let _: Option<String> = None;
let _: &'static Option<String> = &None;
}

0 comments on commit a656bc5

Please sign in to comment.