//@ [fstar] aeneas-args=-decreases-clauses -template-clauses pub trait BoolTrait { // Required method fn get_bool(&self) -> bool; // Provided method fn ret_true(&self) -> bool { true } } impl BoolTrait for bool { fn get_bool(&self) -> bool { *self } } pub fn test_bool_trait_bool(x: bool) -> bool { x.get_bool() && x.ret_true() } #[allow(clippy::redundant_pattern_matching)] impl BoolTrait for Option { fn get_bool(&self) -> bool { match self { Option::Some(_) => true, Option::None => false, } } } pub fn test_bool_trait_option(x: Option) -> bool { x.get_bool() && x.ret_true() } pub fn test_bool_trait(x: T) -> bool { x.get_bool() } pub trait ToU64 { fn to_u64(self) -> u64; } impl ToU64 for u64 { fn to_u64(self) -> u64 { self } } impl ToU64 for (A, A) { fn to_u64(self) -> u64 { self.0.to_u64() + self.1.to_u64() } } pub fn f(x: (T, T)) -> u64 { x.to_u64() } pub fn g(x: (T, T)) -> u64 where (T, T): ToU64, { x.to_u64() } pub fn h0(x: u64) -> u64 { x.to_u64() } pub struct Wrapper { x: T, } impl ToU64 for Wrapper { fn to_u64(self) -> u64 { self.x.to_u64() } } pub fn h1(x: Wrapper) -> u64 { x.to_u64() } pub fn h2(x: Wrapper) -> u64 { x.to_u64() } pub trait ToType { fn to_type(self) -> T; } impl ToType for u64 { fn to_type(self) -> bool { self > 0 } } pub trait OfType { fn of_type>(x: T) -> Self where Self: std::marker::Sized; } pub fn h3>(y: T2) -> T1 { T1::of_type(y) } // Checking what happens if we move trait clauses from a method to its enclosing block pub trait OfTypeBis> where Self: std::marker::Sized, { fn of_type(x: T) -> Self where Self: std::marker::Sized; } pub fn h4, T2: ToType>(y: T2) -> T1 { T1::of_type(y) } pub struct TestType(T); // Checking what happens with nested blocks impl TestType { pub fn test(&self, x: T) -> bool { struct TestType1(u64); trait TestTrait { fn test(&self) -> bool; } // Remark: we can't write: impl TestTrait for TestType, // we have to use a *local* parameter (can't use the outer T). // In other words: the parameters used in the items inside // an impl must be bound by the impl block (can't come from outer // blocks). impl TestTrait for TestType1 { fn test(&self) -> bool { self.0 > 1 } } let x = x.to_u64(); let y = TestType1(0); x > 0 && y.test() } } pub struct BoolWrapper(pub bool); impl ToType for BoolWrapper where bool: ToType, { fn to_type(self) -> T { self.0.to_type() } } pub trait WithConstTy { const LEN1: usize; // Testing default values const LEN2: usize = 32; type V; type W: ToU64; // Below: we can't use [Self::Len1] in the type of the array. // Probably because of dyn traits... fn f(x: &mut Self::W, y: &[u8; LEN]); } impl WithConstTy<32> for bool { const LEN1: usize = 12; type V = u8; type W = u64; fn f(_: &mut Self::W, _: &[u8; 32]) {} } pub fn use_with_const_ty1>() -> usize { H::LEN1 } pub fn use_with_const_ty2>(_: H::W) {} pub fn use_with_const_ty3>(x: H::W) -> u64 { x.to_u64() } pub fn test_where1<'a, T: 'a>(_x: &'a T) {} pub fn test_where2>(_x: T::V) {} // Below: testing super traits. // // Actually, this comes for free: ChildTrait : ParentTrait just adds a trait // clause for Self: `Self : ParentTrait`. pub trait ParentTrait0 { type W; fn get_name(&self) -> String; fn get_w(&self) -> Self::W; } pub trait ParentTrait1 {} pub trait ChildTrait: ParentTrait0 + ParentTrait1 {} // But we still need to correctly reference the traits pub fn test_child_trait1(x: &T) -> String { x.get_name() } pub fn test_child_trait2(x: &T) -> T::W { x.get_w() } // Checking if the order has an importance (we use U::W before we declare that // U:ParentTrait0) pub fn order1, U: ParentTrait0>() {} /* */ pub trait ChildTrait1: ParentTrait1 {} impl ParentTrait1 for usize {} impl ChildTrait1 for usize {} /* [IntoIterator] is interesting because of the condition [Item = Self::Item] for the [IntoIter] associated type. */ pub trait Iterator { type Item; } pub trait IntoIterator { type Item; type IntoIter: Iterator; // Required method fn into_iter(self) -> Self::IntoIter; } /* The traits below are inspired by [Try] and [FromResidual]. The reference to `Self as Try` in the `FromResidual` clause used to cause a bug. */ trait Try: FromResidual<::Residual> { type Residual; } trait FromResidual {} pub trait WithTarget { type Target; } pub trait ParentTrait2 { type U: WithTarget; } pub trait ChildTrait2: ParentTrait2 { fn convert(x: Self::U) -> ::Target; } impl WithTarget for u32 { type Target = u32; } impl ParentTrait2 for u32 { type U = u32; } impl ChildTrait2 for u32 { fn convert(x: u32) -> u32 { x } } /* // This one requires a lot of traits pub fn test_enumerate(x: usize) { for _ in 0..x {} } */ /* Custom function pointers */ pub trait CFnOnce { type Output; fn call_once(self, args: Args) -> Self::Output; } pub trait CFnMut: CFnOnce { fn call_mut(&mut self, args: Args) -> Self::Output; } pub trait CFn: CFnMut { fn call(&self, args: Args) -> Self::Output; } pub trait GetTrait { type W; fn get_w(&self) -> Self::W; } pub fn test_get_trait(x: &T) -> T::W { x.get_w() } // Constants with generics pub trait Trait { const LEN: usize; } impl Trait for [T; N] { const LEN: usize = N; } impl Trait for Wrapper { const LEN: usize = 0; } pub fn use_wrapper_len() -> usize { Wrapper::::LEN } pub struct Foo { pub x: T, pub y: U, } impl Foo { pub const FOO: Result = Err(0); } pub fn use_foo1() -> Result { Foo::::FOO } pub fn use_foo2() -> Result { Foo::::FOO }