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

rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts. #62275

Merged
merged 1 commit into from
Jul 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 20 additions & 3 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 };
eddyb marked this conversation as resolved.
Show resolved Hide resolved

// 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
Original file line number Diff line number Diff line change
@@ -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`.