diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 47b9535abc521..12f14cfbb9afa 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1915,19 +1915,22 @@ pub enum PlaceBase<'tcx> { Static(Box>), } -/// 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, + 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` @@ -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) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 3f6133a7331a1..b1e2df0ae986b 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 066b38be3dbc2..4774f8fe5a380 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -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; @@ -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 { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 1608429b07024..7cafa0088a012 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -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 { @@ -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. diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index b9877945e7eac..fac75989aa590 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -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; @@ -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 { @@ -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!( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0358fffcde587..40b329c108401 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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; @@ -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 @@ -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) => { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 2661d765718dd..f351212e9d587 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -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; @@ -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(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 2a32b475c7991..e12077fd5f7ae 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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 } } diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index 0452465f0b9d7..6bc56ab721f98 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -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; @@ -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(..) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 783751056d76b..dc9b059de4657 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -2,7 +2,7 @@ use crate::borrow_check::ArtificialField; use crate::borrow_check::Overlap; use crate::borrow_check::{Deep, Shallow, AccessDepth}; use rustc::hir; -use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem}; +use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind}; use rustc::ty::{self, TyCtxt}; use std::cmp::max; @@ -370,47 +370,71 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( Overlap::Disjoint } } - (Place::Base(PlaceBase::Static(s1)), Place::Base(PlaceBase::Static(s2))) => { - match (s1.promoted, s2.promoted) { - (None, None) => { - if s1.def_id != s2.def_id { - debug!("place_element_conflict: DISJOINT-STATIC"); - Overlap::Disjoint - } else if tcx.is_static(s1.def_id) == Some(hir::Mutability::MutMutable) { - // We ignore mutable statics - they can only be unsafe code. - debug!("place_element_conflict: IGNORE-STATIC-MUT"); - Overlap::Disjoint - } else { - debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC"); - Overlap::EqualOrDisjoint - } - }, - (Some(p1), Some(p2)) => { - if p1 == p2 { - 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 + ( + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id_1), .. })), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id_2), .. })), + ) => { + if *def_id_1 != *def_id_2 { + debug!("place_element_conflict: DISJOINT-STATIC"); + Overlap::Disjoint + } else if tcx.is_static(*def_id_1) == Some(hir::Mutability::MutMutable) { + // We ignore mutable statics - they can only be unsafe code. + debug!("place_element_conflict: IGNORE-STATIC-MUT"); + Overlap::Disjoint + } else { + debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC"); + Overlap::EqualOrDisjoint + } + } + ( + Place::Base( + PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted_1), ty }) + ), + Place::Base( + PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted_2), .. }) + ), + ) => { + if *promoted_1 == *promoted_2 { + if let ty::Array(_, size) = 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; } - }, - (_, _) => { - 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::Static(_))) | - (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => { + ( + Place::Base(PlaceBase::Local(_)), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) + ) | + ( + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })), + Place::Base(PlaceBase::Local(_)) + ) | + ( + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) + ) | + ( + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) + ) | + ( + Place::Base(PlaceBase::Local(_)), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) + ) | + ( + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })), + Place::Base(PlaceBase::Local(_)) + ) => { debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED"); Overlap::Disjoint } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 83e1d3ebb3e06..199d03ac445ba 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -126,9 +126,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block.and(place) } ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static { - def_id: id, ty: expr.ty, - promoted: None, + kind: StaticKind::Static(id), })))), ExprKind::PlaceTypeAscription { source, user_ty } => { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 6089e491684e9..d2c279e48fe28 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -582,9 +582,9 @@ where ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { use rustc::mir::Place::*; use rustc::mir::PlaceBase; - use rustc::mir::Static; + use rustc::mir::{Static, StaticKind}; Ok(match *mir_place { - Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty: _, ..})) => { + Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => { let instance = self.frame().instance; self.const_eval_raw(GlobalId { instance, @@ -592,7 +592,7 @@ where })? } - Base(PlaceBase::Static(box Static {promoted: None, ty, def_id})) => { + Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => { assert!(!ty.needs_subst()); let layout = self.layout_of(ty)?; let instance = ty::Instance::mono(*self.tcx, def_id); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 075b81e9fd98f..0ad6962cc4ac5 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -184,7 +184,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; use rustc::ty::adjustment::CustomCoerceUnsized; 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::mono::MonoItem; use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled}; @@ -655,8 +655,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { context: mir::visit::PlaceContext<'tcx>, location: Location) { match place { - mir::Place::Base( - mir::PlaceBase::Static(box mir::Static{def_id, promoted:None, ..}) + Place::Base( + PlaceBase::Static(box Static{ kind:StaticKind::Static(def_id), .. }) ) => { debug!("visiting static {:?} @ {:?}", def_id, location); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 2ebe28e6ac091..0e31515e4af90 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -300,9 +300,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { &Place::Base(PlaceBase::Local(..)) => { // locals are safe } - &Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => { - assert!(promoted.is_none(), "unsafety checking should happen before promotion"); - + &Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => { + bug!("unsafety checking should happen before promotion") + } + &Place::Base( + PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) + ) => { if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) { self.require_unsafe("use of mutable static", "mutable statics can be mutated by multiple threads: aliasing violations \ diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 81cdb00100595..c2d594ba7b7fe 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,7 @@ use rustc::hir::def::Def; 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::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult}; @@ -266,7 +266,6 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { } fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { - use rustc::mir::Static; match *place { Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(), Place::Projection(ref proj) => match proj.elem { @@ -283,7 +282,9 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { // an `Index` projection would throw us off-track. _ => None, }, - Place::Base(PlaceBase::Static(box Static {promoted: Some(promoted), ..})) => { + Place::Base( + PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) + ) => { let generics = self.tcx.generics_of(self.source.def_id()); if generics.requires_monomorphization(self.tcx) { // FIXME: can't handle code with generics diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index ec2cf8a4c0348..1063381d6aa57 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -692,7 +692,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { // Return pointer; update the place itself *place = self.destination.clone(); }, - Place::Base(PlaceBase::Static(box Static { promoted: Some(promoted), .. })) => { + Place::Base( + PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. }) + ) => { if let Some(p) = self.promoted_map.get(*promoted).cloned() { *promoted = p; } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 2344f070ea670..92039618d85d9 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -12,7 +12,6 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. -use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; @@ -152,8 +151,7 @@ struct Promoter<'a, 'tcx: 'a> { /// If true, all nested temps are also kept in the /// source MIR, not moved to the promoted MIR. - keep_original: bool, - def_id: DefId, + keep_original: bool } impl<'a, 'tcx> Promoter<'a, 'tcx> { @@ -289,16 +287,16 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn promote_candidate(mut self, candidate: Candidate) { - use rustc::mir::Static; let mut operand = { - let def_id = self.def_id; let promoted = &mut self.promoted; let promoted_id = Promoted::new(self.source.promoted.len()); let mut promoted_place = |ty, span| { promoted.span = span; - promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); + promoted.local_decls[RETURN_PLACE] = + LocalDecl::new_return_place(ty, span); Place::Base( - PlaceBase::Static(Box::new(Static { def_id, ty, promoted: Some(promoted_id) }))) + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(promoted_id), ty }) + ) }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); match candidate { @@ -371,8 +369,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut temps: IndexVec, - candidates: Vec, - def_id: DefId) { + candidates: Vec) { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); @@ -417,8 +414,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, tcx, source: mir, temps: &mut temps, - keep_original: false, - def_id, + keep_original: false }; promoter.promote_candidate(candidate); } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index c01ed4b1c59e8..c35bf80bb2eda 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -188,8 +188,9 @@ trait Qualif { fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool { match *place { Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local), + Place::Base(PlaceBase::Static(box Static {kind: StaticKind::Promoted(_), .. })) => + bug!("qualifying already promoted MIR"), Place::Base(PlaceBase::Static(ref static_)) => { - assert!(static_.promoted.is_none(), "qualifying already promoted MIR"); Self::in_static(cx, static_) }, Place::Projection(ref proj) => Self::in_projection(cx, proj), @@ -372,11 +373,18 @@ impl Qualif for IsNotConst { const IDX: usize = 2; fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool { - // Only allow statics (not consts) to refer to other statics. - let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut; + match static_.kind { + 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 || - cx.tcx.get_attrs(static_.def_id).iter().any(|attr| attr.check_name("thread_local")) + !allowed || + cx.tcx.get_attrs(def_id).iter().any( + |attr| attr.check_name("thread_local" + )) + } + } } fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool { @@ -770,8 +778,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { ); dest = &proj.base; }, - Place::Base(PlaceBase::Static(st)) => { - assert!(st.promoted.is_none(), "promoteds don't exist yet during promotion"); + Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => + bug!("promoteds don't exist yet during promotion"), + Place::Base(PlaceBase::Static(box Static{ kind: _, .. })) => { // 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 self.visit_place( @@ -921,10 +930,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { self.super_place(place, context, location); match *place { Place::Base(PlaceBase::Local(_)) => {} - Place::Base(PlaceBase::Static(ref global)) => { - assert!(global.promoted.is_none()); + Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {} + Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => { if self.tcx - .get_attrs(global.def_id) + .get_attrs(def_id) .iter() .any(|attr| attr.check_name("thread_local")) { if self.mode != Mode::Fn { @@ -1516,7 +1525,7 @@ impl MirPass for QualifyAndPromoteConstants { }; // Do the actual promotion, now that we know what's viable. - promote_consts::promote_candidates(mir, tcx, temps, candidates, def_id); + promote_consts::promote_candidates(mir, tcx, temps, candidates); } else { if !mir.control_flow_destroyed.is_empty() { let mut locals = mir.vars_iter(); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index da849faf40aae..8742c5d759c8f 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -257,8 +257,8 @@ fn check_place( match place { Place::Base(PlaceBase::Local(_)) => Ok(()), // promoteds are always fine, they are essentially constants - Place::Base(PlaceBase::Static(box Static {def_id: _, ty: _, promoted: Some(_)})) => Ok(()), - Place::Base(PlaceBase::Static(box Static {def_id: _, ty: _, promoted: None})) => + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()), + Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) => Err((span, "cannot access `static` items in const fn".into())), Place::Projection(proj) => { match proj.elem {