Skip to content

Commit 39bbc1e

Browse files
committed
Revert "Rollup merge of #80458 - RalfJung:promotion-refactor, r=oli-obk"
This reverts commit 46111c1, reversing changes made to 1975142.
1 parent 68ec332 commit 39bbc1e

File tree

1 file changed

+99
-115
lines changed

1 file changed

+99
-115
lines changed

compiler/rustc_mir/src/transform/promote_consts.rs

Lines changed: 99 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub enum TempState {
9090
impl TempState {
9191
pub fn is_promotable(&self) -> bool {
9292
debug!("is_promotable: self={:?}", self);
93-
matches!(self, TempState::Defined { .. })
93+
matches!(self, TempState::Defined { .. } )
9494
}
9595
}
9696

@@ -309,26 +309,50 @@ impl<'tcx> Validator<'_, 'tcx> {
309309
let statement = &self.body[loc.block].statements[loc.statement_index];
310310
match &statement.kind {
311311
StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => {
312+
match kind {
313+
BorrowKind::Shared | BorrowKind::Mut { .. } => {}
314+
315+
// FIXME(eddyb) these aren't promoted here but *could*
316+
// be promoted as part of a larger value because
317+
// `validate_rvalue` doesn't check them, need to
318+
// figure out what is the intended behavior.
319+
BorrowKind::Shallow | BorrowKind::Unique => return Err(Unpromotable),
320+
}
321+
312322
// We can only promote interior borrows of promotable temps (non-temps
313323
// don't get promoted anyway).
314324
self.validate_local(place.local)?;
315325

316-
// The reference operation itself must be promotable.
317-
// (Needs to come after `validate_local` to avoid ICEs.)
318-
self.validate_ref(*kind, place)?;
319-
320-
// We do not check all the projections (they do not get promoted anyway),
321-
// but we do stay away from promoting anything involving a dereference.
322326
if place.projection.contains(&ProjectionElem::Deref) {
323327
return Err(Unpromotable);
324328
}
325-
326-
// We cannot promote things that need dropping, since the promoted value
327-
// would not get dropped.
328329
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
329330
return Err(Unpromotable);
330331
}
331332

333+
// FIXME(eddyb) this duplicates part of `validate_rvalue`.
334+
let has_mut_interior =
335+
self.qualif_local::<qualifs::HasMutInterior>(place.local);
336+
if has_mut_interior {
337+
return Err(Unpromotable);
338+
}
339+
340+
if let BorrowKind::Mut { .. } = kind {
341+
let ty = place.ty(self.body, self.tcx).ty;
342+
343+
// In theory, any zero-sized value could be borrowed
344+
// mutably without consequences. However, only &mut []
345+
// is allowed right now.
346+
if let ty::Array(_, len) = ty.kind() {
347+
match len.try_eval_usize(self.tcx, self.param_env) {
348+
Some(0) => {}
349+
_ => return Err(Unpromotable),
350+
}
351+
} else {
352+
return Err(Unpromotable);
353+
}
354+
}
355+
332356
Ok(())
333357
}
334358
_ => bug!(),
@@ -548,115 +572,58 @@ impl<'tcx> Validator<'_, 'tcx> {
548572
}
549573
}
550574

