#![crate_type = "lib"] #![feature(transmutability)] #![allow(dead_code, incomplete_features, non_camel_case_types)] use std::cell::UnsafeCell; mod assert { use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable() where Dst: TransmuteFrom {} } fn value_to_value() { // We accept value-to-value transmutations of `UnsafeCell`-containing types, // because owning a value implies exclusive access. assert::is_maybe_transmutable::, u8>(); assert::is_maybe_transmutable::>(); assert::is_maybe_transmutable::, UnsafeCell>(); } fn ref_to_ref() { // We forbid `UnsafeCell`-containing ref-to-ref transmutations, because the // two types may use different, incompatible synchronization strategies. assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell>(); //~ ERROR: cannot be safely transmuted assert::is_maybe_transmutable::<&'static UnsafeCell, &'static UnsafeCell>(); //~ ERROR: cannot be safely transmuted } fn mut_to_mut() { // `UnsafeCell` does't matter for `&mut T` to `&mut U`, since exclusive // borrows can't be used for shared access. assert::is_maybe_transmutable::<&'static mut u8, &'static mut UnsafeCell>(); assert::is_maybe_transmutable::<&'static mut UnsafeCell, &'static mut u8>(); assert::is_maybe_transmutable::<&'static mut UnsafeCell, &'static mut UnsafeCell>(); } fn mut_to_ref() { // We don't care about `UnsafeCell` for transmutations in the form `&mut T // -> &U`, because downgrading a `&mut T` to a `&U` deactivates `&mut T` for // the lifetime of `&U`. assert::is_maybe_transmutable::<&'static mut u8, &'static UnsafeCell>(); assert::is_maybe_transmutable::<&'static mut UnsafeCell, &'static u8>(); assert::is_maybe_transmutable::<&'static mut UnsafeCell, &'static UnsafeCell>(); }