use batch_impl::batch_impl;
use std::rc::Rc;
#[batch_impl(usize, isize)]
trait Numeric {}
#[test]
fn basic_numeric() {
fn check<T: Numeric>(_: &T) {}
check(&0usize);
check(&0isize);
}
#[batch_impl(<T> Vec<T>)]
trait Collection {}
#[test]
fn generic_vec() {
fn check<T: Collection>(_: &T) {}
check(&vec![1, 2, 3]);
check(&vec!["a", "b"]);
}
#[batch_impl(
[usize { fn name() -> &'static str { "usize" } },
isize { fn name() -> &'static str { "isize" } }]
{ fn zero() -> Self { 0 } }
)]
trait Zero {
fn zero() -> Self;
fn name() -> &'static str;
}
#[test]
fn shared_independent_body() {
assert_eq!(usize::zero(), 0);
assert_eq!(isize::zero(), 0);
assert_eq!(<usize as Zero>::name(), "usize");
assert_eq!(<isize as Zero>::name(), "isize");
}
#[batch_impl([&, Box, Rc].u32)]
trait RefOrOwnedEmpty {}
#[test]
fn caret_prefix_list() {
fn check<T: RefOrOwnedEmpty>(_: &T) {}
let v: u32 = 5;
check(&(&v));
check(&Box::new(v));
check(&Rc::new(v));
}
#[batch_impl(().3)]
trait Tuple3 {}
#[test]
fn tuple_pow_basic() {
fn check<T: Tuple3>(_: &T) {}
check(&(1u8, 2u16, 3u32));
}
#[batch_impl(().1)]
trait Tuple1 {}
#[batch_impl(().2)]
trait Tuple2 {}
#[batch_impl(().3)]
trait Tuple3R {}
#[test]
fn tuple_range_pow() {
fn t1<T: Tuple1>(_: &T) {}
fn t2<T: Tuple2>(_: &T) {}
fn t3<T: Tuple3R>(_: &T) {}
t1(&(1u8,));
t2(&(1u8, 2u16));
t3(&(1u8, 2u16, 3u32));
}
#[batch_impl(<T> Iter<Item=T> Vec<T> {
fn count(&self) -> usize { self.len() }
})]
trait Iter {
type Item;
fn count(&self) -> usize;
}
#[test]
fn assoc_type_binding() {
assert_eq!(vec![1, 2, 3].count(), 3);
}
#[batch_impl(usize, Box<u32>)]
unsafe trait UnsafeAll {}
#[test]
fn unsafe_trait_impls() {
fn check<T: UnsafeAll>(_: &T) {}
check(&0usize);
check(&Box::new(0u32));
}
#[batch_impl(unsafe.usize, isize)]
unsafe trait PartialUnsafe {}
#[test]
fn partial_unsafe() {
fn check<T: PartialUnsafe>(_: &T) {}
check(&0usize);
check(&0isize);
}
#[batch_impl(fn.(i32, u32))]
trait FnSimple {}
#[batch_impl(fn(i32, u32) String)]
trait FnWithReturn {}
#[test]
fn fn_types() {
fn check_simple<T: FnSimple>(_: &T) {}
fn check_ret<T: FnWithReturn>(_: &T) {}
let f: fn(i32, u32) = |_, _| {};
check_simple(&f);
let fr: fn(i32, u32) -> String = |_, _| String::new();
check_ret(&fr);
}
#[batch_impl(unsafe fn(u8) -> u8)]
trait UnsafeFnType {}
#[batch_impl(unsafe.fn(u8) -> u8)]
unsafe trait UnsafeFnImpl {}
#[batch_impl(fn(u8) -> ! { #[allow(dead_code)] fn call(&self, _: u8) -> ! { unreachable!() } })]
trait NeverReturning {
#[allow(dead_code)]
fn call(&self, x: u8) -> !;
}
#[test]
fn unsafe_fn_vs_unsafe_impl() {
fn check_type<T: UnsafeFnType>(_: &T) {}
let f: unsafe fn(u8) -> u8 = |x| x;
check_type(&f);
unsafe fn check_impl<T: UnsafeFnImpl>(_: &T) {}
let g: fn(u8) -> u8 = |x| x;
unsafe { check_impl(&g) };
fn check_never<T: NeverReturning>(_: &T) {}
let n: fn(u8) -> ! = |_| unreachable!();
check_never(&n);
}
#[batch_impl(&'static mut u8 { fn tag(&self) -> &'static str { "m" } })]
trait RefMutLt {
fn tag(&self) -> &'static str;
}
#[batch_impl(for<'a> fn(&'a u8) -> u8 { fn tag(&self) -> &'static str { "hrtb" } })]
trait HrtbFn {
fn tag(&self) -> &'static str;
}
#[batch_impl(extern "C" fn(u8) -> u8 { fn tag(&self) -> &'static str { "c" } })]
trait ExternFn {
fn tag(&self) -> &'static str;
}
#[test]
fn space_accepts_dot_operands() {
fn check<T: RefMutLt>(t: T) {
assert_eq!(t.tag(), "m");
}
check(Box::leak(Box::new(0u8)));
fn check2<T: HrtbFn>(t: &T) {
assert_eq!(t.tag(), "hrtb");
}
let g: for<'a> fn(&'a u8) -> u8 = |x| *x;
check2(&g);
fn check3<T: ExternFn>(t: &T) {
assert_eq!(t.tag(), "c");
}
extern "C" fn c_fn(x: u8) -> u8 {
x
}
let h: extern "C" fn(u8) -> u8 = c_fn;
check3(&h);
}
#[batch_impl(#[allow(dead_code)].usize, isize)]
trait AttrSimple {}
#[test]
fn attr_support() {
fn check<T: AttrSimple>(_: &T) {}
check(&0usize);
check(&0isize);
}
#[batch_impl(
(i32, String),
&str,
Box<dyn std::fmt::Display>,
fn(i32) -> bool,
dyn Fn() + Send + Sync
)]
trait ComplexMarker {}
#[test]
fn complex_passthrough() {
fn check<T: ComplexMarker + ?Sized>(_: &T) {}
check(&(1i32, String::from("x")));
check(&"hi");
let bd: Box<dyn std::fmt::Display> = Box::new(1i32);
check(&bd);
let ft: fn(i32) -> bool = |_| true;
check(&ft);
fn _dyn_check<T: ComplexMarker + ?Sized>() {}
_dyn_check::<dyn Fn() + Send + Sync>();
}
#[batch_impl(unsafe fn(u32) -> u32)]
trait UnsafeFnMarker {}
#[batch_impl(unsafe fn.(u32, i32))]
trait UnsafeFnPow {}
#[batch_impl(unsafe fn.(u32, i32) i64)]
trait UnsafeFnRet {}
#[test]
fn unsafe_fn_type() {
fn check<T: UnsafeFnMarker>(_: &T) {}
let f: unsafe fn(u32) -> u32 = |x| x;
check(&f);
fn check_pow<T: UnsafeFnPow>(_: &T) {}
let g: unsafe fn(u32, i32) = |_, _| {};
check_pow(&g);
fn check_ret<T: UnsafeFnRet>(_: &T) {}
let h: unsafe fn(u32, i32) -> i64 = |a, b| a as i64 + b as i64;
check_ret(&h);
}
#[batch_impl([Box, self] u8 { fn tag(&self) -> &'static str { "x" } })]
#[allow(dead_code)]
trait WrapOrBare {
fn tag(&self) -> &'static str;
}
#[test]
fn self_identity_in_matrix() {
fn check<T: WrapOrBare>(_: &T) {}
check(&Box::new(0u8));
check(&0u8);
}