551-
fn validate_ref(&self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> {
552-
match kind {
553-
// Reject these borrow types just to be safe.
554-
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
555-
BorrowKind::Shallow | BorrowKind::Unique => return Err(Unpromotable),
556-
557-
BorrowKind::Shared => {
558-
let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);
559-
if has_mut_interior {
575+
fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
576+
match *rvalue {
577+
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
578+
let operand_ty = operand.ty(self.body, self.tcx);
579+
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
580+
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
581+
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
582+
// ptr-to-int casts are not possible in consts and thus not promotable
560583
return Err(Unpromotable);
561584
}
562585
}
563586

564-
BorrowKind::Mut { .. } => {
565-
let ty = place.ty(self.body, self.tcx).ty;
587+
Rvalue::BinaryOp(op, ref lhs, _) => {
588+
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
589+
assert!(
590+
op == BinOp::Eq
591+
|| op == BinOp::Ne
592+
|| op == BinOp::Le
593+
|| op == BinOp::Lt
594+
|| op == BinOp::Ge
595+
|| op == BinOp::Gt
596+
|| op == BinOp::Offset
597+
);
566598

567-
// In theory, any zero-sized value could be borrowed
568-
// mutably without consequences. However, only &mut []
569-
// is allowed right now.
570-
if let ty::Array(_, len) = ty.kind() {
571-
match len.try_eval_usize(self.tcx, self.param_env) {
572-
Some(0) => {}
573-
_ => return Err(Unpromotable),
574-
}
575-
} else {
599+
// raw pointer operations are not allowed inside consts and thus not promotable
576600
return Err(Unpromotable);
577601
}
578602
}
579-
}
580-
581-
Ok(())
582-
}
583-
584-
fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
585-
match rvalue {
586-
Rvalue::Use(operand)
587-
| Rvalue::Repeat(operand, _)
588-
| Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => {
589-
self.validate_operand(operand)?;
590-
}
591603

592-
Rvalue::Discriminant(place) | Rvalue::Len(place) => {
593-
self.validate_place(place.as_ref())?
594-
}
604+
Rvalue::NullaryOp(NullOp::Box, _) => return Err(Unpromotable),
595605

596-
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
606+
// FIXME(RalfJung): the rest is *implicitly considered promotable*... that seems dangerous.
607+
_ => {}
608+
}
597609

598-
Rvalue::Cast(kind, operand, cast_ty) => {
599-
if matches!(kind, CastKind::Misc) {
600-
let operand_ty = operand.ty(self.body, self.tcx);
601-
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
602-
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
603-
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
604-
// ptr-to-int casts are not possible in consts and thus not promotable
605-
return Err(Unpromotable);
606-
}
607-
// int-to-ptr casts are fine, they just use the integer value at pointer type.
608-
}
610+
match rvalue {
611+
Rvalue::ThreadLocalRef(_) => Err(Unpromotable),
609612

610-
self.validate_operand(operand)?;
611-
}
613+
Rvalue::NullaryOp(..) => Ok(()),
612614

613-
Rvalue::BinaryOp(op, lhs, rhs) | Rvalue::CheckedBinaryOp(op, lhs, rhs) => {
614-
let op = *op;
615-
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
616-
// raw pointer operations are not allowed inside consts and thus not promotable
617-
assert!(matches!(
618-
op,
619-
BinOp::Eq
620-
| BinOp::Ne
621-
| BinOp::Le
622-
| BinOp::Lt
623-
| BinOp::Ge
624-
| BinOp::Gt
625-
| BinOp::Offset
626-
));
627-
return Err(Unpromotable);
628-
}
615+
Rvalue::Discriminant(place) | Rvalue::Len(place) => self.validate_place(place.as_ref()),
629616

630-
match op {
631-
// FIXME: reject operations that can fail -- namely, division and modulo.
632-
BinOp::Eq
633-
| BinOp::Ne
634-
| BinOp::Le
635-
| BinOp::Lt
636-
| BinOp::Ge
637-
| BinOp::Gt
638-
| BinOp::Offset
639-
| BinOp::Add
640-
| BinOp::Sub
641-
| BinOp::Mul
642-
| BinOp::Div
643-
| BinOp::Rem
644-
| BinOp::BitXor
645-
| BinOp::BitAnd
646-
| BinOp::BitOr
647-
| BinOp::Shl
648-
| BinOp::Shr => {}
649-
}
617+
Rvalue::Use(operand)
618+
| Rvalue::Repeat(operand, _)
619+
| Rvalue::UnaryOp(_, operand)
620+
| Rvalue::Cast(_, operand, _) => self.validate_operand(operand),
650621

622+
Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
651623
self.validate_operand(lhs)?;
652-
self.validate_operand(rhs)?;
624+
self.validate_operand(rhs)
653625
}
654626

655-
Rvalue::NullaryOp(op, _) => match op {
656-
NullOp::Box => return Err(Unpromotable),
657-
NullOp::SizeOf => {}
658-
},
659-
660627
Rvalue::AddressOf(_, place) => {
661628
// We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is
662629
// no problem, only using it is.
@@ -669,36 +636,53 @@ impl<'tcx> Validator<'_, 'tcx> {
669636
});
670637
}
671638
}
672-
return Err(Unpromotable);
639+
Err(Unpromotable)
673640
}
674641

675642
Rvalue::Ref(_, kind, place) => {
643+
if let BorrowKind::Mut { .. } = kind {
644+
let ty = place.ty(self.body, self.tcx).ty;
645+
646+
// In theory, any zero-sized value could be borrowed
647+
// mutably without consequences. However, only &mut []
648+
// is allowed right now.
649+
if let ty::Array(_, len) = ty.kind() {
650+
match len.try_eval_usize(self.tcx, self.param_env) {
651+
Some(0) => {}
652+
_ => return Err(Unpromotable),
653+
}
654+
} else {
655+
return Err(Unpromotable);
656+
}
657+
}
658+
676659
// Special-case reborrows to be more like a copy of the reference.
677-
let mut place_simplified = place.as_ref();
678-
if let [proj_base @ .., ProjectionElem::Deref] = &place_simplified.projection {
679-
let base_ty =
680-
Place::ty_from(place_simplified.local, proj_base, self.body, self.tcx).ty;
660+
let mut place = place.as_ref();
661+
if let [proj_base @ .., ProjectionElem::Deref] = &place.projection {
662+
let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
681663
if let ty::Ref(..) = base_ty.kind() {
682-
place_simplified =
683-
PlaceRef { local: place_simplified.local, projection: proj_base };
664+
place = PlaceRef { local: place.local, projection: proj_base };
684665
}
685666
}
686667

687-
self.validate_place(place_simplified)?;
668+
self.validate_place(place)?;
669+
670+
let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);
671+
if has_mut_interior {
672+
return Err(Unpromotable);
673+
}
688674

689-
// Check that the reference is fine (using the original place!).
690-
// (Needs to come after `validate_place` to avoid ICEs.)
691-
self.validate_ref(*kind, place)?;
675+
Ok(())
692676
}
693677

694-
Rvalue::Aggregate(_, operands) => {
678+
Rvalue::Aggregate(_, ref operands) => {
695679
for o in operands {
696680
self.validate_operand(o)?;
697681
}
682+
683+
Ok(())
698684
}
699685
}
700-
701-
Ok(())
702686
}
703687

704688
fn validate_call(

0 commit comments

Comments
 (0)