diff options
| author | Saleem Jaffer <saleem@acko.com> | 2019-03-16 17:40:41 +0530 |
|---|---|---|
| committer | Saleem Jaffer <saleem@acko.com> | 2019-03-18 15:03:29 +0530 |
| commit | 7fb1c22da181426f6ea7662f5c7f47edbbe24f56 (patch) | |
| tree | fe473b57dc513f00eb6a140124cdcf1ce150398e | |
| parent | 03dafa7da38decbe74fcd8a23d7ec835e637c8e4 (diff) | |
| download | rust-7fb1c22da181426f6ea7662f5c7f47edbbe24f56.tar.gz rust-7fb1c22da181426f6ea7662f5c7f47edbbe24f56.zip | |
promoted is still left in 2 places
22 files changed, 336 insertions, 283 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9f2027e7d05..47b9535abc5 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1913,9 +1913,6 @@ pub enum PlaceBase<'tcx> { /// static or static mut variable 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 @@ -1924,11 +1921,13 @@ pub enum PlaceBase<'tcx> { pub struct Static<'tcx> { pub def_id: DefId, pub ty: Ty<'tcx>, + pub promoted: Option<Promoted>, } impl_stable_hash_for!(struct Static<'tcx> { def_id, - ty + ty, + promoted }); /// The `Projection` data structure defines things of the form `B.x` @@ -2048,7 +2047,7 @@ impl<'tcx> Place<'tcx> { match self { Place::Base(PlaceBase::Local(local)) => Some(*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 +2058,22 @@ impl<'tcx> Debug for Place<'tcx> { match *self { Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id), - Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!( - fmt, - "({}: {:?})", - ty::tls::with(|tcx| tcx.def_path_str(def_id)), - ty - ), - Base(PlaceBase::Promoted(ref promoted)) => write!( - fmt, - "({:?}: {:?})", - promoted.0, - promoted.1 - ), + 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 + ), + } + }, Projection(ref data) => match data.elem { ProjectionElem::Downcast(ref adt_def, index) => { write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index a6f153eaf64..ac42eacacd7 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -160,7 +160,6 @@ impl<'tcx> Place<'tcx> { match *self { Place::Base(PlaceBase::Local(index)) => 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)) => PlaceTy::Ty { ty: data.ty }, Place::Projection(ref proj) => diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 8bc0075c477..cddf5782121 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -737,11 +737,18 @@ macro_rules! make_mir_visitor { self.visit_local(local, context, location); } Place::Base(PlaceBase::Static(static_)) => { + match static_.promoted { + None => { + self.visit_static(static_, context, location); + } + Some(_) => { + self.visit_ty( + & $($mutability)? static_.ty, TyContext::Location(location) + ); + } + } self.visit_static(static_, context, location); } - Place::Base(PlaceBase::Promoted(promoted)) => { - self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location)); - }, Place::Projection(proj) => { self.visit_projection(proj, context, location); } @@ -752,7 +759,7 @@ macro_rules! make_mir_visitor { static_: & $($mutability)? Static<'tcx>, _context: PlaceContext<'tcx>, location: Location) { - let Static { def_id, ty } = static_; + let Static { def_id, ty, promoted: _ } = static_; self.visit_def_id(def_id, location); self.visit_ty(ty, TyContext::Location(location)); } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 14289381aef..8f83c025ceb 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1598,14 +1598,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { including_downcast: &IncludingDowncast, ) -> Result<(), ()> { match *place { - Place::Base(PlaceBase::Promoted(_)) => { - buf.push_str("promoted"); - } Place::Base(PlaceBase::Local(local)) => { self.append_local_to_string(local, buf)?; } Place::Base(PlaceBase::Static(ref static_)) => { - buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string()); + match static_.promoted { + Some(_) => { + buf.push_str("promoted"); + } + None => { + buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string()); + } + } } Place::Projection(ref proj) => { match proj.elem { @@ -1744,8 +1748,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[local]; 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_)) => self.describe_field_from_ty(&static_.ty, field), Place::Projection(ref proj) => match proj.elem { @@ -1828,8 +1830,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let tcx = self.infcx.tcx; match place { Place::Base(PlaceBase::Local(_)) | - Place::Base(PlaceBase::Static(_)) | - Place::Base(PlaceBase::Promoted(_)) => { + Place::Base(PlaceBase::Static(_)) => { StorageDeadOrDrop::LocalStorageDead } Place::Projection(box PlaceProjection { base, elem }) => { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c4e371d5afe..5726eba9bda 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1226,8 +1226,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } Operand::Move(Place::Base(PlaceBase::Static(..))) | Operand::Copy(Place::Base(PlaceBase::Static(..))) - | Operand::Move(Place::Base(PlaceBase::Promoted(..))) - | Operand::Copy(Place::Base(PlaceBase::Promoted(..))) | Operand::Constant(..) => {} } } @@ -1310,12 +1308,16 @@ 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::Promoted(_)) => (true, false), - Place::Base(PlaceBase::Static(_)) => { - // Thread-locals might be dropped after the function exits, but - // "true" statics will never be. - let is_thread_local = self.is_place_thread_local(&root_place); - (true, is_thread_local) + Place::Base(PlaceBase::Static(st)) => { + match st.promoted { + None => { + // Thread-locals might be dropped after the function exits, but + // "true" statics will never be. + let is_thread_local = self.is_place_thread_local(&root_place); + (true, is_thread_local) + } + Some(_) => (true, false), + } } Place::Base(PlaceBase::Local(_)) => { // Locals are always dropped at function exit, and if they @@ -1578,7 +1580,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match *last_prefix { Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"), Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"), - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic), } } @@ -1605,7 +1606,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut place = place; loop { match *place { - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => { // assigning to `x` does not require `x` be initialized. break; @@ -1954,10 +1954,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } RootPlace { - place: Place::Base(PlaceBase::Promoted(..)), - is_local_mutation_allowed: _, - } => {} - RootPlace { place: Place::Base(PlaceBase::Static(..)), is_local_mutation_allowed: _, } => {} @@ -1994,18 +1990,28 @@ 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::Promoted(_)) => Ok(RootPlace { - place, - is_local_mutation_allowed, - }), +// Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace { +// place, +// is_local_mutation_allowed, +// }), Place::Base(PlaceBase::Static(ref static_)) => { - if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { - Err(place) - } else { - Ok(RootPlace { - place, - is_local_mutation_allowed, - }) + match static_.promoted { + Some(_) => { + Ok(RootPlace { + place, + is_local_mutation_allowed, + }) + } + None => { + if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { + Err(place) + } else { + Ok(RootPlace { + place, + is_local_mutation_allowed, + }) + } + } } } 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 b8dae98ec64..d8c39e0715a 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -129,16 +129,19 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } - Place::Base(PlaceBase::Promoted(_)) => unreachable!(), - - Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => { - if let Place::Base(PlaceBase::Static(_)) = access_place { - item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); - reason = String::new(); - } else { - item_msg = format!("`{}`", access_place_desc.unwrap()); - let static_name = &self.infcx.tcx.item_name(*def_id); - reason = format!(", as `{}` is an immutable static item", static_name); + Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => { + match promoted { + Some(_) => unreachable!(), + None => { + if let Place::Base(PlaceBase::Static(_)) = access_place { + item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); + reason = String::new(); + } else { + item_msg = format!("`{}`", access_place_desc.unwrap()); + let static_name = &self.infcx.tcx.item_name(*def_id); + reason = format!(", as `{}` is an immutable static item", static_name); + } + } } } 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 25a3160a498..334c20761e7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -453,51 +453,55 @@ 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::Promoted(box (index, sty))) => { - let sty = self.sanitize_type(place, sty); - - if !self.errors_reported { - let promoted_mir = &self.mir.promoted[index]; - self.sanitize_promoted(promoted_mir, location); - - let promoted_ty = promoted_mir.return_ty(); - - if let Err(terr) = self.cx.eq_types( - sty, - promoted_ty, - location.to_locations(), - ConstraintCategory::Boring, - ) { - span_mirbug!( - self, - place, - "bad promoted type ({:?}: {:?}): {:?}", - promoted_ty, - sty, - terr - ); - }; - } - PlaceTy::Ty { ty: sty } - } - Place::Base(PlaceBase::Static(box 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 - ); + Place::Base(PlaceBase::Static(box Static { def_id, ty: sty, promoted })) => { + match promoted { + Some(pr) => { + let sty = self.sanitize_type(place, sty); + + if !self.errors_reported { + let promoted_mir = &self.mir.promoted[pr]; + self.sanitize_promoted(promoted_mir, location); + + let promoted_ty = promoted_mir.return_ty(); + + if let Err(terr) = self.cx.eq_types( + sty, + promoted_ty, + location.to_locations(), + ConstraintCategory::Boring, + ) { + span_mirbug!( + self, + place, + "bad promoted type ({:?}: {:?}): {:?}", + promoted_ty, + sty, + terr + ); + }; + } + PlaceTy::Ty { ty: sty } + } + None => { + 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 } + } } - PlaceTy::Ty { ty: sty } } Place::Projection(ref proj) => { let base_context = if context.is_mutating_use() { diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 9e0bb93c33a..42eb502b907 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -138,7 +138,6 @@ pub(super) fn is_active<'tcx>( /// This is called for all Yield statements on movable generators pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool { match place { - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Static(..)) => false, Place::Base(PlaceBase::Local(..)) => true, Place::Projection(box proj) => { diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index c05ee3cf65b..0bbd147d824 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -30,8 +30,6 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { locals_state_at_exit: &LocalsStateAtExit, ) -> bool { match self { - Place::Base(PlaceBase::Promoted(_)) => false, - // If a local variable is immutable, then we only need to track borrows to guard // against two kinds of errors: // * The variable being dropped while still borrowed (e.g., because the fn returns @@ -52,7 +50,12 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } } Place::Base(PlaceBase::Static(static_)) => { - tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) + match static_.promoted { + Some(_) => false, + None => { + tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) + } + } } Place::Projection(proj) => match proj.elem { ProjectionElem::Field(..) @@ -88,7 +91,6 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { loop { match p { Place::Projection(pi) => p = &pi.base, - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Static(_)) => return None, Place::Base(PlaceBase::Local(l)) => return Some(*l), } diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 1d18ada1fb6..7babdfcdd68 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -338,7 +338,6 @@ fn unroll_place<'tcx, R>( op, ), - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => { let list = PlaceComponents { component: place, @@ -371,41 +370,45 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( Overlap::Disjoint } } - (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => { - if static1.def_id != static2.def_id { - debug!("place_element_conflict: DISJOINT-STATIC"); - Overlap::Disjoint - } else if tcx.is_static(static1.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 - } - } - (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; + (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 + } + }, + (p1_, p2_) => { + debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-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::Static(_)), Place::Base(PlaceBase::Local(_))) => { debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED"); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 384fd5c9987..e70c9e81ebd 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -26,7 +26,6 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> { } match *cursor { - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => return false, Place::Projection(ref proj) => { @@ -87,7 +86,6 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { 'cursor: loop { let proj = match *cursor { - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Local(_)) | // search yielded this leaf Place::Base(PlaceBase::Static(_)) => { self.next = None; diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 20b95c363f5..83e1d3ebb3e 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -128,6 +128,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static { def_id: id, ty: expr.ty, + promoted: None, })))), ExprKind::PlaceTypeAscription { source, user_ty } => { diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index b9c8879b3c3..9d4600d13ac 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,7 +93,6 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> { fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> { match *place { Place::Base(PlaceBase::Local(l)) => Some(l), - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Static(..)) => None, Place::Projection(ref proj) => { match proj.elem { diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 7a9140bce62..71805fd02b8 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -97,7 +97,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { debug!("lookup({:?})", place); match *place { Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]), - Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => { Err(MoveError::cannot_move_out_of(self.loc, Static)) } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 97f84675f94..7eef68e5f80 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -286,7 +286,6 @@ impl<'tcx> MovePathLookup<'tcx> { pub fn find(&self, place: &Place<'tcx>) -> LookupResult { match *place { Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]), - Place::Base(PlaceBase::Promoted(_)) | Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None), Place::Projection(ref proj) => { match self.find(&proj.base) { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 755bbd96b02..62e2cdffadf 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -583,35 +583,38 @@ where use rustc::mir::Place::*; use rustc::mir::PlaceBase; Ok(match *mir_place { - Base(PlaceBase::Promoted(ref promoted)) => { - let instance = self.frame().instance; - self.const_eval_raw(GlobalId { - instance, - promoted: Some(promoted.0), - })? - } - Base(PlaceBase::Static(ref static_)) => { - assert!(!static_.ty.needs_subst()); - let layout = self.layout_of(static_.ty)?; - let instance = ty::Instance::mono(*self.tcx, static_.def_id); - let cid = GlobalId { - instance, - promoted: None - }; - // Just create a lazy reference, so we can support recursive statics. - // tcx takes are of assigning every static one and only one unique AllocId. - // When the data here is ever actually used, memory will notice, - // and it knows how to deal with alloc_id that are present in the - // global table but not in its local memory: It calls back into tcx through - // a query, triggering the CTFE machinery to actually turn this lazy reference - // into a bunch of bytes. IOW, statics are evaluated with CTFE even when - // this EvalContext uses another Machine (e.g., in miri). This is what we - // want! This way, computing statics works concistently between codegen - // and miri: They use the same query to eventually obtain a `ty::Const` - // and use that for further computation. - let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id()); - MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout) + match static_.promoted { + Some(promoted) => { + let instance = self.frame().instance; + self.const_eval_raw(GlobalId { + instance, + promoted: Some(promoted), + })? + } + None => { + assert!(!static_.ty.needs_subst()); + let layout = self.layout_of(static_.ty)?; + let instance = ty::Instance::mono(*self.tcx, static_.def_id); + let cid = GlobalId { + instance, + promoted: None + }; + // Just create a lazy reference, so we can support recursive statics. + // tcx takes are of assigning every static one and only one unique AllocId. + // When the data here is ever actually used, memory will notice, + // and it knows how to deal with alloc_id that are present in the + // global table but not in its local memory: It calls back into tcx through + // a query, triggering the CTFE machinery to actually turn this lazy reference + // into a bunch of bytes. IOW, statics are evaluated with CTFE even when + // this EvalContext uses another Machine (e.g., in miri). This is what we + // want! This way, computing statics works concistently between codegen + // and miri: They use the same query to eventually obtain a `ty::Const` + // and use that for further computation. + let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id()); + MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout) + } + } } _ => bug!("eval_place_to_mplace called on {:?}", mir_place), diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 20b75c55867..b13a5fd2fd1 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -22,7 +22,6 @@ fn is_stable<'tcx>( match *place { // Locals and statics have stable addresses, for sure Base(PlaceBase::Local { .. }) | - Base(PlaceBase::Promoted { .. }) | Base(PlaceBase::Static { .. }) => true, // Recurse for projections diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index b494592c89f..01cb58a481a 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -300,29 +300,33 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { &Place::Base(PlaceBase::Local(..)) => { // locals are safe } - &Place::Base(PlaceBase::Promoted(_)) => { - bug!("unsafety checking should happen before promotion") - } - &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => { - 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 \ - or data races will cause undefined behavior", - UnsafetyViolationKind::General); - } else if self.tcx.is_foreign_item(def_id) { - let source_info = self.source_info; - let lint_root = - self.source_scope_local_data[source_info.scope].lint_root; - self.register_violations(&[UnsafetyViolation { - source_info, - description: Symbol::intern("use of extern static").as_interned_str(), - details: - Symbol::intern("extern statics are not controlled by the Rust type \ - system: invalid data, aliasing violations or data \ - races will cause undefined behavior") - .as_interned_str(), - kind: UnsafetyViolationKind::ExternStatic(lint_root) - }], &[]); + &Place::Base(PlaceBase::Static(box Static { def_id, ty: _, promoted })) => { + match promoted { + Some(..) => { + bug!("unsafety checking should happen before promotion") + } + None => { + 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 \ + or data races will cause undefined behavior", + UnsafetyViolationKind::General); + } else if self.tcx.is_foreign_item(def_id) { + let source_info = self.source_info; + let lint_root = + self.source_scope_local_data[source_info.scope].lint_root; + self.register_violations(&[UnsafetyViolation { + source_info, + description: Symbol::intern("use of extern static").as_interned_str(), + details: + Symbol::intern("extern statics are not controlled by the Rust type \ + system: invalid data, aliasing violations or data \ + races will cause undefined behavior") + .as_interned_str(), + kind: UnsafetyViolationKind::ExternStatic(lint_root) + }], &[]); + } + } } } }; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d8169684420..bbe62fa2d7b 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -282,25 +282,31 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { // an `Index` projection would throw us off-track. _ => None, }, - Place::Base(PlaceBase::Promoted(ref promoted)) => { - let generics = self.tcx.generics_of(self.source.def_id()); - if generics.requires_monomorphization(self.tcx) { - // FIXME: can't handle code with generics - return None; + Place::Base(PlaceBase::Static(ref static_)) => { + match static_.promoted { + Some(promoted) => { + let generics = self.tcx.generics_of(self.source.def_id()); + if generics.requires_monomorphization(self.tcx) { + // FIXME: can't handle code with generics + return None; + } + let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); + let instance = Instance::new(self.source.def_id(), substs); + let cid = GlobalId { + instance, + promoted: Some(promoted), + }; + // 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 + let res = self.use_ecx(source_info, |this| { + eval_promoted(this.tcx, cid, this.mir, this.param_env) + })?; + trace!("evaluated promoted {:?} to {:?}", promoted, res); + Some((res.into(), source_info.span)) + } + None => None } - let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id()); - let instance = Instance::new(self.source.def_id(), substs); - let cid = GlobalId { - instance, - promoted: Some(promoted.0), - }; - // 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 - let res = self.use_ecx(source_info, |this| { - eval_promoted(this.tcx, cid, this.mir, this.param_env) - })?; - trace!("evaluated promoted {:?} to {:?}", promoted, res); - Some((res.into(), source_info.span)) + }, _ => None, } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 234483df13a..0b2a34d5fb9 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -692,12 +692,16 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { // Return pointer; update the place itself *place = self.destination.clone(); }, - Place::Base(PlaceBase::Promoted(ref mut promoted)) => { - if let Some(p) = self.promoted_map.get(promoted.0).cloned() { - promoted.0 = p; + Place::Base(PlaceBase::Static(ref mut static_)) => { + match static_.promoted { + Some(promoted) => { + if let Some(p) = self.promoted_map.get(promoted).cloned() { + static_.promoted = Some(p); + } + } + None => self.super_place(place, _ctxt, _location) } }, - _ => self.super_place(place, _ctxt, _location), } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index e96689809ad..f0ba1306c99 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -188,8 +188,12 @@ 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::Promoted(_)) => bug!("qualifying already promoted MIR"), - Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_), + Place::Base(PlaceBase::Static(ref static_)) => { + match static_.promoted { + Some(..) => bug!("qualifying already promoted MIR"), + None => Self::in_static(cx, static_), + } + }, Place::Projection(ref proj) => Self::in_projection(cx, proj), } } @@ -768,17 +772,20 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { ); dest = &proj.base; }, - Place::Base(PlaceBase::Promoted(..)) => - bug!("promoteds don't exist yet during promotion"), - Place::Base(PlaceBase::Static(..)) => { - // 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( - dest, - PlaceContext::MutatingUse(MutatingUseContext::Store), - location - ); - return; + Place::Base(PlaceBase::Static(st)) => { + match st.promoted { + Some(..) => bug!("promoteds don't exist yet during promotion"), + None => { + // 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( + dest, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); + return; + } + } } } }; @@ -919,51 +926,55 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location); self.super_place(place, context, location); match *place { - Place::Base(PlaceBase::Local(_)) | - Place::Base(PlaceBase::Promoted(_)) => {} + Place::Base(PlaceBase::Local(_)) => {} Place::Base(PlaceBase::Static(ref global)) => { - if self.tcx - .get_attrs(global.def_id) - .iter() - .any(|attr| attr.check_name("thread_local")) { - if self.mode != Mode::Fn { - span_err!(self.tcx.sess, self.span, E0625, - "thread-local statics cannot be \ - accessed at compile-time"); - } - return; - } + match global.promoted { + Some(..) => {} + None => { + if self.tcx + .get_attrs(global.def_id) + .iter() + .any(|attr| attr.check_name("thread_local")) { + if self.mode != Mode::Fn { + span_err!(self.tcx.sess, self.span, E0625, + "thread-local statics cannot be \ + accessed at compile-time"); + } + return; + } - // Only allow statics (not consts) to refer to other statics. - if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if self.mode == Mode::Static && context.is_mutating_use() { - // this is not strictly necessary as miri will also bail out - // For interior mutability we can't really catch this statically as that - // goes through raw pointers and intermediate temporaries, so miri has - // to catch this anyway - self.tcx.sess.span_err( - self.span, - "cannot mutate statics in the initializer of another static", - ); - } - return; - } - unleash_miri!(self); + // Only allow statics (not consts) to refer to other statics. + if self.mode == Mode::Static || self.mode == Mode::StaticMut { + if self.mode == Mode::Static && context.is_mutating_use() { + // this is not strictly necessary as miri will also bail out + // For interior mutability we can't really catch this statically as that + // goes through raw pointers and intermediate temporaries, so miri has + // to catch this anyway + self.tcx.sess.span_err( + self.span, + "cannot mutate statics in the initializer of another static", + ); + } + return; + } + unleash_miri!(self); - if self.mode != Mode::Fn { - let mut err = struct_span_err!(self.tcx.sess, self.span, E0013, - "{}s cannot refer to statics, use \ - a constant instead", self.mode); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "Static and const variables can refer to other const variables. But a \ - const variable cannot refer to a static variable." - ); - err.help( - "To fix this, the value can be extracted as a const and then used." - ); + if self.mode != Mode::Fn { + let mut err = struct_span_err!(self.tcx.sess, self.span, E0013, + "{}s cannot refer to statics, use \ + a constant instead", self.mode); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "Static and const variables can refer to other const variables. But a \ + const variable cannot refer to a static variable." + ); + err.help( + "To fix this, the value can be extracted as a const and then used." + ); + } + err.emit() + } } - err.emit() } } Place::Projection(ref proj) => { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index f82e536ab25..ea5bbaeb400 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -256,10 +256,13 @@ fn check_place( ) -> McfResult { match place { Place::Base(PlaceBase::Local(_)) => Ok(()), - // promoteds are always fine, they are essentially constants - Place::Base(PlaceBase::Promoted(_)) => Ok(()), - Place::Base(PlaceBase::Static(_)) => - Err((span, "cannot access `static` items in const fn".into())), + Place::Base(PlaceBase::Static(st)) => { + match st.promoted { + // promoteds are always fine, they are essentially constants + Some(..) => Ok(()), + None => Err((span, "cannot access `static` items in const fn".into())), + } + } Place::Projection(proj) => { match proj.elem { | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } |
