Skip to content

Commit

Permalink
rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jul 2, 2019
1 parent 765eebf commit f6e5ac6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 13 deletions.
23 changes: 20 additions & 3 deletions src/librustc_mir/transform/qualify_consts.rs
Expand Up @@ -142,6 +142,7 @@ impl<'a, 'tcx> ConstCx<'a, 'tcx> {
#[derive(Copy, Clone, Debug)]
enum ValueSource<'a, 'tcx> {
Rvalue(&'a Rvalue<'tcx>),
DropAndReplace(&'a Operand<'tcx>),
Call {
callee: &'a Operand<'tcx>,
args: &'a [Operand<'tcx>],
Expand Down Expand Up @@ -298,6 +299,7 @@ trait Qualif {
fn in_value(cx: &ConstCx<'_, 'tcx>, source: ValueSource<'_, 'tcx>) -> bool {
match source {
ValueSource::Rvalue(rvalue) => Self::in_rvalue(cx, rvalue),
ValueSource::DropAndReplace(source) => Self::in_operand(cx, source),
ValueSource::Call { callee, args, return_ty } => {
Self::in_call(cx, callee, args, return_ty)
}
Expand Down Expand Up @@ -889,6 +891,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
let target = match body[bb].terminator().kind {
TerminatorKind::Goto { target } |
TerminatorKind::Drop { target, .. } |
TerminatorKind::DropAndReplace { target, .. } |
TerminatorKind::Assert { target, .. } |
TerminatorKind::Call { destination: Some((_, target)), .. } => {
Some(target)
Expand All @@ -900,7 +903,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
}

TerminatorKind::SwitchInt {..} |
TerminatorKind::DropAndReplace { .. } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::GeneratorDrop |
Expand Down Expand Up @@ -1393,8 +1395,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
for arg in args {
self.visit_operand(arg, location);
}
} else if let TerminatorKind::Drop { location: ref place, .. } = *kind {
self.super_terminator_kind(kind, location);
} else if let TerminatorKind::Drop {
location: ref place, ..
} | TerminatorKind::DropAndReplace {
location: ref place, ..
} = *kind {
match *kind {
TerminatorKind::DropAndReplace { .. } => {}
_ => self.super_terminator_kind(kind, location),
}

// Deny *any* live drops anywhere other than functions.
if self.mode.requires_const_checking() {
Expand Down Expand Up @@ -1423,6 +1432,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
}
}
}

match *kind {
TerminatorKind::DropAndReplace { ref value, .. } => {
self.assign(place, ValueSource::DropAndReplace(value), location);
self.visit_operand(value, location);
}
_ => {}
}
} else {
// Qualify any operands inside other terminators.
self.super_terminator_kind(kind, location);
Expand Down
15 changes: 13 additions & 2 deletions src/test/ui/consts/const-eval/const_let.rs
Expand Up @@ -9,10 +9,21 @@ impl Drop for FakeNeedsDrop {
// ok
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };

// ok (used to incorrectly error, see #62273)
const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x };

// error
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
//~^ ERROR constant contains unimplemented expression type
//~^ ERROR destructors cannot be evaluated at compile-time

// error
const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
//~^ ERROR destructors cannot be evaluated at compile-time

// error
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
//~^ ERROR constant contains unimplemented expression type
//~^ ERROR destructors cannot be evaluated at compile-time

// error
const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
//~^ ERROR destructors cannot be evaluated at compile-time
27 changes: 19 additions & 8 deletions src/test/ui/consts/const-eval/const_let.stderr
@@ -1,15 +1,26 @@
error[E0019]: constant contains unimplemented expression type
--> $DIR/const_let.rs:13:55
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/const_let.rs:16:32
|
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
| ^
| ^^^^^ constants cannot evaluate destructors

error[E0019]: constant contains unimplemented expression type
--> $DIR/const_let.rs:17:35
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/const_let.rs:20:33
|
LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
| ^^^^^ constants cannot evaluate destructors

error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/const_let.rs:24:21
|
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
| ^
| ^^^^^ constants cannot evaluate destructors

error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/const_let.rs:28:22
|
LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
| ^^^^^ constants cannot evaluate destructors

error: aborting due to 2 previous errors
error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0019`.

0 comments on commit f6e5ac6

Please sign in to comment.