Skip to content

Merge Promoted and Static in mir::Place #59232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 26, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @arielb1 @nikomatsakis Are pre-normalized types in MIR still needed?

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