use batch_impl::{batch_impl, batch_impl_only, batch_preprocess_test, batch_trait};
use std::collections::HashMap;
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(#[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(
usize #to_str{"usize"},
isize #to_str{"isize"}
)]
trait IdentToString {
fn to_str(&self) -> &'static str;
}
#[test]
fn directive_single_name() {
assert_eq!(0usize.to_str(), "usize");
assert_eq!(0isize.to_str(), "isize");
}
#[batch_impl(usize #fill(name, kind){"u"})]
trait Describable {
fn name(&self) -> &'static str;
fn kind(&self) -> &'static str;
}
#[test]
fn directive_fill() {
assert_eq!(0usize.name(), "u");
assert_eq!(0usize.kind(), "u");
}
#[batch_impl(
Vec<u32> #d_len{self.len()},
Box^Vec^u32 #delegate(d_len){**self}
)]
trait MyLen {
fn d_len(&self) -> usize;
}
#[test]
fn directive_delegate() {
let v: Vec<u32> = vec![1, 2, 3];
assert_eq!(v.d_len(), 3);
let b: Box<Vec<u32>> = Box::new(vec![1, 2, 3, 4]);
assert_eq!(b.d_len(), 4);
}
trait WildcardInner {
fn m(&self, ab: (u32, u32)) -> u32;
}
impl WildcardInner for Vec<u32> {
fn m(&self, ab: (u32, u32)) -> u32 {
ab.0 + ab.1
}
}
#[batch_impl(Box<Vec<u32>> #delegate(@all_methods){**self})]
trait WildcardOuter {
fn m(&self, _: (u32, u32)) -> u32;
}
#[test]
fn delegate_wildcard_param() {
let b = Box::new(vec![1u32, 2]);
assert_eq!(<Box<Vec<u32>> as WildcardOuter>::m(&b, (3, 4)), 7);
}
#[allow(dead_code)]
struct DestrBox(usize);
#[allow(dead_code)]
trait DestructureNum {
fn dm(&self, ab: (u32, u32)) -> u32;
}
impl DestructureNum for DestrBox {
fn dm(&self, ab: (u32, u32)) -> u32 {
ab.0 * ab.1
}
}
#[batch_impl(Box<DestrBox> #delegate(dm){**self})]
trait DestructureOuter {
fn dm(&self, (a, b): (u32, u32)) -> u32 {
a + b
}
}
#[test]
fn delegate_tuple_pattern() {
let b = Box::new(DestrBox(5));
assert_eq!(<Box<DestrBox> as DestructureOuter>::dm(&b, (3, 4)), 12);
}
struct RefBox;
trait RefNum {
fn rm(&self, ab: (u32, u32), extra: &u32) -> u32;
}
impl RefNum for RefBox {
fn rm(&self, ab: (u32, u32), extra: &u32) -> u32 {
ab.0 + ab.1 + *extra
}
}
#[batch_impl(Box<RefBox> #delegate(rm){**self})]
trait RefOuter {
fn rm(&self, (ref _a, ref _b): (u32, u32), _extra: &u32) -> u32 {
0
}
}
#[test]
fn delegate_ref_nested_pattern() {
let b = Box::new(RefBox);
assert_eq!(<Box<RefBox> as RefOuter>::rm(&b, (3, 4), &5), 12);
}
trait BlanketAt0 {
fn tag(&self) -> u32;
}
#[batch_impl_only(u32 { fn tag(&self) -> u32 { 7 } })]
trait BlanketAt0 {}
#[batch_impl_only(#blanket(@all_methods){Box<@0>})]
trait BlanketAt0 {
fn tag(&self) -> u32;
}
#[test]
fn blanket_at0_position() {
let b = Box::new(5u32);
assert_eq!(<Box<u32> as BlanketAt0>::tag(&b), 7);
}
struct MyPtrWithNum<T, const N: usize>(Box<T>, [u8; N]);
impl<T, const N: usize> std::ops::Deref for MyPtrWithNum<T, N> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
trait CfgT {
fn tag(&self) -> u32;
}
#[batch_impl_only(u32 { fn tag(&self) -> u32 { 7 } })]
trait CfgT {}
#[batch_impl_only(<const N: usize> #blanket(@all){MyPtrWithNum<@0, N>})]
trait CfgT {
fn tag(&self) -> u32;
}
#[test]
fn blanket_at0_const_generic() {
let p = MyPtrWithNum(Box::new(5u32), [0u8; 4]);
assert_eq!(<MyPtrWithNum<u32, 4> as CfgT>::tag(&p), 7);
}
trait BTNumeric {}
trait BTMap {}
batch_trait!(
BTNumeric: u8, u16, u32, u64;
BTMap: HashMap<i32, i32>
);
#[test]
fn batch_trait_macro_basic() {
fn check_num<T: BTNumeric>(_: &T) {}
fn check_map<T: BTMap>(_: &T) {}
check_num(&0u8);
check_num(&0u16);
check_num(&0u32);
check_num(&0u64);
check_map(&HashMap::<i32, i32>::new());
}
trait PairSegment {}
batch_trait!(
PairSegment: usize, isize;
unsafe YieldUnsafe: u32
);
#[allow(dead_code)] unsafe trait YieldUnsafe {}
#[test]
fn batch_trait_multi_segment_unsafe() {
fn check_pair<T: PairSegment>(_: &T) {}
check_pair(&0usize);
check_pair(&0isize);
}
trait DropDefOnly {
fn m(&self) -> u32;
}
#[batch_impl_only(usize #m{42})]
trait DropDefOnly {
fn m(&self) -> u32;
}
#[test]
fn batch_impl_only_drops_trait() {
assert_eq!(0usize.m(), 42);
}
#[batch_impl(HashMap-u32-String)]
trait DashMapGen {}
#[test]
fn dash_op() {
fn check<T: DashMapGen>(_: &T) {}
check(&HashMap::<u32, String>::new());
}
#[batch_impl(<T> Describe<T> [Vec<T>, <U> HashMap<T, U>] {
fn describe(&self) -> String { format!("len={}", self.len()) }
})]
trait Describe<T> {
fn describe(&self) -> String;
}
#[test]
fn nested_generic_list() {
let v: Vec<i32> = vec![1, 2, 3];
assert_eq!(v.describe(), "len=3");
let m: HashMap<i32, String> = HashMap::from([(1, String::from("a"))]);
assert_eq!(m.describe(), "len=1");
}
#[batch_impl(<T: Clone> Sortable<T> Vec<T> where{ T: Ord } {
fn is_sorted(&self) -> bool {
self.windows(2).all(|w| w[0] <= w[1])
}
})]
trait Sortable<T> {
fn is_sorted(&self) -> bool;
}
#[test]
fn dsl_where_clause() {
let v: Vec<i32> = vec![1, 2, 3];
assert!(v.is_sorted());
let v: Vec<i32> = vec![3, 1, 2];
assert!(!v.is_sorted());
}
#[batch_impl(
<T> Singleton<T> Vec<T> where{ T: Clone + Default }
{ fn only(&self) -> T { self.first().cloned().unwrap_or_default() } }
)]
trait Singleton<T> {
fn only(&self) -> T;
}
#[test]
fn suffix_where_clause() {
let v: Vec<i32> = vec![42];
assert_eq!(v.only(), 42);
let v: Vec<String> = vec![];
assert_eq!(v.only(), String::new());
}
trait PairAB<A, B> {
fn pair(&self) -> (A, B);
}
#[batch_impl_only(
<A> <B> PairAB<A, B> (A, B) where{ A: Clone, B: Clone }
{ fn pair(&self) -> (A, B) { (self.0.clone(), self.1.clone()) } }
)]
trait PairAB<A, B> {
fn pair(&self) -> (A, B);
}
#[test]
fn nested_generics_merge() {
let p = (1u32, String::from("x"));
assert_eq!(p.pair(), (1u32, String::from("x")));
}
#[batch_impl(
<T> WrapOrd<T> [Box, Rc]^Vec<T> where{ T: Ord }
{ fn is_sorted(&self) -> bool { self.windows(2).all(|w| w[0] <= w[1]) } }
)]
trait WrapOrd<T> {
fn is_sorted(&self) -> bool;
}
#[test]
fn where_with_list_modifier() {
use std::rc::Rc;
assert!(WrapOrd::<i32>::is_sorted(&Box::new(vec![1, 2, 3])));
assert!(!WrapOrd::<i32>::is_sorted(&Rc::new(vec![3, 1, 2])));
}
#[batch_impl(
<A> <B> PairComma<A, B> (A, B)
where A: Clone, B: Clone #both{ (self.0.clone(), self.1.clone()) }
)]
trait PairComma<A, B> {
fn both(&self) -> (A, B);
}
#[test]
fn where_bare_comma_predicates() {
let p = (1u32, String::from("x"));
assert_eq!(PairComma::both(&p), (1u32, String::from("x")));
}
macro_rules! m {
() => {
u32
};
}
#[batch_impl(
<T> FnRet<T> Vec<T> where T: Fn(u32) -> m!{}
{ fn ret_is_ok(&self) -> bool { true } }
)]
trait FnRet<T> {
fn ret_is_ok(&self) -> bool;
}
#[test]
fn where_macro_body_excluded() {
let v: Vec<fn(u32) -> u32> = vec![|x| x + 1];
assert!(v.ret_is_ok());
}
#[batch_impl(
<T> MultiOrd<T> Vec<T> where T: Ord where T: Clone {}
)]
trait MultiOrd<T> {}
#[test]
fn where_bare_multi_clause() {
fn check<T: MultiOrd<i32>>() {}
check::<Vec<i32>>();
}
#[batch_impl(usize #batch_preprocess_test(add,inc){*self+1})]
trait AddInc {
fn add(&self) -> Self;
fn inc(&self) -> Self;
}
#[test]
fn open_extension_fn_like_macro() {
assert_eq!(5usize.add(), 6);
assert_eq!(5usize.inc(), 6);
}
#[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(usize #fill(@all,-skip_me){0})]
trait ExceptInline {
fn keep_me(&self) -> u32;
fn skip_me(&self) -> u32 {
999
}
const VALUE: u32;
}
#[batch_impl(isize #fill(@all,-@all_methods){1})]
trait MarkMinus {
fn m(&self) -> u32 {
7
}
const C: u32;
}
#[batch_impl(u32 #fill(a, -b){2})]
trait ListMinus {
fn a(&self) -> u32;
fn b(&self) -> u32 {
8
}
}
#[test]
fn directive_minus_exclude() {
assert_eq!(1usize.keep_me(), 0);
assert_eq!(1usize.skip_me(), 999);
assert_eq!(<usize as ExceptInline>::VALUE, 0);
assert_eq!(<isize as MarkMinus>::C, 1);
assert_eq!(0isize.m(), 7);
let u = 3u32;
assert_eq!(u.a(), 2);
assert_eq!(u.b(), 8);
}
#[batch_impl(u32 #fill(@all_required_methods){1} #fill(@all_default_methods){2})]
trait ReqDefMix {
fn req(&self) -> u32;
fn opt(&self) -> u32 {
100
}
}
#[batch_impl(u64 #fill(@all_required_methods){3})]
trait ReqOnly {
fn req(&self) -> u32;
fn opt(&self) -> u32 {
7
}
}
#[batch_impl(#blanket(@all_required_methods){Box})]
trait BlanketReq {
fn req(&self) -> u32;
fn opt(&self) -> u32 {
7
}
}
impl BlanketReq for u16 {
fn req(&self) -> u32 {
1
}
}
#[test]
fn all_default_required_markers() {
assert_eq!(0u32.req(), 1);
assert_eq!(0u32.opt(), 2); assert_eq!(0u64.req(), 3);
assert_eq!(0u64.opt(), 7); let b = Box::new(1u16);
assert_eq!(b.req(), 1); assert_eq!(b.opt(), 7); }
#[rustfmt::skip]
#[batch_impl(usize, isize,)]
trait TrailingCommaOk {}
#[batch_impl(())]
trait EmptyTupleOk {}
#[batch_impl(usize, isize)]
trait NoTrailingIssue {}
#[test]
fn strictness_legal_forms() {
fn check<T: TrailingCommaOk>() {}
check::<usize>();
check::<isize>();
fn check2<T: EmptyTupleOk>() {}
check2::<()>();
fn check3<T: NoTrailingIssue>() {}
check3::<isize>();
}
#[batch_impl(<T> Cloned<T> Vec<T> {
fn get(&self) -> T {
self[0].clone()
}
})]
trait Cloned<T: Clone> {
fn get(&self) -> T;
}
trait SupA {}
trait SupB: SupA {}
struct SupS;
impl SupA for SupS {}
impl SupB for SupS {}
#[batch_impl(<T: SupB> Inherit<T> ())]
trait Inherit<T: SupA> {}
#[batch_impl(<'a, T> Lifetime<'a, T> ())]
trait Lifetime<'a, T: 'a> {}
#[batch_impl(<'b, T: 'b> LifetimeRenamed<'b, T> ())]
trait LifetimeRenamed<'a, T: 'a> {}
#[batch_impl(<T> StaticT<T> ())]
trait StaticT<T: 'static> {}
#[batch_impl(<'a, T> Mix<'a, T> ())]
trait Mix<'a, T: Clone + 'a> {}
#[batch_impl(<T: SupB, U> PartialBound<T, U> ())]
trait PartialBound<T: SupA, U: SupA> {}
#[batch_impl(<T, U: SupB> PartialBound2<T, U> ())]
trait PartialBound2<T: SupA, U: SupA> {}
impl SupA for i32 {}
#[test]
fn trait_bound_inherit() {
let v: Vec<i32> = vec![42];
assert_eq!(v.get(), 42);
fn check<T: Inherit<SupS>>() {}
check::<()>();
fn check2<T: Lifetime<'static, ()>>() {}
check2::<()>();
fn check2r<T: LifetimeRenamed<'static, ()>>() {}
check2r::<()>();
fn check3<T: StaticT<()>>() {}
check3::<()>();
fn check4<T: Mix<'static, ()>>() {}
check4::<()>();
fn check_p<T: PartialBound<SupS, i32>>() {}
check_p::<()>();
fn check_p2<T: PartialBound2<i32, SupS>>() {}
check_p2::<()>();
}
#[batch_impl(EmptyGenA<> ())]
trait EmptyGenA<T: Clone> {}
#[batch_impl(EmptyGenB<> ())]
trait EmptyGenB<'a, T: 'a> {}
#[batch_impl(EmptyGenC<> Vec<T>)]
trait EmptyGenC<T> {}
#[batch_impl(AssocGen<Item=T> ())]
trait AssocGen<T: Clone> {
type Item;
}
#[batch_impl(AssocGen2<First=T, Second=U> ())]
trait AssocGen2<'a, T: Clone + 'a, U: Ord> {
type First;
type Second;
}
#[test]
fn empty_trait_generics() {
fn check_a<T: EmptyGenA<i32>>() {}
check_a::<()>();
fn check_b<T: EmptyGenB<'static, ()>>() {}
check_b::<()>();
fn check_c<T: EmptyGenC<i32>>() {}
check_c::<Vec<i32>>();
fn check_d<T: AssocGen<i32, Item = i32>>() {}
check_d::<()>();
fn check_e<T: AssocGen2<'static, i32, u32, First = i32, Second = u32>>() {}
check_e::<()>();
}
#[batch_impl(<T> WhereCloned<T> Vec<T> {
fn wget(&self) -> T {
self[0].clone()
}
})]
trait WhereCloned<T>
where
T: Clone,
{
fn wget(&self) -> T;
}
#[batch_impl(<T> WhereBoth<T> ())]
trait WhereBoth<T: Clone>
where
T: Ord,
{
}
#[batch_impl(<'a, T> WhereLifetime<'a, T> ())]
trait WhereLifetime<'a, T>
where
T: 'a,
{
}
#[batch_impl(<T> WhereGen<T> ())]
trait WhereGen<T: Clone>
where
T: IntoIterator,
T::Item: Clone,
{
}
#[batch_impl(WhereGen2<> ())]
trait WhereGen2<T: Clone>
where
T: IntoIterator,
T::Item: Clone,
{
}
trait HasB {
type B;
}
trait OtherTrait {}
struct S;
impl HasB for S {
type B = u8;
}
impl OtherTrait for u8 {}
#[batch_impl(<A> ProjAssoc<A, u8> ())]
trait ProjAssoc<A, B>
where
A: HasB,
A::B: OtherTrait,
{
}
#[batch_impl(WhereArr<> ())]
trait WhereArr<T, const N: usize>
where
[T; N]: Sized,
{
}
trait HasB2 {
type B;
}
struct S2;
impl HasB2 for S2 {
type B = u8;
}
#[batch_impl(Deep<> ())]
trait Deep<T, U>
where
U: HasB2,
Vec<(T, <U as HasB2>::B)>: Sized,
{
}
trait TupleT {
type Assoc;
}
trait TupleT2 {}
impl TupleT for u8 {
type Assoc = u8;
}
impl TupleT2 for (u8, u8) {}
#[batch_impl(TuplePred<> ())]
trait TuplePred<A, B>
where
A: TupleT,
(A, B): TupleT2,
{
}
#[batch_impl(FnType<> ())]
trait FnType<A, B>
where
fn(A) -> B: Sized,
{
}
#[batch_impl(RefPred<> ())]
trait RefPred<'a, T>
where
T: 'a,
&'a T: Sized,
{
}
#[batch_impl(<T> ListPred2<T> [Vec<T>, <U> HashMap<T, U>])]
trait ListPred2<T>
where
T: IntoIterator,
T::Item: Clone,
{
}
#[test]
fn trait_where_clause_inherit() {
let v: Vec<i32> = vec![42];
assert_eq!(v.wget(), 42);
fn check_b<T: WhereBoth<i32>>() {}
check_b::<()>();
fn check_l<T: WhereLifetime<'static, ()>>() {}
check_l::<()>();
fn check_g<T: WhereGen<Vec<i32>>>() {}
check_g::<()>();
fn check_g2<T: WhereGen2<Vec<i32>>>() {}
check_g2::<()>();
fn check_p<T: ProjAssoc<S, u8>>() {}
check_p::<()>();
fn check_a<T: WhereArr<u8, 4>>() {}
check_a::<()>();
fn check_d<T: Deep<S2, S2>>() {}
check_d::<()>();
fn check_t<T: TuplePred<u8, u8>>() {}
check_t::<()>();
fn check_f<T: FnType<u8, u8>>() {}
check_f::<()>();
fn check_r<T: RefPred<'static, u8>>() {}
check_r::<()>();
fn check_lp<T: ListPred2<Vec<i32>>>() {}
check_lp::<Vec<Vec<i32>>>();
check_lp::<HashMap<Vec<i32>, i32>>();
}
#[batch_impl(@u8..u128)]
trait UintConst {}
#[batch_impl(@scalar)]
trait ScalarConst {}
#[batch_impl(@num)]
trait NumConst {}
trait ConstA {}
trait ConstB {}
batch_trait!(
@nums=[u8, u16, u32];
@uints=@u*;
ConstA: @nums;
ConstB: [Box, Rc]^@uints;
);
#[test]
fn const_system() {
fn _u<T: UintConst>(_: &T) {}
_u(&0u8);
_u(&0u64);
_u(&0u128);
fn _s<T: ScalarConst>(_: &T) {}
_s(&true);
_s(&'a');
_s(&0f64);
_s(&0usize);
_s(&0i16);
fn _n<T: NumConst>(_: &T) {}
_n(&0f32);
_n(&0i128);
fn _a<T: ConstA>(_: &T) {}
_a(&0u8);
_a(&0u32);
fn _b<T: ConstB>(_: &T) {}
_b(&Box::new(0u8));
_b(&Rc::new(0usize));
}
#[batch_impl(u32 { fn name(&self) -> String { self.to_string() } })]
#[batch_impl(#blanket(@all){&,Box,Rc})]
trait BlanketName {
fn name(&self) -> String;
}
#[batch_impl(u16 { fn inc(&mut self) -> u16 { *self += 1; *self } })]
#[batch_impl(#blanket(inc){&mut})]
trait BlanketInc {
fn inc(&mut self) -> u16;
}
#[batch_impl(u32 { fn deep(&self) -> u32 { *self } })]
#[batch_impl(#blanket(deep){Box^Rc:2, Box^Box^Box:3})]
trait BlanketDeep {
fn deep(&self) -> u32;
}
#[test]
fn blanket_delegate() {
let v = 42u32;
assert_eq!(v.name(), "42");
assert_eq!(Box::new(7u32).name(), "7");
assert_eq!(Rc::new(9u32).name(), "9");
let mut b = Box::new(2u16);
b.inc(); assert_eq!(*b, 3);
let mut x = 2u16;
let mut xr: &mut u16 = &mut x;
BlanketInc::inc(&mut xr); assert_eq!(x, 3);
let br: Box<Rc<u32>> = Box::new(Rc::new(1u32));
assert_eq!(br.deep(), 1);
let bbb: Box<Box<Box<u32>>> = Box::new(Box::new(Box::new(2u32)));
assert_eq!(bbb.deep(), 2);
}
trait LazyA {}
trait LazyB {}
batch_trait!(
@lazy_nums=[u8, u16];
@lazy_wrapped=[Box, Rc]^@lazy_nums;
@lazy_chain=@lazy_wrapped;
LazyA: @lazy_chain;
LazyB: @lazy_nums;
);
#[batch_impl(Foo<u32> u32 {
type Item = u8;
const LIMIT: usize = 42;
fn m(&self) -> u32 { *self }
})]
#[batch_impl(#blanket(@all){&})]
trait Foo<X: Clone>
where
X: Send,
{
type Item;
const LIMIT: usize;
fn m(&self) -> X;
}
#[test]
fn lazy_const_and_generic_blanket() {
fn _a<T: LazyA>(_: &T) {}
_a(&Box::new(0u8));
_a(&Rc::new(0u16));
fn _b<T: LazyB>(_: &T) {}
_b(&0u8);
_b(&0u16);
assert_eq!(<u32 as Foo<u32>>::m(&5u32), 5);
assert_eq!(<&u32 as Foo<u32>>::m(&&5u32), 5); assert_eq!(<&u32 as Foo<u32>>::LIMIT, 42); let _: <&u32 as Foo<u32>>::Item = 8u8; }
trait RangeVal {}
trait RangeValNested {}
trait BareVal {}
batch_trait!(
@rv=@u8..u128;
@nested=[bool, @rv];
@bare=u8, u32;
RangeVal: @rv;
RangeValNested: @nested;
BareVal: @bare;
);
#[test]
fn lazy_value_forms() {
fn _r<T: RangeVal>() {}
_r::<u8>();
_r::<u64>();
_r::<u128>();
fn _n<T: RangeValNested>() {}
_n::<bool>();
_n::<u16>();
fn _b<T: BareVal>() {}
_b::<u8>();
_b::<u32>();
}
#[batch_impl(Two<u8, u16> (u8, u16) { fn pair(&self) -> (u8, u16) { (self.0, self.1) } })]
#[batch_impl(#blanket(pair){Box})]
trait Two<A, B> {
fn pair(&self) -> (A, B);
}
struct Arr4;
#[batch_impl(ArrWrap<4> Arr4 { fn len(&self) -> usize { 4 } })]
#[batch_impl(#blanket(len){Box})]
trait ArrWrap<const N: usize> {
fn len(&self) -> usize;
}
#[batch_impl(LtWrap<'static, u32> u32 { fn m(&self) -> &'static str { "u32" } })]
#[batch_impl(#blanket(m){Box})]
trait LtWrap<'a, X: Clone> {
fn m(&self) -> &'a str;
}
#[batch_impl(IncGen<u16> u16 { fn inc(&mut self) -> u16 { *self += 1; *self } })]
#[batch_impl(#blanket(inc){Box})]
trait IncGen<X: Clone> {
fn inc(&mut self) -> X;
}
#[batch_impl(u16 {
type Item = u32;
const TAG: u8 = 7;
fn tag(&self) -> u8 { 9 }
})]
#[batch_impl(#blanket(@all){Box})]
trait HasAssoc {
type Item;
const TAG: u8;
fn tag(&self) -> u8;
}
#[test]
fn blanket_generic_full_forms() {
let b: Box<(u8, u16)> = Box::new((1, 2));
assert_eq!(b.pair(), (1u8, 2u16));
let t = Two::<u8, u16>::pair(&(3u8, 4u16));
assert_eq!(t, (3u8, 4u16));
assert_eq!(Box::new(Arr4).len(), 4);
assert_eq!(ArrWrap::<4>::len(&Arr4), 4);
assert_eq!(Box::new(7u32).m(), "u32");
let mut b = Box::new(5u16);
assert_eq!(b.inc(), 6);
assert_eq!(*b, 6);
assert_eq!(Box::new(3u16).tag(), 9);
assert_eq!(<Box<u16> as HasAssoc>::TAG, 7);
let _: <Box<u16> as HasAssoc>::Item = 5u32;
}
trait FooMap {}
trait FooNest {}
batch_trait!(
@map = HashMap<u32, String>;
FooMap: @map
);
batch_trait!(
@inner = Vec<u8>;
@outer = Vec<@inner>;
FooNest: @outer
);
#[test]
fn trait_const_value_with_angles() {
fn _check_map<T: FooMap>() {}
fn _check_nest<T: FooNest>() {}
_check_map::<HashMap<u32, String>>();
_check_nest::<Vec<Vec<u8>>>();
}
use std::borrow::Cow;
#[batch_impl(#blanket(@all_methods){Cow<'_> where{@0: ToOwned + ?Sized, @0::Owned: @trait}})]
trait CowWhereTrait {
fn klen(&self) -> usize;
}
impl CowWhereTrait for str {
fn klen(&self) -> usize {
self.len()
}
}
impl CowWhereTrait for String {
fn klen(&self) -> usize {
self.len()
}
}
#[batch_impl(#blanket(@all_methods){@Cow})]
trait CowConstTrait {
fn clen(&self) -> usize;
}
impl CowConstTrait for str {
fn clen(&self) -> usize {
self.len()
}
}
impl CowConstTrait for String {
fn clen(&self) -> usize {
self.len()
}
}
#[batch_impl(u8 #fill([m1, m2]){1} #fill(@all, -[m1, m2]){3})]
trait BracketArgs {
fn m1(&self) -> u32;
fn m2(&self) -> u32;
fn m3(&self) -> u32;
}
#[batch_impl(<T> WhereStyle<T> Vec<T> where{T: Clone} { fn wdup(&self) -> usize { self.len() } })]
trait WhereStyle<T: Clone> {
fn wdup(&self) -> usize;
}
#[test]
fn macro_meta_complete() {
let c: Cow<'static, str> = Cow::Borrowed("abc");
assert_eq!(c.klen(), 3); assert_eq!(c.clen(), 3); let s: Cow<'static, str> = Cow::Owned("xy".to_string());
assert_eq!(s.klen(), 2);
assert_eq!(s.clen(), 2);
assert_eq!(0u8.m1(), 1); assert_eq!(0u8.m2(), 1);
assert_eq!(0u8.m3(), 3); let v = vec![1u32];
assert_eq!(v.wdup(), 1); }
#[batch_impl(()^2 where{@0: Clone, @1: Copy} { fn tmk() -> u32 { 2 } })]
trait TupleWhereAt {
fn tmk() -> u32;
}
#[batch_impl(<T> AtWhere<T> Vec<T> where{T: Default} { fn an(&self) -> usize { self.len() } })]
trait AtWhere<T: Clone> {
fn an(&self) -> usize;
}
#[test]
fn where_position_refs() {
assert_eq!(<(u32, u32) as TupleWhereAt>::tmk(), 2);
let v = vec![1u32];
assert_eq!(v.an(), 1);
}
trait SegA<T> {}
trait SegB<T> {}
batch_trait! {
@type_t = <T> @trait <T>;
SegA: @type_t [&, Box]^T;
SegB: @type_t Box^[T, Vec<T>];
}
#[test]
fn trait_const_segment() {
fn check_a<T: SegA<u8>>() {}
fn check_b<T: SegB<u8>>() {}
check_a::<&u8>();
check_a::<Box<u8>>();
check_b::<Box<u8>>();
check_b::<Box<Vec<u8>>>();
}
#[batch_impl(u32 #fill(@all_required){4})]
trait ReqMix2 {
fn rfn(&self) -> u32;
fn dfn(&self) -> u32 {
1
}
const RC: u32;
const DC: u32 = 2;
}
#[batch_impl(u64 #fill(@all_default_constants){8})]
trait DefConstOnly {
fn m(&self) -> u32 {
3
}
const C: u32 = 7;
}
#[batch_impl(u16 #fill(@all_required_types){u16})]
trait ReqTypesOnly {
type RT;
}
#[batch_impl(u8 #fill(@all_methods, -@all_default_methods){1})]
trait MarkerMinus2 {
fn r1(&self) -> u32;
fn r2(&self) -> u32;
fn d1(&self) -> u32 {
9
}
}
#[batch_impl(<T> @trait<T> Vec<T> { fn tl(&self) -> usize { self.len() } })]
trait AtTraitSpec<T> {
fn tl(&self) -> usize;
}
#[batch_impl(
Vec<u32> {
fn dl1(&self) -> usize { self.len() }
fn dl2(&self) -> usize { self.len() }
},
Box^Vec^u32 #delegate([dl1, dl2]){**self}
)]
trait DelBr {
fn dl1(&self) -> usize;
fn dl2(&self) -> usize;
}
#[batch_impl(u32 { fn own(&self) -> u32 { *self } })]
#[batch_impl(#blanket(own){Box where{@0: Copy}})]
trait OwnAt0 {
fn own(&self) -> u32;
}
#[batch_impl(()^3 where{@2: Clone} { fn tk3() -> u32 { 3 } })]
trait TupleWhereAt3 {
fn tk3() -> u32;
}
#[test]
fn macro_meta_review_extras() {
assert_eq!(0u32.rfn(), 4);
assert_eq!(0u32.dfn(), 1); assert_eq!(<u32 as ReqMix2>::RC, 4);
assert_eq!(<u32 as ReqMix2>::DC, 2);
assert_eq!(<u64 as DefConstOnly>::C, 8); assert_eq!(0u64.m(), 3);
fn _check_t<T: ReqTypesOnly>() {}
_check_t::<u16>();
let _: <u16 as ReqTypesOnly>::RT = 5u16;
assert_eq!(0u8.r1(), 1);
assert_eq!(0u8.r2(), 1);
assert_eq!(0u8.d1(), 9);
let v = vec![1u32, 2];
assert_eq!(v.tl(), 2);
let b: Box<Vec<u32>> = Box::new(vec![1, 2, 3]);
assert_eq!(b.dl1(), 3);
assert_eq!(b.dl2(), 3);
assert_eq!(Box::new(5u32).own(), 5);
assert_eq!(<(u8, u16, u32) as TupleWhereAt3>::tk3(), 3);
}
#[batch_impl(<T> WhereAtTrait<T> Vec<T> where{T: @trait<T>} { fn wn(&self) -> usize { self.len() } })]
trait WhereAtTrait<T: Clone> {
fn wn(&self) -> usize;
}
impl WhereAtTrait<u32> for u32 {
fn wn(&self) -> usize {
1
}
}
macro_rules! make_impls {
($($spec:tt)*) => {
#[batch_impl($($spec)*)]
trait MacroGenTrait {
fn gm(&self) -> u32;
}
};
}
make_impls!([Box, Rc]^@u* { fn gm(&self) -> u32 { 9 } });
#[test]
fn review_fixes_locked() {
let v = vec![1u32];
assert_eq!(v.wn(), 1); let b = Box::new(1u32);
let r = Rc::new(1u32);
assert_eq!(b.gm(), 9); assert_eq!(r.gm(), 9);
}
#[test]
fn receiver_kind_filters() {
#[batch_impl(
u8
#fill(@all_ref_methods){ 7 }
#fill(@all_value_methods){ 8 }
#fill(@all_static_methods){ 9 }
#C{ 10 }
#Item{ u8 }
)]
trait RecvT {
fn by_ref(&self) -> u8;
fn by_mut(&mut self) -> u8;
fn by_val(self) -> u8;
fn make() -> u8;
const C: u8;
type Item;
}
let x = 5u8;
assert_eq!(RecvT::by_ref(&x), 7);
let mut y = 5u8;
assert_eq!(RecvT::by_mut(&mut y), 7);
assert_eq!(RecvT::by_val(x), 8);
assert_eq!(<u8 as RecvT>::make(), 9);
assert_eq!(<u8 as RecvT>::C, 10);
let _: <u8 as RecvT>::Item = 1u8;
}
#[test]
fn blanket_receiver_filter() {
#[batch_impl(u8 { fn by_ref(&self) -> u8 { *self } })]
#[batch_impl(#blanket(@all_ref_methods){Box})]
trait RecvB {
fn by_ref(&self) -> u8;
fn by_val(self) -> u8
where
Self: Sized,
{
0
}
}
let b = Box::new(3u8);
assert_eq!(RecvB::by_ref(&b), 3); assert_eq!(RecvB::by_val(b), 0); }
#[batch_impl(u8 #fill(@all_value_methods){4} #fill(@all_static_methods){5})]
trait TypedRecv2 {
fn plain(self) -> u8;
fn boxed(self: Box<Self>) -> u8;
fn by_ref(&self) -> u8 {
7
}
fn make() -> u8;
}
#[batch_impl(u16 #fill(@all_methods, -@all_value_methods){6})]
trait MarkerMinus3 {
fn by_ref(&self) -> u16;
fn by_val(self) -> u16
where
Self: Sized,
{
0
}
fn make() -> u16;
}
#[test]
fn receiver_filters_review() {
assert_eq!(TypedRecv2::plain(3u8), 4);
assert_eq!(TypedRecv2::boxed(Box::new(3u8)), 4);
assert_eq!(TypedRecv2::by_ref(&3u8), 7); assert_eq!(<u8 as TypedRecv2>::make(), 5);
assert_eq!(MarkerMinus3::by_ref(&1u16), 6);
assert_eq!(MarkerMinus3::by_val(1u16), 0); assert_eq!(<u16 as MarkerMinus3>::make(), 6);
}
#[batch_impl(#blanket(@all_static_methods){Box})]
trait BlanketStaticT {
fn make() -> u8;
fn pair(a: u8, b: u8) -> u16;
}
impl BlanketStaticT for u8 {
fn make() -> u8 {
7
}
fn pair(a: u8, b: u8) -> u16 {
(a as u16) * 10 + b as u16
}
}
#[test]
fn blanket_static_delegation() {
assert_eq!(<Box<u8> as BlanketStaticT>::make(), 7);
assert_eq!(<Box<Box<u8>> as BlanketStaticT>::make(), 7);
assert_eq!(<Box<u8> as BlanketStaticT>::pair(3, 4), 34);
assert_eq!(<Box<Box<u8>> as BlanketStaticT>::pair(3, 4), 34);
}
#[batch_impl(@all_type_params GenT<T> Vec<T> { fn head(&self) -> T { self[0].clone() } })]
trait GenT<T: Clone> {
fn head(&self) -> T;
}
#[batch_impl(@all_lifetimes @all_type_params GenB<'a, T> &'a T { fn get(&self) -> &'a T { self } })]
trait GenB<'a, T: Clone> {
fn get(&self) -> &'a T;
}
#[batch_impl(@all_const_params GenC<N> [u8; N] { fn n(&self) -> usize { N } })]
trait GenC<const N: usize> {
fn n(&self) -> usize;
}
#[test]
fn generic_param_families() {
let v = vec![1u32, 2];
assert_eq!(v.head(), 1u32);
let b = &5u8;
assert_eq!(b.get(), &5u8);
let a: [u8; 3] = [1, 2, 3];
assert_eq!(a.n(), 3);
}