2013-05-08 17:32:50 -07:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-12-24 17:08:28 +01:00
|
|
|
//! Miscellaneous helpers for common patterns
|
2012-09-19 16:52:32 -07:00
|
|
|
|
2013-05-24 19:35:29 -07:00
|
|
|
use cast;
|
|
|
|
use ptr;
|
2013-01-08 19:37:25 -08:00
|
|
|
use prelude::*;
|
2013-05-06 00:43:06 -04:00
|
|
|
use unstable::intrinsics;
|
2012-08-30 12:15:53 -07:00
|
|
|
|
2012-08-02 14:26:52 -04:00
|
|
|
/// The identity function.
|
2013-06-18 14:45:18 -07:00
|
|
|
#[inline]
|
2013-03-21 21:20:48 -07:00
|
|
|
pub fn id<T>(x: T) -> T { x }
|
2012-08-02 14:26:52 -04:00
|
|
|
|
2012-08-01 19:04:43 -04:00
|
|
|
/**
|
|
|
|
* Swap the values at two mutable locations of the same type, without
|
|
|
|
* deinitialising or copying either one.
|
|
|
|
*/
|
2013-06-18 14:45:18 -07:00
|
|
|
#[inline]
|
2012-09-28 17:41:45 -07:00
|
|
|
pub fn swap<T>(x: &mut T, y: &mut T) {
|
2013-05-06 00:43:06 -04:00
|
|
|
unsafe {
|
2013-05-23 22:54:46 -04:00
|
|
|
// Give ourselves some scratch space to work with
|
|
|
|
let mut tmp: T = intrinsics::uninit();
|
|
|
|
let t: *mut T = &mut tmp;
|
|
|
|
|
|
|
|
// Perform the swap, `&mut` pointers never alias
|
2013-08-02 21:41:06 -07:00
|
|
|
let x_raw: *mut T = x;
|
|
|
|
let y_raw: *mut T = y;
|
|
|
|
ptr::copy_nonoverlapping_memory(t, x_raw, 1);
|
|
|
|
ptr::copy_nonoverlapping_memory(x, y_raw, 1);
|
2013-05-23 22:54:46 -04:00
|
|
|
ptr::copy_nonoverlapping_memory(y, t, 1);
|
|
|
|
|
|
|
|
// y and t now point to the same thing, but we need to completely forget `tmp`
|
|
|
|
// because it's no longer relevant.
|
|
|
|
cast::forget(tmp);
|
2013-05-06 00:43:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replace the value at a mutable location with a new one, returning the old
|
|
|
|
* value, without deinitialising or copying either one.
|
|
|
|
*/
|
2013-06-18 14:45:18 -07:00
|
|
|
#[inline]
|
2013-05-06 00:43:06 -04:00
|
|
|
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
|
|
|
swap(dest, &mut src);
|
|
|
|
src
|
2012-08-01 19:04:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A non-copyable dummy type.
|
2013-06-27 03:32:21 -04:00
|
|
|
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
|
2013-06-27 20:47:45 +03:00
|
|
|
#[unsafe_no_drop_flag]
|
2013-06-10 20:30:01 -04:00
|
|
|
pub struct NonCopyable;
|
2013-02-27 19:13:53 -05:00
|
|
|
|
|
|
|
impl Drop for NonCopyable {
|
2013-09-16 21:18:07 -04:00
|
|
|
fn drop(&mut self) { }
|
2012-08-01 19:04:43 -04:00
|
|
|
}
|
|
|
|
|
2013-05-08 17:32:50 -07:00
|
|
|
/// A type with no inhabitants
|
|
|
|
pub enum Void { }
|
|
|
|
|
2013-05-31 15:17:22 -07:00
|
|
|
impl Void {
|
2013-05-08 17:32:50 -07:00
|
|
|
/// A utility function for ignoring this uninhabited type
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn uninhabited(self) -> ! {
|
2013-05-12 19:43:44 -07:00
|
|
|
match self {
|
2013-05-08 17:32:50 -07:00
|
|
|
// Nothing to match on
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-27 00:10:03 -05:00
|
|
|
#[cfg(test)]
|
2012-08-01 19:04:43 -04:00
|
|
|
mod tests {
|
2013-06-27 03:32:21 -04:00
|
|
|
use super::*;
|
2014-01-06 22:33:37 -08:00
|
|
|
use prelude::*;
|
2013-10-16 18:34:01 -07:00
|
|
|
use mem::size_of;
|
2013-01-08 19:37:25 -08:00
|
|
|
|
2012-08-02 14:26:52 -04:00
|
|
|
#[test]
|
2013-06-27 03:32:21 -04:00
|
|
|
fn identity_crisis() {
|
2012-08-02 14:26:52 -04:00
|
|
|
// Writing a test for the identity function. How did it come to this?
|
2012-08-27 16:26:35 -07:00
|
|
|
let x = ~[(5, false)];
|
2013-07-02 12:47:32 -07:00
|
|
|
//FIXME #3387 assert!(x.eq(id(x.clone())));
|
|
|
|
let y = x.clone();
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(x.eq(&id(y)));
|
2012-08-02 14:26:52 -04:00
|
|
|
}
|
2013-06-27 03:32:21 -04:00
|
|
|
|
2012-08-01 19:04:43 -04:00
|
|
|
#[test]
|
2013-06-27 03:32:21 -04:00
|
|
|
fn test_swap() {
|
2012-08-01 19:04:43 -04:00
|
|
|
let mut x = 31337;
|
|
|
|
let mut y = 42;
|
|
|
|
swap(&mut x, &mut y);
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(x, 42);
|
|
|
|
assert_eq!(y, 31337);
|
2012-08-01 19:04:43 -04:00
|
|
|
}
|
2013-06-27 03:32:21 -04:00
|
|
|
|
2012-08-01 19:04:43 -04:00
|
|
|
#[test]
|
2013-06-27 03:32:21 -04:00
|
|
|
fn test_replace() {
|
|
|
|
let mut x = Some(NonCopyable);
|
2012-08-20 12:23:37 -07:00
|
|
|
let y = replace(&mut x, None);
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(x.is_none());
|
|
|
|
assert!(y.is_some());
|
2012-08-01 19:04:43 -04:00
|
|
|
}
|
2013-06-27 03:32:21 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_noncopyable() {
|
|
|
|
assert_eq!(size_of::<NonCopyable>(), 0);
|
|
|
|
|
2013-06-27 20:47:45 +03:00
|
|
|
// verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
|
2013-06-27 03:32:21 -04:00
|
|
|
|
2013-07-22 00:06:29 -04:00
|
|
|
static mut did_run: bool = false;
|
2013-06-27 03:32:21 -04:00
|
|
|
|
|
|
|
struct Foo { five: int }
|
|
|
|
|
|
|
|
impl Drop for Foo {
|
2013-09-16 21:18:07 -04:00
|
|
|
fn drop(&mut self) {
|
2013-06-27 03:32:21 -04:00
|
|
|
assert_eq!(self.five, 5);
|
2013-07-22 00:06:29 -04:00
|
|
|
unsafe {
|
|
|
|
did_run = true;
|
|
|
|
}
|
2013-06-27 03:32:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
|
|
|
|
}
|
|
|
|
|
2013-07-22 00:06:29 -04:00
|
|
|
unsafe { assert_eq!(did_run, true); }
|
2013-06-27 03:32:21 -04:00
|
|
|
}
|
2012-08-01 19:04:43 -04:00
|
|
|
}
|
2013-07-22 16:50:36 -07:00
|
|
|
|
|
|
|
/// Completely miscellaneous language-construct benchmarks.
|
|
|
|
#[cfg(test)]
|
|
|
|
mod bench {
|
|
|
|
|
|
|
|
use extra::test::BenchHarness;
|
|
|
|
use option::{Some,None};
|
|
|
|
|
|
|
|
// Static/dynamic method dispatch
|
|
|
|
|
|
|
|
struct Struct {
|
|
|
|
field: int
|
|
|
|
}
|
|
|
|
|
|
|
|
trait Trait {
|
|
|
|
fn method(&self) -> int;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Trait for Struct {
|
|
|
|
fn method(&self) -> int {
|
|
|
|
self.field
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn trait_vtable_method_call(bh: &mut BenchHarness) {
|
|
|
|
let s = Struct { field: 10 };
|
|
|
|
let t = &s as &Trait;
|
2013-11-21 17:23:21 -08:00
|
|
|
bh.iter(|| {
|
2013-07-22 16:50:36 -07:00
|
|
|
t.method();
|
2013-11-21 17:23:21 -08:00
|
|
|
});
|
2013-07-22 16:50:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn trait_static_method_call(bh: &mut BenchHarness) {
|
|
|
|
let s = Struct { field: 10 };
|
2013-11-21 17:23:21 -08:00
|
|
|
bh.iter(|| {
|
2013-07-22 16:50:36 -07:00
|
|
|
s.method();
|
2013-11-21 17:23:21 -08:00
|
|
|
});
|
2013-07-22 16:50:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Overhead of various match forms
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn match_option_some(bh: &mut BenchHarness) {
|
|
|
|
let x = Some(10);
|
2013-11-21 17:23:21 -08:00
|
|
|
bh.iter(|| {
|
2013-07-22 16:50:36 -07:00
|
|
|
let _q = match x {
|
|
|
|
Some(y) => y,
|
|
|
|
None => 11
|
|
|
|
};
|
2013-11-21 17:23:21 -08:00
|
|
|
});
|
2013-07-22 16:50:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn match_vec_pattern(bh: &mut BenchHarness) {
|
|
|
|
let x = [1,2,3,4,5,6];
|
2013-11-21 17:23:21 -08:00
|
|
|
bh.iter(|| {
|
2013-07-22 16:50:36 -07:00
|
|
|
let _q = match x {
|
2013-11-28 12:22:53 -08:00
|
|
|
[1,2,3,..] => 10,
|
2013-07-22 16:50:36 -07:00
|
|
|
_ => 11
|
|
|
|
};
|
2013-11-21 17:23:21 -08:00
|
|
|
});
|
2013-07-22 16:50:36 -07:00
|
|
|
}
|
|
|
|
}
|