#![allow(dead_code)]
use facet::{Facet, Variance};
#[test]
fn const_ptr_propagates_variance() {
let shape = <*const i32>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"*const T propagates T's variance; *const i32 is bivariant"
);
}
#[test]
fn const_ptr_propagates_inner_bivariance() {
let shape = <*const String>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"*const String propagates String's bivariance"
);
}
#[test]
fn mut_ptr_invariant_in_t() {
let shape = <*mut i32>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"*mut T should be invariant with respect to T (Rust Reference)"
);
}
#[test]
fn mut_ptr_stays_invariant_regardless_of_inner() {
let shape = <*mut String>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"*mut T must stay invariant regardless of T's variance"
);
}
#[test]
fn array_propagates_variance() {
let shape = <[i32; 5]>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"[i32; N] propagates i32's bivariance"
);
}
#[test]
fn array_propagates_inner_invariance() {
#[derive(Facet)]
struct InvariantWrapper {
ptr: *mut i32,
}
let shape = <[InvariantWrapper; 3]>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"[T; N] should propagate T's invariance"
);
}
#[derive(Facet)]
struct AllBivariantFields {
a: i32,
b: String,
c: bool,
}
#[test]
fn struct_all_bivariant_fields() {
let shape = AllBivariantFields::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Struct with all bivariant fields should be bivariant"
);
}
#[derive(Facet)]
struct HasInvariantField {
a: i32,
b: *mut u8, }
#[test]
fn struct_with_invariant_field() {
let shape = HasInvariantField::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Struct with any invariant field should be invariant"
);
}
#[derive(Facet)]
struct NestedInvariant {
inner: HasInvariantField,
}
#[test]
fn struct_nested_invariant() {
let shape = NestedInvariant::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Struct containing invariant struct should be invariant"
);
}
#[test]
fn vec_propagates_bivariance() {
let shape = <Vec<i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Vec<i32> propagates i32's bivariance"
);
}
#[test]
fn vec_propagates_invariance() {
let shape = <Vec<*mut i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Vec<*mut T> should be invariant because *mut T is invariant"
);
}
#[test]
fn box_propagates_bivariance() {
let shape = <Box<i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Box<i32> propagates i32's bivariance"
);
}
#[test]
fn box_propagates_invariance() {
let shape = <Box<*mut i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Box<*mut T> should be invariant because *mut T is invariant"
);
}
#[test]
fn option_propagates_bivariance() {
let shape = <Option<i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Option<i32> propagates i32's bivariance"
);
}
#[test]
fn option_propagates_invariance() {
let shape = <Option<*mut i32>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Option<*mut T> should be invariant because *mut T is invariant"
);
}
#[test]
fn tuple_all_bivariant() {
let shape = <(i32, String, bool)>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Tuple of bivariant types should be bivariant"
);
}
#[test]
fn tuple_with_invariant() {
let shape = <(i32, *mut u8)>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Tuple containing invariant type should be invariant"
);
}
#[derive(Facet)]
#[repr(u8)]
enum AllBivariantVariants {
A(i32),
B(String),
C { x: bool, y: u64 },
}
#[test]
fn enum_all_bivariant_variants() {
let shape = AllBivariantVariants::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Enum with all bivariant variants should be bivariant"
);
}
#[derive(Facet)]
#[repr(u8)]
enum HasInvariantVariant {
A(i32),
B(*mut u8), }
#[test]
fn enum_with_invariant_variant() {
let shape = HasInvariantVariant::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Enum with any invariant variant should be invariant"
);
}
#[test]
fn scalars_are_bivariant() {
assert_eq!(i8::SHAPE.computed_variance(), Variance::Bivariant, "i8");
assert_eq!(i16::SHAPE.computed_variance(), Variance::Bivariant, "i16");
assert_eq!(i32::SHAPE.computed_variance(), Variance::Bivariant, "i32");
assert_eq!(i64::SHAPE.computed_variance(), Variance::Bivariant, "i64");
assert_eq!(i128::SHAPE.computed_variance(), Variance::Bivariant, "i128");
assert_eq!(
isize::SHAPE.computed_variance(),
Variance::Bivariant,
"isize"
);
assert_eq!(u8::SHAPE.computed_variance(), Variance::Bivariant, "u8");
assert_eq!(u16::SHAPE.computed_variance(), Variance::Bivariant, "u16");
assert_eq!(u32::SHAPE.computed_variance(), Variance::Bivariant, "u32");
assert_eq!(u64::SHAPE.computed_variance(), Variance::Bivariant, "u64");
assert_eq!(u128::SHAPE.computed_variance(), Variance::Bivariant, "u128");
assert_eq!(
usize::SHAPE.computed_variance(),
Variance::Bivariant,
"usize"
);
assert_eq!(f32::SHAPE.computed_variance(), Variance::Bivariant, "f32");
assert_eq!(f64::SHAPE.computed_variance(), Variance::Bivariant, "f64");
assert_eq!(bool::SHAPE.computed_variance(), Variance::Bivariant, "bool");
assert_eq!(char::SHAPE.computed_variance(), Variance::Bivariant, "char");
assert_eq!(<()>::SHAPE.computed_variance(), Variance::Bivariant, "unit");
}
#[test]
fn string_is_bivariant() {
assert_eq!(
String::SHAPE.computed_variance(),
Variance::Bivariant,
"String should be bivariant (owns its data, no lifetime)"
);
}
#[test]
fn nested_vec_bivariant() {
let shape = <Vec<Vec<i32>>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Vec<Vec<i32>> propagates i32's bivariance"
);
}
#[test]
fn nested_vec_invariant() {
let shape = <Vec<Vec<*mut i32>>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Vec<Vec<*mut T>> should be invariant"
);
}
#[test]
fn box_of_vec_bivariant() {
let shape = <Box<Vec<i32>>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Box<Vec<i32>> propagates i32's bivariance"
);
}
#[test]
fn option_of_box_bivariant() {
let shape = <Option<Box<i32>>>::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Option<Box<i32>> propagates i32's bivariance"
);
}
#[derive(Facet)]
struct ComplexBivariant {
vec: Vec<i32>,
boxed: Box<i32>,
opt: Option<bool>,
arr: [u8; 4],
}
#[test]
fn complex_struct_all_bivariant() {
let shape = ComplexBivariant::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Bivariant,
"Struct with all bivariant container fields should be bivariant"
);
}
#[derive(Facet)]
struct ComplexWithOneInvariant {
vec: Vec<i32>,
ptr: *mut u8, opt: Option<bool>,
}
#[test]
fn complex_struct_one_invariant_field() {
let shape = ComplexWithOneInvariant::SHAPE;
assert_eq!(
shape.computed_variance(),
Variance::Invariant,
"Struct with one invariant field should be invariant"
);
}