From ae9677c82f592a7d6d25a5e3451f1f9cda55e754 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 11 Nov 2019 12:15:38 +0100 Subject: [PATCH] Readjust const qualification to detect statics again --- src/librustc/mir/mod.rs | 20 ++++++++++++++++++- .../transform/check_consts/qualifs.rs | 18 ++++++----------- .../transform/check_consts/validation.rs | 15 +++++++++++--- .../transform/qualify_min_const_fn.rs | 13 +++++------- .../consts/const-fn-not-safe-for-const.stderr | 4 ++-- .../consts/min_const_fn/min_const_fn.stderr | 4 ++-- 6 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b7d0f538db5..dd27a592004 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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}; @@ -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 { + 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 diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index aad14299c1d..9ed1ca740b8 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -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}; @@ -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 } @@ -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: [.., _], @@ -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) diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 21e7c9ce565..61de6b185e3 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -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() { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 83bde5ed34e..65fc7cd2043 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -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(()), + }, } } @@ -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(..., , ...)` is present. diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr index ba5d58a51d2..2d4175ea8eb 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr +++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr @@ -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 diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 5ce21e378cd..cb1663ed22f 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -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