compiler: treat &raw (const|mut) UNSAFE_STATIC
implied deref as safe
The implied deref to statics introduced by HIR->THIR lowering is only used to create place expressions, it lacks unsafe semantics. It is also confusing, as there is no visible `*ident` in the source. For both classes of "unsafe static" (extern static and static mut) allow this operation. We lack a clear story around `thread_local! { static mut }`, which is actually its own category of item that reuses the static syntax but has its own rules. It's possible they should be similarly included, but in the absence of a good reason one way or another, we do not bless it.
This commit is contained in:
parent
ada5e2c7b5
commit
3fdd8d5ef3
9 changed files with 123 additions and 9 deletions
|
@ -449,6 +449,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ExprKind::AddressOf { arg, .. } => {
|
||||
if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind
|
||||
// THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where
|
||||
// UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps
|
||||
&& let ExprKind::Deref { arg } = self.thir[arg].kind
|
||||
// FIXME(workingjubiee): we lack a clear reason to reject ThreadLocalRef here,
|
||||
// but we also have no conclusive reason to allow it either!
|
||||
&& let ExprKind::StaticRef { .. } = self.thir[arg].kind
|
||||
{
|
||||
// A raw ref to a place expr, even an "unsafe static", is okay!
|
||||
// We short-circuit to not recursively traverse this expression.
|
||||
return;
|
||||
// note: const_mut_refs enables this code, and it currently remains unsafe:
|
||||
// static mut BYTE: u8 = 0;
|
||||
// static mut BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(BYTE) };
|
||||
// static mut DEREF_BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(*BYTE_PTR) };
|
||||
}
|
||||
}
|
||||
ExprKind::Deref { arg } => {
|
||||
if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
|
||||
self.thir[arg].kind
|
||||
|
|
|
@ -939,9 +939,11 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
|
||||
// a constant reference (or constant raw pointer for `static mut`) in MIR
|
||||
// A source Rust `path::to::STATIC` is a place expr like *&ident is.
|
||||
// In THIR, we make them exactly equivalent by inserting the implied *& or *&raw,
|
||||
// but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
|
||||
Res::Def(DefKind::Static { .. }, id) => {
|
||||
// this is &raw for extern static or static mut, and & for other statics
|
||||
let ty = self.tcx.static_ptr_ty(id);
|
||||
let temp_lifetime = self
|
||||
.rvalue_scopes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue