Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Readjust const qualification to detect statics again
  • Loading branch information
spastorino authored and matthewjasper committed Nov 21, 2019
1 parent a1d04cc commit ae9677c
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 28 deletions.
20 changes: 19 additions & 1 deletion src/librustc/mir/mod.rs
Expand Up @@ -7,7 +7,7 @@
use crate::hir::def::{CtorKind, Namespace};
use crate::hir::def_id::DefId;
use crate::hir;
use crate::mir::interpret::{PanicInfo, Scalar};
use crate::mir::interpret::{ConstValue, GlobalAlloc, PanicInfo, Scalar};
use crate::mir::visit::MirVisitable;
use crate::ty::adjustment::PointerCast;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
Expand Down Expand Up @@ -2341,6 +2341,24 @@ pub struct Constant<'tcx> {
pub literal: &'tcx ty::Const<'tcx>,
}

impl Constant<'tcx> {
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.literal.val {
ConstValue::Scalar(Scalar::Ptr(ptr)) => match tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Static(def_id)) => Some(def_id),
Some(_) => None,
None => {
tcx.sess.delay_span_bug(
DUMMY_SP, "MIR cannot contain dangling const pointers",
);
None
},
},
_ => None,
}
}
}

/// A collection of projections into user types.
///
/// They are projections because a binding can occur a part of a
Expand Down
18 changes: 6 additions & 12 deletions src/librustc_mir/transform/check_consts/qualifs.rs
Expand Up @@ -2,6 +2,7 @@

use rustc::mir::*;
use rustc::ty::{self, Ty};
use rustc::hir::def_id::DefId;
use syntax_pos::DUMMY_SP;

use super::{ConstKind, Item as ConstCx};
Expand Down Expand Up @@ -32,7 +33,7 @@ pub trait Qualif {
/// of the type.
fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;

fn in_static(_cx: &ConstCx<'_, 'tcx>, _static: &Static<'tcx>) -> bool {
fn in_static(_cx: &ConstCx<'_, 'tcx>, _def_id: DefId) -> bool {
// FIXME(eddyb) should we do anything here for value properties?
false
}
Expand Down Expand Up @@ -86,18 +87,9 @@ pub trait Qualif {
projection: [],
} => per_local(*local),
PlaceRef {
base: PlaceBase::Static(box Static {
kind: StaticKind::Promoted(..),
..
}),
base: PlaceBase::Static(_),
projection: [],
} => bug!("qualifying already promoted MIR"),
PlaceRef {
base: PlaceBase::Static(static_),
projection: [],
} => {
Self::in_static(cx, static_)
},
PlaceRef {
base: _,
projection: [.., _],
Expand All @@ -115,7 +107,9 @@ pub trait Qualif {
Operand::Move(ref place) => Self::in_place(cx, per_local, place.as_ref()),

Operand::Constant(ref constant) => {
if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
if let Some(static_) = constant.check_static_ptr(cx.tcx) {
Self::in_static(cx, static_)
} else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(def_id).is_some() {
Self::in_any_value_of_ty(cx, constant.literal.ty)
Expand Down
15 changes: 12 additions & 3 deletions src/librustc_mir/transform/check_consts/validation.rs
Expand Up @@ -408,12 +408,21 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {

match place_base {
PlaceBase::Local(_) => {}
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => {
PlaceBase::Static(_) => {
bug!("Promotion must be run after const validation");
}
}
}

PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => {
let is_thread_local = self.tcx.has_attr(*def_id, sym::thread_local);
fn visit_operand(
&mut self,
op: &Operand<'tcx>,
location: Location,
) {
self.super_operand(op, location);
if let Operand::Constant(c) = op {
if let Some(def_id) = c.check_static_ptr(self.tcx) {
let is_thread_local = self.tcx.has_attr(def_id, sym::thread_local);
if is_thread_local {
self.check_op(ops::ThreadLocalAccess);
} else if self.const_kind() != ConstKind::Static || !context.is_mutating_use() {
Expand Down
13 changes: 5 additions & 8 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Expand Up @@ -249,7 +249,10 @@ fn check_operand(
Operand::Move(place) | Operand::Copy(place) => {
check_place(tcx, place, span, def_id, body)
}
Operand::Constant(_) => Ok(()),
Operand::Constant(c) => match c.check_static_ptr(tcx) {
Some(_) => Err((span, "cannot access `static` items in const fn".into())),
None => Ok(()),
},
}
}

Expand Down Expand Up @@ -285,13 +288,7 @@ fn check_place(
}
}

match place.base {
PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
Err((span, "cannot access `static` items in const fn".into()))
}
PlaceBase::Local(_)
| PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()),
}
Ok(())
}

/// Returns whether `allow_internal_unstable(..., <feature_gate>, ...)` is present.
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/consts/const-fn-not-safe-for-const.stderr
Expand Up @@ -11,10 +11,10 @@ LL | Y
| ^

error[E0013]: constant functions cannot refer to statics, use a constant instead
--> $DIR/const-fn-not-safe-for-const.rs:25:5
--> $DIR/const-fn-not-safe-for-const.rs:25:6
|
LL | &Y
| ^^
| ^

error: aborting due to 3 previous errors

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/consts/min_const_fn/min_const_fn.stderr
Expand Up @@ -116,10 +116,10 @@ LL | const fn foo25() -> u32 { BAR }
= help: add `#![feature(const_fn)]` to the crate attributes to enable

error[E0723]: cannot access `static` items in const fn
--> $DIR/min_const_fn.rs:91:36
--> $DIR/min_const_fn.rs:91:37
|
LL | const fn foo26() -> &'static u32 { &BAR }
| ^^^^
| ^^^
|
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add `#![feature(const_fn)]` to the crate attributes to enable
Expand Down

0 comments on commit ae9677c

Please sign in to comment.