Skip to content

Commit

Permalink
adding mir::StaticKind enum for static and promoted
Browse files Browse the repository at this point in the history
  • Loading branch information
Saleem Jaffer committed Mar 23, 2019
1 parent cf2f1bb commit 752544b
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 166 deletions.
47 changes: 26 additions & 21 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1915,19 +1915,22 @@ pub enum PlaceBase<'tcx> {
Static(Box<Static<'tcx>>),
}

/// The `DefId` of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
/// We store the normalized type to avoid requiring normalization when reading MIR
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
pub def_id: DefId,
pub ty: Ty<'tcx>,
pub promoted: Option<Promoted>,
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> {
def_id,
ty,
promoted
kind
});

/// The `Projection` data structure defines things of the form `B.x`
Expand Down Expand Up @@ -2058,21 +2061,23 @@ impl<'tcx> Debug for Place<'tcx> {

match *self {
Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
Base(PlaceBase::Static(box self::Static { def_id, ty, promoted })) => {
match promoted {
None => write!(
fmt,
"({}: {:?})",
ty::tls::with(|tcx| tcx.def_path_str(def_id)),
ty
),
Some(pr) => write!(
fmt,
"({:?}: {:?})",
pr,
ty
),
}
Base(PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) })) => {
write!(
fmt,
"({}: {:?})",
ty::tls::with(|tcx| tcx.def_path_str(def_id)),
ty
)
},
Base(PlaceBase::Static(
box self::Static { ty, kind: StaticKind::Promoted(promoted) })
) => {
write!(
fmt,
"({:?}: {:?})",
promoted,
ty
)
},
Projection(ref data) => match data.elem {
ProjectionElem::Downcast(ref adt_def, index) => {
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,15 +725,18 @@ macro_rules! make_mir_visitor {
place: & $($mutability)? Place<'tcx>,
context: PlaceContext<'tcx>,
location: Location) {
use crate::mir::{Static, StaticKind};
match place {
Place::Base(PlaceBase::Local(local)) => {
self.visit_local(local, context, location);
}
Place::Base(PlaceBase::Static(static_)) => {
if static_.promoted.is_none() {
self.visit_def_id(& $($mutability)? static_.def_id, location);
}
self.visit_ty(& $($mutability)? static_.ty, TyContext::Location(location));
Place::Base(
PlaceBase::Static(box Static{kind: StaticKind::Static(def_id), ..})
) => {
self.visit_def_id(& $($mutability)? *def_id, location)
}
Place::Base(PlaceBase::Static(box Static{ty, ..})) => {
self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
}
Place::Projection(proj) => {
self.visit_projection(proj, context, location);
Expand Down
18 changes: 11 additions & 7 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc::middle::lang_items;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
use rustc::mir::{self, Place, PlaceBase};
use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
use rustc::mir::interpret::EvalErrorKind;
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
use rustc_target::spec::abi::Abi;
Expand Down Expand Up @@ -621,14 +621,18 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// but specified directly in the code. This means it gets promoted
// and we can then extract the value by evaluating the promoted.
mir::Operand::Copy(
Place::Base(PlaceBase::Static(
box mir::Static {promoted: Some(promoted), ty, ..}
))
Place::Base(
PlaceBase::Static(
box Static { kind: StaticKind::Promoted(promoted), ty }
)
)
) |
mir::Operand::Move(
Place::Base(PlaceBase::Static(
box mir::Static {promoted: Some(promoted), ty, ..}
))
Place::Base(
PlaceBase::Static(
box Static { kind: StaticKind::Promoted(promoted), ty }
)
)
) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
Expand Down
8 changes: 6 additions & 2 deletions src/librustc_codegen_ssa/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let result = match *place {
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
mir::Place::Base(
mir::PlaceBase::Static(box mir::Static { def_id: _, ty, promoted: Some(promoted) })
mir::PlaceBase::Static(
box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
)
) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
Expand Down Expand Up @@ -438,7 +440,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
mir::Place::Base(
mir::PlaceBase::Static(box mir::Static { def_id, ty, promoted: None })
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
// with a static that is an extern_type.
Expand Down
19 changes: 10 additions & 9 deletions src/librustc_mir/borrow_check/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
TerminatorKind, VarBindingForm,
Static, StaticKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, DefIdTree};
use rustc::ty::print::Print;
Expand Down Expand Up @@ -1601,12 +1601,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Base(PlaceBase::Local(local)) => {
self.append_local_to_string(local, buf)?;
}
Place::Base(PlaceBase::Static(ref static_)) => {
if static_.promoted.is_some() {
buf.push_str("promoted");
} else {
buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
}
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
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) => {
match proj.elem {
Expand Down Expand Up @@ -1808,8 +1807,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {

/// Checks if a place is a thread-local static.
pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
if let Place::Base(PlaceBase::Static(statik)) = place {
let attrs = self.infcx.tcx.get_attrs(statik.def_id);
if let Place::Base(
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"));

debug!(
Expand Down
30 changes: 19 additions & 11 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use rustc::infer::InferCtxt;
use rustc::lint::builtin::UNUSED_MUT;
use rustc::middle::borrowck::SignalledError;
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::{Terminator, TerminatorKind};
use rustc::ty::query::Providers;
Expand Down Expand Up @@ -1308,8 +1310,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
//
// FIXME: allow thread-locals to borrow other thread locals?
let (might_be_alive, will_be_dropped) = match root_place {
Place::Base(PlaceBase::Static(st)) => {
(true, st.promoted.is_none() && self.is_place_thread_local(&root_place))
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
(true, false)
}
Place::Base(PlaceBase::Static(box Static{ kind: _, .. })) => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
(true, self.is_place_thread_local(&root_place))
}
Place::Base(PlaceBase::Local(_)) => {
// Locals are always dropped at function exit, and if they
Expand Down Expand Up @@ -1982,18 +1989,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
// 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::Base(PlaceBase::Static(ref static_)) => {
if static_.promoted.is_some() ||
(static_.promoted.is_none() &&
self.infcx.tcx.is_static(static_.def_id)
== Some(hir::Mutability::MutMutable)
){
Place::Base(PlaceBase::Static(box Static{kind: StaticKind::Promoted(_), ..})) =>
Ok(RootPlace {
place,
is_local_mutation_allowed,
}),
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)
} else {
Ok(RootPlace {
place,
is_local_mutation_allowed,
})
} else {
Err(place)
}
}
Place::Projection(ref proj) => {
Expand Down
10 changes: 7 additions & 3 deletions src/librustc_mir/borrow_check/mutability_errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use rustc::hir;
use rustc::hir::Node;
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::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
Expand Down Expand Up @@ -129,8 +131,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
}
}

Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => {
assert!(promoted.is_none());
Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) =>
unreachable!(),

Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => {
if let Place::Base(PlaceBase::Static(_)) = access_place {
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
reason = String::new();
Expand Down
62 changes: 35 additions & 27 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,45 +453,53 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
ty: self.mir.local_decls[index].ty,
},
Place::Base(PlaceBase::Static(box Static { def_id, ty: sty, promoted })) => {
Place::Base(
PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), ty: sty })
) => {
let sty = self.sanitize_type(place, sty);
let check_err =
|verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx> ,
place: &Place<'tcx>,
ty,
sty| {
if let Err(terr) = verifier.cx.eq_types(

if !self.errors_reported {
let promoted_mir = &self.mir.promoted[promoted];
self.sanitize_promoted(promoted_mir, location);

let promoted_ty = promoted_mir.return_ty();

if let Err(terr) = self.cx.eq_types(
sty,
ty,
promoted_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
span_mirbug!(
verifier,
self,
place,
"bad promoted type ({:?}: {:?}): {:?}",
ty,
promoted_ty,
sty,
terr
);
};
};
match promoted {
Some(pr) => {
if !self.errors_reported {
let promoted_mir = &self.mir.promoted[pr];
self.sanitize_promoted(promoted_mir, location);

let promoted_ty = promoted_mir.return_ty();
check_err(self, place, promoted_ty, sty);
}
}
None => {
let ty = self.tcx().type_of(def_id);
let ty = self.cx.normalize(ty, location);

check_err(self, place, ty, sty);
}
}
PlaceTy::Ty { ty: sty }
}
Place::Base(
PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty: sty })
) => {
let sty = self.sanitize_type(place, sty);
let ty = self.tcx().type_of(def_id);
let ty = self.cx.normalize(ty, location);
if let Err(terr) =
self.cx
.eq_types(ty, sty, location.to_locations(), ConstraintCategory::Boring)
{
span_mirbug!(
self,
place,
"bad static type ({:?}: {:?}): {:?}",
ty,
sty,
terr
);
}
PlaceTy::Ty { ty: sty }
}
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_mir/borrow_check/place_ext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc::hir;
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 crate::borrow_check::borrow_set::LocalsStateAtExit;

Expand Down Expand Up @@ -49,9 +49,10 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
}
}
}
Place::Base(PlaceBase::Static(static_)) => {
static_.promoted.is_none() &&
(tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable))
Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
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 {
ProjectionElem::Field(..)
Expand Down
Loading

0 comments on commit 752544b

Please sign in to comment.