Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some Promotion Refactoring #80458

Merged
merged 4 commits into from
Dec 31, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 41 additions & 39 deletions compiler/rustc_mir/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub enum TempState {
impl TempState {
pub fn is_promotable(&self) -> bool {
debug!("is_promotable: self={:?}", self);
matches!(self, TempState::Defined { .. } )
matches!(self, TempState::Defined { .. })
}
}

Expand Down Expand Up @@ -329,7 +329,6 @@ impl<'tcx> Validator<'_, 'tcx> {
return Err(Unpromotable);
}


Ok(())
}
_ => bug!(),
Expand Down Expand Up @@ -583,18 +582,33 @@ impl<'tcx> Validator<'_, 'tcx> {
}

fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
match *rvalue {
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
let operand_ty = operand.ty(self.body, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
// ptr-to-int casts are not possible in consts and thus not promotable
return Err(Unpromotable);
match rvalue {
Rvalue::Use(operand) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_, operand) => {
self.validate_operand(operand)?;
}

Rvalue::Discriminant(place) | Rvalue::Len(place) => self.validate_place(place.as_ref())?,

Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),

Rvalue::Cast(kind, operand, cast_ty) => {
if matches!(kind, CastKind::Misc) {
let operand_ty = operand.ty(self.body, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
// ptr-to-int casts are not possible in consts and thus not promotable
return Err(Unpromotable);
}
// int-to-ptr casts are fine, they just use the integer value at pointer type.
}

self.validate_operand(operand)?;
}

Rvalue::BinaryOp(op, ref lhs, _) => {
Rvalue::BinaryOp(op, lhs, rhs)
| Rvalue::CheckedBinaryOp(op, lhs, rhs) => {
let op = *op;
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
assert!(
op == BinOp::Eq
Expand All @@ -609,29 +623,17 @@ impl<'tcx> Validator<'_, 'tcx> {
// raw pointer operations are not allowed inside consts and thus not promotable
return Err(Unpromotable);
}
}

Rvalue::NullaryOp(NullOp::Box, _) => return Err(Unpromotable),

// FIXME(RalfJung): the rest is *implicitly considered promotable*... that seems dangerous.
_ => {}
}

match rvalue {
Rvalue::ThreadLocalRef(_) => Err(Unpromotable),

Rvalue::NullaryOp(..) => Ok(()),

Rvalue::Discriminant(place) | Rvalue::Len(place) => self.validate_place(place.as_ref()),
// FIXME: reject operations that can fail -- namely, division and modulo.

Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_, operand)
| Rvalue::Cast(_, operand, _) => self.validate_operand(operand),

Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
self.validate_operand(lhs)?;
self.validate_operand(rhs)
self.validate_operand(rhs)?;
}

Rvalue::NullaryOp(op, _) => {
if matches!(op, NullOp::Box) {
return Err(Unpromotable);
}
}

Rvalue::AddressOf(_, place) => {
Expand All @@ -646,16 +648,18 @@ impl<'tcx> Validator<'_, 'tcx> {
});
}
}
Err(Unpromotable)
return Err(Unpromotable);
}

Rvalue::Ref(_, kind, place) => {
// Special-case reborrows to be more like a copy of the reference.
let mut place_simplified = place.as_ref();
if let [proj_base @ .., ProjectionElem::Deref] = &place_simplified.projection {
let base_ty = Place::ty_from(place_simplified.local, proj_base, self.body, self.tcx).ty;
let base_ty =
Place::ty_from(place_simplified.local, proj_base, self.body, self.tcx).ty;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh what happened here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just rustfmt, or is there any other difference that I am missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, but I was confused why rustfmt would do this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is being rustfmt? ;)

The variable name got longer, since I need to keep the original place around. As a result this line crossed the threshold.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh... this is due to an intermediate state that was reverted later? Because this specific line is exactly the same (modulo whitespace) as the line that was there before.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I didn't fmt between all commits.

if let ty::Ref(..) = base_ty.kind() {
place_simplified = PlaceRef { local: place_simplified.local, projection: proj_base };
place_simplified =
PlaceRef { local: place_simplified.local, projection: proj_base };
}
}

Expand All @@ -664,18 +668,16 @@ impl<'tcx> Validator<'_, 'tcx> {
// Check that the reference is fine (using the original place!).
// (Needs to come after `validate_local` to avoid ICEs.)
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
self.validate_ref(*kind, place)?;

Ok(())
}

Rvalue::Aggregate(_, ref operands) => {
Rvalue::Aggregate(_, operands) => {
for o in operands {
self.validate_operand(o)?;
}

Ok(())
}
}

Ok(())
}

fn validate_call(
Expand Down