Readjust const qualification to detect statics again
This commit is contained in:
parent
a1d04cc1d8
commit
ae9677c82f
@ -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<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
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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(..., <feature_gate>, ...)` is present.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user