]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 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 | ||
54a0048b | 11 | //! Basic functions for dealing with memory. |
1a4d82fc JJ |
12 | //! |
13 | //! This module contains functions for querying the size and alignment of | |
14 | //! types, initializing and manipulating memory. | |
15 | ||
85aaf69f | 16 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
17 | |
18 | use marker::Sized; | |
19 | use intrinsics; | |
20 | use ptr; | |
21 | ||
85aaf69f | 22 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
23 | pub use intrinsics::transmute; |
24 | ||
bd371182 AL |
25 | /// Leaks a value into the void, consuming ownership and never running its |
26 | /// destructor. | |
1a4d82fc | 27 | /// |
bd371182 AL |
28 | /// This function will take ownership of its argument, but is distinct from the |
29 | /// `mem::drop` function in that it **does not run the destructor**, leaking the | |
30 | /// value and any resources that it owns. | |
1a4d82fc | 31 | /// |
e9174d1e SL |
32 | /// There's only a few reasons to use this function. They mainly come |
33 | /// up in unsafe code or FFI code. | |
34 | /// | |
35 | /// * You have an uninitialized value, perhaps for performance reasons, and | |
36 | /// need to prevent the destructor from running on it. | |
37 | /// * You have two copies of a value (like when writing something like | |
38 | /// [`mem::swap`][swap]), but need the destructor to only run once to | |
39 | /// prevent a double `free`. | |
b039eaaf | 40 | /// * Transferring resources across [FFI][ffi] boundaries. |
e9174d1e SL |
41 | /// |
42 | /// [swap]: fn.swap.html | |
43 | /// [ffi]: ../../book/ffi.html | |
44 | /// | |
bd371182 AL |
45 | /// # Safety |
46 | /// | |
47 | /// This function is not marked as `unsafe` as Rust does not guarantee that the | |
48 | /// `Drop` implementation for a value will always run. Note, however, that | |
49 | /// leaking resources such as memory or I/O objects is likely not desired, so | |
50 | /// this function is only recommended for specialized use cases. | |
51 | /// | |
52 | /// The safety of this function implies that when writing `unsafe` code | |
53 | /// yourself care must be taken when leveraging a destructor that is required to | |
54 | /// run to preserve memory safety. There are known situations where the | |
55 | /// destructor may not run (such as if ownership of the object with the | |
56 | /// destructor is returned) which must be taken into account. | |
57 | /// | |
58 | /// # Other forms of Leakage | |
59 | /// | |
60 | /// It's important to point out that this function is not the only method by | |
61 | /// which a value can be leaked in safe Rust code. Other known sources of | |
62 | /// leakage are: | |
63 | /// | |
64 | /// * `Rc` and `Arc` cycles | |
65 | /// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally) | |
66 | /// * Panicking destructors are likely to leak local resources | |
67 | /// | |
68 | /// # Example | |
69 | /// | |
e9174d1e | 70 | /// Leak some heap memory by never deallocating it: |
62682a34 SL |
71 | /// |
72 | /// ```rust | |
bd371182 | 73 | /// use std::mem; |
bd371182 | 74 | /// |
bd371182 AL |
75 | /// let heap_memory = Box::new(3); |
76 | /// mem::forget(heap_memory); | |
62682a34 SL |
77 | /// ``` |
78 | /// | |
e9174d1e | 79 | /// Leak an I/O object, never closing the file: |
62682a34 SL |
80 | /// |
81 | /// ```rust,no_run | |
82 | /// use std::mem; | |
83 | /// use std::fs::File; | |
bd371182 | 84 | /// |
bd371182 AL |
85 | /// let file = File::open("foo.txt").unwrap(); |
86 | /// mem::forget(file); | |
87 | /// ``` | |
62682a34 | 88 | /// |
e9174d1e | 89 | /// The `mem::swap` function uses `mem::forget` to good effect: |
62682a34 SL |
90 | /// |
91 | /// ```rust | |
92 | /// use std::mem; | |
93 | /// use std::ptr; | |
94 | /// | |
92a42be0 | 95 | /// # #[allow(dead_code)] |
62682a34 SL |
96 | /// fn swap<T>(x: &mut T, y: &mut T) { |
97 | /// unsafe { | |
98 | /// // Give ourselves some scratch space to work with | |
99 | /// let mut t: T = mem::uninitialized(); | |
100 | /// | |
101 | /// // Perform the swap, `&mut` pointers never alias | |
102 | /// ptr::copy_nonoverlapping(&*x, &mut t, 1); | |
103 | /// ptr::copy_nonoverlapping(&*y, x, 1); | |
104 | /// ptr::copy_nonoverlapping(&t, y, 1); | |
105 | /// | |
106 | /// // y and t now point to the same thing, but we need to completely | |
107 | /// // forget `t` because we do not want to run the destructor for `T` | |
108 | /// // on its value, which is still owned somewhere outside this function. | |
109 | /// mem::forget(t); | |
110 | /// } | |
111 | /// } | |
112 | /// ``` | |
85aaf69f | 113 | #[stable(feature = "rust1", since = "1.0.0")] |
bd371182 AL |
114 | pub fn forget<T>(t: T) { |
115 | unsafe { intrinsics::forget(t) } | |
116 | } | |
1a4d82fc JJ |
117 | |
118 | /// Returns the size of a type in bytes. | |
119 | /// | |
120 | /// # Examples | |
121 | /// | |
122 | /// ``` | |
123 | /// use std::mem; | |
124 | /// | |
125 | /// assert_eq!(4, mem::size_of::<i32>()); | |
126 | /// ``` | |
127 | #[inline] | |
85aaf69f SL |
128 | #[stable(feature = "rust1", since = "1.0.0")] |
129 | pub fn size_of<T>() -> usize { | |
1a4d82fc JJ |
130 | unsafe { intrinsics::size_of::<T>() } |
131 | } | |
132 | ||
9cc50fc6 | 133 | /// Returns the size of the given value in bytes. |
d9579d0f AL |
134 | /// |
135 | /// # Examples | |
136 | /// | |
137 | /// ``` | |
138 | /// use std::mem; | |
139 | /// | |
140 | /// assert_eq!(4, mem::size_of_val(&5i32)); | |
141 | /// ``` | |
d9579d0f AL |
142 | #[inline] |
143 | #[stable(feature = "rust1", since = "1.0.0")] | |
144 | pub fn size_of_val<T: ?Sized>(val: &T) -> usize { | |
145 | unsafe { intrinsics::size_of_val(val) } | |
146 | } | |
147 | ||
1a4d82fc JJ |
148 | /// Returns the ABI-required minimum alignment of a type |
149 | /// | |
150 | /// This is the alignment used for struct fields. It may be smaller than the preferred alignment. | |
151 | /// | |
152 | /// # Examples | |
153 | /// | |
154 | /// ``` | |
92a42be0 | 155 | /// # #![allow(deprecated)] |
1a4d82fc JJ |
156 | /// use std::mem; |
157 | /// | |
158 | /// assert_eq!(4, mem::min_align_of::<i32>()); | |
159 | /// ``` | |
160 | #[inline] | |
85aaf69f | 161 | #[stable(feature = "rust1", since = "1.0.0")] |
92a42be0 | 162 | #[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] |
85aaf69f | 163 | pub fn min_align_of<T>() -> usize { |
1a4d82fc JJ |
164 | unsafe { intrinsics::min_align_of::<T>() } |
165 | } | |
166 | ||
d9579d0f AL |
167 | /// Returns the ABI-required minimum alignment of the type of the value that `val` points to |
168 | /// | |
169 | /// # Examples | |
170 | /// | |
171 | /// ``` | |
92a42be0 | 172 | /// # #![allow(deprecated)] |
d9579d0f AL |
173 | /// use std::mem; |
174 | /// | |
175 | /// assert_eq!(4, mem::min_align_of_val(&5i32)); | |
176 | /// ``` | |
d9579d0f AL |
177 | #[inline] |
178 | #[stable(feature = "rust1", since = "1.0.0")] | |
92a42be0 | 179 | #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] |
d9579d0f AL |
180 | pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize { |
181 | unsafe { intrinsics::min_align_of_val(val) } | |
182 | } | |
183 | ||
1a4d82fc JJ |
184 | /// Returns the alignment in memory for a type. |
185 | /// | |
62682a34 | 186 | /// This is the alignment used for struct fields. It may be smaller than the preferred alignment. |
1a4d82fc JJ |
187 | /// |
188 | /// # Examples | |
189 | /// | |
190 | /// ``` | |
191 | /// use std::mem; | |
192 | /// | |
193 | /// assert_eq!(4, mem::align_of::<i32>()); | |
194 | /// ``` | |
195 | #[inline] | |
85aaf69f SL |
196 | #[stable(feature = "rust1", since = "1.0.0")] |
197 | pub fn align_of<T>() -> usize { | |
62682a34 | 198 | unsafe { intrinsics::min_align_of::<T>() } |
1a4d82fc JJ |
199 | } |
200 | ||
62682a34 | 201 | /// Returns the ABI-required minimum alignment of the type of the value that `val` points to |
1a4d82fc JJ |
202 | /// |
203 | /// # Examples | |
204 | /// | |
205 | /// ``` | |
206 | /// use std::mem; | |
207 | /// | |
208 | /// assert_eq!(4, mem::align_of_val(&5i32)); | |
209 | /// ``` | |
210 | #[inline] | |
85aaf69f | 211 | #[stable(feature = "rust1", since = "1.0.0")] |
62682a34 SL |
212 | pub fn align_of_val<T: ?Sized>(val: &T) -> usize { |
213 | unsafe { intrinsics::min_align_of_val(val) } | |
1a4d82fc JJ |
214 | } |
215 | ||
9346a6ac | 216 | /// Creates a value initialized to zero. |
1a4d82fc JJ |
217 | /// |
218 | /// This function is similar to allocating space for a local variable and zeroing it out (an unsafe | |
219 | /// operation). | |
220 | /// | |
221 | /// Care must be taken when using this function, if the type `T` has a destructor and the value | |
222 | /// falls out of scope (due to unwinding or returning) before being initialized, then the | |
223 | /// destructor will run on zeroed data, likely leading to crashes. | |
224 | /// | |
225 | /// This is useful for FFI functions sometimes, but should generally be avoided. | |
226 | /// | |
227 | /// # Examples | |
228 | /// | |
229 | /// ``` | |
230 | /// use std::mem; | |
231 | /// | |
85aaf69f | 232 | /// let x: i32 = unsafe { mem::zeroed() }; |
1a4d82fc JJ |
233 | /// ``` |
234 | #[inline] | |
85aaf69f | 235 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
236 | pub unsafe fn zeroed<T>() -> T { |
237 | intrinsics::init() | |
238 | } | |
239 | ||
9346a6ac | 240 | /// Creates a value initialized to an unspecified series of bytes. |
c34b1796 AL |
241 | /// |
242 | /// The byte sequence usually indicates that the value at the memory | |
243 | /// in question has been dropped. Thus, *if* T carries a drop flag, | |
244 | /// any associated destructor will not be run when the value falls out | |
245 | /// of scope. | |
246 | /// | |
247 | /// Some code at one time used the `zeroed` function above to | |
248 | /// accomplish this goal. | |
249 | /// | |
250 | /// This function is expected to be deprecated with the transition | |
251 | /// to non-zeroing drop. | |
252 | #[inline] | |
e9174d1e | 253 | #[unstable(feature = "filling_drop", issue = "5016")] |
c34b1796 AL |
254 | pub unsafe fn dropped<T>() -> T { |
255 | #[inline(always)] | |
256 | unsafe fn dropped_impl<T>() -> T { intrinsics::init_dropped() } | |
257 | ||
258 | dropped_impl() | |
259 | } | |
260 | ||
c1a9b12d SL |
261 | /// Bypasses Rust's normal memory-initialization checks by pretending to |
262 | /// produce a value of type T, while doing nothing at all. | |
1a4d82fc | 263 | /// |
c1a9b12d SL |
264 | /// **This is incredibly dangerous, and should not be done lightly. Deeply |
265 | /// consider initializing your memory with a default value instead.** | |
1a4d82fc | 266 | /// |
c1a9b12d SL |
267 | /// This is useful for FFI functions and initializing arrays sometimes, |
268 | /// but should generally be avoided. | |
269 | /// | |
b039eaaf | 270 | /// # Undefined Behavior |
c1a9b12d | 271 | /// |
b039eaaf | 272 | /// It is Undefined Behavior to read uninitialized memory. Even just an |
c1a9b12d SL |
273 | /// uninitialized boolean. For instance, if you branch on the value of such |
274 | /// a boolean your program may take one, both, or neither of the branches. | |
275 | /// | |
276 | /// Note that this often also includes *writing* to the uninitialized value. | |
277 | /// Rust believes the value is initialized, and will therefore try to Drop | |
278 | /// the uninitialized value and its fields if you try to overwrite the memory | |
279 | /// in a normal manner. The only way to safely initialize an arbitrary | |
280 | /// uninitialized value is with one of the `ptr` functions: `write`, `copy`, or | |
281 | /// `copy_nonoverlapping`. This isn't necessary if `T` is a primitive | |
282 | /// or otherwise only contains types that don't implement Drop. | |
283 | /// | |
284 | /// If this value *does* need some kind of Drop, it must be initialized before | |
285 | /// it goes out of scope (and therefore would be dropped). Note that this | |
286 | /// includes a `panic` occurring and unwinding the stack suddenly. | |
1a4d82fc JJ |
287 | /// |
288 | /// # Examples | |
289 | /// | |
c1a9b12d SL |
290 | /// Here's how to safely initialize an array of `Vec`s. |
291 | /// | |
1a4d82fc JJ |
292 | /// ``` |
293 | /// use std::mem; | |
c1a9b12d | 294 | /// use std::ptr; |
1a4d82fc | 295 | /// |
c1a9b12d SL |
296 | /// // Only declare the array. This safely leaves it |
297 | /// // uninitialized in a way that Rust will track for us. | |
298 | /// // However we can't initialize it element-by-element | |
299 | /// // safely, and we can't use the `[value; 1000]` | |
300 | /// // constructor because it only works with `Copy` data. | |
301 | /// let mut data: [Vec<u32>; 1000]; | |
302 | /// | |
303 | /// unsafe { | |
304 | /// // So we need to do this to initialize it. | |
305 | /// data = mem::uninitialized(); | |
306 | /// | |
307 | /// // DANGER ZONE: if anything panics or otherwise | |
308 | /// // incorrectly reads the array here, we will have | |
b039eaaf | 309 | /// // Undefined Behavior. |
c1a9b12d SL |
310 | /// |
311 | /// // It's ok to mutably iterate the data, since this | |
312 | /// // doesn't involve reading it at all. | |
313 | /// // (ptr and len are statically known for arrays) | |
314 | /// for elem in &mut data[..] { | |
315 | /// // *elem = Vec::new() would try to drop the | |
316 | /// // uninitialized memory at `elem` -- bad! | |
317 | /// // | |
318 | /// // Vec::new doesn't allocate or do really | |
319 | /// // anything. It's only safe to call here | |
320 | /// // because we know it won't panic. | |
321 | /// ptr::write(elem, Vec::new()); | |
322 | /// } | |
323 | /// | |
324 | /// // SAFE ZONE: everything is initialized. | |
325 | /// } | |
326 | /// | |
327 | /// println!("{:?}", &data[0]); | |
328 | /// ``` | |
329 | /// | |
330 | /// This example emphasizes exactly how delicate and dangerous doing this is. | |
331 | /// Note that the `vec!` macro *does* let you initialize every element with a | |
332 | /// value that is only `Clone`, so the following is semantically equivalent and | |
333 | /// vastly less dangerous, as long as you can live with an extra heap | |
334 | /// allocation: | |
335 | /// | |
336 | /// ``` | |
337 | /// let data: Vec<Vec<u32>> = vec![Vec::new(); 1000]; | |
338 | /// println!("{:?}", &data[0]); | |
1a4d82fc JJ |
339 | /// ``` |
340 | #[inline] | |
85aaf69f | 341 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
342 | pub unsafe fn uninitialized<T>() -> T { |
343 | intrinsics::uninit() | |
344 | } | |
345 | ||
b039eaaf | 346 | /// Swap the values at two mutable locations of the same type, without deinitializing or copying |
1a4d82fc JJ |
347 | /// either one. |
348 | /// | |
349 | /// # Examples | |
350 | /// | |
351 | /// ``` | |
352 | /// use std::mem; | |
353 | /// | |
85aaf69f SL |
354 | /// let x = &mut 5; |
355 | /// let y = &mut 42; | |
1a4d82fc JJ |
356 | /// |
357 | /// mem::swap(x, y); | |
358 | /// | |
85aaf69f SL |
359 | /// assert_eq!(42, *x); |
360 | /// assert_eq!(5, *y); | |
1a4d82fc JJ |
361 | /// ``` |
362 | #[inline] | |
85aaf69f | 363 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
364 | pub fn swap<T>(x: &mut T, y: &mut T) { |
365 | unsafe { | |
366 | // Give ourselves some scratch space to work with | |
367 | let mut t: T = uninitialized(); | |
368 | ||
369 | // Perform the swap, `&mut` pointers never alias | |
c34b1796 AL |
370 | ptr::copy_nonoverlapping(&*x, &mut t, 1); |
371 | ptr::copy_nonoverlapping(&*y, x, 1); | |
372 | ptr::copy_nonoverlapping(&t, y, 1); | |
1a4d82fc | 373 | |
62682a34 SL |
374 | // y and t now point to the same thing, but we need to completely |
375 | // forget `t` because we do not want to run the destructor for `T` | |
376 | // on its value, which is still owned somewhere outside this function. | |
1a4d82fc JJ |
377 | forget(t); |
378 | } | |
379 | } | |
380 | ||
9346a6ac | 381 | /// Replaces the value at a mutable location with a new one, returning the old value, without |
b039eaaf | 382 | /// deinitializing or copying either one. |
1a4d82fc JJ |
383 | /// |
384 | /// This is primarily used for transferring and swapping ownership of a value in a mutable | |
385 | /// location. | |
386 | /// | |
387 | /// # Examples | |
388 | /// | |
389 | /// A simple example: | |
390 | /// | |
391 | /// ``` | |
392 | /// use std::mem; | |
393 | /// | |
394 | /// let mut v: Vec<i32> = Vec::new(); | |
395 | /// | |
396 | /// mem::replace(&mut v, Vec::new()); | |
397 | /// ``` | |
398 | /// | |
399 | /// This function allows consumption of one field of a struct by replacing it with another value. | |
400 | /// The normal approach doesn't always work: | |
401 | /// | |
402 | /// ```rust,ignore | |
403 | /// struct Buffer<T> { buf: Vec<T> } | |
404 | /// | |
405 | /// impl<T> Buffer<T> { | |
406 | /// fn get_and_reset(&mut self) -> Vec<T> { | |
407 | /// // error: cannot move out of dereference of `&mut`-pointer | |
408 | /// let buf = self.buf; | |
409 | /// self.buf = Vec::new(); | |
410 | /// buf | |
411 | /// } | |
412 | /// } | |
413 | /// ``` | |
414 | /// | |
415 | /// Note that `T` does not necessarily implement `Clone`, so it can't even clone and reset | |
416 | /// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from | |
417 | /// `self`, allowing it to be returned: | |
418 | /// | |
c34b1796 | 419 | /// ``` |
92a42be0 | 420 | /// # #![allow(dead_code)] |
1a4d82fc JJ |
421 | /// use std::mem; |
422 | /// # struct Buffer<T> { buf: Vec<T> } | |
423 | /// impl<T> Buffer<T> { | |
424 | /// fn get_and_reset(&mut self) -> Vec<T> { | |
425 | /// mem::replace(&mut self.buf, Vec::new()) | |
426 | /// } | |
427 | /// } | |
428 | /// ``` | |
429 | #[inline] | |
85aaf69f | 430 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
431 | pub fn replace<T>(dest: &mut T, mut src: T) -> T { |
432 | swap(dest, &mut src); | |
433 | src | |
434 | } | |
435 | ||
436 | /// Disposes of a value. | |
437 | /// | |
c1a9b12d SL |
438 | /// While this does call the argument's implementation of `Drop`, it will not |
439 | /// release any borrows, as borrows are based on lexical scope. | |
1a4d82fc | 440 | /// |
b039eaaf SL |
441 | /// This effectively does nothing for |
442 | /// [types which implement `Copy`](../../book/ownership.html#copy-types), | |
443 | /// e.g. integers. Such values are copied and _then_ moved into the function, | |
444 | /// so the value persists after this function call. | |
445 | /// | |
1a4d82fc JJ |
446 | /// # Examples |
447 | /// | |
c1a9b12d SL |
448 | /// Basic usage: |
449 | /// | |
450 | /// ``` | |
451 | /// let v = vec![1, 2, 3]; | |
452 | /// | |
453 | /// drop(v); // explicitly drop the vector | |
454 | /// ``` | |
455 | /// | |
456 | /// Borrows are based on lexical scope, so this produces an error: | |
457 | /// | |
458 | /// ```ignore | |
459 | /// let mut v = vec![1, 2, 3]; | |
460 | /// let x = &v[0]; | |
461 | /// | |
462 | /// drop(x); // explicitly drop the reference, but the borrow still exists | |
463 | /// | |
464 | /// v.push(4); // error: cannot borrow `v` as mutable because it is also | |
465 | /// // borrowed as immutable | |
466 | /// ``` | |
467 | /// | |
468 | /// An inner scope is needed to fix this: | |
469 | /// | |
470 | /// ``` | |
471 | /// let mut v = vec![1, 2, 3]; | |
472 | /// | |
473 | /// { | |
474 | /// let x = &v[0]; | |
475 | /// | |
476 | /// drop(x); // this is now redundant, as `x` is going out of scope anyway | |
477 | /// } | |
478 | /// | |
479 | /// v.push(4); // no problems | |
480 | /// ``` | |
481 | /// | |
482 | /// Since `RefCell` enforces the borrow rules at runtime, `drop()` can | |
483 | /// seemingly release a borrow of one: | |
484 | /// | |
1a4d82fc JJ |
485 | /// ``` |
486 | /// use std::cell::RefCell; | |
487 | /// | |
85aaf69f | 488 | /// let x = RefCell::new(1); |
1a4d82fc JJ |
489 | /// |
490 | /// let mut mutable_borrow = x.borrow_mut(); | |
491 | /// *mutable_borrow = 1; | |
492 | /// | |
493 | /// drop(mutable_borrow); // relinquish the mutable borrow on this slot | |
494 | /// | |
495 | /// let borrow = x.borrow(); | |
496 | /// println!("{}", *borrow); | |
497 | /// ``` | |
b039eaaf SL |
498 | /// |
499 | /// Integers and other types implementing `Copy` are unaffected by `drop()` | |
500 | /// | |
501 | /// ``` | |
502 | /// #[derive(Copy, Clone)] | |
503 | /// struct Foo(u8); | |
504 | /// | |
505 | /// let x = 1; | |
506 | /// let y = Foo(2); | |
507 | /// drop(x); // a copy of `x` is moved and dropped | |
508 | /// drop(y); // a copy of `y` is moved and dropped | |
509 | /// | |
510 | /// println!("x: {}, y: {}", x, y.0); // still available | |
511 | /// ``` | |
512 | /// | |
1a4d82fc | 513 | #[inline] |
85aaf69f | 514 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
515 | pub fn drop<T>(_x: T) { } |
516 | ||
c34b1796 AL |
517 | macro_rules! repeat_u8_as_u32 { |
518 | ($name:expr) => { (($name as u32) << 24 | | |
519 | ($name as u32) << 16 | | |
520 | ($name as u32) << 8 | | |
521 | ($name as u32)) } | |
522 | } | |
523 | macro_rules! repeat_u8_as_u64 { | |
524 | ($name:expr) => { ((repeat_u8_as_u32!($name) as u64) << 32 | | |
525 | (repeat_u8_as_u32!($name) as u64)) } | |
526 | } | |
527 | ||
528 | // NOTE: Keep synchronized with values used in librustc_trans::trans::adt. | |
529 | // | |
530 | // In particular, the POST_DROP_U8 marker must never equal the | |
531 | // DTOR_NEEDED_U8 marker. | |
532 | // | |
533 | // For a while pnkfelix was using 0xc1 here. | |
534 | // But having the sign bit set is a pain, so 0x1d is probably better. | |
535 | // | |
536 | // And of course, 0x00 brings back the old world of zero'ing on drop. | |
e9174d1e | 537 | #[unstable(feature = "filling_drop", issue = "5016")] |
c1a9b12d | 538 | #[allow(missing_docs)] |
c34b1796 | 539 | pub const POST_DROP_U8: u8 = 0x1d; |
e9174d1e | 540 | #[unstable(feature = "filling_drop", issue = "5016")] |
c1a9b12d | 541 | #[allow(missing_docs)] |
c34b1796 | 542 | pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8); |
e9174d1e | 543 | #[unstable(feature = "filling_drop", issue = "5016")] |
c1a9b12d | 544 | #[allow(missing_docs)] |
c34b1796 AL |
545 | pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8); |
546 | ||
547 | #[cfg(target_pointer_width = "32")] | |
e9174d1e | 548 | #[unstable(feature = "filling_drop", issue = "5016")] |
c1a9b12d | 549 | #[allow(missing_docs)] |
c34b1796 AL |
550 | pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize; |
551 | #[cfg(target_pointer_width = "64")] | |
e9174d1e | 552 | #[unstable(feature = "filling_drop", issue = "5016")] |
c1a9b12d | 553 | #[allow(missing_docs)] |
c34b1796 AL |
554 | pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize; |
555 | ||
556 | /// Interprets `src` as `&U`, and then reads `src` without moving the contained | |
557 | /// value. | |
1a4d82fc | 558 | /// |
c34b1796 AL |
559 | /// This function will unsafely assume the pointer `src` is valid for |
560 | /// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It | |
561 | /// will also unsafely create a copy of the contained value instead of moving | |
562 | /// out of `src`. | |
1a4d82fc | 563 | /// |
c34b1796 AL |
564 | /// It is not a compile-time error if `T` and `U` have different sizes, but it |
565 | /// is highly encouraged to only invoke this function where `T` and `U` have the | |
566 | /// same size. This function triggers undefined behavior if `U` is larger than | |
567 | /// `T`. | |
1a4d82fc JJ |
568 | /// |
569 | /// # Examples | |
570 | /// | |
571 | /// ``` | |
572 | /// use std::mem; | |
573 | /// | |
7453a54e SL |
574 | /// #[repr(packed)] |
575 | /// struct Foo { | |
576 | /// bar: u8, | |
577 | /// } | |
578 | /// | |
579 | /// let foo_slice = [10u8]; | |
580 | /// | |
581 | /// unsafe { | |
582 | /// // Copy the data from 'foo_slice' and treat it as a 'Foo' | |
583 | /// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice); | |
584 | /// assert_eq!(foo_struct.bar, 10); | |
585 | /// | |
586 | /// // Modify the copied data | |
587 | /// foo_struct.bar = 20; | |
588 | /// assert_eq!(foo_struct.bar, 20); | |
589 | /// } | |
1a4d82fc | 590 | /// |
7453a54e SL |
591 | /// // The contents of 'foo_slice' should not have changed |
592 | /// assert_eq!(foo_slice, [10]); | |
1a4d82fc JJ |
593 | /// ``` |
594 | #[inline] | |
85aaf69f | 595 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
596 | pub unsafe fn transmute_copy<T, U>(src: &T) -> U { |
597 | ptr::read(src as *const T as *const U) | |
598 | } |