1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 #![feature(box_syntax)]
13 #![feature(intrinsics)]
16 extern "rust-intrinsic" {
17 pub fn init<T>() -> T;
18 pub fn move_val_init<T>(dst: *mut T, src: T);
25 check_drops_state(0, None);
27 let mut x: Box<D> = box D(1);
30 // A normal overwrite, to demonstrate `check_drops_state`.
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));
37 let mut y: Box<D> = rusti::init();
39 // An initial binding does not overwrite anything.
40 check_drops_state(1, Some(1));
42 // Since `y` has been initialized via the `init` intrinsic, it
43 // would be unsound to directly overwrite its value via normal
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).
54 // `x` is moved here; the manner in which this is tracked by the
55 // compiler is hidden.
56 rusti::move_val_init(&mut y, x);
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.
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`.)
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
76 check_drops_state(1, Some(1));
79 check_drops_state(2, Some(3));
82 static mut NUM_DROPS: i32 = 0;
83 static mut LAST_DROPPED: Option<i32> = None;
85 fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
87 assert_eq!(NUM_DROPS, num_drops);
88 assert_eq!(LAST_DROPPED, last_dropped);
97 LAST_DROPPED = Some(self.0);