use std::cell::*; struct SyncPtr { x: *const T, } unsafe impl Sync for SyncPtr {} // These pass the lifetime checks because of the "tail expression" / "outer scope" rule. // (This relies on `SyncPtr` being a curly brace struct.) // However, we intern the inner memory as read-only. // The resulting constant would pass all validation checks, so it is crucial that this gets rejected // by static const checks! static RAW_SYNC_S: SyncPtr> = SyncPtr { x: &Cell::new(42) }; //~^ ERROR: cannot refer to interior mutable data const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; //~^ ERROR: cannot refer to interior mutable data // This one does not get promoted because of `Drop`, and then enters interesting codepaths because // as a value it has no interior mutability, but as a type it does. See // . Value-based reasoning for interior mutability // is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) but we've // done it since Rust 1.0 so we can't stop now. pub enum JsValue { Undefined, Object(Cell), } impl Drop for JsValue { fn drop(&mut self) {} } const UNDEFINED: &JsValue = &JsValue::Undefined; // Here's a variant of the above that uses promotion instead of the "outer scope" rule. const NONE: &'static Option> = &None; // Making it clear that this is promotion, not "outer scope". const NONE_EXPLICIT_PROMOTED: &'static Option> = { let x = &None; x }; // Not okay, since we are borrowing something with interior mutability. const INTERIOR_MUT_VARIANT: &Option> = &{ //~^ERROR: cannot refer to interior mutable data let mut x = None; assert!(x.is_none()); x = Some(UnsafeCell::new(false)); x }; fn main() {}