]> git.lizzy.rs Git - rust.git/blob - src/libcore/mem.rs
6b08a32944c960d4ce6d296fb0ebd94c879ec235
[rust.git] / src / libcore / mem.rs
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
11 //! Basic functions for dealing with memory
12 //!
13 //! This module contains functions for querying the size and alignment of
14 //! types, initializing and manipulating memory.
15
16 use clone::Clone;
17 use ptr;
18 use intrinsics;
19 use intrinsics::{bswap16, bswap32, bswap64};
20
21 pub use intrinsics::transmute;
22
23 /// Returns the size of a type in bytes.
24 #[inline]
25 #[stable]
26 pub fn size_of<T>() -> uint {
27     unsafe { intrinsics::size_of::<T>() }
28 }
29
30 /// Returns the size of the type that `_val` points to in bytes.
31 #[inline]
32 #[stable]
33 pub fn size_of_val<T>(_val: &T) -> uint {
34     size_of::<T>()
35 }
36
37 /// Deprecated, this function will be removed soon
38 #[inline]
39 #[deprecated = "this function will be removed soon"]
40 pub fn nonzero_size_of<T>() -> uint {
41     match size_of::<T>() {
42         0 => 1,
43         n => n,
44     }
45 }
46
47 /// Deprecated, this function will be removed soon
48 #[inline]
49 #[deprecated = "this function will be removed soon"]
50 pub fn nonzero_size_of_val<T>(val: &T) -> uint {
51     match size_of_val::<T>(val) {
52         0 => 1,
53         n => n,
54     }
55 }
56
57 /// Returns the ABI-required minimum alignment of a type
58 ///
59 /// This is the alignment used for struct fields. It may be smaller
60 /// than the preferred alignment.
61 #[inline]
62 #[stable]
63 pub fn min_align_of<T>() -> uint {
64     unsafe { intrinsics::min_align_of::<T>() }
65 }
66
67 /// Returns the ABI-required minimum alignment of the type of the value that
68 /// `_val` points to
69 #[inline]
70 #[stable]
71 pub fn min_align_of_val<T>(_val: &T) -> uint {
72     min_align_of::<T>()
73 }
74
75 /// Returns the alignment in memory for a type.
76 ///
77 /// This function will return the alignment, in bytes, of a type in memory. If
78 /// the alignment returned is adhered to, then the type is guaranteed to
79 /// function properly.
80 #[inline]
81 #[stable]
82 pub fn align_of<T>() -> uint {
83     // We use the preferred alignment as the default alignment for a type. This
84     // appears to be what clang migrated towards as well:
85     //
86     // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
87     unsafe { intrinsics::pref_align_of::<T>() }
88 }
89
90 /// Returns the alignment of the type of the value that `_val` points to.
91 ///
92 /// This is similar to `align_of`, but function will properly handle types such
93 /// as trait objects (in the future), returning the alignment for an arbitrary
94 /// value at runtime.
95 #[inline]
96 #[stable]
97 pub fn align_of_val<T>(_val: &T) -> uint {
98     align_of::<T>()
99 }
100
101 /// Deprecated, this function has been renamed to align_of
102 #[inline]
103 #[deprecated = "use mem::align_of instead"]
104 pub fn pref_align_of<T>() -> uint { align_of::<T>() }
105
106 /// Deprecated, this function has been renamed to align_of_val
107 #[inline]
108 #[deprecated = "use mem::align_of_val instead"]
109 pub fn pref_align_of_val<T>(val: &T) -> uint { align_of_val(val) }
110
111 /// Create a value initialized to zero.
112 ///
113 /// This function is similar to allocating space for a a local variable and
114 /// zeroing it out (an unsafe operation).
115 ///
116 /// Care must be taken when using this function, if the type `T` has a
117 /// destructor and the value falls out of scope (due to unwinding or returning)
118 /// before being initialized, then the destructor will run on zeroed
119 /// data, likely leading to crashes.
120 ///
121 /// This is useful for FFI functions sometimes, but should generally be avoided.
122 #[inline]
123 #[stable]
124 pub unsafe fn zeroed<T>() -> T {
125     intrinsics::init()
126 }
127
128 /// Deprecated, use zeroed() instead
129 #[inline]
130 #[deprecated = "this function has been renamed to zeroed()"]
131 pub unsafe fn init<T>() -> T { zeroed() }
132
133 /// Create an uninitialized value.
134 ///
135 /// Care must be taken when using this function, if the type `T` has a
136 /// destructor and the value falls out of scope (due to unwinding or returning)
137 /// before being initialized, then the destructor will run on uninitialized
138 /// data, likely leading to crashes.
139 ///
140 /// This is useful for FFI functions sometimes, but should generally be avoided.
141 #[inline]
142 #[stable]
143 pub unsafe fn uninitialized<T>() -> T {
144     intrinsics::uninit()
145 }
146
147 /// Deprecated, use `uninitialized` instead.
148 #[inline]
149 #[deprecated = "this function has been renamed to `uninitialized`"]
150 pub unsafe fn uninit<T>() -> T {
151     intrinsics::uninit()
152 }
153
154 /// Unsafely overwrite a memory location with the given value without destroying
155 /// the old value.
156 ///
157 /// This operation is unsafe because it does not destroy the previous value
158 /// contained at the location `dst`. This could leak allocations or resources,
159 /// so care must be taken to previously deallocate the value at `dst`.
160 #[inline]
161 #[deprecated = "use ptr::write"]
162 pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
163     intrinsics::move_val_init(&mut *dst, src)
164 }
165
166 /// Deprecated, use `overwrite` instead
167 #[inline]
168 #[deprecated = "use ptr::write"]
169 pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
170     ptr::write(dst, src)
171 }
172
173 /// A type that can have its bytes re-ordered.
174 pub trait ByteOrder: Clone {
175     /// Reverses the byte order of the value.
176     ///
177     /// # Example
178     ///
179     /// ```rust
180     /// use std::mem::ByteOrder;
181     ///
182     /// let n = 0x0123456789ABCDEFu64;
183     /// let m = 0xEFCDAB8967452301u64;
184     ///
185     /// assert_eq!(n.swap_bytes(), m);
186     /// ```
187     fn swap_bytes(&self) -> Self;
188
189     /// Convert a value from big endian to the target's endianness.
190     ///
191     /// On big endian this is a no-op. On little endian the bytes are swapped.
192     ///
193     /// # Example
194     ///
195     /// ```rust
196     /// use std::mem::ByteOrder;
197     ///
198     /// let n = 0x0123456789ABCDEFu64;
199     ///
200     /// if cfg!(target_endian = "big") {
201     ///     assert_eq!(ByteOrder::from_big_endian(n), n)
202     /// } else {
203     ///     assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes())
204     /// }
205     /// ```
206     #[inline]
207     fn from_big_endian(x: Self) -> Self {
208         if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
209     }
210
211     /// Convert a value from little endian to the target's endianness.
212     ///
213     /// On little endian this is a no-op. On big endian the bytes are swapped.
214     ///
215     /// # Example
216     ///
217     /// ```rust
218     /// use std::mem::ByteOrder;
219     ///
220     /// let n = 0x0123456789ABCDEFu64;
221     ///
222     /// if cfg!(target_endian = "little") {
223     ///     assert_eq!(ByteOrder::from_little_endian(n), n)
224     /// } else {
225     ///     assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes())
226     /// }
227     /// ```
228     #[inline]
229     fn from_little_endian(x: Self) -> Self {
230         if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
231     }
232
233     /// Convert the value to big endian from the target's endianness.
234     ///
235     /// On big endian this is a no-op. On little endian the bytes are swapped.
236     ///
237     /// # Example
238     ///
239     /// ```rust
240     /// use std::mem::ByteOrder;
241     ///
242     /// let n = 0x0123456789ABCDEFu64;
243     ///
244     /// if cfg!(target_endian = "big") {
245     ///     assert_eq!(n.to_big_endian(), n)
246     /// } else {
247     ///     assert_eq!(n.to_big_endian(), n.swap_bytes())
248     /// }
249     /// ```
250     #[inline]
251     fn to_big_endian(&self) -> Self {
252         if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() }
253     }
254
255     /// Convert the value to little endian from the target's endianness.
256     ///
257     /// On little endian this is a no-op. On big endian the bytes are swapped.
258     ///
259     /// # Example
260     ///
261     /// ```rust
262     /// use std::mem::ByteOrder;
263     ///
264     /// let n = 0x0123456789ABCDEFu64;
265     ///
266     /// if cfg!(target_endian = "little") {
267     ///     assert_eq!(n.to_little_endian(), n)
268     /// } else {
269     ///     assert_eq!(n.to_little_endian(), n.swap_bytes())
270     /// }
271     /// ```
272     #[inline]
273     fn to_little_endian(&self) -> Self {
274         if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() }
275     }
276 }
277
278 impl ByteOrder for u8 {
279     #[inline]
280     fn swap_bytes(&self) -> u8 {
281         *self // swapping a single byte does nothing
282     }
283 }
284
285 impl ByteOrder for u16 {
286     #[inline]
287     fn swap_bytes(&self) -> u16 {
288         unsafe { intrinsics::bswap16(*self) }
289     }
290 }
291
292 impl ByteOrder for u32 {
293     #[inline]
294     fn swap_bytes(&self) -> u32 {
295         unsafe { intrinsics::bswap32(*self) }
296     }
297 }
298
299 impl ByteOrder for u64 {
300     #[inline]
301     fn swap_bytes(&self) -> u64 {
302         unsafe { intrinsics::bswap64(*self) }
303     }
304 }
305
306 #[cfg(target_word_size = "32")]
307 impl ByteOrder for uint {
308     #[inline]
309     fn swap_bytes(&self) -> uint {
310         (*self as u32).swap_bytes() as uint
311     }
312 }
313
314 #[cfg(target_word_size = "64")]
315 impl ByteOrder for uint {
316     #[inline]
317     fn swap_bytes(&self) -> uint {
318         (*self as u64).swap_bytes() as uint
319     }
320 }
321
322 /// Convert an u16 to little endian from the target's endianness.
323 ///
324 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
325 #[inline]
326 #[stable]
327 pub fn to_le16(x: u16) -> u16 { x.to_little_endian() }
328
329 /// Convert an u32 to little endian from the target's endianness.
330 ///
331 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
332 #[inline]
333 #[stable]
334 pub fn to_le32(x: u32) -> u32 { x.to_little_endian() }
335
336 /// Convert an u64 to little endian from the target's endianness.
337 ///
338 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
339 #[inline]
340 #[stable]
341 pub fn to_le64(x: u64) -> u64 { x.to_little_endian() }
342
343 /// Convert an u16 to big endian from the target's endianness.
344 ///
345 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
346 #[inline]
347 #[stable]
348 pub fn to_be16(x: u16) -> u16 { x.to_big_endian() }
349
350 /// Convert an u32 to big endian from the target's endianness.
351 ///
352 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
353 #[inline]
354 #[stable]
355 pub fn to_be32(x: u32) -> u32 { x.to_big_endian() }
356
357 /// Convert an u64 to big endian from the target's endianness.
358 ///
359 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
360 #[inline]
361 #[stable]
362 pub fn to_be64(x: u64) -> u64 { x.to_big_endian() }
363
364 /// Convert an u16 from little endian to the target's endianness.
365 ///
366 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
367 #[inline]
368 #[stable]
369 pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) }
370
371 /// Convert an u32 from little endian to the target's endianness.
372 ///
373 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
374 #[inline]
375 #[stable]
376 pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) }
377
378 /// Convert an u64 from little endian to the target's endianness.
379 ///
380 /// On little endian, this is a no-op.  On big endian, the bytes are swapped.
381 #[inline]
382 #[stable]
383 pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) }
384
385 /// Convert an u16 from big endian to the target's endianness.
386 ///
387 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
388 #[inline]
389 #[stable]
390 pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) }
391
392 /// Convert an u32 from big endian to the target's endianness.
393 ///
394 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
395 #[inline]
396 #[stable]
397 pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) }
398
399 /// Convert an u64 from big endian to the target's endianness.
400 ///
401 /// On big endian, this is a no-op.  On little endian, the bytes are swapped.
402 #[inline]
403 #[stable]
404 pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) }
405
406 /**
407  * Swap the values at two mutable locations of the same type, without
408  * deinitialising or copying either one.
409  */
410 #[inline]
411 #[stable]
412 pub fn swap<T>(x: &mut T, y: &mut T) {
413     unsafe {
414         // Give ourselves some scratch space to work with
415         let mut t: T = uninitialized();
416
417         // Perform the swap, `&mut` pointers never alias
418         ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
419         ptr::copy_nonoverlapping_memory(x, &*y, 1);
420         ptr::copy_nonoverlapping_memory(y, &t, 1);
421
422         // y and t now point to the same thing, but we need to completely forget `t`
423         // because it's no longer relevant.
424         forget(t);
425     }
426 }
427
428 /**
429  * Replace the value at a mutable location with a new one, returning the old
430  * value, without deinitialising or copying either one.
431  *
432  * This is primarily used for transferring and swapping ownership of a value
433  * in a mutable location. For example, this function allows consumption of
434  * one field of a struct by replacing it with another value. The normal approach
435  * doesn't always work:
436  *
437  * ```rust,ignore
438  * struct Buffer<T> { buf: Vec<T> }
439  *
440  * impl<T> Buffer<T> {
441  *     fn get_and_reset(&mut self) -> Vec<T> {
442  *         // error: cannot move out of dereference of `&mut`-pointer
443  *         let buf = self.buf;
444  *         self.buf = Vec::new();
445  *         buf
446  *     }
447  * }
448  * ```
449  *
450  * Note that `T` does not necessarily implement `Clone`, so it can't even
451  * clone and reset `self.buf`. But `replace` can be used to disassociate
452  * the original value of `self.buf` from `self`, allowing it to be returned:
453  *
454  * ```rust
455  * # struct Buffer<T> { buf: Vec<T> }
456  * impl<T> Buffer<T> {
457  *     fn get_and_reset(&mut self) -> Vec<T> {
458  *         use std::mem::replace;
459  *         replace(&mut self.buf, Vec::new())
460  *     }
461  * }
462  * ```
463  */
464 #[inline]
465 #[stable]
466 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
467     swap(dest, &mut src);
468     src
469 }
470
471 /// Disposes of a value.
472 ///
473 /// This function can be used to destroy any value by allowing `drop` to take
474 /// ownership of its argument.
475 ///
476 /// # Example
477 ///
478 /// ```
479 /// use std::cell::RefCell;
480 ///
481 /// let x = RefCell::new(1);
482 ///
483 /// let mut mutable_borrow = x.borrow_mut();
484 /// *mutable_borrow = 1;
485 /// drop(mutable_borrow); // relinquish the mutable borrow on this slot
486 ///
487 /// let borrow = x.borrow();
488 /// println!("{}", *borrow);
489 /// ```
490 #[inline]
491 #[stable]
492 pub fn drop<T>(_x: T) { }
493
494 /// Moves a thing into the void.
495 ///
496 /// The forget function will take ownership of the provided value but neglect
497 /// to run any required cleanup or memory management operations on it.
498 ///
499 /// This function is the unsafe version of the `drop` function because it does
500 /// not run any destructors.
501 #[inline]
502 #[stable]
503 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing) }
504
505 /// Interprets `src` as `&U`, and then reads `src` without moving the contained
506 /// value.
507 ///
508 /// This function will unsafely assume the pointer `src` is valid for
509 /// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
510 /// will also unsafely create a copy of the contained value instead of moving
511 /// out of `src`.
512 ///
513 /// It is not a compile-time error if `T` and `U` have different sizes, but it
514 /// is highly encouraged to only invoke this function where `T` and `U` have the
515 /// same size. This function triggers undefined behavior if `U` is larger than
516 /// `T`.
517 #[inline]
518 #[stable]
519 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
520     ptr::read(src as *T as *U)
521 }
522
523 /// Transforms lifetime of the second pointer to match the first.
524 #[inline]
525 #[unstable = "this function may be removed in the future due to its \
526               questionable utility"]
527 pub unsafe fn copy_lifetime<'a, S, T>(_ptr: &'a S, ptr: &T) -> &'a T {
528     transmute(ptr)
529 }
530
531 /// Transforms lifetime of the second mutable pointer to match the first.
532 #[inline]
533 #[unstable = "this function may be removed in the future due to its \
534               questionable utility"]
535 pub unsafe fn copy_mut_lifetime<'a, S, T>(_ptr: &'a mut S,
536                                           ptr: &mut T) -> &'a mut T {
537     transmute(ptr)
538 }
539
540 #[cfg(test)]
541 mod tests {
542     use mem::*;
543     use option::{Some,None};
544     use realstd::str::StrAllocating;
545     use realstd::owned::Box;
546     use realstd::vec::Vec;
547     use raw;
548
549     #[test]
550     fn size_of_basic() {
551         assert_eq!(size_of::<u8>(), 1u);
552         assert_eq!(size_of::<u16>(), 2u);
553         assert_eq!(size_of::<u32>(), 4u);
554         assert_eq!(size_of::<u64>(), 8u);
555     }
556
557     #[test]
558     #[cfg(target_arch = "x86")]
559     #[cfg(target_arch = "arm")]
560     #[cfg(target_arch = "mips")]
561     fn size_of_32() {
562         assert_eq!(size_of::<uint>(), 4u);
563         assert_eq!(size_of::<*uint>(), 4u);
564     }
565
566     #[test]
567     #[cfg(target_arch = "x86_64")]
568     fn size_of_64() {
569         assert_eq!(size_of::<uint>(), 8u);
570         assert_eq!(size_of::<*uint>(), 8u);
571     }
572
573     #[test]
574     fn size_of_val_basic() {
575         assert_eq!(size_of_val(&1u8), 1);
576         assert_eq!(size_of_val(&1u16), 2);
577         assert_eq!(size_of_val(&1u32), 4);
578         assert_eq!(size_of_val(&1u64), 8);
579     }
580
581     #[test]
582     fn align_of_basic() {
583         assert_eq!(align_of::<u8>(), 1u);
584         assert_eq!(align_of::<u16>(), 2u);
585         assert_eq!(align_of::<u32>(), 4u);
586     }
587
588     #[test]
589     #[cfg(target_arch = "x86")]
590     #[cfg(target_arch = "arm")]
591     #[cfg(target_arch = "mips")]
592     fn align_of_32() {
593         assert_eq!(align_of::<uint>(), 4u);
594         assert_eq!(align_of::<*uint>(), 4u);
595     }
596
597     #[test]
598     #[cfg(target_arch = "x86_64")]
599     fn align_of_64() {
600         assert_eq!(align_of::<uint>(), 8u);
601         assert_eq!(align_of::<*uint>(), 8u);
602     }
603
604     #[test]
605     fn align_of_val_basic() {
606         assert_eq!(align_of_val(&1u8), 1u);
607         assert_eq!(align_of_val(&1u16), 2u);
608         assert_eq!(align_of_val(&1u32), 4u);
609     }
610
611     #[test]
612     fn test_swap() {
613         let mut x = 31337;
614         let mut y = 42;
615         swap(&mut x, &mut y);
616         assert_eq!(x, 42);
617         assert_eq!(y, 31337);
618     }
619
620     #[test]
621     fn test_replace() {
622         let mut x = Some("test".to_string());
623         let y = replace(&mut x, None);
624         assert!(x.is_none());
625         assert!(y.is_some());
626     }
627
628     #[test]
629     fn test_transmute_copy() {
630         assert_eq!(1u, unsafe { ::mem::transmute_copy(&1) });
631     }
632
633     #[test]
634     fn test_transmute() {
635         trait Foo {}
636         impl Foo for int {}
637
638         let a = box 100 as Box<Foo>;
639         unsafe {
640             let x: raw::TraitObject = transmute(a);
641             assert!(*(x.data as *int) == 100);
642             let _x: Box<Foo> = transmute(x);
643         }
644
645         unsafe {
646             assert!(Vec::from_slice([76u8]) == transmute("L".to_string()));
647         }
648     }
649
650     macro_rules! test_byte_order {
651         ($T:ident) => {
652             mod $T {
653                 use mem::ByteOrder;
654
655                 static A: $T = 0b0101100;
656                 static B: $T = 0b0100001;
657                 static C: $T = 0b1111001;
658
659                 static _0: $T = 0;
660                 static _1: $T = !0;
661
662                 #[test]
663                 fn test_swap_bytes() {
664                     assert_eq!(A.swap_bytes().swap_bytes(), A);
665                     assert_eq!(B.swap_bytes().swap_bytes(), B);
666                     assert_eq!(C.swap_bytes().swap_bytes(), C);
667
668                     // Swapping these should make no difference
669                     assert_eq!(_0.swap_bytes(), _0);
670                     assert_eq!(_1.swap_bytes(), _1);
671                 }
672
673                 #[test]
674                 fn test_little_endian() {
675                     assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A);
676                     assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B);
677                     assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C);
678                     assert_eq!(ByteOrder::from_little_endian(_0), _0);
679                     assert_eq!(ByteOrder::from_little_endian(_1), _1);
680                     assert_eq!(_0.to_little_endian(), _0);
681                     assert_eq!(_1.to_little_endian(), _1);
682                 }
683
684                 #[test]
685                 fn test_big_endian() {
686                     assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A);
687                     assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B);
688                     assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C);
689                     assert_eq!(ByteOrder::from_big_endian(_0), _0);
690                     assert_eq!(ByteOrder::from_big_endian(_1), _1);
691                     assert_eq!(_0.to_big_endian(), _0);
692                     assert_eq!(_1.to_big_endian(), _1);
693                 }
694             }
695         }
696     }
697
698     test_byte_order!(u8)
699     test_byte_order!(u16)
700     test_byte_order!(u32)
701     test_byte_order!(u64)
702     test_byte_order!(uint)
703 }
704
705 // FIXME #13642 (these benchmarks should be in another place)
706 /// Completely miscellaneous language-construct benchmarks.
707 #[cfg(test)]
708 mod bench {
709     extern crate test;
710     use self::test::Bencher;
711     use option::{Some,None};
712
713     // Static/dynamic method dispatch
714
715     struct Struct {
716         field: int
717     }
718
719     trait Trait {
720         fn method(&self) -> int;
721     }
722
723     impl Trait for Struct {
724         fn method(&self) -> int {
725             self.field
726         }
727     }
728
729     #[bench]
730     fn trait_vtable_method_call(b: &mut Bencher) {
731         let s = Struct { field: 10 };
732         let t = &s as &Trait;
733         b.iter(|| {
734             t.method()
735         });
736     }
737
738     #[bench]
739     fn trait_static_method_call(b: &mut Bencher) {
740         let s = Struct { field: 10 };
741         b.iter(|| {
742             s.method()
743         });
744     }
745
746     // Overhead of various match forms
747
748     #[bench]
749     fn match_option_some(b: &mut Bencher) {
750         let x = Some(10);
751         b.iter(|| {
752             match x {
753                 Some(y) => y,
754                 None => 11
755             }
756         });
757     }
758
759     #[bench]
760     fn match_vec_pattern(b: &mut Bencher) {
761         let x = [1,2,3,4,5,6];
762         b.iter(|| {
763             match x {
764                 [1,2,3,..] => 10,
765                 _ => 11
766             }
767         });
768     }
769 }