Skip to content

Commit f6e5ac6

Browse files
committed
rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts.
1 parent 765eebf commit f6e5ac6

File tree

3 files changed

+52
-13
lines changed

3 files changed

+52
-13
lines changed

src/librustc_mir/transform/qualify_consts.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ impl<'a, 'tcx> ConstCx<'a, 'tcx> {
142142
#[derive(Copy, Clone, Debug)]
143143
enum ValueSource<'a, 'tcx> {
144144
Rvalue(&'a Rvalue<'tcx>),
145+
DropAndReplace(&'a Operand<'tcx>),
145146
Call {
146147
callee: &'a Operand<'tcx>,
147148
args: &'a [Operand<'tcx>],
@@ -298,6 +299,7 @@ trait Qualif {
298299
fn in_value(cx: &ConstCx<'_, 'tcx>, source: ValueSource<'_, 'tcx>) -> bool {
299300
match source {
300301
ValueSource::Rvalue(rvalue) => Self::in_rvalue(cx, rvalue),
302+
ValueSource::DropAndReplace(source) => Self::in_operand(cx, source),
301303
ValueSource::Call { callee, args, return_ty } => {
302304
Self::in_call(cx, callee, args, return_ty)
303305
}
@@ -889,6 +891,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
889891
let target = match body[bb].terminator().kind {
890892
TerminatorKind::Goto { target } |
891893
TerminatorKind::Drop { target, .. } |
894+
TerminatorKind::DropAndReplace { target, .. } |
892895
TerminatorKind::Assert { target, .. } |
893896
TerminatorKind::Call { destination: Some((_, target)), .. } => {
894897
Some(target)
@@ -900,7 +903,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
900903
}
901904

902905
TerminatorKind::SwitchInt {..} |
903-
TerminatorKind::DropAndReplace { .. } |
904906
TerminatorKind::Resume |
905907
TerminatorKind::Abort |
906908
TerminatorKind::GeneratorDrop |
@@ -1393,8 +1395,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
13931395
for arg in args {
13941396
self.visit_operand(arg, location);
13951397
}
1396-
} else if let TerminatorKind::Drop { location: ref place, .. } = *kind {
1397-
self.super_terminator_kind(kind, location);
1398+
} else if let TerminatorKind::Drop {
1399+
location: ref place, ..
1400+
} | TerminatorKind::DropAndReplace {
1401+
location: ref place, ..
1402+
} = *kind {
1403+
match *kind {
1404+
TerminatorKind::DropAndReplace { .. } => {}
1405+
_ => self.super_terminator_kind(kind, location),
1406+
}
13981407

13991408
// Deny *any* live drops anywhere other than functions.
14001409
if self.mode.requires_const_checking() {
@@ -1423,6 +1432,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
14231432
}
14241433
}
14251434
}
1435+
1436+
match *kind {
1437+
TerminatorKind::DropAndReplace { ref value, .. } => {
1438+
self.assign(place, ValueSource::DropAndReplace(value), location);
1439+
self.visit_operand(value, location);
1440+
}
1441+
_ => {}
1442+
}
14261443
} else {
14271444
// Qualify any operands inside other terminators.
14281445
self.super_terminator_kind(kind, location);

src/test/ui/consts/const-eval/const_let.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,21 @@ impl Drop for FakeNeedsDrop {
99
// ok
1010
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
1111

12+
// ok (used to incorrectly error, see #62273)
13+
const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x };
14+
1215
// error
1316
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
14-
//~^ ERROR constant contains unimplemented expression type
17+
//~^ ERROR destructors cannot be evaluated at compile-time
18+
19+
// error
20+
const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
21+
//~^ ERROR destructors cannot be evaluated at compile-time
1522

1623
// error
1724
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
18-
//~^ ERROR constant contains unimplemented expression type
25+
//~^ ERROR destructors cannot be evaluated at compile-time
26+
27+
// error
28+
const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
29+
//~^ ERROR destructors cannot be evaluated at compile-time

src/test/ui/consts/const-eval/const_let.stderr

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
error[E0019]: constant contains unimplemented expression type
2-
--> $DIR/const_let.rs:13:55
1+
error[E0493]: destructors cannot be evaluated at compile-time
2+
--> $DIR/const_let.rs:16:32
33
|
44
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
5-
| ^
5+
| ^^^^^ constants cannot evaluate destructors
66

7-
error[E0019]: constant contains unimplemented expression type
8-
--> $DIR/const_let.rs:17:35
7+
error[E0493]: destructors cannot be evaluated at compile-time
8+
--> $DIR/const_let.rs:20:33
9+
|
10+
LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
11+
| ^^^^^ constants cannot evaluate destructors
12+
13+
error[E0493]: destructors cannot be evaluated at compile-time
14+
--> $DIR/const_let.rs:24:21
915
|
1016
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
11-
| ^
17+
| ^^^^^ constants cannot evaluate destructors
18+
19+
error[E0493]: destructors cannot be evaluated at compile-time
20+
--> $DIR/const_let.rs:28:22
21+
|
22+
LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
23+
| ^^^^^ constants cannot evaluate destructors
1224

13-
error: aborting due to 2 previous errors
25+
error: aborting due to 4 previous errors
1426

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

0 commit comments

Comments
 (0)