Rollup merge of #62275 - eddyb:const-drop-replace, r=pnkfelix
rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts. This slipped through the cracks and never got implemented (thankfully that just meant it was overly conservative and didn't allow assignments that don't *actually* drop the previous value). Fixes #62273. r? @oli-obk
This commit is contained in:
@@ -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>],
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
@@ -900,7 +903,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
TerminatorKind::SwitchInt {..} |
|
||||
TerminatorKind::DropAndReplace { .. } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Abort |
|
||||
TerminatorKind::GeneratorDrop |
|
||||
@@ -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() {
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: aborting due to 2 previous errors
|
||||
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 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0019`.
|
||||
|
||||
Reference in New Issue
Block a user