diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f082b5e5a046c..72180d60bd6d0 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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); diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs index 63321b9120076..18692dbced679 100644 --- a/src/test/ui/consts/const-eval/const_let.rs +++ b/src/test/ui/consts/const-eval/const_let.rs @@ -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 diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 00de97e6fb3a0..0a6a222ae2963 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/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`.