]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/intrinsic-move-val.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / test / run-pass / intrinsic-move-val.rs
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.
4 //
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.
10
11
12 #![feature(box_syntax)]
13 #![feature(intrinsics)]
14
15 mod rusti {
16     extern "rust-intrinsic" {
17         pub fn init<T>() -> T;
18         pub fn move_val_init<T>(dst: *mut T, src: T);
19     }
20 }
21
22 pub fn main() {
23     unsafe {
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.
56         rusti::move_val_init(&mut y, x);
57
58         // But what we *can* observe is how many times the destructor
59         // for `D` is invoked, and what the last value we saw was
60         // during such a destructor call. We do so after the end of
61         // this scope.
62
63         assert_eq!(y.0, 2);
64         y.0 = 3;
65         assert_eq!(y.0, 3);
66
67         check_drops_state(1, Some(1));
68     }
69
70     check_drops_state(2, Some(3));
71 }
72
73 static mut NUM_DROPS: i32 = 0;
74 static mut LAST_DROPPED: Option<i32> = None;
75
76 fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
77     unsafe {
78         assert_eq!(NUM_DROPS, num_drops);
79         assert_eq!(LAST_DROPPED, last_dropped);
80     }
81 }
82
83 struct D(i32);
84 impl Drop for D {
85     fn drop(&mut self) {
86         unsafe {
87             NUM_DROPS += 1;
88             LAST_DROPPED = Some(self.0);
89         }
90     }
91 }