Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::ThreadLocalRef(def_id) => {
assert!(bx.cx().tcx().is_static(def_id));
let static_ = bx.get_static(def_id);
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
let layout =
bx.layout_of(bx.cx().tcx().mk_imm_ptr(bx.cx().tcx().static_ty(def_id)));
let operand = OperandRef::from_immediate_or_packed_pair(&mut bx, static_, layout);
(bx, operand)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl<'tcx> Rvalue<'tcx> {
}
Rvalue::ThreadLocalRef(did) => {
if tcx.is_mutable_static(did) {
tcx.mk_mut_ptr(tcx.type_of(did))
tcx.mk_mut_ref(tcx.lifetimes.re_static, tcx.type_of(did))
} else {
tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.type_of(did))
}
Expand Down
13 changes: 4 additions & 9 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,16 +538,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.static_mutability(def_id) == Some(hir::Mutability::Mut)
}

/// Get the type of the pointer to the static that we use in MIR.
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
/// Get the type of the static with all constant's in the static's type fully
/// evaluated.
pub fn static_ty(self, def_id: DefId) -> Ty<'tcx> {
// Make sure that any constants in the static's type are evaluated.
let static_ty = self.normalize_erasing_regions(ty::ParamEnv::empty(), self.type_of(def_id));

if self.is_mutable_static(def_id) {
self.mk_mut_ptr(static_ty)
} else {
self.mk_imm_ref(self.lifetimes.re_erased, static_ty)
}
self.normalize_erasing_regions(ty::ParamEnv::empty(), self.type_of(def_id))
}

/// Expands the given impl trait type, stopping if the type is recursive.
Expand Down
28 changes: 12 additions & 16 deletions compiler/rustc_mir/src/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,18 +425,20 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {

match elem {
ProjectionElem::Deref => {
let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
if let ty::RawPtr(_) = base_ty.kind() {
if proj_base.is_empty() {
if let (local, []) = (place_local, proj_base) {
let decl = &self.body.local_decls[local];
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
let span = decl.source_info.span;
self.check_static(def_id, span);
return;
}
if proj_base.is_empty() {
if let (local, []) = (place_local, proj_base) {
Comment thread
oli-obk marked this conversation as resolved.
Outdated
let decl = &self.body.local_decls[local];
if let Some(box LocalInfo::StaticRef { def_id, is_thread_local: false }) =
decl.local_info
{
let span = decl.source_info.span;
self.check_static(def_id, span);
return;
}
}
}
let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
if let ty::RawPtr(_) = base_ty.kind() {
self.check_op(ops::RawPtrDeref);
}

Expand Down Expand Up @@ -636,12 +638,6 @@ fn place_as_reborrow(
return None;
}

// A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
// that points to the allocation for the static. Don't treat these as reborrows.
if body.local_decls[place.local].is_ref_to_static() {
return None;
}

Comment thread
oli-obk marked this conversation as resolved.
// Ensure the type being derefed is a reference and not a raw pointer.
//
// This is sufficient to prevent an access to a `static mut` from being marked as a
Expand Down
46 changes: 26 additions & 20 deletions compiler/rustc_mir/src/transform/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,19 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
_ => {}
}
}
Rvalue::ThreadLocalRef(did) => self.check_static(*did),
_ => {}
}
self.super_rvalue(rvalue, location);
}

fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) {
// Accesses to statics are encoded as constants with `&STATIC` or `&mut STATIC` value.
if let Some(did) = constant.check_static_ptr(self.tcx) {
self.check_static(did);
}
}

fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
// On types with `scalar_valid_range`, prevent
// * `&mut x.field`
Expand Down Expand Up @@ -204,26 +212,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
if let [] = proj_base {
let decl = &self.body.local_decls[place.local];
if decl.internal {
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
if self.tcx.is_mutable_static(def_id) {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfMutableStatic,
);
return;
} else if self.tcx.is_foreign_item(def_id) {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfExternStatic,
);
return;
}
} else {
// Internal locals are used in the `move_val_init` desugaring.
// We want to check unsafety against the source info of the
// desugaring, rather than the source info of the RHS.
self.source_info = self.body.local_decls[place.local].source_info;
}
// Internal locals are used in the `move_val_init` desugaring.
// We want to check unsafety against the source info of the
// desugaring, rather than the source info of the RHS.
self.source_info = self.body.local_decls[place.local].source_info;
}
}
let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
Expand Down Expand Up @@ -273,6 +265,20 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}

impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
fn check_static(&mut self, did: DefId) {
if self.tcx.is_mutable_static(did) {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfMutableStatic,
)
} else if self.tcx.is_foreign_item(did) {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::UseOfExternStatic,
)
}
}

fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) {
let source_info = self.source_info;
let lint_root = self.body.source_scopes[self.source_info.scope]
Expand Down
85 changes: 68 additions & 17 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
}
}

hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => {
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: arg.to_ref() }
}

hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
ExprKind::AddressOf { mutability, arg: arg.to_ref() }
hir::ExprKind::AddrOf(kind, mutability, arg) => {
convert_addr_of_expr(cx, kind, mutability, arg)
}

hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
Expand Down Expand Up @@ -859,20 +855,23 @@ fn convert_path_expr<'a, '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 constant reference in MIR
Res::Def(DefKind::Static, id) => {
let ty = cx.tcx.static_ptr_ty(id);
let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
let kind = if cx.tcx.is_thread_local_static(id) {
ExprKind::ThreadLocalRef(id)
let static_ty = cx.tcx.static_ty(id);
let ty = if cx.tcx.is_mutable_static(id) {
cx.tcx.mk_mut_ref(cx.tcx.lifetimes.re_erased, static_ty)
} else {
let ptr = cx.tcx.create_static_alloc(id);
ExprKind::StaticRef {
literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
def_id: id,
}
cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_erased, static_ty)
};
ExprKind::Deref { arg: Expr { ty, temp_lifetime, span: expr.span, kind }.to_ref() }
ExprKind::Deref {
arg: Expr {
ty,
temp_lifetime: cx.region_scope_tree.temporary_scope(expr.hir_id.local_id),
span: expr.span,
kind: convert_static_ref(cx, id, ty),
}
.to_ref(),
}
}

Res::Local(var_hir_id) => convert_var(cx, expr, var_hir_id),
Expand All @@ -881,6 +880,58 @@ fn convert_path_expr<'a, 'tcx>(
}
}

fn convert_static_ref<'tcx>(cx: &mut Cx<'_, 'tcx>, id: DefId, ty: Ty<'tcx>) -> ExprKind<'tcx> {
if cx.tcx.is_thread_local_static(id) {
ExprKind::ThreadLocalRef(id)
} else {
let ptr = cx.tcx.create_static_alloc(id);
ExprKind::StaticRef {
literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
def_id: id,
}
}
}

fn convert_addr_of_expr<'tcx>(
cx: &mut Cx<'_, 'tcx>,
kind: hir::BorrowKind,
mutability: hir::Mutability,
arg: &'tcx hir::Expr<'tcx>,
) -> ExprKind<'tcx> {
// Fast path so that taking a reference to a static doesn't end up
// as `&*&STATIC` but just `&STATIC`
if let hir::ExprKind::Path(qpath) = &arg.kind {
let res = cx.typeck_results().qpath_res(qpath, arg.hir_id);
if let Res::Def(DefKind::Static, id) = res {
// FIXME(oli-obk): can we give TLS the same treatment? I was not able to figure out
// how to coax mir borrowck to be able to handle TLS directly from the `Rvalue` instead
// of going through the local.
if !cx.tcx.is_thread_local_static(id) {
let ty = cx.tcx.static_ty(id);
// Taking a mutable reference to an immutable static should not yield a mutable
// reference. So we do not do this optimization for things that will error anyway.
if mutability == hir::Mutability::Not || cx.tcx.is_mutable_static(id) {
let tm = ty::TypeAndMut { ty, mutbl: mutability };
let ty = match kind {
hir::BorrowKind::Ref => cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, tm),
hir::BorrowKind::Raw => cx.tcx.mk_ptr(tm),
};
return convert_static_ref(cx, id, ty);
} else {
cx.tcx.sess.delay_span_bug(arg.span, "mutable reference to immutable static");
}
}
}
}
match kind {
hir::BorrowKind::Ref => {
ExprKind::Borrow { borrow_kind: mutability.to_borrow_kind(), arg: arg.to_ref() }
}

hir::BorrowKind::Raw => ExprKind::AddressOf { mutability, arg: arg.to_ref() },
}
}

fn convert_var<'tcx>(
cx: &mut Cx<'_, 'tcx>,
expr: &'tcx hir::Expr<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
promoted[0] in BAR: &[&i32; 1] = {
let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34

bb0: {
_3 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
_1 = [const {alloc0: &i32}]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
// ty::Const
// + ty: &i32
// + val: Value(Scalar(alloc0))
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
// + span: $DIR/const-promotion-extern-static.rs:9:32: 9:34
// + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
_2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
_1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
_0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,26 @@
let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
let _5: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
+ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ let mut _4: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35

bb0: {
StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
- StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
- _5 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34
+ _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- _3 = [const {alloc0: &i32}]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ _4 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
// ty::Const
- // + ty: &i32
- // + val: Value(Scalar(alloc0))
+ // + ty: &[&i32; 1]
+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), const_param_did: None }, [], Some(promoted[0]))
// mir::Constant
- // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
- // + span: $DIR/const-promotion-extern-static.rs:9:32: 9:34
- // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
- _4 = &(*_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), const_param_did: None }, [], Some(promoted[0])) }
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ _2 = &(*_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
// mir::Constant
Expand All @@ -44,7 +38,6 @@
}

bb2: {
- StorageDead(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
- StorageDead(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:43: 9:44
return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:1: 9:45
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@ promoted[0] in FOO: &[&i32; 1] = {
let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45
let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
scope 1 {
}

bb0: {
_3 = const {alloc2: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43
_2 = const {alloc2: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43
// ty::Const
// + ty: &i32
// + val: Value(Scalar(alloc2))
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43
// + span: $DIR/const-promotion-extern-static.rs:13:41: 13:43
// + literal: Const { ty: &i32, val: Value(Scalar(alloc2)) }
_2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43
_1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
_0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
Expand Down
Loading