Skip to content

Commit ff14eaf

Browse files
committed
Revise intrinsic-move-val test to not require knowledge of whether filling drop is in use.
1 parent e25427a commit ff14eaf

File tree

1 file changed

+74
-11
lines changed

1 file changed

+74
-11
lines changed

src/test/run-pass/intrinsic-move-val.rs

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,8 @@
99
// except according to those terms.
1010

1111

12-
#![allow(unknown_features)]
1312
#![feature(box_syntax)]
1413
#![feature(intrinsics)]
15-
// needed to check for drop fill word.
16-
#![feature(filling_drop)]
17-
18-
use std::mem::{self, transmute};
1914

2015
mod rusti {
2116
extern "rust-intrinsic" {
@@ -26,12 +21,80 @@ mod rusti {
2621

2722
pub fn main() {
2823
unsafe {
29-
let x: Box<_> = box 1;
30-
let mut y = rusti::init();
31-
let mut z: *const usize = transmute(&x);
24+
// sanity check
25+
check_drops_state(0, None);
26+
27+
let mut x: Box<D> = box D(1);
28+
assert_eq!(x.0, 1);
29+
30+
// A normal overwrite, to demonstrate `check_drops_state`.
31+
x = box D(2);
32+
33+
// At this point, one destructor has run, because the
34+
// overwrite of `x` drops its initial value.
35+
check_drops_state(1, Some(1));
36+
37+
let mut y: Box<D> = rusti::init();
38+
39+
// An initial binding does not overwrite anything.
40+
check_drops_state(1, Some(1));
41+
42+
// Since `y` has been initialized via the `init` intrinsic, it
43+
// would be unsound to directly overwrite its value via normal
44+
// assignment.
45+
//
46+
// The code currently generated by the compiler is overly
47+
// accepting, however, in that it will check if `y` is itself
48+
// null and thus avoid the unsound action of attempting to
49+
// free null. In other words, if we were to do a normal
50+
// assignment like `y = box D(4);` here, it probably would not
51+
// crash today. But the plan is that it may well crash in the
52+
// future, (I believe).
53+
54+
// `x` is moved here; the manner in which this is tracked by the
55+
// compiler is hidden.
3256
rusti::move_val_init(&mut y, x);
33-
assert_eq!(*y, 1);
34-
// `x` is nulled out, not directly visible
35-
assert_eq!(*z, mem::POST_DROP_USIZE);
57+
58+
// In particular, it may be tracked via a drop-flag embedded
59+
// in the value, or via a null pointer, or via
60+
// mem::POST_DROP_USIZE, or (most preferably) via a
61+
// stack-local drop flag.
62+
//
63+
// (This test used to build-in knowledge of how it was
64+
// tracked, and check that the underlying stack slot had been
65+
// set to `mem::POST_DROP_USIZE`.)
66+
67+
// But what we *can* observe is how many times the destructor
68+
// for `D` is invoked, and what the last value we saw was
69+
// during such a destructor call. We do so after the end of
70+
// this scope.
71+
72+
assert_eq!(y.0, 2);
73+
y.0 = 3;
74+
assert_eq!(y.0, 3);
75+
76+
check_drops_state(1, Some(1));
77+
}
78+
79+
check_drops_state(2, Some(3));
80+
}
81+
82+
static mut NUM_DROPS: i32 = 0;
83+
static mut LAST_DROPPED: Option<i32> = None;
84+
85+
fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
86+
unsafe {
87+
assert_eq!(NUM_DROPS, num_drops);
88+
assert_eq!(LAST_DROPPED, last_dropped);
89+
}
90+
}
91+
92+
struct D(i32);
93+
impl Drop for D {
94+
fn drop(&mut self) {
95+
unsafe {
96+
NUM_DROPS += 1;
97+
LAST_DROPPED = Some(self.0);
98+
}
3699
}
37100
}

0 commit comments

Comments
 (0)