Skip to content

Commit 0f0c640

Browse files
committed
Auto merge of #66385 - ecstatic-morse:check-only-pass2, r=eddyb
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
2 parents d801458 + a1135cc commit 0f0c640

File tree

20 files changed

+296
-1650
lines changed

20 files changed

+296
-1650
lines changed

src/librustc/mir/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2763,6 +2763,17 @@ pub struct BorrowCheckResult<'tcx> {
27632763
pub used_mut_upvars: SmallVec<[Field; 8]>,
27642764
}
27652765

2766+
/// The result of the `mir_const_qualif` query.
2767+
///
2768+
/// Each field corresponds to an implementer of the `Qualif` trait in
2769+
/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
2770+
/// `Qualif`.
2771+
#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
2772+
pub struct ConstQualifs {
2773+
pub has_mut_interior: bool,
2774+
pub needs_drop: bool,
2775+
}
2776+
27662777
/// After we borrow check a closure, we are left with various
27672778
/// requirements that we have inferred between the free regions that
27682779
/// appear in the closure's signature or on its field types. These

src/librustc/query/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ rustc_queries! {
9191
}
9292

9393
/// Maps DefId's that have an associated `mir::Body` to the result
94-
/// of the MIR qualify_consts pass. The actual meaning of
95-
/// the value isn't known except to the pass itself.
96-
query mir_const_qualif(key: DefId) -> u8 {
94+
/// of the MIR const-checking pass. This is the set of qualifs in
95+
/// the final value of a `const`.
96+
query mir_const_qualif(key: DefId) -> mir::ConstQualifs {
9797
desc { |tcx| "const checking `{}`", tcx.def_path_str(key) }
9898
cache_on_disk_if { key.is_local() }
9999
}

src/librustc/session/config.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1373,8 +1373,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
13731373
"describes how to render the `rendered` field of json diagnostics"),
13741374
unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED],
13751375
"take the breaks off const evaluation. NOTE: this is unsound"),
1376-
suppress_const_validation_back_compat_ice: bool = (false, parse_bool, [TRACKED],
1377-
"silence ICE triggered when the new const validator disagrees with the old"),
13781376
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
13791377
"pass `-install_name @rpath/...` to the macOS linker"),
13801378
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],

src/librustc_metadata/rmeta/decoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -952,12 +952,12 @@ impl<'a, 'tcx> CrateMetadata {
952952
.decode((self, tcx))
953953
}
954954

955-
fn mir_const_qualif(&self, id: DefIndex) -> u8 {
955+
fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
956956
match self.kind(id) {
957957
EntryKind::Const(qualif, _) |
958958
EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) |
959959
EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => {
960-
qualif.mir
960+
qualif
961961
}
962962
_ => bug!(),
963963
}

src/librustc_metadata/rmeta/encoder.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,11 @@ impl EncodeContext<'tcx> {
875875
hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item));
876876
let rendered_const = self.lazy(RenderedConst(rendered));
877877

