50 lines
1.8 KiB
Rust
50 lines
1.8 KiB
Rust
use std::cell::*;
|
|
|
|
struct SyncPtr<T> {
|
|
x: *const T,
|
|
}
|
|
unsafe impl<T> Sync for SyncPtr<T> {}
|
|
|
|
// 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<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
|
|
//~^ ERROR: cannot refer to interior mutable data
|
|
const RAW_SYNC_C: SyncPtr<Cell<i32>> = 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
|
|
// <https://github.com/rust-lang/rust/issues/121610>. 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<bool>),
|
|
}
|
|
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<Cell<i32>> = &None;
|
|
// Making it clear that this is promotion, not "outer scope".
|
|
const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {
|
|
let x = &None;
|
|
x
|
|
};
|
|
|
|
// Not okay, since we are borrowing something with interior mutability.
|
|
const INTERIOR_MUT_VARIANT: &Option<UnsafeCell<bool>> = &{
|
|
//~^ERROR: cannot refer to interior mutable data
|
|
let mut x = None;
|
|
assert!(x.is_none());
|
|
x = Some(UnsafeCell::new(false));
|
|
x
|
|
};
|
|
|
|
fn main() {}
|