pub unsafe trait Coerce<To: ?Sized> { }
Expand description
A marker trait such that the existence of From: Coerce<To>
implies
that From
can be treat as To
without any data manipulation.
Particularly useful for containers, e.g. Vec<From>
can be treated as
Vec<To>
in O(1). If such an instance is available,
you can use coerce
to perform the conversion.
Importantly, you must make sure Rust does not change the type representation
between the different types (typically using a repr
directive),
and it must be safe for the From
to be treated as To
, namely same (or less restrictive) alignment,
no additional invariants, value can be dropped as To
.
One use of Coerce
is around newtype wrappers:
use starlark::coerce::coerce;
use starlark::coerce::Coerce;
#[repr(transparent)]
#[derive(Debug, Coerce)]
struct Wrapper(String);
let value = vec![Wrapper("hello".to_owned()), Wrapper("world".to_owned())];
assert_eq!(coerce::<_, &Vec<String>>(&value).join(" "), "hello world");
let mut value = coerce::<_, Vec<String>>(value);
assert_eq!(value.pop(), Some("world".to_owned()));
Another involves containers:
use starlark::coerce::coerce;
use starlark::coerce::Coerce;
#[derive(Coerce)]
#[repr(C)]
struct Container<T>(i32, T);
let value = Container(20, Wrapper("twenty".to_owned()));
assert_eq!(coerce::<_, &Container<String>>(&value).1, "twenty");
If you only need coerce
on newtype references,
then the ref-cast
crate
provides that, along with automatic derivations (no unsafe
required).