Skip to content

Commit a9b1abe

Browse files
Remove IsNotPromotable and IsNotImplicitlyPromotable
The former was cleared from `qualifs_in_return_place`, and the latter was never checked. `QUALIF_ERROR_BIT` no longer corresponds to a real `Qualif`, however.
1 parent 383eb01 commit a9b1abe

File tree

1 file changed

+11
-235
lines changed

1 file changed

+11
-235
lines changed

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 11 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl fmt::Display for Mode {
6969
}
7070
}
7171

72-
const QUALIF_COUNT: usize = 4;
72+
const QUALIF_COUNT: usize = 2;
7373

7474
// FIXME(eddyb) once we can use const generics, replace this array with
7575
// something like `IndexVec` but for fixed-size arrays (`IndexArray`?).
@@ -78,20 +78,20 @@ struct PerQualif<T>([T; QUALIF_COUNT]);
7878

7979
impl<T: Clone> PerQualif<T> {
8080
fn new(x: T) -> Self {
81-
PerQualif([x.clone(), x.clone(), x.clone(), x])
81+
PerQualif([x.clone(), x])
8282
}
8383
}
8484

8585
impl<T> PerQualif<T> {
8686
fn as_mut(&mut self) -> PerQualif<&mut T> {
87-
let [x0, x1, x2, x3] = &mut self.0;
88-
PerQualif([x0, x1, x2, x3])
87+
let [x0, x1] = &mut self.0;
88+
PerQualif([x0, x1])
8989
}
9090

9191
fn zip<U>(self, other: PerQualif<U>) -> PerQualif<(T, U)> {
92-
let [x0, x1, x2, x3] = self.0;
93-
let [y0, y1, y2, y3] = other.0;
94-
PerQualif([(x0, y0), (x1, y1), (x2, y2), (x3, y3)])
92+
let [x0, x1] = self.0;
93+
let [y0, y1] = other.0;
94+
PerQualif([(x0, y0), (x1, y1)])
9595
}
9696
}
9797

@@ -427,195 +427,6 @@ impl Qualif for NeedsDrop {
427427
}
428428
}
429429

