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)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
enum ValueSource<'a, 'tcx> {
|
enum ValueSource<'a, 'tcx> {
|
||||||
Rvalue(&'a Rvalue<'tcx>),
|
Rvalue(&'a Rvalue<'tcx>),
|
||||||
|
DropAndReplace(&'a Operand<'tcx>),
|
||||||
Call {
|
Call {
|
||||||
callee: &'a Operand<'tcx>,
|
callee: &'a Operand<'tcx>,
|
||||||
args: &'a [Operand<'tcx>],
|
args: &'a [Operand<'tcx>],
|
||||||
@@ -298,6 +299,7 @@ trait Qualif {
|
|||||||
fn in_value(cx: &ConstCx<'_, 'tcx>, source: ValueSource<'_, 'tcx>) -> bool {
|
fn in_value(cx: &ConstCx<'_, 'tcx>, source: ValueSource<'_, 'tcx>) -> bool {
|
||||||
match source {
|
match source {
|
||||||
ValueSource::Rvalue(rvalue) => Self::in_rvalue(cx, rvalue),
|
ValueSource::Rvalue(rvalue) => Self::in_rvalue(cx, rvalue),
|
||||||
|
ValueSource::DropAndReplace(source) => Self::in_operand(cx, source),
|
||||||
ValueSource::Call { callee, args, return_ty } => {
|
ValueSource::Call { callee, args, return_ty } => {
|
||||||
Self::in_call(cx, 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 {
|
let target = match body[bb].terminator().kind {
|
||||||
TerminatorKind::Goto { target } |
|
TerminatorKind::Goto { target } |
|
||||||
TerminatorKind::Drop { target, .. } |
|
TerminatorKind::Drop { target, .. } |
|
||||||
|
TerminatorKind::DropAndReplace { target, .. } |
|
||||||
TerminatorKind::Assert { target, .. } |
|
TerminatorKind::Assert { target, .. } |
|
||||||
TerminatorKind::Call { destination: Some((_, target)), .. } => {
|
TerminatorKind::Call { destination: Some((_, target)), .. } => {
|
||||||
Some(target)
|
Some(target)
|
||||||
@@ -900,7 +903,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::SwitchInt {..} |
|
TerminatorKind::SwitchInt {..} |
|
||||||
TerminatorKind::DropAndReplace { .. } |
|
|
||||||
TerminatorKind::Resume |
|
TerminatorKind::Resume |
|
||||||
TerminatorKind::Abort |
|
TerminatorKind::Abort |
|
||||||
TerminatorKind::GeneratorDrop |
|
TerminatorKind::GeneratorDrop |
|
||||||
@@ -1393,8 +1395,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||||||
for arg in args {
|
for arg in args {
|
||||||
self.visit_operand(arg, location);
|
self.visit_operand(arg, location);
|
||||||
}
|
}
|
||||||
} else if let TerminatorKind::Drop { location: ref place, .. } = *kind {
|
} else if let TerminatorKind::Drop {
|
||||||
self.super_terminator_kind(kind, location);
|
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.
|
// Deny *any* live drops anywhere other than functions.
|
||||||
if self.mode.requires_const_checking() {
|
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 {
|
} else {
|
||||||
// Qualify any operands inside other terminators.
|
// Qualify any operands inside other terminators.
|
||||||
self.super_terminator_kind(kind, location);
|
self.super_terminator_kind(kind, location);
|
||||||
|
|||||||
@@ -9,10 +9,21 @@ impl Drop for FakeNeedsDrop {
|
|||||||
// ok
|
// ok
|
||||||
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
|
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
|
||||||
|
|
||||||
|
// ok (used to incorrectly error, see #62273)
|
||||||
|
const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x };
|
||||||
|
|
||||||
// error
|
// error
|
||||||
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
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
|
// error
|
||||||
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
|
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
|
error[E0493]: destructors cannot be evaluated at compile-time
|
||||||
--> $DIR/const_let.rs:13:55
|
--> $DIR/const_let.rs:16:32
|
||||||
|
|
|
|
||||||
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||||
| ^
|
| ^^^^^ constants cannot evaluate destructors
|
||||||
|
|
||||||
error[E0019]: constant contains unimplemented expression type
|
error[E0493]: destructors cannot be evaluated at compile-time
|
||||||
--> $DIR/const_let.rs:17:35
|
--> $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); };
|
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