From 4ce3e9c7c11744abae52d7a3ae1a3962395784be Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 23 May 2024 10:41:10 +0200 Subject: Import test suite from charon --- tests/src/traits.rs | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 tests/src/traits.rs (limited to 'tests/src/traits.rs') diff --git a/tests/src/traits.rs b/tests/src/traits.rs new file mode 100644 index 00000000..27c90586 --- /dev/null +++ b/tests/src/traits.rs @@ -0,0 +1,341 @@ +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 +} -- cgit v1.2.3