878-
EntryKind::AssocConst(container, ConstQualif { mir: 0 }, rendered_const)
878+
EntryKind::AssocConst(
879+
container,
880+
Default::default(),
881+
rendered_const,
882+
)
879883
}
880884
ty::AssocKind::Method => {
881885
let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind {
@@ -955,10 +959,11 @@ impl EncodeContext<'tcx> {
955959
record!(self.per_def.kind[def_id] <- match impl_item.kind {
956960
ty::AssocKind::Const => {
957961
if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
958-
let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
962+
let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
959963

960-
EntryKind::AssocConst(container,
961-
ConstQualif { mir },
964+
EntryKind::AssocConst(
965+
container,
966+
qualifs,
962967
self.encode_rendered_const_for_body(body_id))
963968
} else {
964969
bug!()
@@ -1089,9 +1094,9 @@ impl EncodeContext<'tcx> {
10891094
hir::ItemKind::Static(_, hir::Mutability::Mutable, _) => EntryKind::MutStatic,
10901095
hir::ItemKind::Static(_, hir::Mutability::Immutable, _) => EntryKind::ImmStatic,
10911096
hir::ItemKind::Const(_, body_id) => {
1092-
let mir = self.tcx.at(item.span).mir_const_qualif(def_id);
1097+
let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
10931098
EntryKind::Const(
1094-
ConstQualif { mir },
1099+
qualifs,
10951100
self.encode_rendered_const_for_body(body_id)
10961101
)
10971102
}
@@ -1368,9 +1373,9 @@ impl EncodeContext<'tcx> {
13681373
let id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
13691374
let body_id = self.tcx.hir().body_owned_by(id);
13701375
let const_data = self.encode_rendered_const_for_body(body_id);
1371-
let mir = self.tcx.mir_const_qualif(def_id);
1376+
let qualifs = self.tcx.mir_const_qualif(def_id);
13721377

1373-
record!(self.per_def.kind[def_id] <- EntryKind::Const(ConstQualif { mir }, const_data));
1378+
record!(self.per_def.kind[def_id] <- EntryKind::Const(qualifs, const_data));
13741379
record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
13751380
record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
13761381
self.encode_item_type(def_id);

src/librustc_metadata/rmeta/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ crate struct LazyPerDefTables<'tcx> {
260260

261261
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
262262
enum EntryKind<'tcx> {
263-
Const(ConstQualif, Lazy<RenderedConst>),
263+
Const(mir::ConstQualifs, Lazy<RenderedConst>),
264264
ImmStatic,
265265
MutStatic,
266266
ForeignImmStatic,
@@ -288,16 +288,10 @@ enum EntryKind<'tcx> {
288288
Method(Lazy<MethodData>),
289289
AssocType(AssocContainer),
290290
AssocOpaqueTy(AssocContainer),
291-
AssocConst(AssocContainer, ConstQualif, Lazy<RenderedConst>),
291+
AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
292292
TraitAlias,
293293
}
294294

295-
/// Additional data for EntryKind::Const and EntryKind::AssocConst
296-
#[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
297-
struct ConstQualif {
298-
mir: u8,
299-
}
300-
301295
/// Contains a constant which has been rendered to a String.
302296
/// Used by rustdoc.
303297
#[derive(RustcEncodable, RustcDecodable)]

src/librustc_mir/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
3232

3333
#[macro_use] extern crate log;
3434
#[macro_use] extern crate rustc;
35-
#[macro_use] extern crate rustc_data_structures;
3635
#[macro_use] extern crate syntax;
3736

3837
mod borrow_check;

src/librustc_mir/transform/check_consts/mod.rs

-10
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,6 @@ impl ConstKind {
9595
ConstKind::ConstFn | ConstKind::Const => false,
9696
}
9797
}
98-
99-
/// Returns `true` if the value returned by this item must be `Sync`.
100-
///
101-
/// This returns false for `StaticMut` since all accesses to one are `unsafe` anyway.
102-
pub fn requires_sync(self) -> bool {
103-
match self {
104-
ConstKind::Static => true,
105-
ConstKind::ConstFn | ConstKind::Const | ConstKind::StaticMut => false,
106-
}
107-
}
10898
}
10999

110100
impl fmt::Display for ConstKind {

src/librustc_mir/transform/check_consts/ops.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,15 @@ impl NonConstOp for HeapAllocation {
138138

139139
#[derive(Debug)]
140140
pub struct IfOrMatch;
141-
impl NonConstOp for IfOrMatch {}
141+
impl NonConstOp for IfOrMatch {
142+
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
143+
// This should be caught by the HIR const-checker.
144+
item.tcx.sess.delay_span_bug(
145+
span,
146+
"complex control flow is forbidden in a const context",
147+
);
148+
}
149+
}
142150

143151
#[derive(Debug)]
144152
pub struct LiveDrop;
@@ -154,7 +162,15 @@ impl NonConstOp for LiveDrop {
154162

155163
#[derive(Debug)]
156164
pub struct Loop;
157-
impl NonConstOp for Loop {}
165+
impl NonConstOp for Loop {
166+
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
167+
// This should be caught by the HIR const-checker.
168+
item.tcx.sess.delay_span_bug(
169+
span,
170+
"complex control flow is forbidden in a const context",
171+
);
172+
}
173+
}
158174

159175
#[derive(Debug)]
160176
pub struct MutBorrow(pub BorrowKind);

src/librustc_mir/transform/check_consts/qualifs.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ use syntax_pos::DUMMY_SP;
66

77
use super::{ConstKind, Item as ConstCx};
88

9-
#[derive(Clone, Copy)]
10-
pub struct QualifSet(u8);
11-
12-
impl QualifSet {
13-
fn contains<Q: ?Sized + Qualif>(self) -> bool {
14-
self.0 & (1 << Q::IDX) != 0
9+
pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs {
10+
ConstQualifs {
11+
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
12+
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
1513
}
1614
}
1715

@@ -22,14 +20,14 @@ impl QualifSet {
2220
///
2321
/// The default implementations proceed structurally.
2422
pub trait Qualif {
25-
const IDX: usize;
26-
2723
/// The name of the file used to debug the dataflow analysis that computes this qualif.
2824
const ANALYSIS_NAME: &'static str;
2925

3026
/// Whether this `Qualif` is cleared when a local is moved from.
3127
const IS_CLEARED_ON_MOVE: bool = false;
3228

29+
fn in_qualifs(qualifs: &ConstQualifs) -> bool;
30+
3331
/// Return the qualification that is (conservatively) correct for any value
3432
/// of the type.
3533
fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
@@ -122,9 +120,8 @@ pub trait Qualif {
122120
if cx.tcx.trait_of_item(def_id).is_some() {
123121
Self::in_any_value_of_ty(cx, constant.literal.ty)
124122
} else {
125-
let bits = cx.tcx.at(constant.span).mir_const_qualif(def_id);
126-
127-
let qualif = QualifSet(bits).contains::<Self>();
123+
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);
124+
let qualif = Self::in_qualifs(&qualifs);
128125

129126
// Just in case the type is more specific than
130127
// the definition, e.g., impl associated const
@@ -210,9 +207,12 @@ pub trait Qualif {
210207
pub struct HasMutInterior;
211208

212209
impl Qualif for HasMutInterior {
213-
const IDX: usize = 0;
214210
const ANALYSIS_NAME: &'static str = "flow_has_mut_interior";
215211

212+
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
213+
qualifs.has_mut_interior
214+
}
215+
216216
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
217217
!ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP)
218218
}
@@ -275,10 +275,13 @@ impl Qualif for HasMutInterior {
275275
pub struct NeedsDrop;
276276

277277
impl Qualif for NeedsDrop {
278-
const IDX: usize = 1;
279278
const ANALYSIS_NAME: &'static str = "flow_needs_drop";
280279
const IS_CLEARED_ON_MOVE: bool = true;
281280

281+
fn in_qualifs(qualifs: &ConstQualifs) -> bool {
282+
qualifs.needs_drop
283+
}
284+
282285
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
283286
ty.needs_drop(cx.tcx, cx.param_env)
284287
}

0 commit comments

Comments
 (0)