mod covariant {
use crate::{tr::Transient, Any, Co, Downcast, TypeId};
#[derive(Debug, Clone, PartialEq, Eq)]
struct S<'a> {
value: &'a String,
}
unsafe impl<'a> Transient for S<'a> {
type Static = S<'static>;
type Transience = Co<'a>;
}
#[test]
pub(super) fn test_owned() {
let value = "qwer".to_string();
let original: S<'_> = S { value: &value };
let erased: Box<dyn Any<Co<'_>> + '_> = Box::new(original.clone());
let restored: Box<S<'_>> = erased.downcast::<S<'_>>().unwrap();
assert_eq!(*restored, original);
}
#[test]
pub(super) fn test_ref() {
let value = "qwer".to_string();
let original = S { value: &value };
let erased: &dyn Any<Co> = &original;
assert_eq!(erased.type_id(), TypeId::of::<S>());
let restored = erased.downcast_ref::<S>().unwrap();
assert_eq!(restored, &original);
}
#[test]
pub(super) fn test_mut() {
let value = "qwer".to_string();
let mut original = S { value: &value };
let erased: &mut dyn Any<Co> = &mut original;
assert_eq!(erased.type_id(), TypeId::of::<S>());
let restored = erased.downcast_mut::<S>().unwrap().clone();
assert_eq!(restored, original);
}
}
mod one_type_param {
use crate::{tr::Transient, Any, Downcast, Inv, TypeId};
#[derive(Debug, Clone, PartialEq, Eq)]
struct S<'a, T> {
value: &'a T,
}
unsafe impl<'a, T: 'static> Transient for S<'a, T> {
type Static = S<'static, T>;
type Transience = Inv<'a>;
}
type SS<'a> = S<'a, String>;
#[test]
pub(super) fn test_owned() {
let value = "qwer".to_string();
let original = SS { value: &value };
let erased: Box<dyn Any<Inv>> = Box::new(original.clone());
assert_eq!(erased.type_id(), TypeId::of::<SS>());
let restored = erased.downcast::<SS>().unwrap();
assert_eq!(*restored, original);
}
#[test]
pub(super) fn test_ref() {
let value = "qwer".to_string();
let original = SS { value: &value };
let erased: &dyn Any<Inv> = &original;
assert_eq!(erased.type_id(), TypeId::of::<SS>());
let restored = erased.downcast_ref::<SS>().unwrap();
assert_eq!(restored, &original);
}
#[test]
pub(super) fn test_mut() {
let value = "qwer".to_string();
let mut original = SS { value: &value };
let erased: &mut dyn Any<Inv> = &mut original;
assert_eq!(erased.type_id(), TypeId::of::<SS>());
let restored = erased.downcast_mut::<SS>().unwrap().clone();
assert_eq!(restored, original);
}
}
mod two_type_params {
use crate::{Inv, Transient};
#[derive(Debug, Clone, PartialEq, Eq)]
struct S<'a, T1, T2> {
value1: &'a T1,
value2: &'a T2,
}
unsafe impl<'a, T1: 'static, T2: 'static> Transient for S<'a, T1, T2> {
type Static = S<'static, T1, T2>;
type Transience = Inv<'a>;
}
}
mod mixed_lifetimes {
use crate::{tr::Transient, Any, Co, Contra, TypeId};
type ContraCo<'s, 'l> = (Contra<'s>, Co<'l>);
#[derive(Debug, Clone, PartialEq, Eq)]
struct M<'s, 'l> {
func: fn(&'s str) -> &'static str,
string: &'l str,
}
unsafe impl<'s, 'l> Transient for M<'s, 'l> {
type Static = M<'static, 'static>;
type Transience = ContraCo<'s, 'l>;
}
fn requires_static(_value: &dyn Any<ContraCo<'static, '_>>) {
}
fn lengthen<'b, 'short, 'long: 'short>(
short: &'b M<'short, 'long>,
) -> &'b dyn Any<ContraCo<'long, 'short>> {
short
}
const STATIC_STR: &str = "static";
#[test]
#[rustfmt::skip]
fn test_owned() {
let short: M<'_, 'static> = M { func: |_| "!", string: STATIC_STR };
let long: M<'static, '_> = M { func: |s| s, string: STATIC_STR };
let _ = lengthen(&short);
let erased_short: Box<dyn Any<ContraCo> + '_> = Box::new(short);
assert_eq!(erased_short.type_id(), TypeId::of::<M>());
requires_static(&*erased_short);
let erased_long: Box<dyn Any<ContraCo> + '_> = Box::new(long);
assert_eq!(erased_long.type_id(), TypeId::of::<M>());
}
#[test]
#[rustfmt::skip]
fn test_ref() {
let short: M<'_, 'static> = M { func: |_| "!", string: STATIC_STR };
let long: M<'static, '_> = M { func: |s| s, string: STATIC_STR };
let _ = lengthen(&short);
let erased_short: &dyn Any<ContraCo> = &short;
assert_eq!(erased_short.type_id(), TypeId::of::<M>());
requires_static(erased_short);
let erased_long: &dyn Any<ContraCo> = &long;
assert_eq!(erased_long.type_id(), TypeId::of::<M>());
}
}