Skip to content

Commit e356d5c

Browse files
Use hir::ConstContext instead of local enums
1 parent 3f661da commit e356d5c

File tree

6 files changed

+34
-134
lines changed

6 files changed

+34
-134
lines changed

src/librustc_mir/transform/check_consts/mod.rs

+3-65
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_middle::mir;
1010
use rustc_middle::ty::{self, TyCtxt};
1111

12-
use std::fmt;
13-
1412
pub use self::qualifs::Qualif;
1513

1614
mod ops;
@@ -25,7 +23,7 @@ pub struct ConstCx<'mir, 'tcx> {
2523
pub tcx: TyCtxt<'tcx>,
2624
pub def_id: DefId,
2725
pub param_env: ty::ParamEnv<'tcx>,
28-
pub const_kind: Option<ConstKind>,
26+
pub const_kind: Option<hir::ConstContext>,
2927
}
3028

3129
impl ConstCx<'mir, 'tcx> {
@@ -40,78 +38,18 @@ impl ConstCx<'mir, 'tcx> {
4038
body: &'mir mir::Body<'tcx>,
4139
param_env: ty::ParamEnv<'tcx>,
4240
) -> Self {
43-
let const_kind = ConstKind::for_item(tcx, def_id);
44-
41+
let const_kind = tcx.hir().body_const_context(def_id);
4542
ConstCx { body, tcx, def_id: def_id.to_def_id(), param_env, const_kind }
4643
}
4744

4845
/// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).
4946
///
5047
/// Panics if this `Item` is not const.
51-
pub fn const_kind(&self) -> ConstKind {
48+
pub fn const_kind(&self) -> hir::ConstContext {
5249
self.const_kind.expect("`const_kind` must not be called on a non-const fn")
5350
}
5451
}
5552

56-
/// The kinds of items which require compile-time evaluation.
57-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
58-
pub enum ConstKind {
59-
/// A `static` item.
60-
Static,
61-
/// A `static mut` item.
62-
StaticMut,
63-
/// A `const fn` item.
64-
ConstFn,
65-
/// A `const` item or an anonymous constant (e.g. in array lengths).
66-
Const,
67-
}
68-
69-
impl ConstKind {
70-
/// Returns the validation mode for the item with the given `DefId`, or `None` if this item
71-
/// does not require validation (e.g. a non-const `fn`).
72-
pub fn for_item(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Self> {
73-
use hir::BodyOwnerKind as HirKind;
74-
75-
let hir_id = tcx.hir().as_local_hir_id(def_id);
76-
77-
let mode = match tcx.hir().body_owner_kind(hir_id) {
78-
HirKind::Closure => return None,
79-
80-
// Note: this is deliberately checking for `is_const_fn_raw`, as the `is_const_fn`
81-
// checks take into account the `rustc_const_unstable` attribute combined with enabled
82-
// feature gates. Otherwise, const qualification would _not check_ whether this
83-
// function body follows the `const fn` rules, as an unstable `const fn` would
84-
// be considered "not const". More details are available in issue #67053.
85-
HirKind::Fn if tcx.is_const_fn_raw(def_id) => ConstKind::ConstFn,
86-
HirKind::Fn => return None,
87-
88-
HirKind::Const => ConstKind::Const,
89-
90-
HirKind::Static(hir::Mutability::Not) => ConstKind::Static,
91-
HirKind::Static(hir::Mutability::Mut) => ConstKind::StaticMut,
92-
};
93-
94-
Some(mode)
95-
}
96-
97-
pub fn is_static(self) -> bool {
98-
match self {
99-
ConstKind::Static | ConstKind::StaticMut => true,
100-
ConstKind::ConstFn | ConstKind::Const => false,
101-
}
102-
}
103-
}
104-
105-
impl fmt::Display for ConstKind {
106-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107-
match *self {
108-
ConstKind::Const => write!(f, "constant"),
109-
ConstKind::Static | ConstKind::StaticMut => write!(f, "static"),
110-
ConstKind::ConstFn => write!(f, "constant function"),
111-
}
112-
}
113-
}
114-
11553
/// Returns `true` if this `DefId` points to one of the official `panic` lang items.
11654
pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
11755
Some(def_id) == tcx.lang_items().panic_fn() || Some(def_id) == tcx.lang_items().begin_panic_fn()

src/librustc_mir/transform/check_consts/ops.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
33
use rustc_errors::struct_span_err;
4+
use rustc_hir as hir;
45
use rustc_hir::def_id::DefId;
56
use rustc_session::config::nightly_options;
67
use rustc_session::parse::feature_err;
78
use rustc_span::symbol::sym;
89
use rustc_span::{Span, Symbol};
910

10-
use super::{ConstCx, ConstKind};
11+
use super::ConstCx;
1112

1213
/// An operation that is not *always* allowed in a const context.
1314
pub trait NonConstOp: std::fmt::Debug {
@@ -323,7 +324,7 @@ impl NonConstOp for RawPtrToIntCast {
323324
pub struct StaticAccess;
324325
impl NonConstOp for StaticAccess {
325326
fn is_allowed_in_item(&self, ccx: &ConstCx<'_, '_>) -> bool {
326-
ccx.const_kind().is_static()
327+
matches!(ccx.const_kind(), hir::ConstContext::Static(_))
327328
}
328329

329330
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
@@ -371,7 +372,7 @@ pub struct UnionAccess;
371372
impl NonConstOp for UnionAccess {
372373
fn is_allowed_in_item(&self, ccx: &ConstCx<'_, '_>) -> bool {
373374
// Union accesses are stable in all contexts except `const fn`.
374-
ccx.const_kind() != ConstKind::ConstFn
375+
ccx.const_kind() != hir::ConstContext::ConstFn
375376
|| ccx.tcx.features().enabled(Self::feature_gate().unwrap())
376377
}
377378

src/librustc_mir/transform/check_consts/validation.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
22
33
use rustc_errors::struct_span_err;
4-
use rustc_hir::lang_items;
4+
use rustc_hir::{self as hir, lang_items};
55
use rustc_hir::{def_id::DefId, HirId};
66
use rustc_infer::infer::TyCtxtInferExt;
77
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
@@ -18,7 +18,7 @@ use std::ops::Deref;
1818
use super::ops::{self, NonConstOp};
1919
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
2020
use super::resolver::FlowSensitiveAnalysis;
21-
use super::{is_lang_panic_fn, ConstCx, ConstKind, Qualif};
21+
use super::{is_lang_panic_fn, ConstCx, Qualif};
2222
use crate::const_eval::{is_const_fn, is_unstable_const_fn};
2323
use crate::dataflow::MaybeMutBorrowedLocals;
2424
use crate::dataflow::{self, Analysis};
@@ -145,17 +145,13 @@ impl Qualifs<'mir, 'tcx> {
145145
// We don't care whether a `const fn` returns a value that is not structurally
146146
// matchable. Functions calls are opaque and always use type-based qualification, so
147147
// this value should never be used.
148-
ConstKind::ConstFn => true,
148+
hir::ConstContext::ConstFn => true,
149149

150150
// If we know that all values of the return type are structurally matchable, there's no
151151
// need to run dataflow.
152-
ConstKind::Const | ConstKind::Static | ConstKind::StaticMut
153-
if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) =>
154-
{
155-
false
156-
}
152+
_ if !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => false,
157153

158-
ConstKind::Const | ConstKind::Static | ConstKind::StaticMut => {
154+
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
159155
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
160156
.into_engine(ccx.tcx, &ccx.body, ccx.def_id)
161157
.iterate_to_fixpoint()
@@ -198,7 +194,7 @@ impl Validator<'mir, 'tcx> {
198194
pub fn check_body(&mut self) {
199195
let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
200196

201-
let use_min_const_fn_checks = (const_kind == Some(ConstKind::ConstFn)
197+
let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn)
202198
&& crate::const_eval::is_min_const_fn(tcx, def_id))
203199
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
204200

@@ -222,8 +218,9 @@ impl Validator<'mir, 'tcx> {
222218
self.visit_body(&body);
223219

224220
// Ensure that the end result is `Sync` in a non-thread local `static`.
225-
let should_check_for_sync =
226-
const_kind == Some(ConstKind::Static) && !tcx.is_thread_local_static(def_id);
221+
let should_check_for_sync = const_kind
222+
== Some(hir::ConstContext::Static(hir::Mutability::Not))
223+
&& !tcx.is_thread_local_static(def_id);
227224

228225
if should_check_for_sync {
229226
let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
@@ -351,7 +348,9 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
351348
let ty = place.ty(self.body, self.tcx).ty;
352349
let is_allowed = match ty.kind {
353350
// Inside a `static mut`, `&mut [...]` is allowed.
354-
ty::Array(..) | ty::Slice(_) if self.const_kind() == ConstKind::StaticMut => {
351+
ty::Array(..) | ty::Slice(_)
352+
if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) =>
353+
{
355354
true
356355
}
357356

src/librustc_mir/transform/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub fn run_passes(
182182
}
183183

184184
fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
185-
let const_kind = check_consts::ConstKind::for_item(tcx, def_id.expect_local());
185+
let const_kind = tcx.hir().body_const_context(def_id.expect_local());
186186

187187
// No need to const-check a non-const `fn`.
188188
if const_kind.is_none() {

src/librustc_mir/transform/promote_consts.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! move analysis runs after promotion on broken MIR.
1414
1515
use rustc_ast::ast::LitKind;
16+
use rustc_hir as hir;
1617
use rustc_hir::def_id::DefId;
1718
use rustc_middle::mir::traversal::ReversePostorder;
1819
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
@@ -30,7 +31,7 @@ use std::cell::Cell;
3031
use std::{cmp, iter, mem};
3132

3233
use crate::const_eval::{is_const_fn, is_unstable_const_fn};
33-
use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx, ConstKind};
34+
use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx};
3435
use crate::transform::{MirPass, MirSource};
3536

3637
/// A `MirPass` for promotion.
@@ -352,7 +353,9 @@ impl<'tcx> Validator<'_, 'tcx> {
352353
// In theory, any zero-sized value could be borrowed
353354
// mutably without consequences. However, only &mut []
354355
// is allowed right now, and only in functions.
355-
if self.const_kind == Some(ConstKind::StaticMut) {
356+
if self.const_kind
357+
== Some(hir::ConstContext::Static(hir::Mutability::Mut))
358+
{
356359
// Inside a `static mut`, &mut [...] is also allowed.
357360
match ty.kind {
358361
ty::Array(..) | ty::Slice(_) => {}
@@ -517,7 +520,7 @@ impl<'tcx> Validator<'_, 'tcx> {
517520
if let Some(def_id) = c.check_static_ptr(self.tcx) {
518521
// Only allow statics (not consts) to refer to other statics.
519522
// FIXME(eddyb) does this matter at all for promotion?
520-
let is_static = self.const_kind.map_or(false, |k| k.is_static());
523+
let is_static = matches!(self.const_kind, Some(hir::ConstContext::Static(_)));
521524
if !is_static {
522525
return Err(Unpromotable);
523526
}
@@ -607,7 +610,7 @@ impl<'tcx> Validator<'_, 'tcx> {
607610
// In theory, any zero-sized value could be borrowed
608611
// mutably without consequences. However, only &mut []
609612
// is allowed right now, and only in functions.
610-
if self.const_kind == Some(ConstKind::StaticMut) {
613+
if self.const_kind == Some(hir::ConstContext::Static(hir::Mutability::Mut)) {
611614
// Inside a `static mut`, &mut [...] is also allowed.
612615
match ty.kind {
613616
ty::Array(..) | ty::Slice(_) => {}

src/librustc_passes/check_const.rs

+7-48
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
88
//! through, but errors for structured control flow in a `const` should be emitted here.
99
10-
use rustc_ast::ast::Mutability;
1110
use rustc_errors::struct_span_err;
1211
use rustc_hir as hir;
1312
use rustc_hir::def_id::DefId;
@@ -19,8 +18,6 @@ use rustc_session::config::nightly_options;
1918
use rustc_session::parse::feature_err;
2019
use rustc_span::{sym, Span, Symbol};
2120

22-
use std::fmt;
23-
2421
/// An expression that is not *always* legal in a const context.
2522
#[derive(Clone, Copy)]
2623
enum NonConstExpr {
@@ -65,46 +62,6 @@ impl NonConstExpr {
6562
}
6663
}
6764

68-
#[derive(Copy, Clone)]
69-
enum ConstKind {
70-
Static,
71-
StaticMut,
72-
ConstFn,
73-
Const,
74-
AnonConst,
75-
}
76-
77-
impl ConstKind {
78-
fn for_body(body: &hir::Body<'_>, tcx: TyCtxt<'_>) -> Option<Self> {
79-
let owner = tcx.hir().body_owner(body.id());
80-
let const_kind = match tcx.hir().body_owner_kind(owner) {
81-
hir::BodyOwnerKind::Const => Self::Const,
82-
hir::BodyOwnerKind::Static(Mutability::Mut) => Self::StaticMut,
83-
hir::BodyOwnerKind::Static(Mutability::Not) => Self::Static,
84-
85-
hir::BodyOwnerKind::Fn if tcx.is_const_fn_raw(tcx.hir().local_def_id(owner)) => {
86-
Self::ConstFn
87-
}
88-
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
89-
};
90-
91-
Some(const_kind)
92-
}
93-
}
94-
95-
impl fmt::Display for ConstKind {
96-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97-
let s = match self {
98-
Self::Static => "static",
99-
Self::StaticMut => "static mut",
100-
Self::Const | Self::AnonConst => "const",
101-
Self::ConstFn => "const fn",
102-
};
103-
104-
write!(f, "{}", s)
105-
}
106-
}
107-
10865
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: DefId) {
10966
let mut vis = CheckConstVisitor::new(tcx);
11067
tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
@@ -117,7 +74,7 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
11774
#[derive(Copy, Clone)]
11875
struct CheckConstVisitor<'tcx> {
11976
tcx: TyCtxt<'tcx>,
120-
const_kind: Option<ConstKind>,
77+
const_kind: Option<hir::ConstContext>,
12178
}
12279

12380
impl<'tcx> CheckConstVisitor<'tcx> {
@@ -147,7 +104,8 @@ impl<'tcx> CheckConstVisitor<'tcx> {
147104
let const_kind = self
148105
.const_kind
149106
.expect("`const_check_violated` may only be called inside a const context");
150-
let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind);
107+
108+
let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
151109

152110
let required_gates = required_gates.unwrap_or(&[]);
153111
let missing_gates: Vec<_> =
@@ -191,7 +149,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
191149
}
192150

193151
/// Saves the parent `const_kind` before calling `f` and restores it afterwards.
194-
fn recurse_into(&mut self, kind: Option<ConstKind>, f: impl FnOnce(&mut Self)) {
152+
fn recurse_into(&mut self, kind: Option<hir::ConstContext>, f: impl FnOnce(&mut Self)) {
195153
let parent_kind = self.const_kind;
196154
self.const_kind = kind;
197155
f(self);
@@ -207,12 +165,13 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
207165
}
208166

209167
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
210-
let kind = Some(ConstKind::AnonConst);
168+
let kind = Some(hir::ConstContext::Const);
211169
self.recurse_into(kind, |this| intravisit::walk_anon_const(this, anon));
212170
}
213171

214172
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
215-
let kind = ConstKind::for_body(body, self.tcx);
173+
let owner = self.tcx.hir().body_owner_def_id(body.id());
174+
let kind = self.tcx.hir().body_const_context(owner);
216175
self.recurse_into(kind, |this| intravisit::walk_body(this, body));
217176
}
218177

0 commit comments

Comments
 (0)