|
| 1 | +// Copyright 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. |
| 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 | +use core::{option, cast}; |
| 12 | + |
| 13 | +// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, |
| 14 | +// which "says that a destructor applied to an object built from a constructor |
| 15 | +// behaves as expected". -- http://coq.inria.fr/doc/Reference-Manual006.html |
| 16 | +// |
| 17 | +// It's a little more complicated here, because of pointers and regions and |
| 18 | +// trying to get assert failure messages that at least identify which case |
| 19 | +// failed. |
| 20 | + |
| 21 | +enum E<T> { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } |
| 22 | +impl<T> E<T> { |
| 23 | + fn is_none(&self) -> bool { |
| 24 | + match *self { |
| 25 | + Thing(*) => false, |
| 26 | + Nothing(*) => true |
| 27 | + } |
| 28 | + } |
| 29 | + fn get_ref<'r>(&'r self) -> (int, &'r T) { |
| 30 | + match *self { |
| 31 | + Nothing(*) => fail!(fmt!("E::get_ref(Nothing::<%s>)", stringify!($T))), |
| 32 | + Thing(x, ref y) => (x, y) |
| 33 | + } |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +macro_rules! check_option { |
| 38 | + ($e:expr: $T:ty) => {{ |
| 39 | + // FIXME #6000: remove the copy |
| 40 | + check_option!(copy $e: $T, |ptr| assert!(*ptr == $e)); |
| 41 | + }}; |
| 42 | + ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ |
| 43 | + assert!(option::None::<$T>.is_none()); |
| 44 | + let s_ = option::Some::<$T>($e); |
| 45 | + let $v = s_.get_ref(); |
| 46 | + $chk |
| 47 | + }} |
| 48 | +} |
| 49 | + |
| 50 | +macro_rules! check_fancy { |
| 51 | + ($e:expr: $T:ty) => {{ |
| 52 | + // FIXME #6000: remove the copy |
| 53 | + check_fancy!(copy $e: $T, |ptr| assert!(*ptr == $e)); |
| 54 | + }}; |
| 55 | + ($e:expr: $T:ty, |$v:ident| $chk:expr) => {{ |
| 56 | + assert!(Nothing::<$T>((), ((), ()), [23i8, ..0]).is_none()); |
| 57 | + let t_ = Thing::<$T>(23, $e); |
| 58 | + match t_.get_ref() { |
| 59 | + (23, $v) => { $chk } |
| 60 | + _ => fail!(fmt!("Thing::<%s>(23, %s).get_ref() != (23, _)", |
| 61 | + stringify!($T), stringify!($e))) |
| 62 | + } |
| 63 | + }} |
| 64 | +} |
| 65 | + |
| 66 | +macro_rules! check_type { |
| 67 | + ($($a:tt)*) => {{ |
| 68 | + check_option!($($a)*); |
| 69 | + check_fancy!($($a)*); |
| 70 | + }} |
| 71 | +} |
| 72 | + |
| 73 | +pub fn main() { |
| 74 | + check_type!(&17: &int); |
| 75 | + check_type!(~18: ~int); |
| 76 | + check_type!(@19: @int); |
| 77 | + check_type!(~"foo": ~str); |
| 78 | + check_type!(@"bar": @str); |
| 79 | + check_type!(~[]: ~[int]); |
| 80 | + check_type!(~[20, 22]: ~[int]); |
| 81 | + check_type!(@[]: @[int]); |
| 82 | + check_type!(@[24, 26]: @[int]); |
| 83 | + let mint: uint = unsafe { cast::transmute(main) }; |
| 84 | + check_type!(main: extern fn(), |pthing| { |
| 85 | + assert!(mint == unsafe { cast::transmute(*pthing) }) |
| 86 | + }); |
| 87 | +} |
0 commit comments