430-
/// Not promotable at all - non-`const fn` calls, `asm!`,
431-
/// pointer comparisons, ptr-to-int casts, etc.
432-
/// Inside a const context all constness rules apply, so promotion simply has to follow the regular
433-
/// constant rules (modulo interior mutability or `Drop` rules which are handled `HasMutInterior`
434-
/// and `NeedsDrop` respectively). Basically this duplicates the checks that the const-checking
435-
/// visitor enforces by emitting errors when working in const context.
436-
struct IsNotPromotable;
437-
438-
impl Qualif for IsNotPromotable {
439-
const IDX: usize = 2;
440-
441-
fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
442-
match static_.kind {
443-
StaticKind::Promoted(_, _) => unreachable!(),
444-
StaticKind::Static => {
445-
// Only allow statics (not consts) to refer to other statics.
446-
// FIXME(eddyb) does this matter at all for promotion?
447-
let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
448-
449-
!allowed ||
450-
cx.tcx.get_attrs(static_.def_id).iter().any(
451-
|attr| attr.check_name(sym::thread_local)
452-
)
453-
}
454-
}
455-
}
456-
457-
fn in_projection(
458-
cx: &ConstCx<'_, 'tcx>,
459-
place: PlaceRef<'_, 'tcx>,
460-
) -> bool {
461-
if let [proj_base @ .., elem] = place.projection {
462-
match elem {
463-
ProjectionElem::Deref |
464-
ProjectionElem::Downcast(..) => return true,
465-
466-
ProjectionElem::ConstantIndex {..} |
467-
ProjectionElem::Subslice {..} |
468-
ProjectionElem::Index(_) => {}
469-
470-
ProjectionElem::Field(..) => {
471-
if cx.mode == Mode::NonConstFn {
472-
let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty;
473-
if let Some(def) = base_ty.ty_adt_def() {
474-
// No promotion of union field accesses.
475-
if def.is_union() {
476-
return true;
477-
}
478-
}
479-
}
480-
}
481-
}
482-
483-
Self::in_projection_structurally(cx, place)
484-
} else {
485-
bug!("This should be called if projection is not empty");
486-
}
487-
}
488-
489-
fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool {
490-
match *rvalue {
491-
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if cx.mode == Mode::NonConstFn => {
492-
let operand_ty = operand.ty(cx.body, cx.tcx);
493-
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
494-
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
495-
match (cast_in, cast_out) {
496-
(CastTy::Ptr(_), CastTy::Int(_)) |
497-
(CastTy::FnPtr, CastTy::Int(_)) => {
498-
// in normal functions, mark such casts as not promotable
499-
return true;
500-
}
501-
_ => {}
502-
}
503-
}
504-
505-
Rvalue::BinaryOp(op, ref lhs, _) if cx.mode == Mode::NonConstFn => {
506-
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(cx.body, cx.tcx).kind {
507-
assert!(op == BinOp::Eq || op == BinOp::Ne ||
508-
op == BinOp::Le || op == BinOp::Lt ||
509-
op == BinOp::Ge || op == BinOp::Gt ||
510-
op == BinOp::Offset);
511-
512-
// raw pointer operations are not allowed inside promoteds
513-
return true;
514-
}
515-
}
516-
517-
Rvalue::NullaryOp(NullOp::Box, _) => return true,
518-
519-
_ => {}
520-
}
521-
522-
Self::in_rvalue_structurally(cx, rvalue)
523-
}
524-
525-
fn in_call(
526-
cx: &ConstCx<'_, 'tcx>,
527-
callee: &Operand<'tcx>,
528-
args: &[Operand<'tcx>],
529-
_return_ty: Ty<'tcx>,
530-
) -> bool {
531-
let fn_ty = callee.ty(cx.body, cx.tcx);
532-
match fn_ty.kind {
533-
ty::FnDef(def_id, _) => {
534-
match cx.tcx.fn_sig(def_id).abi() {
535-
Abi::RustIntrinsic |
536-
Abi::PlatformIntrinsic => {
537-
assert!(!cx.tcx.is_const_fn(def_id));
538-
match &*cx.tcx.item_name(def_id).as_str() {
539-
| "size_of"
540-
| "min_align_of"
541-
| "needs_drop"
542-
| "type_id"
543-
| "bswap"
544-
| "bitreverse"
545-
| "ctpop"
546-
| "cttz"
547-
| "cttz_nonzero"
548-
| "ctlz"
549-
| "ctlz_nonzero"
550-
| "wrapping_add"
551-
| "wrapping_sub"
552-
| "wrapping_mul"
553-
| "unchecked_shl"
554-
| "unchecked_shr"
555-
| "rotate_left"
556-
| "rotate_right"
557-
| "add_with_overflow"
558-
| "sub_with_overflow"
559-
| "mul_with_overflow"
560-
| "saturating_add"
561-
| "saturating_sub"
562-
| "transmute"
563-
| "simd_insert"
564-
| "simd_extract"
565-
| "ptr_offset_from"
566-
=> return true,
567-
568-
_ => {}
569-
}
570-
}
571-
_ => {
572-
let is_const_fn =
573-
cx.tcx.is_const_fn(def_id) ||
574-
cx.tcx.is_unstable_const_fn(def_id).is_some() ||
575-
cx.is_const_panic_fn(def_id);
576-
if !is_const_fn {
577-
return true;
578-
}
579-
}
580-
}
581-
}
582-
_ => return true,
583-
}
584-
585-
Self::in_operand(cx, callee) || args.iter().any(|arg| Self::in_operand(cx, arg))
586-
}
587-
}
588-
589-
/// Refers to temporaries which cannot be promoted *implicitly*.
590-
/// Explicit promotion happens e.g. for constant arguments declared via `rustc_args_required_const`.
591-
/// Implicit promotion has almost the same rules, except that disallows `const fn` except for
592-
/// those marked `#[rustc_promotable]`. This is to avoid changing a legitimate run-time operation
593-
/// into a failing compile-time operation e.g. due to addresses being compared inside the function.
594-
struct IsNotImplicitlyPromotable;
595-
596-
impl Qualif for IsNotImplicitlyPromotable {
597-
const IDX: usize = 3;
598-
599-
fn in_call(
600-
cx: &ConstCx<'_, 'tcx>,
601-
callee: &Operand<'tcx>,
602-
args: &[Operand<'tcx>],
603-
_return_ty: Ty<'tcx>,
604-
) -> bool {
605-
if cx.mode == Mode::NonConstFn {
606-
if let ty::FnDef(def_id, _) = callee.ty(cx.body, cx.tcx).kind {
607-
// Never promote runtime `const fn` calls of
608-
// functions without `#[rustc_promotable]`.
609-
if !cx.tcx.is_promotable_const_fn(def_id) {
610-
return true;
611-
}
612-
}
613-
}
614-
615-
Self::in_operand(cx, callee) || args.iter().any(|arg| Self::in_operand(cx, arg))
616-
}
617-
}
618-
619430
// Ensure the `IDX` values are sequential (`0..QUALIF_COUNT`).
620431
macro_rules! static_assert_seq_qualifs {
621432
($i:expr => $first:ident $(, $rest:ident)*) => {
@@ -630,35 +441,28 @@ macro_rules! static_assert_seq_qualifs {
630441
};
631442
}
632443
static_assert_seq_qualifs!(
633-
0 => HasMutInterior, NeedsDrop, IsNotPromotable, IsNotImplicitlyPromotable
444+
0 => HasMutInterior, NeedsDrop
634445
);
635446

636447
impl ConstCx<'_, 'tcx> {
637448
fn qualifs_in_any_value_of_ty(&self, ty: Ty<'tcx>) -> PerQualif<bool> {
638449
let mut qualifs = PerQualif::default();
639450
qualifs[HasMutInterior] = HasMutInterior::in_any_value_of_ty(self, ty).unwrap_or(false);
640451
qualifs[NeedsDrop] = NeedsDrop::in_any_value_of_ty(self, ty).unwrap_or(false);
641-
qualifs[IsNotPromotable] = IsNotPromotable::in_any_value_of_ty(self, ty).unwrap_or(false);
642-
qualifs[IsNotImplicitlyPromotable] =
643-
IsNotImplicitlyPromotable::in_any_value_of_ty(self, ty).unwrap_or(false);
644452
qualifs
645453
}
646454

647455
fn qualifs_in_local(&self, local: Local) -> PerQualif<bool> {
648456
let mut qualifs = PerQualif::default();
649457
qualifs[HasMutInterior] = HasMutInterior::in_local(self, local);
650458
qualifs[NeedsDrop] = NeedsDrop::in_local(self, local);
651-
qualifs[IsNotPromotable] = IsNotPromotable::in_local(self, local);
652-
qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_local(self, local);
653459
qualifs
654460
}
655461

656462
fn qualifs_in_value(&self, source: ValueSource<'_, 'tcx>) -> PerQualif<bool> {
657463
let mut qualifs = PerQualif::default();
658464
qualifs[HasMutInterior] = HasMutInterior::in_value(self, source);
659465
qualifs[NeedsDrop] = NeedsDrop::in_value(self, source);
660-
qualifs[IsNotPromotable] = IsNotPromotable::in_value(self, source);
661-
qualifs[IsNotImplicitlyPromotable] = IsNotImplicitlyPromotable::in_value(self, source);
662466
qualifs
663467
}
664468
}
@@ -729,14 +533,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
729533
}
730534
}
731535
}
732-
if !temps[local].is_promotable() {
733-
cx.per_local[IsNotPromotable].insert(local);
734-
}
735-
if let LocalKind::Var = body.local_kind(local) {
736-
// Sanity check to prevent implicit and explicit promotion of
737-
// named locals
738-
assert!(cx.per_local[IsNotPromotable].contains(local));
739-
}
740536
}
741537

