Rollup merge of #59232 - saleemjaffer:mir_place_refactor, r=oli-obk
Merge `Promoted` and `Static` in `mir::Place` fixes #53848
This commit is contained in:
commit
90c2d641eb
@ -1913,22 +1913,24 @@ pub enum PlaceBase<'tcx> {
|
|||||||
|
|
||||||
/// static or static mut variable
|
/// static or static mut variable
|
||||||
Static(Box<Static<'tcx>>),
|
Static(Box<Static<'tcx>>),
|
||||||
|
|
||||||
/// Constant code promoted to an injected static
|
|
||||||
Promoted(Box<(Promoted, Ty<'tcx>)>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `DefId` of a static, along with its normalized type (which is
|
/// We store the normalized type to avoid requiring normalization when reading MIR
|
||||||
/// stored to avoid requiring normalization when reading MIR).
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Static<'tcx> {
|
pub struct Static<'tcx> {
|
||||||
pub def_id: DefId,
|
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
|
pub kind: StaticKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable)]
|
||||||
|
pub enum StaticKind {
|
||||||
|
Promoted(Promoted),
|
||||||
|
Static(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct Static<'tcx> {
|
impl_stable_hash_for!(struct Static<'tcx> {
|
||||||
def_id,
|
ty,
|
||||||
ty
|
kind
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The `Projection` data structure defines things of the form `B.x`
|
/// The `Projection` data structure defines things of the form `B.x`
|
||||||
@ -2048,7 +2050,7 @@ impl<'tcx> Place<'tcx> {
|
|||||||
match self {
|
match self {
|
||||||
Place::Base(PlaceBase::Local(local)) => Some(*local),
|
Place::Base(PlaceBase::Local(local)) => Some(*local),
|
||||||
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
|
Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
|
||||||
Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
|
Place::Base(PlaceBase::Static(..)) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2059,18 +2061,24 @@ impl<'tcx> Debug for Place<'tcx> {
|
|||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
|
Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
|
||||||
Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
|
Base(PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) })) => {
|
||||||
fmt,
|
write!(
|
||||||
"({}: {:?})",
|
fmt,
|
||||||
ty::tls::with(|tcx| tcx.def_path_str(def_id)),
|
"({}: {:?})",
|
||||||
ty
|
ty::tls::with(|tcx| tcx.def_path_str(def_id)),
|
||||||
),
|
ty
|
||||||
Base(PlaceBase::Promoted(ref promoted)) => write!(
|
)
|
||||||
fmt,
|
},
|
||||||
"({:?}: {:?})",
|
Base(PlaceBase::Static(
|
||||||
promoted.0,
|
box self::Static { ty, kind: StaticKind::Promoted(promoted) })
|
||||||
promoted.1
|
) => {
|
||||||
),
|
write!(
|
||||||
|
fmt,
|
||||||
|
"({:?}: {:?})",
|
||||||
|
promoted,
|
||||||
|
ty
|
||||||
|
)
|
||||||
|
},
|
||||||
Projection(ref data) => match data.elem {
|
Projection(ref data) => match data.elem {
|
||||||
ProjectionElem::Downcast(ref adt_def, index) => {
|
ProjectionElem::Downcast(ref adt_def, index) => {
|
||||||
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
|
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
|
||||||
|
@ -160,7 +160,6 @@ impl<'tcx> Place<'tcx> {
|
|||||||
match *self {
|
match *self {
|
||||||
Place::Base(PlaceBase::Local(index)) =>
|
Place::Base(PlaceBase::Local(index)) =>
|
||||||
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
|
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
|
||||||
Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
|
|
||||||
Place::Base(PlaceBase::Static(ref data)) =>
|
Place::Base(PlaceBase::Static(ref data)) =>
|
||||||
PlaceTy::Ty { ty: data.ty },
|
PlaceTy::Ty { ty: data.ty },
|
||||||
Place::Projection(ref proj) =>
|
Place::Projection(ref proj) =>
|
||||||
|
@ -156,13 +156,6 @@ macro_rules! make_mir_visitor {
|
|||||||
self.super_place(place, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_static(&mut self,
|
|
||||||
static_: & $($mutability)? Static<'tcx>,
|
|
||||||
context: PlaceContext<'tcx>,
|
|
||||||
location: Location) {
|
|
||||||
self.super_static(static_, context, location);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_projection(&mut self,
|
fn visit_projection(&mut self,
|
||||||
place: & $($mutability)? PlaceProjection<'tcx>,
|
place: & $($mutability)? PlaceProjection<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
@ -736,27 +729,18 @@ macro_rules! make_mir_visitor {
|
|||||||
Place::Base(PlaceBase::Local(local)) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
self.visit_local(local, context, location);
|
self.visit_local(local, context, location);
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Static(static_)) => {
|
Place::Base(PlaceBase::Static(box Static { kind, ty })) => {
|
||||||
self.visit_static(static_, context, location);
|
if let StaticKind::Static(def_id) = kind {
|
||||||
|
self.visit_def_id(& $($mutability)? *def_id, location)
|
||||||
|
}
|
||||||
|
self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Promoted(promoted)) => {
|
|
||||||
self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
|
|
||||||
},
|
|
||||||
Place::Projection(proj) => {
|
Place::Projection(proj) => {
|
||||||
self.visit_projection(proj, context, location);
|
self.visit_projection(proj, context, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn super_static(&mut self,
|
|
||||||
static_: & $($mutability)? Static<'tcx>,
|
|
||||||
_context: PlaceContext<'tcx>,
|
|
||||||
location: Location) {
|
|
||||||
let Static { def_id, ty } = static_;
|
|
||||||
self.visit_def_id(def_id, location);
|
|
||||||
self.visit_ty(ty, TyContext::Location(location));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn super_projection(&mut self,
|
fn super_projection(&mut self,
|
||||||
proj: & $($mutability)? PlaceProjection<'tcx>,
|
proj: & $($mutability)? PlaceProjection<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
|
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
|
||||||
use rustc::mir;
|
use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
|
||||||
use rustc::mir::interpret::EvalErrorKind;
|
use rustc::mir::interpret::EvalErrorKind;
|
||||||
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
|
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
@ -621,15 +621,23 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
// but specified directly in the code. This means it gets promoted
|
// but specified directly in the code. This means it gets promoted
|
||||||
// and we can then extract the value by evaluating the promoted.
|
// and we can then extract the value by evaluating the promoted.
|
||||||
mir::Operand::Copy(
|
mir::Operand::Copy(
|
||||||
mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
|
Place::Base(
|
||||||
|
PlaceBase::Static(
|
||||||
|
box Static { kind: StaticKind::Promoted(promoted), ty }
|
||||||
|
)
|
||||||
|
)
|
||||||
) |
|
) |
|
||||||
mir::Operand::Move(
|
mir::Operand::Move(
|
||||||
mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
|
Place::Base(
|
||||||
|
PlaceBase::Static(
|
||||||
|
box Static { kind: StaticKind::Promoted(promoted), ty }
|
||||||
|
)
|
||||||
|
)
|
||||||
) => {
|
) => {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let cid = mir::interpret::GlobalId {
|
let cid = mir::interpret::GlobalId {
|
||||||
instance: self.instance,
|
instance: self.instance,
|
||||||
promoted: Some(index),
|
promoted: Some(promoted),
|
||||||
};
|
};
|
||||||
let c = bx.tcx().const_eval(param_env.and(cid));
|
let c = bx.tcx().const_eval(param_env.and(cid));
|
||||||
let (llval, ty) = self.simd_shuffle_indices(
|
let (llval, ty) = self.simd_shuffle_indices(
|
||||||
|
@ -408,11 +408,15 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
let result = match *place {
|
let result = match *place {
|
||||||
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
|
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
|
||||||
mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
|
mir::Place::Base(
|
||||||
|
mir::PlaceBase::Static(
|
||||||
|
box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
|
||||||
|
)
|
||||||
|
) => {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let cid = mir::interpret::GlobalId {
|
let cid = mir::interpret::GlobalId {
|
||||||
instance: self.instance,
|
instance: self.instance,
|
||||||
promoted: Some(index),
|
promoted: Some(promoted),
|
||||||
};
|
};
|
||||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||||
match bx.tcx().const_eval(param_env.and(cid)) {
|
match bx.tcx().const_eval(param_env.and(cid)) {
|
||||||
@ -435,7 +439,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
|
mir::Place::Base(
|
||||||
|
mir::PlaceBase::Static(
|
||||||
|
box mir::Static { ty, kind: mir::StaticKind::Static(def_id) }
|
||||||
|
)
|
||||||
|
) => {
|
||||||
// NB: The layout of a static may be unsized as is the case when working
|
// NB: The layout of a static may be unsized as is the case when working
|
||||||
// with a static that is an extern_type.
|
// with a static that is an extern_type.
|
||||||
let layout = cx.layout_of(self.monomorphize(&ty));
|
let layout = cx.layout_of(self.monomorphize(&ty));
|
||||||
|
@ -10,7 +10,7 @@ use rustc::mir::{
|
|||||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
|
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
|
||||||
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
|
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
|
||||||
Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
|
Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
|
||||||
TerminatorKind, VarBindingForm,
|
Static, StaticKind, TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc::ty::{self, DefIdTree};
|
use rustc::ty::{self, DefIdTree};
|
||||||
use rustc::ty::print::Print;
|
use rustc::ty::print::Print;
|
||||||
@ -1598,14 +1598,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
including_downcast: &IncludingDowncast,
|
including_downcast: &IncludingDowncast,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Promoted(_)) => {
|
|
||||||
buf.push_str("promoted");
|
|
||||||
}
|
|
||||||
Place::Base(PlaceBase::Local(local)) => {
|
Place::Base(PlaceBase::Local(local)) => {
|
||||||
self.append_local_to_string(local, buf)?;
|
self.append_local_to_string(local, buf)?;
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Static(ref static_)) => {
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
|
||||||
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
|
buf.push_str("promoted");
|
||||||
|
}
|
||||||
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
|
||||||
|
buf.push_str(&self.infcx.tcx.item_name(def_id).to_string());
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
@ -1744,8 +1744,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
let local = &self.mir.local_decls[local];
|
let local = &self.mir.local_decls[local];
|
||||||
self.describe_field_from_ty(&local.ty, field)
|
self.describe_field_from_ty(&local.ty, field)
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Promoted(ref prom)) =>
|
|
||||||
self.describe_field_from_ty(&prom.1, field),
|
|
||||||
Place::Base(PlaceBase::Static(ref static_)) =>
|
Place::Base(PlaceBase::Static(ref static_)) =>
|
||||||
self.describe_field_from_ty(&static_.ty, field),
|
self.describe_field_from_ty(&static_.ty, field),
|
||||||
Place::Projection(ref proj) => match proj.elem {
|
Place::Projection(ref proj) => match proj.elem {
|
||||||
@ -1809,8 +1807,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
/// Checks if a place is a thread-local static.
|
/// Checks if a place is a thread-local static.
|
||||||
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
|
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
|
||||||
if let Place::Base(PlaceBase::Static(statik)) = place {
|
if let Place::Base(
|
||||||
let attrs = self.infcx.tcx.get_attrs(statik.def_id);
|
PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })
|
||||||
|
) = place {
|
||||||
|
let attrs = self.infcx.tcx.get_attrs(*def_id);
|
||||||
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
|
let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
@ -1828,8 +1828,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
match place {
|
match place {
|
||||||
Place::Base(PlaceBase::Local(_)) |
|
Place::Base(PlaceBase::Local(_)) |
|
||||||
Place::Base(PlaceBase::Static(_)) |
|
Place::Base(PlaceBase::Static(_)) => {
|
||||||
Place::Base(PlaceBase::Promoted(_)) => {
|
|
||||||
StorageDeadOrDrop::LocalStorageDead
|
StorageDeadOrDrop::LocalStorageDead
|
||||||
}
|
}
|
||||||
Place::Projection(box PlaceProjection { base, elem }) => {
|
Place::Projection(box PlaceProjection { base, elem }) => {
|
||||||
|
@ -8,7 +8,9 @@ use rustc::infer::InferCtxt;
|
|||||||
use rustc::lint::builtin::UNUSED_MUT;
|
use rustc::lint::builtin::UNUSED_MUT;
|
||||||
use rustc::middle::borrowck::SignalledError;
|
use rustc::middle::borrowck::SignalledError;
|
||||||
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||||
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
|
use rustc::mir::{
|
||||||
|
ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase, Static, StaticKind
|
||||||
|
};
|
||||||
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
||||||
use rustc::mir::{Terminator, TerminatorKind};
|
use rustc::mir::{Terminator, TerminatorKind};
|
||||||
use rustc::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
@ -1226,8 +1228,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
Operand::Move(Place::Base(PlaceBase::Static(..)))
|
Operand::Move(Place::Base(PlaceBase::Static(..)))
|
||||||
| Operand::Copy(Place::Base(PlaceBase::Static(..)))
|
| Operand::Copy(Place::Base(PlaceBase::Static(..)))
|
||||||
| Operand::Move(Place::Base(PlaceBase::Promoted(..)))
|
|
||||||
| Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
|
|
||||||
| Operand::Constant(..) => {}
|
| Operand::Constant(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1310,12 +1310,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
//
|
//
|
||||||
// FIXME: allow thread-locals to borrow other thread locals?
|
// FIXME: allow thread-locals to borrow other thread locals?
|
||||||
let (might_be_alive, will_be_dropped) = match root_place {
|
let (might_be_alive, will_be_dropped) = match root_place {
|
||||||
Place::Base(PlaceBase::Promoted(_)) => (true, false),
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
|
||||||
Place::Base(PlaceBase::Static(_)) => {
|
(true, false)
|
||||||
|
}
|
||||||
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(_), .. })) => {
|
||||||
// Thread-locals might be dropped after the function exits, but
|
// Thread-locals might be dropped after the function exits, but
|
||||||
// "true" statics will never be.
|
// "true" statics will never be.
|
||||||
let is_thread_local = self.is_place_thread_local(&root_place);
|
(true, self.is_place_thread_local(&root_place))
|
||||||
(true, is_thread_local)
|
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Local(_)) => {
|
Place::Base(PlaceBase::Local(_)) => {
|
||||||
// Locals are always dropped at function exit, and if they
|
// Locals are always dropped at function exit, and if they
|
||||||
@ -1578,7 +1579,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
match *last_prefix {
|
match *last_prefix {
|
||||||
Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
|
Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
|
||||||
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
|
Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
|
Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1605,7 +1605,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
let mut place = place;
|
let mut place = place;
|
||||||
loop {
|
loop {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
||||||
// assigning to `x` does not require `x` be initialized.
|
// assigning to `x` does not require `x` be initialized.
|
||||||
break;
|
break;
|
||||||
@ -1953,10 +1952,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
self.used_mut_upvars.push(field);
|
self.used_mut_upvars.push(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RootPlace {
|
|
||||||
place: Place::Base(PlaceBase::Promoted(..)),
|
|
||||||
is_local_mutation_allowed: _,
|
|
||||||
} => {}
|
|
||||||
RootPlace {
|
RootPlace {
|
||||||
place: Place::Base(PlaceBase::Static(..)),
|
place: Place::Base(PlaceBase::Static(..)),
|
||||||
is_local_mutation_allowed: _,
|
is_local_mutation_allowed: _,
|
||||||
@ -1994,12 +1989,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
|
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
|
||||||
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
|
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
|
||||||
Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
|
Place::Base(PlaceBase::Static(box Static{kind: StaticKind::Promoted(_), ..})) =>
|
||||||
place,
|
Ok(RootPlace {
|
||||||
is_local_mutation_allowed,
|
place,
|
||||||
}),
|
is_local_mutation_allowed,
|
||||||
Place::Base(PlaceBase::Static(ref static_)) => {
|
}),
|
||||||
if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
|
||||||
|
if self.infcx.tcx.is_static(def_id) != Some(hir::Mutability::MutMutable) {
|
||||||
Err(place)
|
Err(place)
|
||||||
} else {
|
} else {
|
||||||
Ok(RootPlace {
|
Ok(RootPlace {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::Node;
|
use rustc::hir::Node;
|
||||||
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
|
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
|
||||||
use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
|
use rustc::mir::{
|
||||||
|
Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
|
||||||
|
};
|
||||||
use rustc::mir::{Terminator, TerminatorKind};
|
use rustc::mir::{Terminator, TerminatorKind};
|
||||||
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
|
use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
@ -129,9 +131,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
|
Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) =>
|
||||||
|
unreachable!(),
|
||||||
|
|
||||||
Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
|
Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => {
|
||||||
if let Place::Base(PlaceBase::Static(_)) = access_place {
|
if let Place::Base(PlaceBase::Static(_)) = access_place {
|
||||||
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
|
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
|
||||||
reason = String::new();
|
reason = String::new();
|
||||||
|
@ -449,53 +449,49 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||||||
context: PlaceContext<'_>,
|
context: PlaceContext<'_>,
|
||||||
) -> PlaceTy<'tcx> {
|
) -> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_place: {:?}", place);
|
debug!("sanitize_place: {:?}", place);
|
||||||
let place_ty = match *place {
|
let place_ty = match place {
|
||||||
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
|
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
|
||||||
ty: self.mir.local_decls[index].ty,
|
ty: self.mir.local_decls[*index].ty,
|
||||||
},
|
},
|
||||||
Place::Base(PlaceBase::Promoted(box (index, sty))) => {
|
Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
|
||||||
let sty = self.sanitize_type(place, sty);
|
let sty = self.sanitize_type(place, sty);
|
||||||
|
let check_err =
|
||||||
if !self.errors_reported {
|
|verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
|
||||||
let promoted_mir = &self.mir.promoted[index];
|
place: &Place<'tcx>,
|
||||||
self.sanitize_promoted(promoted_mir, location);
|
ty,
|
||||||
|
sty| {
|
||||||
let promoted_ty = promoted_mir.return_ty();
|
if let Err(terr) = verifier.cx.eq_types(
|
||||||
|
sty,
|
||||||
if let Err(terr) = self.cx.eq_types(
|
ty,
|
||||||
sty,
|
location.to_locations(),
|
||||||
promoted_ty,
|
ConstraintCategory::Boring,
|
||||||
location.to_locations(),
|
) {
|
||||||
ConstraintCategory::Boring,
|
span_mirbug!(
|
||||||
) {
|
verifier,
|
||||||
span_mirbug!(
|
|
||||||
self,
|
|
||||||
place,
|
place,
|
||||||
"bad promoted type ({:?}: {:?}): {:?}",
|
"bad promoted type ({:?}: {:?}): {:?}",
|
||||||
promoted_ty,
|
ty,
|
||||||
sty,
|
sty,
|
||||||
terr
|
terr
|
||||||
);
|
);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
match kind {
|
||||||
PlaceTy::Ty { ty: sty }
|
StaticKind::Promoted(promoted) => {
|
||||||
}
|
if !self.errors_reported {
|
||||||
Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
|
let promoted_mir = &self.mir.promoted[*promoted];
|
||||||
let sty = self.sanitize_type(place, sty);
|
self.sanitize_promoted(promoted_mir, location);
|
||||||
let ty = self.tcx().type_of(def_id);
|
|
||||||
let ty = self.cx.normalize(ty, location);
|
let promoted_ty = promoted_mir.return_ty();
|
||||||
if let Err(terr) =
|
check_err(self, place, promoted_ty, sty);
|
||||||
self.cx
|
}
|
||||||
.eq_types(ty, sty, location.to_locations(), ConstraintCategory::Boring)
|
}
|
||||||
{
|
StaticKind::Static(def_id) => {
|
||||||
span_mirbug!(
|
let ty = self.tcx().type_of(*def_id);
|
||||||
self,
|
let ty = self.cx.normalize(ty, location);
|
||||||
place,
|
|
||||||
"bad static type ({:?}: {:?}): {:?}",
|
check_err(self, place, ty, sty);
|
||||||
ty,
|
}
|
||||||
sty,
|
|
||||||
terr
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
PlaceTy::Ty { ty: sty }
|
PlaceTy::Ty { ty: sty }
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,6 @@ pub(super) fn is_active<'tcx>(
|
|||||||
/// This is called for all Yield statements on movable generators
|
/// This is called for all Yield statements on movable generators
|
||||||
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
|
||||||
match place {
|
match place {
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Static(..)) => false,
|
Place::Base(PlaceBase::Static(..)) => false,
|
||||||
Place::Base(PlaceBase::Local(..)) => true,
|
Place::Base(PlaceBase::Local(..)) => true,
|
||||||
Place::Projection(box proj) => {
|
Place::Projection(box proj) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::mir::ProjectionElem;
|
use rustc::mir::ProjectionElem;
|
||||||
use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
|
use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability, Static, StaticKind};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use crate::borrow_check::borrow_set::LocalsStateAtExit;
|
use crate::borrow_check::borrow_set::LocalsStateAtExit;
|
||||||
|
|
||||||
@ -30,8 +30,6 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
|||||||
locals_state_at_exit: &LocalsStateAtExit,
|
locals_state_at_exit: &LocalsStateAtExit,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Place::Base(PlaceBase::Promoted(_)) => false,
|
|
||||||
|
|
||||||
// If a local variable is immutable, then we only need to track borrows to guard
|
// If a local variable is immutable, then we only need to track borrows to guard
|
||||||
// against two kinds of errors:
|
// against two kinds of errors:
|
||||||
// * The variable being dropped while still borrowed (e.g., because the fn returns
|
// * The variable being dropped while still borrowed (e.g., because the fn returns
|
||||||
@ -51,8 +49,10 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Place::Base(PlaceBase::Static(static_)) => {
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
|
||||||
tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
|
false,
|
||||||
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
|
||||||
|
tcx.is_static(*def_id) == Some(hir::Mutability::MutMutable)
|
||||||
}
|
}
|
||||||
Place::Projection(proj) => match proj.elem {
|
Place::Projection(proj) => match proj.elem {
|
||||||
ProjectionElem::Field(..)
|
ProjectionElem::Field(..)
|
||||||
@ -88,7 +88,6 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
|||||||
loop {
|
loop {
|
||||||
match p {
|
match p {
|
||||||
Place::Projection(pi) => p = &pi.base,
|
Place::Projection(pi) => p = &pi.base,
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Static(_)) => return None,
|
Place::Base(PlaceBase::Static(_)) => return None,
|
||||||
Place::Base(PlaceBase::Local(l)) => return Some(*l),
|
Place::Base(PlaceBase::Local(l)) => return Some(*l),
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::borrow_check::ArtificialField;
|
|||||||
use crate::borrow_check::Overlap;
|
use crate::borrow_check::Overlap;
|
||||||
use crate::borrow_check::{Deep, Shallow, AccessDepth};
|
use crate::borrow_check::{Deep, Shallow, AccessDepth};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
|
use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, StaticKind};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
@ -338,7 +338,6 @@ fn unroll_place<'tcx, R>(
|
|||||||
op,
|
op,
|
||||||
),
|
),
|
||||||
|
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
|
||||||
let list = PlaceComponents {
|
let list = PlaceComponents {
|
||||||
component: place,
|
component: place,
|
||||||
@ -371,41 +370,45 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
|||||||
Overlap::Disjoint
|
Overlap::Disjoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
|
(Place::Base(PlaceBase::Static(s1)), Place::Base(PlaceBase::Static(s2))) => {
|
||||||
if static1.def_id != static2.def_id {
|
match (&s1.kind, &s2.kind) {
|
||||||
debug!("place_element_conflict: DISJOINT-STATIC");
|
(StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => {
|
||||||
Overlap::Disjoint
|
if def_id_1 != def_id_2 {
|
||||||
} else if tcx.is_static(static1.def_id) == Some(hir::Mutability::MutMutable) {
|
debug!("place_element_conflict: DISJOINT-STATIC");
|
||||||
// We ignore mutable statics - they can only be unsafe code.
|
Overlap::Disjoint
|
||||||
debug!("place_element_conflict: IGNORE-STATIC-MUT");
|
} else if tcx.is_static(*def_id_1) == Some(hir::Mutability::MutMutable) {
|
||||||
Overlap::Disjoint
|
// We ignore mutable statics - they can only be unsafe code.
|
||||||
} else {
|
debug!("place_element_conflict: IGNORE-STATIC-MUT");
|
||||||
debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
|
Overlap::Disjoint
|
||||||
Overlap::EqualOrDisjoint
|
} else {
|
||||||
}
|
debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
|
||||||
}
|
Overlap::EqualOrDisjoint
|
||||||
(Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
|
|
||||||
if p1.0 == p2.0 {
|
|
||||||
if let ty::Array(_, size) = p1.1.sty {
|
|
||||||
if size.unwrap_usize(tcx) == 0 {
|
|
||||||
// Ignore conflicts with promoted [T; 0].
|
|
||||||
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
|
|
||||||
return Overlap::Disjoint;
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
(StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
|
||||||
|
if promoted_1 == promoted_2 {
|
||||||
|
if let ty::Array(_, size) = s1.ty.sty {
|
||||||
|
if size.unwrap_usize(tcx) == 0 {
|
||||||
|
// Ignore conflicts with promoted [T; 0].
|
||||||
|
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
|
||||||
|
return Overlap::Disjoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the same promoted - base case, equal
|
||||||
|
debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
|
||||||
|
Overlap::EqualOrDisjoint
|
||||||
|
} else {
|
||||||
|
// different promoteds - base case, disjoint
|
||||||
|
debug!("place_element_conflict: DISJOINT-PROMOTED");
|
||||||
|
Overlap::Disjoint
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_, _) => {
|
||||||
|
debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
|
||||||
|
Overlap::Disjoint
|
||||||
}
|
}
|
||||||
// the same promoted - base case, equal
|
|
||||||
debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
|
|
||||||
Overlap::EqualOrDisjoint
|
|
||||||
} else {
|
|
||||||
// different promoteds - base case, disjoint
|
|
||||||
debug!("place_element_conflict: DISJOINT-PROMOTED");
|
|
||||||
Overlap::Disjoint
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
|
|
||||||
(Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
|
|
||||||
(Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
|
|
||||||
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
|
|
||||||
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
|
(Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
|
||||||
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
|
(Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
|
||||||
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
|
debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
|
||||||
|
@ -26,7 +26,6 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match *cursor {
|
match *cursor {
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Local(_)) |
|
Place::Base(PlaceBase::Local(_)) |
|
||||||
Place::Base(PlaceBase::Static(_)) => return false,
|
Place::Base(PlaceBase::Static(_)) => return false,
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
@ -87,7 +86,6 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
'cursor: loop {
|
'cursor: loop {
|
||||||
let proj = match *cursor {
|
let proj = match *cursor {
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
|
Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
|
||||||
Place::Base(PlaceBase::Static(_)) => {
|
Place::Base(PlaceBase::Static(_)) => {
|
||||||
self.next = None;
|
self.next = None;
|
||||||
|
@ -126,8 +126,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
block.and(place)
|
block.and(place)
|
||||||
}
|
}
|
||||||
ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
|
ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
|
||||||
def_id: id,
|
|
||||||
ty: expr.ty,
|
ty: expr.ty,
|
||||||
|
kind: StaticKind::Static(id),
|
||||||
})))),
|
})))),
|
||||||
|
|
||||||
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
||||||
|
@ -93,7 +93,6 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
|
|||||||
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
|
fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Local(l)) => Some(l),
|
Place::Base(PlaceBase::Local(l)) => Some(l),
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Static(..)) => None,
|
Place::Base(PlaceBase::Static(..)) => None,
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
|
@ -97,7 +97,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
|||||||
debug!("lookup({:?})", place);
|
debug!("lookup({:?})", place);
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
|
Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
|
||||||
Place::Base(PlaceBase::Promoted(..)) |
|
|
||||||
Place::Base(PlaceBase::Static(..)) => {
|
Place::Base(PlaceBase::Static(..)) => {
|
||||||
Err(MoveError::cannot_move_out_of(self.loc, Static))
|
Err(MoveError::cannot_move_out_of(self.loc, Static))
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,6 @@ impl<'tcx> MovePathLookup<'tcx> {
|
|||||||
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
|
pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
|
Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
|
||||||
Place::Base(PlaceBase::Promoted(_)) |
|
|
||||||
Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
|
Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match self.find(&proj.base) {
|
match self.find(&proj.base) {
|
||||||
|
@ -582,19 +582,20 @@ where
|
|||||||
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
use rustc::mir::PlaceBase;
|
use rustc::mir::PlaceBase;
|
||||||
|
use rustc::mir::{Static, StaticKind};
|
||||||
Ok(match *mir_place {
|
Ok(match *mir_place {
|
||||||
Base(PlaceBase::Promoted(ref promoted)) => {
|
Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => {
|
||||||
let instance = self.frame().instance;
|
let instance = self.frame().instance;
|
||||||
self.const_eval_raw(GlobalId {
|
self.const_eval_raw(GlobalId {
|
||||||
instance,
|
instance,
|
||||||
promoted: Some(promoted.0),
|
promoted: Some(promoted),
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
|
||||||
Base(PlaceBase::Static(ref static_)) => {
|
Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => {
|
||||||
assert!(!static_.ty.needs_subst());
|
assert!(!ty.needs_subst());
|
||||||
let layout = self.layout_of(static_.ty)?;
|
let layout = self.layout_of(ty)?;
|
||||||
let instance = ty::Instance::mono(*self.tcx, static_.def_id);
|
let instance = ty::Instance::mono(*self.tcx, def_id);
|
||||||
let cid = GlobalId {
|
let cid = GlobalId {
|
||||||
instance,
|
instance,
|
||||||
promoted: None
|
promoted: None
|
||||||
|
@ -184,7 +184,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
|
|||||||
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
|
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
|
||||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||||
use rustc::session::config::EntryFnType;
|
use rustc::session::config::EntryFnType;
|
||||||
use rustc::mir::{self, Location, Promoted};
|
use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
|
||||||
use rustc::mir::visit::Visitor as MirVisitor;
|
use rustc::mir::visit::Visitor as MirVisitor;
|
||||||
use rustc::mir::mono::MonoItem;
|
use rustc::mir::mono::MonoItem;
|
||||||
use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
|
use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
|
||||||
@ -650,19 +650,26 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||||||
self.super_terminator_kind(block, kind, location);
|
self.super_terminator_kind(block, kind, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_static(&mut self,
|
fn visit_place(&mut self,
|
||||||
static_: &mir::Static<'tcx>,
|
place: &mir::Place<'tcx>,
|
||||||
context: mir::visit::PlaceContext<'tcx>,
|
context: mir::visit::PlaceContext<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
debug!("visiting static {:?} @ {:?}", static_.def_id, location);
|
match place {
|
||||||
|
Place::Base(
|
||||||
|
PlaceBase::Static(box Static{ kind:StaticKind::Static(def_id), .. })
|
||||||
|
) => {
|
||||||
|
debug!("visiting static {:?} @ {:?}", def_id, location);
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let instance = Instance::mono(tcx, static_.def_id);
|
let instance = Instance::mono(tcx, *def_id);
|
||||||
if should_monomorphize_locally(tcx, &instance) {
|
if should_monomorphize_locally(tcx, &instance) {
|
||||||
self.output.push(MonoItem::Static(static_.def_id));
|
self.output.push(MonoItem::Static(*def_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.super_static(static_, context, location);
|
self.super_place(place, context, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ fn is_stable<'tcx>(
|
|||||||
match *place {
|
match *place {
|
||||||
// Locals and statics have stable addresses, for sure
|
// Locals and statics have stable addresses, for sure
|
||||||
Base(PlaceBase::Local { .. }) |
|
Base(PlaceBase::Local { .. }) |
|
||||||
Base(PlaceBase::Promoted { .. }) |
|
|
||||||
Base(PlaceBase::Static { .. }) =>
|
Base(PlaceBase::Static { .. }) =>
|
||||||
true,
|
true,
|
||||||
// Recurse for projections
|
// Recurse for projections
|
||||||
|
@ -300,10 +300,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
|||||||
&Place::Base(PlaceBase::Local(..)) => {
|
&Place::Base(PlaceBase::Local(..)) => {
|
||||||
// locals are safe
|
// locals are safe
|
||||||
}
|
}
|
||||||
&Place::Base(PlaceBase::Promoted(_)) => {
|
&Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => {
|
||||||
bug!("unsafety checking should happen before promotion")
|
bug!("unsafety checking should happen before promotion")
|
||||||
}
|
}
|
||||||
&Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
|
&Place::Base(
|
||||||
|
PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })
|
||||||
|
) => {
|
||||||
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
|
if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
|
||||||
self.require_unsafe("use of mutable static",
|
self.require_unsafe("use of mutable static",
|
||||||
"mutable statics can be mutated by multiple threads: aliasing violations \
|
"mutable statics can be mutated by multiple threads: aliasing violations \
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
|
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
|
||||||
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
|
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind, Static, StaticKind};
|
||||||
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
|
||||||
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
|
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
|
||||||
use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
|
use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
|
||||||
@ -283,7 +283,9 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||||||
// an `Index` projection would throw us off-track.
|
// an `Index` projection would throw us off-track.
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
Place::Base(PlaceBase::Promoted(ref promoted)) => {
|
Place::Base(
|
||||||
|
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
|
||||||
|
) => {
|
||||||
let generics = self.tcx.generics_of(self.source.def_id());
|
let generics = self.tcx.generics_of(self.source.def_id());
|
||||||
if generics.requires_monomorphization(self.tcx) {
|
if generics.requires_monomorphization(self.tcx) {
|
||||||
// FIXME: can't handle code with generics
|
// FIXME: can't handle code with generics
|
||||||
@ -293,7 +295,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
|
|||||||
let instance = Instance::new(self.source.def_id(), substs);
|
let instance = Instance::new(self.source.def_id(), substs);
|
||||||
let cid = GlobalId {
|
let cid = GlobalId {
|
||||||
instance,
|
instance,
|
||||||
promoted: Some(promoted.0),
|
promoted: Some(promoted),
|
||||||
};
|
};
|
||||||
// cannot use `const_eval` here, because that would require having the MIR
|
// cannot use `const_eval` here, because that would require having the MIR
|
||||||
// for the current function available, but we're producing said MIR right now
|
// for the current function available, but we're producing said MIR right now
|
||||||
|
@ -692,12 +692,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
|||||||
// Return pointer; update the place itself
|
// Return pointer; update the place itself
|
||||||
*place = self.destination.clone();
|
*place = self.destination.clone();
|
||||||
},
|
},
|
||||||
Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
|
Place::Base(
|
||||||
if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
|
PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })
|
||||||
promoted.0 = p;
|
) => {
|
||||||
|
if let Some(p) = self.promoted_map.get(*promoted).cloned() {
|
||||||
|
*promoted = p;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => self.super_place(place, _ctxt, _location),
|
_ => self.super_place(place, _ctxt, _location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +292,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||||||
let promoted_id = Promoted::new(self.source.promoted.len());
|
let promoted_id = Promoted::new(self.source.promoted.len());
|
||||||
let mut promoted_place = |ty, span| {
|
let mut promoted_place = |ty, span| {
|
||||||
promoted.span = span;
|
promoted.span = span;
|
||||||
promoted.local_decls[RETURN_PLACE] =
|
promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
|
||||||
LocalDecl::new_return_place(ty, span);
|
Place::Base(
|
||||||
Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
|
PlaceBase::Static(box Static{ kind: StaticKind::Promoted(promoted_id), ty })
|
||||||
|
)
|
||||||
};
|
};
|
||||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
||||||
match candidate {
|
match candidate {
|
||||||
|
@ -188,8 +188,11 @@ trait Qualif {
|
|||||||
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
|
fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
|
Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
|
||||||
Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
|
Place::Base(PlaceBase::Static(box Static {kind: StaticKind::Promoted(_), .. })) =>
|
||||||
Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
|
bug!("qualifying already promoted MIR"),
|
||||||
|
Place::Base(PlaceBase::Static(ref static_)) => {
|
||||||
|
Self::in_static(cx, static_)
|
||||||
|
},
|
||||||
Place::Projection(ref proj) => Self::in_projection(cx, proj),
|
Place::Projection(ref proj) => Self::in_projection(cx, proj),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,11 +373,18 @@ impl Qualif for IsNotConst {
|
|||||||
const IDX: usize = 2;
|
const IDX: usize = 2;
|
||||||
|
|
||||||
fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
|
fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
|
||||||
// Only allow statics (not consts) to refer to other statics.
|
match static_.kind {
|
||||||
let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
|
StaticKind::Promoted(_) => unreachable!(),
|
||||||
|
StaticKind::Static(def_id) => {
|
||||||
|
// Only allow statics (not consts) to refer to other statics.
|
||||||
|
let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
|
||||||
|
|
||||||
!allowed ||
|
!allowed ||
|
||||||
cx.tcx.get_attrs(static_.def_id).iter().any(|attr| attr.check_name("thread_local"))
|
cx.tcx.get_attrs(def_id).iter().any(
|
||||||
|
|attr| attr.check_name("thread_local"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
|
fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
|
||||||
@ -768,9 +778,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
dest = &proj.base;
|
dest = &proj.base;
|
||||||
},
|
},
|
||||||
Place::Base(PlaceBase::Promoted(..)) =>
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
|
||||||
bug!("promoteds don't exist yet during promotion"),
|
bug!("promoteds don't exist yet during promotion"),
|
||||||
Place::Base(PlaceBase::Static(..)) => {
|
Place::Base(PlaceBase::Static(box Static{ kind: _, .. })) => {
|
||||||
// Catch more errors in the destination. `visit_place` also checks that we
|
// Catch more errors in the destination. `visit_place` also checks that we
|
||||||
// do not try to access statics from constants or try to mutate statics
|
// do not try to access statics from constants or try to mutate statics
|
||||||
self.visit_place(
|
self.visit_place(
|
||||||
@ -919,11 +929,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||||||
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
|
||||||
self.super_place(place, context, location);
|
self.super_place(place, context, location);
|
||||||
match *place {
|
match *place {
|
||||||
Place::Base(PlaceBase::Local(_)) |
|
Place::Base(PlaceBase::Local(_)) => {}
|
||||||
Place::Base(PlaceBase::Promoted(_)) => {}
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
|
||||||
Place::Base(PlaceBase::Static(ref global)) => {
|
unreachable!()
|
||||||
|
}
|
||||||
|
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
|
||||||
if self.tcx
|
if self.tcx
|
||||||
.get_attrs(global.def_id)
|
.get_attrs(def_id)
|
||||||
.iter()
|
.iter()
|
||||||
.any(|attr| attr.check_name("thread_local")) {
|
.any(|attr| attr.check_name("thread_local")) {
|
||||||
if self.mode != Mode::Fn {
|
if self.mode != Mode::Fn {
|
||||||
|
@ -257,8 +257,8 @@ fn check_place(
|
|||||||
match place {
|
match place {
|
||||||
Place::Base(PlaceBase::Local(_)) => Ok(()),
|
Place::Base(PlaceBase::Local(_)) => Ok(()),
|
||||||
// promoteds are always fine, they are essentially constants
|
// promoteds are always fine, they are essentially constants
|
||||||
Place::Base(PlaceBase::Promoted(_)) => Ok(()),
|
Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()),
|
||||||
Place::Base(PlaceBase::Static(_)) =>
|
Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) =>
|
||||||
Err((span, "cannot access `static` items in const fn".into())),
|
Err((span, "cannot access `static` items in const fn".into())),
|
||||||
Place::Projection(proj) => {
|
Place::Projection(proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user