]> git.proxmox.com Git - rustc.git/blob - src/test/run-pass/intrinsics/intrinsic-move-val.rs
New upstream version 1.31.0~beta.4+dfsg1
[rustc.git] / src / test / run-pass / intrinsics / 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 // run-pass
12
13 #![feature(box_syntax)]
14 #![feature(intrinsics)]
15
16 mod rusti {
17 extern "rust-intrinsic" {
18 pub fn init<T>() -> T;
19 pub fn move_val_init<T>(dst: *mut T, src: T);
20 }
21 }
22
23 pub fn main() {
24 unsafe {
25 // sanity check
26 check_drops_state(0, None);
27
28 let mut x: Box<D> = box D(1);
29 assert_eq!(x.0, 1);
30
31 // A normal overwrite, to demonstrate `check_drops_state`.
32 x = box D(2);
33
34 // At this point, one destructor has run, because the
35 // overwrite of `x` drops its initial value.
36 check_drops_state(1, Some(1));
37
38 let mut y: Box<D> = rusti::init();
39
40 // An initial binding does not overwrite anything.
41 check_drops_state(1, Some(1));
42
43 // Since `y` has been initialized via the `init` intrinsic, it
44 // would be unsound to directly overwrite its value via normal
45 // assignment.
46 //
47 // The code currently generated by the compiler is overly
48 // accepting, however, in that it will check if `y` is itself
49 // null and thus avoid the unsound action of attempting to
50 // free null. In other words, if we were to do a normal
51 // assignment like `y = box D(4);` here, it probably would not
52 // crash today. But the plan is that it may well crash in the
53 // future, (I believe).
54
55 // `x` is moved here; the manner in which this is tracked by the
56 // compiler is hidden.
57 rusti::move_val_init(&mut y, x);
58
59 // But what we *can* observe is how many times the destructor
60 // for `D` is invoked, and what the last value we saw was
61 // during such a destructor call. We do so after the end of
62 // this scope.
63
64 assert_eq!(y.0, 2);
65 y.0 = 3;
66 assert_eq!(y.0, 3);
67
68 check_drops_state(1, Some(1));
69 }
70
71 check_drops_state(2, Some(3));
72 }
73
74 static mut NUM_DROPS: i32 = 0;
75 static mut LAST_DROPPED: Option<i32> = None;
76
77 fn check_drops_state(num_drops: i32, last_dropped: Option<i32>) {
78 unsafe {
79 assert_eq!(NUM_DROPS, num_drops);
80 assert_eq!(LAST_DROPPED, last_dropped);
81 }
82 }
83
84 struct D(i32);
85 impl Drop for D {
86 fn drop(&mut self) {
87 unsafe {
88 NUM_DROPS += 1;
89 LAST_DROPPED = Some(self.0);
90 }
91 }
92 }