1 // Copyright 2012-2013 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.
11 //! Miscellaneous helpers for common patterns.
16 use unstable::intrinsics;
18 /// The identity function.
20 pub fn id<T>(x: T) -> T { x }
24 pub fn ignore<T>(_x: T) { }
26 /// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
27 /// original value of `*ptr`.
29 /// NB: This function accepts `@mut T` and not `&mut T` to avoid
30 /// an obvious borrowck hazard. Typically passing in `&mut T` will
31 /// cause borrow check errors because it freezes whatever location
32 /// that `&mut T` is stored in (either statically or dynamically).
39 let prev = replace(ptr, value);
46 * Swap the values at two mutable locations of the same type, without
47 * deinitialising or copying either one.
50 pub fn swap<T>(x: &mut T, y: &mut T) {
52 // Give ourselves some scratch space to work with
53 let mut tmp: T = intrinsics::uninit();
54 let t: *mut T = &mut tmp;
56 // Perform the swap, `&mut` pointers never alias
57 let x_raw: *mut T = x;
58 let y_raw: *mut T = y;
59 ptr::copy_nonoverlapping_memory(t, x_raw, 1);
60 ptr::copy_nonoverlapping_memory(x, y_raw, 1);
61 ptr::copy_nonoverlapping_memory(y, t, 1);
63 // y and t now point to the same thing, but we need to completely forget `tmp`
64 // because it's no longer relevant.
70 * Replace the value at a mutable location with a new one, returning the old
71 * value, without deinitialising or copying either one.
74 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
79 /// A non-copyable dummy type.
80 #[deriving(Eq, TotalEq, Ord, TotalOrd)]
81 #[unsafe_no_drop_flag]
82 pub struct NonCopyable;
85 // FIXME(#8233) should not be necessary
86 /// Create a new noncopyable token.
87 pub fn new() -> NonCopyable { NonCopyable }
90 impl Drop for NonCopyable {
94 /// A type with no inhabitants
98 /// A utility function for ignoring this uninhabited type
99 pub fn uninhabited(self) -> ! {
101 // Nothing to match on
108 A utility function for indicating unreachable code. It will fail if
109 executed. This is occasionally useful to put after loops that never
110 terminate normally, but instead directly return from a function.
115 fn choose_weighted_item(v: &[Item]) -> Item {
116 assert!(!v.is_empty());
119 so_far += item.weight;
124 // The above loop always returns, so we must hint to the
125 // type checker that it isn't possible to get down here
131 pub fn unreachable() -> ! {
132 fail!("internal error: entered unreachable code");
140 use option::{None, Some};
141 use either::{Either, Left, Right};
146 fn identity_crisis() {
147 // Writing a test for the identity function. How did it come to this?
148 let x = ~[(5, false)];
149 //FIXME #3387 assert!(x.eq(id(x.clone())));
151 assert!(x.eq(&id(y)));
158 swap(&mut x, &mut y);
160 assert_eq!(y, 31337);
165 let mut x = Some(NonCopyable);
166 let y = replace(&mut x, None);
167 assert!(x.is_none());
168 assert!(y.is_some());
172 fn test_uninhabited() {
173 let could_only_be_coin : Either <Void, ()> = Right (());
174 match could_only_be_coin {
175 Right (coin) => coin,
176 Left (is_void) => is_void.uninhabited ()
181 fn test_noncopyable() {
182 assert_eq!(size_of::<NonCopyable>(), 0);
184 // verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
186 static mut did_run: bool = false;
188 struct Foo { five: int }
192 assert_eq!(self.five, 5);
200 let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
203 unsafe { assert_eq!(did_run, true); }
207 /// Completely miscellaneous language-construct benchmarks.
211 use extra::test::BenchHarness;
212 use option::{Some,None};
214 // Static/dynamic method dispatch
221 fn method(&self) -> int;
224 impl Trait for Struct {
225 fn method(&self) -> int {
231 fn trait_vtable_method_call(bh: &mut BenchHarness) {
232 let s = Struct { field: 10 };
233 let t = &s as &Trait;
240 fn trait_static_method_call(bh: &mut BenchHarness) {
241 let s = Struct { field: 10 };
247 // Overhead of various match forms
250 fn match_option_some(bh: &mut BenchHarness) {
261 fn match_vec_pattern(bh: &mut BenchHarness) {
262 let x = [1,2,3,4,5,6];