#![feature(const_refs_to_cell)] use std::cell::*; // not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); //~^ ERROR encountered dangling pointer const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); //~^ ERROR encountered dangling pointer // Ok, these are just base values and it is the `Wrap` author's job to uphold `Send` and `Sync` // invariants, since they used `unsafe impl`. static FOO3: Wrap> = Wrap(Cell::new(42)); const FOO3_CONST: Wrap> = Wrap(Cell::new(42)); // ok, we are referring to the memory of another static item. static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr()); // not ok, the use of a constant here is equivalent to an inline declaration of the value, so // its memory will get freed before the constant is finished evaluating, thus creating a dangling // pointer. This would happen exactly the same at runtime. const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); //~^ ERROR encountered dangling pointer // not ok, because the `as_ptr` call takes a reference to a temporary that will get freed // before the constant is finished evaluating. const FOO2: *mut u32 = Cell::new(42).as_ptr(); //~^ ERROR encountered dangling pointer struct IMSafeTrustMe(UnsafeCell); unsafe impl Send for IMSafeTrustMe {} unsafe impl Sync for IMSafeTrustMe {} static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5)); struct Wrap(T); unsafe impl Send for Wrap {} unsafe impl Sync for Wrap {} static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get()); const fn fst_ref(x: &(T, U)) -> &T { &x.0 } fn main() {}