742538
Checker {
@@ -795,11 +591,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
795591
// the borrowed place is disallowed from being borrowed,
796592
// due to either a mutable borrow (with some exceptions),
797593
// or an shared borrow of a value with interior mutability.
798-
// Then `HasMutInterior` is replaced with `IsNotPromotable`,
594+
// Then `HasMutInterior` is cleared
799595
// to avoid duplicate errors (e.g. from reborrowing).
800596
if qualifs[HasMutInterior] {
801597
qualifs[HasMutInterior] = false;
802-
qualifs[IsNotPromotable] = true;
803598

804599
debug!("suppress_errors: {}", self.suppress_errors);
805600
if self.mode.requires_const_checking() && !self.suppress_errors {
@@ -884,18 +679,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
884679
per_local.insert(index);
885680
}
886681
}
887-
888-
// Ensure the `IsNotPromotable` qualification is preserved.
889-
// NOTE(eddyb) this is actually unnecessary right now, as
890-
// we never replace the local's qualif, but we might in
891-
// the future, and so it serves to catch changes that unset
892-
// important bits (in which case, asserting `contains` could
893-
// be replaced with calling `insert` to re-set the bit).
894-
if kind == LocalKind::Temp {
895-
if !self.temp_promotion_state[index].is_promotable() {
896-
assert!(self.cx.per_local[IsNotPromotable].contains(index));
897-
}
898-
}
899682
}
900683

901684
/// Check a whole const, static initializer or const fn.
@@ -1041,14 +824,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
1041824
}
1042825
}
1043826

1044-
let mut qualifs = self.qualifs_in_local(RETURN_PLACE);
1045-
1046-
// Account for errors in consts by using the
1047-
// conservative type qualification instead.
1048-
if qualifs[IsNotPromotable] {
1049-
qualifs = self.qualifs_in_any_value_of_ty(body.return_ty());
1050-
}
1051-
827+
let qualifs = self.qualifs_in_local(RETURN_PLACE);
1052828
(qualifs.encode_to_bits(), self.tcx.arena.alloc(promoted_temps))
1053829
}
1054830
}
@@ -1577,7 +1353,7 @@ pub fn provide(providers: &mut Providers<'_>) {
15771353

15781354
// FIXME(eddyb) this is only left around for the validation logic
15791355
// in `promote_consts`, see the comment in `validate_operand`.
1580-
pub(super) const QUALIF_ERROR_BIT: u8 = 1 << IsNotPromotable::IDX;
1356+
pub(super) const QUALIF_ERROR_BIT: u8 = 1 << 2;
15811357

15821358
fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet<Local>) {
15831359
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value

0 commit comments

Comments
 (0)