Skip to content

Commit

Permalink
Rollup merge of rust-lang#90069 - tmiasko:promoted-const-qualif, r=ol…
Browse files Browse the repository at this point in the history
…i-obk

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 rust-lang#89938.
  • Loading branch information
JohnTitor authored Oct 22, 2021
2 parents a93e7e0 + 74c6636 commit efdb8e5
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 efdb8e5

Please sign in to comment.