Skip to content

Commit 748bbf2

Browse files
Deduplicate promote_consts::Validator and check_consts::Item
1 parent 8a462ff commit 748bbf2

File tree

1 file changed

+30
-48
lines changed

1 file changed

+30
-48
lines changed

src/librustc_mir/transform/promote_consts.rs

+30-48
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//! initialization and can otherwise silence errors, if
1313
//! move analysis runs after promotion on broken MIR.
1414
15-
use rustc::hir;
1615
use rustc::hir::def_id::DefId;
1716
use rustc::mir::*;
1817
use rustc::mir::interpret::ConstValue;
@@ -30,7 +29,7 @@ use rustc_target::spec::abi::Abi;
3029

3130
use std::{iter, mem, usize};
3231

33-
use crate::transform::check_consts::{qualifs, Item as ConstCx};
32+
use crate::transform::check_consts::{qualifs, Item, ConstKind};
3433

3534
/// State of a temporary during collection and promotion.
3635
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -224,18 +223,13 @@ pub fn collect_temps_and_candidates(
224223
(collector.temps, collector.candidates)
225224
}
226225

226+
/// Checks whether locals that appear in a promotion context (`Candidate`) are actually promotable.
227+
///
228+
/// This wraps an `Item`, and has access to all fields of that `Item` via `Deref` coercion.
227229
struct Validator<'a, 'tcx> {
228-
tcx: TyCtxt<'tcx>,
229-
param_env: ty::ParamEnv<'tcx>,
230-
body: &'a Body<'tcx>,
231-
is_static: bool,
232-
is_static_mut: bool,
233-
is_non_const_fn: bool,
230+
item: Item<'a, 'tcx>,
234231
temps: &'a IndexVec<Local, TempState>,
235232

236-
// FIXME(eddyb) deduplicate the data in this vs other fields.
237-
const_cx: ConstCx<'a, 'tcx>,
238-
239233
/// Explicit promotion happens e.g. for constant arguments declared via
240234
/// `rustc_args_required_const`.
241235
/// Implicit promotion has almost the same rules, except that disallows `const fn`
@@ -245,6 +239,14 @@ struct Validator<'a, 'tcx> {
245239
explicit: bool,
246240
}
247241

242+
impl std::ops::Deref for Validator<'a, 'tcx> {
243+
type Target = Item<'a, 'tcx>;
244+
245+
fn deref(&self) -> &Self::Target {
246+
&self.item
247+
}
248+
}
249+
248250
struct Unpromotable;
249251

250252
impl<'tcx> Validator<'_, 'tcx> {
@@ -317,13 +319,14 @@ impl<'tcx> Validator<'_, 'tcx> {
317319
if self.qualif_local::<qualifs::NeedsDrop>(base) {
318320
return Err(Unpromotable);
319321
}
322+
320323
if let BorrowKind::Mut { .. } = kind {
321324
let ty = place.ty(self.body, self.tcx).ty;
322325

323326
// In theory, any zero-sized value could be borrowed
324327
// mutably without consequences. However, only &mut []
325328
// is allowed right now, and only in functions.
326-
if self.is_static_mut {
329+
if self.const_kind == Some(ConstKind::StaticMut) {
327330
// Inside a `static mut`, &mut [...] is also allowed.
328331
match ty.kind {
329332
ty::Array(..) | ty::Slice(_) => {}
@@ -333,7 +336,7 @@ impl<'tcx> Validator<'_, 'tcx> {
333336
// FIXME(eddyb) the `self.is_non_const_fn` condition
334337
// seems unnecessary, given that this is merely a ZST.
335338
match len.try_eval_usize(self.tcx, self.param_env) {
336-
Some(0) if self.is_non_const_fn => {},
339+
Some(0) if self.const_kind.is_none() => {},
337340
_ => return Err(Unpromotable),
338341
}
339342
} else {
@@ -386,7 +389,7 @@ impl<'tcx> Validator<'_, 'tcx> {
386389
let statement = &self.body[loc.block].statements[loc.statement_index];
387390
match &statement.kind {
388391
StatementKind::Assign(box(_, rhs)) => {
389-
Q::in_rvalue(&self.const_cx, per_local, rhs)
392+
Q::in_rvalue(&self.item, per_local, rhs)
390393
}
391394
_ => {
392395
span_bug!(statement.source_info.span, "{:?} is not an assignment",
@@ -398,7 +401,7 @@ impl<'tcx> Validator<'_, 'tcx> {
398401
match &terminator.kind {
399402
TerminatorKind::Call { func, args, .. } => {
400403
let return_ty = self.body.local_decls[local].ty;
401-
Q::in_call(&self.const_cx, per_local, func, args, return_ty)
404+
Q::in_call(&self.item, per_local, func, args, return_ty)
402405
}
403406
kind => {
404407
span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
@@ -462,8 +465,8 @@ impl<'tcx> Validator<'_, 'tcx> {
462465
} => {
463466
// Only allow statics (not consts) to refer to other statics.
464467
// FIXME(eddyb) does this matter at all for promotion?
465-
let allowed = self.is_static || self.is_static_mut;
466-
if !allowed {
468+
let is_static = self.const_kind.map_or(false, |k| k.is_static());
469+
if !is_static {
467470
return Err(Unpromotable);
468471
}
469472

@@ -490,7 +493,7 @@ impl<'tcx> Validator<'_, 'tcx> {
490493
}
491494

492495
ProjectionElem::Field(..) => {
493-
if self.is_non_const_fn {
496+
if self.const_kind.is_none() {
494497
let base_ty =
495498
Place::ty_from(place.base, proj_base, self.body, self.tcx).ty;
496499
if let Some(def) = base_ty.ty_adt_def() {
@@ -545,7 +548,7 @@ impl<'tcx> Validator<'_, 'tcx> {
545548

546549
fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
547550
match *rvalue {
548-
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.is_non_const_fn => {
551+
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => {
549552
let operand_ty = operand.ty(self.body, self.tcx);
550553
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
551554
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
@@ -559,7 +562,7 @@ impl<'tcx> Validator<'_, 'tcx> {
559562
}
560563
}
561564

562-
Rvalue::BinaryOp(op, ref lhs, _) if self.is_non_const_fn => {
565+
Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => {
563566
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind {
564567
assert!(op == BinOp::Eq || op == BinOp::Ne ||
565568
op == BinOp::Le || op == BinOp::Lt ||
@@ -600,17 +603,17 @@ impl<'tcx> Validator<'_, 'tcx> {
600603
// In theory, any zero-sized value could be borrowed
601604
// mutably without consequences. However, only &mut []
602605
// is allowed right now, and only in functions.
603-
if self.is_static_mut {
606+
if self.const_kind == Some(ConstKind::StaticMut) {
604607
// Inside a `static mut`, &mut [...] is also allowed.
605608
match ty.kind {
606609
ty::Array(..) | ty::Slice(_) => {}
607610
_ => return Err(Unpromotable),
608611
}
609612
} else if let ty::Array(_, len) = ty.kind {
610-
// FIXME(eddyb) the `self.is_non_const_fn` condition
611-
// seems unnecessary, given that this is merely a ZST.
613+
// FIXME(eddyb): We only return `Unpromotable` for `&mut []` inside a
614+
// const context which seems unnecessary given that this is merely a ZST.
612615
match len.try_eval_usize(self.tcx, self.param_env) {
613-
Some(0) if self.is_non_const_fn => {},
616+
Some(0) if self.const_kind.is_none() => {},
614617
_ => return Err(Unpromotable),
615618
}
616619
} else {
@@ -683,7 +686,7 @@ impl<'tcx> Validator<'_, 'tcx> {
683686
) -> Result<(), Unpromotable> {
684687
let fn_ty = callee.ty(self.body, self.tcx);
685688

686-
if !self.explicit && self.is_non_const_fn {
689+
if !self.explicit && self.const_kind.is_none() {
687690
if let ty::FnDef(def_id, _) = fn_ty.kind {
688691
// Never promote runtime `const fn` calls of
689692
// functions without `#[rustc_promotable]`.
@@ -714,6 +717,7 @@ impl<'tcx> Validator<'_, 'tcx> {
714717
}
715718
}
716719

720+
// FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`.
717721
pub fn validate_candidates(
718722
tcx: TyCtxt<'tcx>,
719723
body: &Body<'tcx>,
@@ -722,33 +726,11 @@ pub fn validate_candidates(
722726
candidates: &[Candidate],
723727
) -> Vec<Candidate> {
724728
let mut validator = Validator {
725-
tcx,
726-
param_env: tcx.param_env(def_id),
727-
body,
728-
is_static: false,
729-
is_static_mut: false,
730-
is_non_const_fn: false,
729+
item: Item::new(tcx, def_id, body),
731730
temps,
732-
733-
const_cx: ConstCx::new(tcx, def_id, body),
734-
735731
explicit: false,
736732
};
737733

738-
// FIXME(eddyb) remove the distinctions that make this necessary.
739-
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
740-
match tcx.hir().body_owner_kind(id) {
741-
hir::BodyOwnerKind::Closure => validator.is_non_const_fn = true,
742-
hir::BodyOwnerKind::Fn => {
743-
if !tcx.is_const_fn(def_id) {
744-
validator.is_non_const_fn = true;
745-
}
746-
},
747-
hir::BodyOwnerKind::Static(hir::MutImmutable) => validator.is_static = true,
748-
hir::BodyOwnerKind::Static(hir::MutMutable) => validator.is_static_mut = true,
749-
_ => {}
750-
}
751-
752734
candidates.iter().copied().filter(|&candidate| {
753735
validator.explicit = match candidate {
754736
Candidate::Ref(_) |

0 commit comments

Comments
 (0)