diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index ed2127cc755f..38ea536b4ee7 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -302,6 +302,9 @@ impl<'a, 'gcx> HashStable> for mir::Place<'gcx> { mir::Place::Static(ref statik) => { statik.hash_stable(hcx, hasher); } + mir::Place::Promoted(ref promoted) => { + promoted.hash_stable(hcx, hasher); + } mir::Place::Projection(ref place_projection) => { place_projection.hash_stable(hcx, hasher); } @@ -527,22 +530,6 @@ impl_stable_hash_for!(enum mir::NullOp { impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal }); -impl<'a, 'gcx> HashStable> for mir::Literal<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - mir::Literal::Value { ref value } => { - value.hash_stable(hcx, hasher); - } - mir::Literal::Promoted { index } => { - index.hash_stable(hcx, hasher); - } - } - } -} - impl_stable_hash_for!(struct mir::Location { block, statement_index }); impl_stable_hash_for!(struct mir::BorrowCheckResult<'tcx> { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 458c2f3885f9..f1f826486a5f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1701,6 +1701,9 @@ pub enum Place<'tcx> { /// static or static mut variable Static(Box>), + /// Constant code promoted to an injected static + Promoted(Box<(Promoted, Ty<'tcx>)>), + /// projection out of a place (access a field, deref a pointer, etc) Projection(Box>), } @@ -1810,6 +1813,7 @@ impl<'tcx> Debug for Place<'tcx> { ty::tls::with(|tcx| tcx.item_path_str(def_id)), ty ), + Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1), Projection(ref data) => match data.elem { ProjectionElem::Downcast(ref adt_def, index) => { write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name) @@ -1910,9 +1914,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(box Constant { span, ty, - literal: Literal::Value { - value: ty::Const::zero_sized(tcx, ty), - }, + literal: ty::Const::zero_sized(tcx, ty), }) } @@ -2200,38 +2202,15 @@ impl<'tcx> Debug for Rvalue<'tcx> { pub struct Constant<'tcx> { pub span: Span, pub ty: Ty<'tcx>, - pub literal: Literal<'tcx>, + pub literal: &'tcx ty::Const<'tcx>, } newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" }); -#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub enum Literal<'tcx> { - Value { - value: &'tcx ty::Const<'tcx>, - }, - Promoted { - // Index into the `promoted` vector of `Mir`. - index: Promoted, - }, -} - impl<'tcx> Debug for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{:?}", self.literal) - } -} - -impl<'tcx> Debug for Literal<'tcx> { - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - use self::Literal::*; - match *self { - Value { value } => { - write!(fmt, "const ")?; - fmt_const_val(fmt, value) - } - Promoted { index } => write!(fmt, "{:?}", index), - } + write!(fmt, "const ")?; + fmt_const_val(fmt, self.literal) } } @@ -2918,20 +2897,3 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { self.ty.visit_with(visitor) || self.literal.visit_with(visitor) } } - -impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - Literal::Value { value } => Literal::Value { - value: value.fold_with(folder), - }, - Literal::Promoted { index } => Literal::Promoted { index }, - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - Literal::Value { value } => value.visit_with(visitor), - Literal::Promoted { .. } => false, - } - } -} diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 0359eb9b95d1..b55843ac527d 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -113,6 +113,7 @@ impl<'tcx> Place<'tcx> { match *self { Place::Local(index) => PlaceTy::Ty { ty: local_decls.local_decls()[index].ty }, + Place::Promoted(ref data) => PlaceTy::Ty { ty: data.1 }, Place::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 758d887cd7b3..cab6ed0c122c 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -191,12 +191,6 @@ macro_rules! make_mir_visitor { self.super_constant(constant, location); } - fn visit_literal(&mut self, - literal: & $($mutability)* Literal<'tcx>, - location: Location) { - self.super_literal(literal, location); - } - fn visit_def_id(&mut self, def_id: & $($mutability)* DefId, _: Location) { @@ -648,6 +642,9 @@ macro_rules! make_mir_visitor { Place::Static(ref $($mutability)* static_) => { self.visit_static(static_, context, location); } + Place::Promoted(ref $($mutability)* promoted) => { + self.visit_ty(& $($mutability)* promoted.1, TyContext::Location(location)); + }, Place::Projection(ref $($mutability)* proj) => { self.visit_projection(proj, context, location); } @@ -748,18 +745,7 @@ macro_rules! make_mir_visitor { self.visit_span(span); self.visit_ty(ty, TyContext::Location(location)); - self.visit_literal(literal, location); - } - - fn super_literal(&mut self, - literal: & $($mutability)* Literal<'tcx>, - location: Location) { - match *literal { - Literal::Value { ref $($mutability)* value } => { - self.visit_const(value, location); - } - Literal::Promoted { index: _ } => {} - } + self.visit_const(literal, location); } fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 5c00947889df..5a2d95803842 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -242,9 +242,11 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { g } -pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - def_id: DefId, - is_mutable: bool) { +pub fn codegen_static<'a, 'tcx>( + cx: &CodegenCx<'a, 'tcx>, + def_id: DefId, + is_mutable: bool, +) { unsafe { let attrs = cx.tcx.codegen_fn_attrs(def_id); diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 14d20b6dbe29..dc4b9e0ae99d 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -507,14 +507,40 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // promotes any complex rvalues to constants. if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") { match *arg { + // The shuffle array argument is usually not an explicit constant, + // 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(mir::Place::Promoted(box(index, ty))) | + mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => { + let param_env = ty::ParamEnv::reveal_all(); + let cid = mir::interpret::GlobalId { + instance: self.instance, + promoted: Some(index), + }; + let c = bx.tcx().const_eval(param_env.and(cid)); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + terminator.source_info.span, + ty, + c, + ); + return OperandRef { + val: Immediate(llval), + layout: bx.cx.layout_of(ty), + }; + + }, mir::Operand::Copy(_) | mir::Operand::Move(_) => { span_bug!(span, "shuffle indices must be constant"); } mir::Operand::Constant(ref constant) => { + let c = self.eval_mir_constant(&bx, constant); let (llval, ty) = self.simd_shuffle_indices( &bx, - constant, + constant.span, + constant.ty, + c, ); return OperandRef { val: Immediate(llval), diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs index d7939bd2ab22..0d682d5d6f6a 100644 --- a/src/librustc_codegen_llvm/mir/constant.rs +++ b/src/librustc_codegen_llvm/mir/constant.rs @@ -25,6 +25,7 @@ use consts; use type_of::LayoutLlvmExt; use type_::Type; use syntax::ast::Mutability; +use syntax::codemap::Span; use super::super::callee; use super::FunctionCx; @@ -117,13 +118,12 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef { pub fn codegen_static_initializer<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, - def_id: DefId) - -> Result<(ValueRef, &'tcx Allocation), Lrc>> -{ + def_id: DefId, +) -> Result<(ValueRef, &'tcx Allocation), Lrc>> { let instance = ty::Instance::mono(cx.tcx, def_id); let cid = GlobalId { instance, - promoted: None + promoted: None, }; let param_env = ty::ParamEnv::reveal_all(); let static_ = cx.tcx.const_eval(param_env.and(cid))?; @@ -161,28 +161,19 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { bx: &Builder<'a, 'tcx>, constant: &mir::Constant<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Lrc>> { - match constant.literal { - mir::Literal::Promoted { index } => { - let param_env = ty::ParamEnv::reveal_all(); - let cid = mir::interpret::GlobalId { - instance: self.instance, - promoted: Some(index), - }; - bx.tcx().const_eval(param_env.and(cid)) - } - mir::Literal::Value { value } => { - Ok(self.monomorphize(&value)) - } - }.and_then(|c| self.fully_evaluate(bx, c)) + let c = self.monomorphize(&constant.literal); + self.fully_evaluate(bx, c) } /// process constant containing SIMD shuffle indices pub fn simd_shuffle_indices( &mut self, bx: &Builder<'a, 'tcx>, - constant: &mir::Constant<'tcx>, + span: Span, + ty: Ty<'tcx>, + constant: Result<&'tcx ty::Const<'tcx>, Lrc>>, ) -> (ValueRef, Ty<'tcx>) { - self.eval_mir_constant(bx, constant) + constant .and_then(|c| { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { @@ -217,11 +208,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { }) .unwrap_or_else(|e| { e.report_as_error( - bx.tcx().at(constant.span), + bx.tcx().at(span), "could not evaluate shuffle_indices at compile time", ); // We've errored, so we don't have to produce working code. - let ty = self.monomorphize(&constant.ty); + let ty = self.monomorphize(&ty); let llty = bx.cx.layout_of(ty).llvm_type(bx.cx); (C_undef(llty), ty) }) diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index 52234af08c1a..777054014dc4 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{ValueRef, LLVMConstInBoundsGEP}; +use llvm::ValueRef; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; use rustc::mir::interpret::ConstValue; @@ -22,14 +22,12 @@ use common::{CodegenCx, C_undef, C_usize}; use builder::{Builder, MemFlags}; use value::Value; use type_of::LayoutLlvmExt; -use type_::Type; -use consts; use std::fmt; use std::ptr; use super::{FunctionCx, LocalRef}; -use super::constant::{scalar_to_llvm, const_alloc_to_llvm}; +use super::constant::scalar_to_llvm; use super::place::PlaceRef; /// The representation of a Rust value. The enum variant is in fact @@ -139,16 +137,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { OperandValue::Pair(a_llval, b_llval) }, ConstValue::ByRef(alloc, offset) => { - let init = const_alloc_to_llvm(bx.cx, alloc); - let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str"); - - let llval = unsafe { LLVMConstInBoundsGEP( - consts::bitcast(base_addr, Type::i8p(bx.cx)), - &C_usize(bx.cx, offset.bytes()), - 1, - )}; - let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to()); - return Ok(PlaceRef::new_sized(llval, layout, alloc.align).load(bx)); + return Ok(PlaceRef::from_const_alloc(bx, layout, alloc, offset).load(bx)); }, }; @@ -409,20 +398,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { self.eval_mir_constant(bx, constant) .and_then(|c| OperandRef::from_const(bx, c)) .unwrap_or_else(|err| { - match constant.literal { - mir::Literal::Promoted { .. } => { - // this is unreachable as long as runtime - // and compile-time agree on values - // With floats that won't always be true - // so we generate an abort below - }, - mir::Literal::Value { .. } => { - err.report_as_error( - bx.tcx().at(constant.span), - "could not evaluate constant operand", - ); - }, - } + err.report_as_error( + bx.tcx().at(constant.span), + "could not evaluate constant operand", + ); + // Allow RalfJ to sleep soundly knowing that even refactorings that remove + // the above error (or silence it under some conditions) will not cause UB let fnname = bx.cx.get_intrinsic(&("llvm.trap")); bx.call(fnname, &[], None); // We've errored, so we don't have to produce working code. diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index e7f9457a6a1c..9abf9077a957 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm::{self, ValueRef, LLVMConstInBoundsGEP}; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size}; use rustc::mir; use rustc::mir::tcx::PlaceTy; use rustc_data_structures::indexed_vec::Idx; @@ -22,6 +22,7 @@ use type_of::LayoutLlvmExt; use type_::Type; use value::Value; use glue; +use mir::constant::const_alloc_to_llvm; use std::ptr; @@ -56,6 +57,24 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } } + pub fn from_const_alloc( + bx: &Builder<'a, 'tcx>, + layout: TyLayout<'tcx>, + alloc: &mir::interpret::Allocation, + offset: Size, + ) -> PlaceRef<'tcx> { + let init = const_alloc_to_llvm(bx.cx, alloc); + let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str"); + + let llval = unsafe { LLVMConstInBoundsGEP( + consts::bitcast(base_addr, Type::i8p(bx.cx)), + &C_usize(bx.cx, offset.bytes()), + 1, + )}; + let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to()); + PlaceRef::new_sized(llval, layout, alloc.align) + } + pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str) -> PlaceRef<'tcx> { debug!("alloca({:?}: {:?})", name, layout); @@ -421,6 +440,32 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let result = match *place { mir::Place::Local(_) => bug!(), // handled above + mir::Place::Promoted(box (index, ty)) => { + let param_env = ty::ParamEnv::reveal_all(); + let cid = mir::interpret::GlobalId { + instance: self.instance, + promoted: Some(index), + }; + let layout = cx.layout_of(self.monomorphize(&ty)); + match bx.tcx().const_eval(param_env.and(cid)) { + Ok(val) => match val.val { + mir::interpret::ConstValue::ByRef(alloc, offset) => { + PlaceRef::from_const_alloc(bx, layout, alloc, offset) + } + _ => bug!("promoteds should have an allocation: {:?}", val), + }, + Err(_) => { + // this is unreachable as long as runtime + // and compile-time agree on values + // With floats that won't always be true + // so we generate an abort + let fnname = bx.cx.get_intrinsic(&("llvm.trap")); + bx.call(fnname, &[], None); + let llval = C_undef(layout.llvm_type(bx.cx).ptr_to()); + PlaceRef::new_sized(llval, layout, layout.align) + } + } + } mir::Place::Static(box mir::Static { def_id, ty }) => { let layout = cx.layout_of(self.monomorphize(&ty)); PlaceRef::new_sized(consts::get_static(cx, def_id), layout, layout.align) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 5dca01f8842a..0d41757e70e5 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -717,6 +717,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { including_downcast: &IncludingDowncast, ) -> Result<(), ()> { match *place { + Place::Promoted(_) => { + buf.push_str("promoted"); + } Place::Local(local) => { self.append_local_to_string(local, buf)?; } @@ -859,6 +862,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[local]; self.describe_field_from_ty(&local.ty, field) } + Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field), Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field), Place::Projection(ref proj) => match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field), @@ -929,6 +933,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[*local]; Some(local.ty) } + Place::Promoted(ref prom) => Some(prom.1), Place::Static(ref st) => Some(st.ty), Place::Projection(ref proj) => match proj.elem { ProjectionElem::Field(_, ty) => Some(ty), diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 62bf2b0abe4c..89bbc42df049 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1221,6 +1221,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } Operand::Move(Place::Static(..)) | Operand::Copy(Place::Static(..)) + | Operand::Move(Place::Promoted(..)) + | Operand::Copy(Place::Promoted(..)) | Operand::Constant(..) => {} } } @@ -1303,6 +1305,7 @@ 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::Promoted(_) => (true, false), Place::Static(statik) => { // Thread-locals might be dropped after the function exits, but // "true" statics will never be. @@ -1587,6 +1590,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match *last_prefix { Place::Local(_) => panic!("should have move path for every Local"), Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"), + Place::Promoted(_) | Place::Static(_) => return Err(NoMovePathFound::ReachedStatic), } } @@ -1613,6 +1617,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut place = place; loop { match *place { + Place::Promoted(_) | Place::Local(_) | Place::Static(_) => { // assigning to `x` does not require `x` be initialized. break; @@ -1808,6 +1813,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.used_mut_upvars.push(field); } } + RootPlace { + place: Place::Promoted(..), + is_local_mutation_allowed: _, + } => {} RootPlace { place: Place::Static(..), is_local_mutation_allowed: _, @@ -1843,6 +1852,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }), } } + // promoteds may never be mutated + Place::Promoted(_) => bug!("encountered mutable promoted"), Place::Static(ref static_) => { if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { Err(place) @@ -2009,6 +2020,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut deepest = place; loop { let proj = match *cursor { + Place::Promoted(_) | Place::Local(..) | Place::Static(..) => return deepest, Place::Projection(ref proj) => proj, }; diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index b7ba5c855b99..7b9b99a7002c 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -247,6 +247,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { Place::Projection(ref proj) => { proj.base == Place::Local(Local::new(1)) } + Place::Promoted(_) | Place::Local(_) | Place::Static(_) => unreachable!(), } } => @@ -389,6 +390,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // overloaded * operator. local_decl.is_user_variable.is_some() && is_shared_ref(local_decl.ty) } + Place::Promoted(_) => true, Place::Static(ref st) => is_shared_ref(st.ty), Place::Projection(ref proj) => match proj.elem { ProjectionElem::Field(_, ty) => is_shared_ref(ty), diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 2a074a84e63e..0143d89d58bc 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -122,6 +122,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } + Place::Promoted(_) => unreachable!(), + Place::Static(box Static { def_id, ty: _ }) => { if let Place::Static(_) = access_place { item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); 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 e23f9b20a10f..945c48a58057 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -281,69 +281,48 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { constant, location ); - let expected_ty = match constant.literal { - Literal::Value { value } => { - // FIXME(#46702) -- We need some way to get the predicates - // associated with the "pre-evaluated" form of the - // constant. For example, consider that the constant - // may have associated constant projections (`>::SOME_CONST`) that impose - // constraints on `'a` and `'b`. These constraints - // would be lost if we just look at the normalized - // value. - if let ty::TyFnDef(def_id, substs) = value.ty.sty { - let tcx = self.tcx(); - let type_checker = &mut self.cx; - - // FIXME -- For now, use the substitutions from - // `value.ty` rather than `value.val`. The - // renumberer will rewrite them to independent - // sets of regions; in principle, we ought to - // derive the type of the `value.val` from "first - // principles" and equate with value.ty, but as we - // are transitioning to the miri-based system, we - // don't have a handy function for that, so for - // now we just ignore `value.val` regions. - - let instantiated_predicates = - tcx.predicates_of(def_id).instantiate(tcx, substs); - type_checker.normalize_and_prove_instantiated_predicates( - instantiated_predicates, - location.boring(), - ); - } - - value.ty - } - - Literal::Promoted { .. } => { - // FIXME -- promoted MIR return types reference - // various "free regions" (e.g., scopes and things) - // that they ought not to do. We have to figure out - // how best to handle that -- probably we want treat - // promoted MIR much like closures, renumbering all - // their free regions and propagating constraints - // upwards. We have the same acyclic guarantees, so - // that should be possible. But for now, ignore them. - // - // let promoted_mir = &self.mir.promoted[index]; - // promoted_mir.return_ty() - return; - } - }; + // FIXME(#46702) -- We need some way to get the predicates + // associated with the "pre-evaluated" form of the + // constant. For example, consider that the constant + // may have associated constant projections (`>::SOME_CONST`) that impose + // constraints on `'a` and `'b`. These constraints + // would be lost if we just look at the normalized + // value. + if let ty::TyFnDef(def_id, substs) = constant.literal.ty.sty { + let tcx = self.tcx(); + let type_checker = &mut self.cx; + + // FIXME -- For now, use the substitutions from + // `value.ty` rather than `value.val`. The + // renumberer will rewrite them to independent + // sets of regions; in principle, we ought to + // derive the type of the `value.val` from "first + // principles" and equate with value.ty, but as we + // are transitioning to the miri-based system, we + // don't have a handy function for that, so for + // now we just ignore `value.val` regions. + + let instantiated_predicates = + tcx.predicates_of(def_id).instantiate(tcx, substs); + type_checker.normalize_and_prove_instantiated_predicates( + instantiated_predicates, + location.boring(), + ); + } - debug!("sanitize_constant: expected_ty={:?}", expected_ty); + debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty); if let Err(terr) = self .cx - .eq_types(expected_ty, constant.ty, location.boring()) + .eq_types(constant.literal.ty, constant.ty, location.boring()) { span_mirbug!( self, constant, "constant {:?} should have type {:?} but has {:?} ({:?})", constant, - expected_ty, + constant.literal.ty, constant.ty, terr, ); @@ -363,6 +342,21 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { Place::Local(index) => PlaceTy::Ty { ty: self.mir.local_decls[index].ty, }, + Place::Promoted(box (_index, sty)) => { + let sty = self.sanitize_type(place, sty); + // FIXME -- promoted MIR return types reference + // various "free regions" (e.g., scopes and things) + // that they ought not to do. We have to figure out + // how best to handle that -- probably we want treat + // promoted MIR much like closures, renumbering all + // their free regions and propagating constraints + // upwards. We have the same acyclic guarantees, so + // that should be possible. But for now, ignore them. + // + // let promoted_mir = &self.mir.promoted[index]; + // promoted_mir.return_ty() + PlaceTy::Ty { ty: sty } + } Place::Static(box Static { def_id, ty: sty }) => { let sty = self.sanitize_type(place, sty); let ty = self.tcx().type_of(def_id); diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 499170acee31..70b4e0ea2f03 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -140,6 +140,7 @@ 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::Promoted(_) | Place::Static(..) => false, Place::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 f6ffe3c6d231..b0517c5e61f2 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -26,6 +26,7 @@ crate trait PlaceExt<'tcx> { impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool { match self { + Place::Promoted(_) | Place::Local(_) => false, Place::Static(static_) => { tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) @@ -52,6 +53,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { loop { match p { Place::Projection(pi) => p = &pi.base, + Place::Promoted(_) | Place::Static(_) => return None, Place::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 a9eec53fd94b..c44af0036547 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -282,6 +282,7 @@ fn unroll_place<'tcx, R>( op, ), + Place::Promoted(_) | Place::Local(_) | Place::Static(_) => { let list = PlaceComponents { component: place, @@ -326,8 +327,21 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( Overlap::EqualOrDisjoint } } + (Place::Promoted(p1), Place::Promoted(p2)) => { + if p1.0 == p2.0 { + // 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::Local(_), Place::Promoted(_)) | (Place::Promoted(_), Place::Local(_)) | + (Place::Promoted(_), Place::Static(_)) | (Place::Static(_), Place::Promoted(_)) | (Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => { - debug!("place_element_conflict: DISJOINT-STATIC-LOCAL"); + debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED"); Overlap::Disjoint } (Place::Projection(pi1), Place::Projection(pi2)) => { diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index dee78341265b..9b16130d25ec 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -36,6 +36,7 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> { } match *cursor { + Place::Promoted(_) | Place::Local(_) | Place::Static(_) => return false, Place::Projection(ref proj) => { cursor = &proj.base; @@ -98,6 +99,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { 'cursor: loop { let proj = match *cursor { + Place::Promoted(_) | Place::Local(_) | // search yielded this leaf Place::Static(_) => { self.next = None; diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 384eb1db04ff..68009e962a30 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -239,12 +239,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { operands.push(Operand::Constant(box Constant { span: expr_span, ty: this.hir.tcx().types.u32, - literal: Literal::Value { - value: ty::Const::from_bits( - this.hir.tcx(), - 0, - ty::ParamEnv::empty().and(this.hir.tcx().types.u32)), - }, + literal: ty::Const::from_bits( + this.hir.tcx(), + 0, + ty::ParamEnv::empty().and(this.hir.tcx().types.u32), + ), })); box AggregateKind::Generator(closure_id, substs, movability) } @@ -513,9 +512,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap()); let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); let n = (!0u128) >> (128 - bits); - let literal = Literal::Value { - value: ty::Const::from_bits(self.hir.tcx(), n, param_ty) - }; + let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); self.literal_operand(span, ty, literal) } @@ -526,9 +523,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap()); let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = Literal::Value { - value: ty::Const::from_bits(self.hir.tcx(), n, param_ty) - }; + let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); self.literal_operand(span, ty, literal) } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index d75b8d506e77..f1591535fa1a 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -505,8 +505,8 @@ enum TestKind<'tcx> { // test whether the value falls within an inclusive or exclusive range Range { - lo: Literal<'tcx>, - hi: Literal<'tcx>, + lo: &'tcx ty::Const<'tcx>, + hi: &'tcx ty::Const<'tcx>, ty: Ty<'tcx>, end: hir::RangeEnd, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index aa5727ee5c7e..e2b460f69fd7 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -74,8 +74,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Test { span: match_pair.pattern.span, kind: TestKind::Range { - lo: Literal::Value { value: lo }, - hi: Literal::Value { value: hi }, + lo, + hi, ty: match_pair.pattern.ty.clone(), end, }, @@ -260,9 +260,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { TestKind::Eq { value, mut ty } => { let mut val = Operand::Copy(place.clone()); - let mut expect = self.literal_operand(test.span, ty, Literal::Value { - value - }); + let mut expect = self.literal_operand(test.span, ty, value); // Use PartialEq::eq instead of BinOp::Eq // (the binop can only handle primitives) let fail = self.cfg.start_new_block(); @@ -300,9 +298,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let array = self.literal_operand( test.span, value.ty, - Literal::Value { - value - }, + value, ); let slice = self.temp(ty, test.span); diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 5907a0cff8e6..ae8070698c29 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -35,7 +35,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn literal_operand(&mut self, span: Span, ty: Ty<'tcx>, - literal: Literal<'tcx>) + literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, @@ -52,9 +52,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Returns a zero literal operand for the appropriate type, works for // bool, char and integers. pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = Literal::Value { - value: ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)) - }; + let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)); self.literal_operand(span, ty, literal) } diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index c7513ac88163..96f4c6b60f51 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -93,6 +93,7 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> { fn find_local<'tcx>(place: &Place<'tcx>) -> Option { match *place { Place::Local(l) => Some(l), + Place::Promoted(_) | Place::Static(..) => None, Place::Projection(ref proj) => { match proj.elem { diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 5bf54286875a..f379e0cf1e4f 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -259,6 +259,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // Issue #46746: Two-phase borrows handles // stmts of form `Tmp = &mut Borrow` ... match lhs { + Place::Promoted(_) | Place::Local(..) | Place::Static(..) => {} // okay Place::Projection(..) => { // ... can assign into projections, diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 48236e5fdd14..44e46e90549a 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -108,6 +108,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { debug!("lookup({:?})", place); match *place { Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]), + Place::Promoted(..) | Place::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 54609674a47d..64bfd36b7eeb 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -249,6 +249,7 @@ impl<'tcx> MovePathLookup<'tcx> { pub fn find(&self, place: &Place<'tcx>) -> LookupResult { match *place { Place::Local(local) => LookupResult::Exact(self.locals[local]), + Place::Promoted(_) | Place::Static(..) => LookupResult::Parent(None), Place::Projection(ref proj) => { match self.find(&proj.base) { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 13b2a0ab8741..b60da286d955 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -627,15 +627,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, None }; let source = if let Some((did, offset, ty)) = var { - let mk_const = |val| Expr { + let mk_const = |literal| Expr { temp_lifetime, ty, span: expr.span, - kind: ExprKind::Literal { - literal: Literal::Value { - value: val, - }, - }, + kind: ExprKind::Literal { literal }, }.to_ref(); let offset = mk_const(ty::Const::from_bits( cx.tcx, @@ -706,9 +702,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty, span: expr.span, kind: ExprKind::Literal { - literal: Literal::Value { - value: ty::Const::zero_sized(cx.tcx(), ty), - }, + literal: ty::Const::zero_sized(cx.tcx(), ty), }, } } @@ -760,22 +754,20 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Method(_) | Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => ExprKind::Literal { - literal: Literal::Value { - value: ty::Const::zero_sized( - cx.tcx, - cx.tables().node_id_to_type(expr.hir_id)), - }, + literal: ty::Const::zero_sized( + cx.tcx, + cx.tables().node_id_to_type(expr.hir_id), + ), }, Def::Const(def_id) | Def::AssociatedConst(def_id) => ExprKind::Literal { - literal: Literal::Value { - value: ty::Const::unevaluated( - cx.tcx, - def_id, - substs, - cx.tables().node_id_to_type(expr.hir_id)) - }, + literal: ty::Const::unevaluated( + cx.tcx, + def_id, + substs, + cx.tables().node_id_to_type(expr.hir_id), + ), }, Def::StructCtor(def_id, CtorKind::Const) | diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 167e031fbeec..4a7225c3a76d 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -112,10 +112,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx.types.usize } - pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> { - Literal::Value { - value: ty::Const::from_usize(self.tcx, value), - } + pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> { + ty::Const::from_usize(self.tcx, value) } pub fn bool_ty(&mut self) -> Ty<'tcx> { @@ -126,16 +124,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx.mk_nil() } - pub fn true_literal(&mut self) -> Literal<'tcx> { - Literal::Value { - value: ty::Const::from_bool(self.tcx, true), - } + pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> { + ty::Const::from_bool(self.tcx, true) } - pub fn false_literal(&mut self) -> Literal<'tcx> { - Literal::Value { - value: ty::Const::from_bool(self.tcx, false), - } + pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> { + ty::Const::from_bool(self.tcx, false) } // FIXME: Combine with rustc_mir::hair::pattern::lit_to_const @@ -145,7 +139,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, sp: Span, neg: bool, - ) -> Literal<'tcx> { + ) -> &'tcx ty::Const<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); let parse_float = |num, fty| -> ConstValue<'tcx> { @@ -209,9 +203,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { defined: 32, }), }; - Literal::Value { - value: ty::Const::from_const_value(self.tcx, lit, ty) - } + ty::Const::from_const_value(self.tcx, lit, ty) } pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> { @@ -231,17 +223,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { method_name: &str, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, Literal<'tcx>) { + -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { let method_name = Symbol::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, - Literal::Value { - value: ty::Const::zero_sized(self.tcx, method_ty) - }); + return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index a8d29df86908..c39aa9ca7806 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -14,11 +14,11 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp}; +use rustc::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::ty::subst::Substs; -use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty}; +use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; use rustc::hir; use syntax::ast; use syntax_pos::Span; @@ -271,7 +271,7 @@ pub enum ExprKind<'tcx> { movability: Option, }, Literal { - literal: Literal<'tcx>, + literal: &'tcx Const<'tcx>, }, InlineAsm { asm: &'tcx hir::InlineAsm, diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index e84132f27cc6..3c92f3f62358 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -178,7 +178,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>( let ptr = ptr.into(); // always try to read the value and report errors let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? { - Some(val) if is_static.is_none() => val, + Some(val) if is_static.is_none() && cid.promoted.is_none() => val, // point at the allocation _ => Value::ByRef(ptr, layout.align), }; @@ -561,7 +561,7 @@ pub fn const_eval_provider<'a, 'tcx>( let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env); res.and_then(|(mut val, _, miri_ty)| { - if tcx.is_static(def_id).is_none() { + if tcx.is_static(def_id).is_none() && cid.promoted.is_none() { val = ecx.try_read_by_ref(val, miri_ty)?; } Ok(value_to_const_value(&ecx, val, miri_ty)) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index fac6e8b69efa..10d3af85337e 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -831,19 +831,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M }, Constant(ref constant) => { - use rustc::mir::Literal; - let mir::Constant { ref literal, .. } = **constant; - let value = match *literal { - Literal::Value { ref value } => self.const_to_value(value.val)?, - - Literal::Promoted { index } => { - let instance = self.frame().instance; - self.read_global_as_value(GlobalId { - instance, - promoted: Some(index), - })? - } - }; + let value = self.const_to_value(constant.literal.val)?; Ok(ValTy { value, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index bb8e5c99d499..28373741c2f5 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -109,6 +109,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Local(local) => self.frame().get_local(local).map(Some), // No fast path for statics. Reading from statics is rare and would require another // Machine function to handle differently in miri. + Promoted(_) | Static(_) => Ok(None), Projection(ref proj) => self.try_read_place_projection(proj), } @@ -214,6 +215,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { local, }, + Promoted(ref promoted) => { + let instance = self.frame().instance; + let val = self.read_global_as_value(GlobalId { + instance, + promoted: Some(promoted.0), + })?; + if let Value::ByRef(ptr, align) = val { + Place::Ptr { + ptr, + align, + extra: PlaceExtra::None, + } + } else { + bug!("evaluated promoted and got {:#?}", val); + } + } + Static(ref static_) => { let layout = self.layout_of(self.place_ty(mir_place))?; let instance = ty::Instance::mono(*self.tcx, static_.def_id); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index c703486560dc..7bfbda8b786e 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -440,9 +440,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { let func = Operand::Constant(box Constant { span: self.span, ty: func_ty, - literal: Literal::Value { - value: ty::Const::zero_sized(self.tcx, func_ty) - }, + literal: ty::Const::zero_sized(self.tcx, func_ty), }); let ref_loc = self.make_place( @@ -500,9 +498,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { box Constant { span: self.span, ty: self.tcx.types.usize, - literal: Literal::Value { - value: ty::Const::from_usize(self.tcx, value), - } + literal: ty::Const::from_usize(self.tcx, value), } } @@ -729,9 +725,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (Operand::Constant(box Constant { span, ty, - literal: Literal::Value { - value: ty::Const::zero_sized(tcx, ty) - }, + literal: ty::Const::zero_sized(tcx, ty), }), vec![rcvr]) } diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs index 6ffd07915d24..4f7f45f173f7 100644 --- a/src/librustc_mir/transform/add_validation.rs +++ b/src/librustc_mir/transform/add_validation.rs @@ -34,6 +34,7 @@ fn place_context<'a, 'tcx, D>( match *place { Local { .. } => (None, hir::MutMutable), + Promoted(_) | Static(_) => (None, hir::MutImmutable), Projection(ref proj) => { match proj.elem { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index b4f0a7cd6c4b..ab7629eb6611 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -222,6 +222,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { &Place::Local(..) => { // locals are safe } + &Place::Promoted(_) => { + bug!("unsafety checking should happen before promotion") + } &Place::Static(box Static { def_id, ty: _ }) => { if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) { self.require_unsafe("use of mutable static", diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d15dd14084aa..94f96d46996d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -13,7 +13,7 @@ use rustc::hir::def::Def; -use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local}; +use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local}; use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind}; use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem}; use rustc::mir::visit::{Visitor, PlaceContext}; @@ -174,48 +174,22 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { c: &Constant<'tcx>, source_info: SourceInfo, ) -> Option> { - match c.literal { - Literal::Value { value } => { - self.ecx.tcx.span = source_info.span; - match self.ecx.const_to_value(value.val) { - Ok(val) => Some((val, value.ty, c.span)), - Err(error) => { - let (stacktrace, span) = self.ecx.generate_stacktrace(None); - let err = ConstEvalErr { - span, - error, - stacktrace, - }; - err.report_as_error( - self.tcx.at(source_info.span), - "could not evaluate constant", - ); - None - }, - } - }, - // evaluate the promoted and replace the constant with the evaluated result - Literal::Promoted { index } => { - 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 = Substs::identity_for_item(self.tcx, self.source.def_id); - let instance = Instance::new(self.source.def_id, substs); - let cid = GlobalId { - instance, - promoted: Some(index), + self.ecx.tcx.span = source_info.span; + match self.ecx.const_to_value(c.literal.val) { + Ok(val) => Some((val, c.literal.ty, c.span)), + Err(error) => { + let (stacktrace, span) = self.ecx.generate_stacktrace(None); + let err = ConstEvalErr { + span, + error, + stacktrace, }; - // 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 (value, _, ty) = self.use_ecx(source_info, |this| { - eval_promoted(&mut this.ecx, cid, this.mir, this.param_env) - })?; - let val = (value, ty, c.span); - trace!("evaluated {:?} to {:?}", c, val); - Some(val) - } + err.report_as_error( + self.tcx.at(source_info.span), + "could not evaluate constant", + ); + None + }, } } @@ -233,6 +207,27 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { }, _ => None, }, + Place::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; + } + let substs = Substs::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 (value, _, ty) = self.use_ecx(source_info, |this| { + eval_promoted(&mut this.ecx, cid, this.mir, this.param_env) + })?; + let val = (value, ty, source_info.span); + trace!("evaluated promoted {:?} to {:?}", promoted, val); + Some(val) + }, _ => None, } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 15b0c4a8bf75..d35608068a6a 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -530,9 +530,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, ty: self.tcx.types.bool, - literal: Literal::Value { - value: ty::Const::from_bool(self.tcx, val) - } + literal: ty::Const::from_bool(self.tcx, val), }))) } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a43f17e40dfb..97467e003850 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -177,12 +177,11 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { let val = Operand::Constant(box Constant { span: source_info.span, ty: self.tcx.types.u32, - literal: Literal::Value { - value: ty::Const::from_bits( - self.tcx, - state_disc.into(), - ty::ParamEnv::empty().and(self.tcx.types.u32)), - }, + literal: ty::Const::from_bits( + self.tcx, + state_disc.into(), + ty::ParamEnv::empty().and(self.tcx.types.u32) + ), }); Statement { source_info, @@ -337,6 +336,7 @@ struct BorrowedLocals(liveness::LiveVarSet); fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { Place::Local(l) => { locals.0.add(&l); }, + Place::Promoted(_) | Place::Static(..) => (), Place::Projection(ref proj) => { match proj.elem { @@ -707,9 +707,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cond: Operand::Constant(box Constant { span: mir.span, ty: tcx.types.bool, - literal: Literal::Value { - value: ty::Const::from_bool(tcx, false), - }, + literal: ty::Const::from_bool(tcx, false), }), expected: true, msg: message, diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index cb57dc572fa2..a0a5980d141d 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -662,11 +662,18 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { place: &mut Place<'tcx>, _ctxt: PlaceContext<'tcx>, _location: Location) { - if let Place::Local(RETURN_PLACE) = *place { - // Return pointer; update the place itself - *place = self.destination.clone(); - } else { - self.super_place(place, _ctxt, _location); + + match place { + Place::Local(RETURN_PLACE) => { + // Return pointer; update the place itself + *place = self.destination.clone(); + }, + Place::Promoted(ref mut promoted) => { + if let Some(p) = self.promoted_map.get(promoted.0).cloned() { + promoted.0 = p; + } + }, + _ => self.super_place(place, _ctxt, _location), } } @@ -749,14 +756,4 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { fn visit_source_scope(&mut self, scope: &mut SourceScope) { *scope = self.scope_map[*scope]; } - - fn visit_literal(&mut self, literal: &mut Literal<'tcx>, loc: Location) { - if let Literal::Promoted { ref mut index } = *literal { - if let Some(p) = self.promoted_map.get(*index).cloned() { - *index = p; - } - } else { - self.super_literal(literal, loc); - } - } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 8856d263864c..6e06beb30419 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -10,7 +10,7 @@ //! Performs various peephole optimizations. -use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local}; +use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local}; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::{TyCtxt, TypeVariants}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -103,8 +103,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> { if let TypeVariants::TyArray(_, len) = place_ty.sty { let span = self.mir.source_info(location).span; let ty = self.tcx.types.usize; - let literal = Literal::Value { value: len }; - let constant = Constant { span, ty, literal }; + let constant = Constant { span, ty, literal: len }; self.optimizations.arrays_lengths.insert(location, constant); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 8dc6539b65d6..1d1ef1a151aa 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -25,12 +25,12 @@ use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::TyCtxt; use syntax_pos::Span; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -use std::{cmp, iter, mem, usize}; +use std::{iter, mem, usize}; /// State of a temporary during collection and promotion. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -152,7 +152,6 @@ struct Promoter<'a, 'tcx: 'a> { source: &'a mut Mir<'tcx>, promoted: Mir<'tcx>, temps: &'a mut IndexVec, - extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>, /// If true, all nested temps are also kept in the /// source MIR, not moved to the promoted MIR. @@ -288,27 +287,21 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn promote_candidate(mut self, candidate: Candidate) { - let mut rvalue = { + let mut operand = { let promoted = &mut self.promoted; - let literal = Literal::Promoted { - index: Promoted::new(self.source.promoted.len()) - }; - let operand = |ty, span| { + 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); - Operand::Constant(box Constant { - span, - ty, - literal - }) + Place::Promoted(box (promoted_id, ty)) }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); match candidate { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(_, Rvalue::Ref(r, bk, ref mut place)) => { + StatementKind::Assign(_, Rvalue::Ref(_, _, ref mut place)) => { // Find the underlying local for this (necessarilly interior) borrow. // HACK(eddyb) using a recursive function because of mutable borrows. fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>) @@ -322,32 +315,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let place = interior_base(place); let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx); - let ref_ty = self.tcx.mk_ref(r, - ty::TypeAndMut { - ty, - mutbl: bk.to_mutbl_lossy() - } - ); let span = statement.source_info.span; - // Create a temp to hold the promoted reference. - // This is because `*r` requires `r` to be a local, - // otherwise we would use the `promoted` directly. - let mut promoted_ref = LocalDecl::new_temp(ref_ty, span); - promoted_ref.source_info = statement.source_info; - promoted_ref.visibility_scope = statement.source_info.scope; - let promoted_ref = local_decls.push(promoted_ref); - assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); - self.extra_statements.push((loc, Statement { - source_info: statement.source_info, - kind: StatementKind::Assign( - Place::Local(promoted_ref), - Rvalue::Use(operand(ref_ty, span)), - ) - })); - let promoted_place = Place::Local(promoted_ref).deref(); - - Rvalue::Ref(r, bk, mem::replace(place, promoted_place)) + Operand::Move(mem::replace(place, promoted_place(ty, span))) } _ => bug!() } @@ -358,7 +328,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); let span = terminator.source_info.span; - Rvalue::Use(mem::replace(&mut args[index], operand(ty, span))) + let operand = Operand::Copy(promoted_place(ty, span)); + mem::replace(&mut args[index], operand) } _ => bug!() } @@ -367,13 +338,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }; assert_eq!(self.new_block(), START_BLOCK); - self.visit_rvalue(&mut rvalue, Location { + self.visit_operand(&mut operand, Location { block: BasicBlock::new(0), statement_index: usize::MAX }); let span = self.promoted.span; - self.assign(RETURN_PLACE, rvalue, span); + self.assign(RETURN_PLACE, Rvalue::Use(operand), span); self.source.promoted.push(self.promoted); } } @@ -397,7 +368,6 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); - let mut extra_statements = vec![]; for candidate in candidates.into_iter().rev() { match candidate { Candidate::Ref(Location { block, statement_index }) => { @@ -437,19 +407,11 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, tcx, source: mir, temps: &mut temps, - extra_statements: &mut extra_statements, keep_original: false }; promoter.promote_candidate(candidate); } - // Insert each of `extra_statements` before its indicated location, which - // has to be done in reverse location order, to not invalidate the rest. - extra_statements.sort_by_key(|&(loc, _)| cmp::Reverse(loc)); - for (loc, statement) in extra_statements { - mir[loc.block].statements.insert(loc.statement_index, statement); - } - // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Local| temps[index] == TempState::PromotedOut; for block in mir.basic_blocks_mut() { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 986957d5a826..4e1129ea7e94 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -449,6 +449,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { location: Location) { match *place { Place::Local(ref local) => self.visit_local(local, context, location), + Place::Promoted(_) => bug!("promoting already promoted MIR"), Place::Static(ref global) => { if self.tcx .get_attrs(global.def_id) @@ -558,12 +559,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } Operand::Constant(ref constant) => { - if let Literal::Value { - value: &ty::Const { val: ConstValue::Unevaluated(def_id, _), ty, .. } - } = constant.literal { + if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { // Don't peek inside trait associated constants. if self.tcx.trait_of_item(def_id).is_some() { - self.add_type(ty); + self.add_type(constant.literal.ty); } else { let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(def_id); @@ -573,7 +572,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Just in case the type is more specific than // the definition, e.g. impl associated const // with type parameters, take it into account. - self.qualif.restrict(ty, self.tcx, self.param_env); + self.qualif.restrict(constant.literal.ty, self.tcx, self.param_env); } } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 2dbba897fa8a..e14941b8aeb9 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -36,11 +36,11 @@ impl MirPass for SimplifyBranches { for block in mir.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { - TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant { - literal: Literal::Value { ref value }, .. - }), switch_ty, ref values, ref targets, .. } => { + TerminatorKind::SwitchInt { + discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. + } => { let switch_ty = ParamEnv::empty().and(switch_ty); - if let Some(constint) = value.assert_bits(tcx, switch_ty) { + if let Some(constint) = c.literal.assert_bits(tcx, switch_ty) { let (otherwise, targets) = targets.split_last().unwrap(); let mut ret = TerminatorKind::Goto { target: *otherwise }; for (&v, t) in values.iter().zip(targets.iter()) { @@ -54,11 +54,9 @@ impl MirPass for SimplifyBranches { continue } }, - TerminatorKind::Assert { target, cond: Operand::Constant(box Constant { - literal: Literal::Value { - value - }, .. - }), expected, .. } if (value.assert_bool(tcx) == Some(true)) == expected => { + TerminatorKind::Assert { + target, cond: Operand::Constant(ref c), expected, .. + } if (c.literal.assert_bool(tcx) == Some(true)) == expected => { TerminatorKind::Goto { target: target } }, TerminatorKind::FalseEdges { real_target, .. } => { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f70a5ef57fe6..689eb62042bc 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -960,9 +960,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> Operand::Constant(box Constant { span: self.source_info.span, ty: self.tcx().types.usize, - literal: Literal::Value { - value: ty::Const::from_usize(self.tcx(), val.into()) - } + literal: ty::Const::from_usize(self.tcx(), val.into()), }) } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index b795685bb6fd..3206fa6e1726 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -13,7 +13,7 @@ // completely accurate (some things might be counted twice, others missed). use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData}; -use rustc::mir::{Constant, Literal, Location, Local, LocalDecl}; +use rustc::mir::{Constant, Location, Local, LocalDecl}; use rustc::mir::{Place, PlaceElem, PlaceProjection}; use rustc::mir::{Mir, Operand, ProjectionElem}; use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; @@ -204,6 +204,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.record(match *place { Place::Local(..) => "Place::Local", Place::Static(..) => "Place::Static", + Place::Promoted(..) => "Place::Promoted", Place::Projection(..) => "Place::Projection", }, place); self.super_place(place, context, location); @@ -240,17 +241,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.super_constant(constant, location); } - fn visit_literal(&mut self, - literal: &Literal<'tcx>, - location: Location) { - self.record("Literal", literal); - self.record(match *literal { - Literal::Value { .. } => "Literal::Value", - Literal::Promoted { .. } => "Literal::Promoted", - }, literal); - self.super_literal(literal, location); - } - fn visit_source_info(&mut self, source_info: &SourceInfo) { self.record("SourceInfo", source_info); diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs index fab2f9eff5af..8f8c406bcb3a 100644 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ b/src/test/mir-opt/end_region_destruction_extents_1.rs @@ -122,19 +122,15 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // let mut _6: &'10s S1; // let mut _7: &'10s S1; // let mut _8: S1; -// let mut _9: &'10s S1; -// let mut _10: &'12ds S1; // bb0: { // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); -// _10 = promoted[1]; -// _4 = &'12ds (*_10); +// _4 = &'12ds (promoted[1]: S1); // _3 = &'12ds (*_4); // StorageLive(_6); // StorageLive(_7); -// _9 = promoted[0]; -// _7 = &'10s (*_9); +// _7 = &'10s (promoted[0]: S1); // _6 = &'10s (*_7); // _2 = D1<'12ds, '10s>::{{constructor}}(move _3, move _6); // EndRegion('10s); diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 739cbc0a9967..43e711ca902f 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -54,8 +54,7 @@ fn main() { // ... // _2 = std::option::Option::Some(const 42i32,); // _3 = discriminant(_2); -// _14 = promoted[1]; -// _4 = &(*_14); +// _4 = &(promoted[1]: std::option::Option); // _9 = discriminant(_2); // switchInt(move _9) -> [0isize: bb5, 1isize: bb3, otherwise: bb7]; // } @@ -86,8 +85,7 @@ fn main() { // } // bb8: { // binding1 and guard // StorageLive(_7); -// _13 = promoted[0]; -// _7 = &(((*_13) as Some).0: i32); +// _7 = &(((promoted[0]: std::option::Option) as Some).0: i32); // StorageLive(_10); // _10 = const guard() -> [return: bb9, unwind: bb1]; // } diff --git a/src/test/ui/const-eval/conditional_array_execution.nll.stderr b/src/test/ui/const-eval/conditional_array_execution.nll.stderr index 3f82311d469a..86287e129972 100644 --- a/src/test/ui/const-eval/conditional_array_execution.nll.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.nll.stderr @@ -12,21 +12,6 @@ note: lint level defined here LL | #![warn(const_err)] | ^^^^^^^^^ -warning: referenced constant has errors - --> $DIR/conditional_array_execution.rs:19:20 - | -LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; - | ----- attempt to subtract with overflow -... -LL | println!("{}", FOO); - | ^^^ - -warning: this expression will panic at runtime - --> $DIR/conditional_array_execution.rs:19:20 - | -LL | println!("{}", FOO); - | ^^^ referenced constant has errors - error[E0080]: referenced constant has errors --> $DIR/conditional_array_execution.rs:19:14 | diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs index 99487eb49792..b3f56f27f635 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -17,8 +17,6 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; fn main() { println!("{}", FOO); - //~^ WARN this expression will panic at runtime - //~| WARN referenced constant - //~| ERROR erroneous constant used + //~^ ERROR erroneous constant used //~| E0080 } diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 649da03a5e7f..29f5f8e2ade5 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -12,21 +12,6 @@ note: lint level defined here LL | #![warn(const_err)] | ^^^^^^^^^ -warning: referenced constant has errors - --> $DIR/conditional_array_execution.rs:19:20 - | -LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; - | ----- attempt to subtract with overflow -... -LL | println!("{}", FOO); - | ^^^ - -warning: this expression will panic at runtime - --> $DIR/conditional_array_execution.rs:19:20 - | -LL | println!("{}", FOO); - | ^^^ referenced constant has errors - error[E0080]: referenced constant has errors --> $DIR/conditional_array_execution.rs:19:20 | diff --git a/src/test/ui/const-eval/issue-43197.nll.stderr b/src/test/ui/const-eval/issue-43197.nll.stderr index e25cb29c1147..732fe4598346 100644 --- a/src/test/ui/const-eval/issue-43197.nll.stderr +++ b/src/test/ui/const-eval/issue-43197.nll.stderr @@ -20,36 +20,6 @@ LL | const Y: u32 = foo(0-1); | | | attempt to subtract with overflow -warning: referenced constant has errors - --> $DIR/issue-43197.rs:24:23 - | -LL | const X: u32 = 0-1; - | --- attempt to subtract with overflow -... -LL | println!("{} {}", X, Y); - | ^ - -warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:24:23 - | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors - -warning: referenced constant has errors - --> $DIR/issue-43197.rs:24:26 - | -LL | const Y: u32 = foo(0-1); - | --- attempt to subtract with overflow -LL | //~^ WARN this constant cannot be used -LL | println!("{} {}", X, Y); - | ^ - -warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:24:26 - | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors - error[E0080]: referenced constant has errors --> $DIR/issue-43197.rs:24:14 | diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs index 9304af7b811c..c0b45f0ba304 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -22,12 +22,8 @@ fn main() { const Y: u32 = foo(0-1); //~^ WARN this constant cannot be used println!("{} {}", X, Y); - //~^ WARN this expression will panic at runtime - //~| WARN this expression will panic at runtime - //~| ERROR erroneous constant used + //~^ ERROR erroneous constant used //~| ERROR erroneous constant used //~| ERROR E0080 //~| ERROR E0080 - //~| WARN referenced constant - //~| WARN referenced constant } diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index bf864d81ea3c..66921dcd7c50 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -20,36 +20,6 @@ LL | const Y: u32 = foo(0-1); | | | attempt to subtract with overflow -warning: referenced constant has errors - --> $DIR/issue-43197.rs:24:23 - | -LL | const X: u32 = 0-1; - | --- attempt to subtract with overflow -... -LL | println!("{} {}", X, Y); - | ^ - -warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:24:23 - | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors - -warning: referenced constant has errors - --> $DIR/issue-43197.rs:24:26 - | -LL | const Y: u32 = foo(0-1); - | --- attempt to subtract with overflow -LL | //~^ WARN this constant cannot be used -LL | println!("{} {}", X, Y); - | ^ - -warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:24:26 - | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors - error[E0080]: referenced constant has errors --> $DIR/issue-43197.rs:24:26 | diff --git a/src/test/ui/const-eval/promoted_const_fn_fail.rs b/src/test/ui/const-eval/promoted_const_fn_fail.rs index 4888ed6e8dc7..f0f35ce614e6 100644 --- a/src/test/ui/const-eval/promoted_const_fn_fail.rs +++ b/src/test/ui/const-eval/promoted_const_fn_fail.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-pass + #![feature(const_fn)] #![deny(const_err)] @@ -23,15 +25,13 @@ const fn bar() -> u8 { // is run on a system whose pointers need more // than 8 bits Bar { a: &42 }.b as u8 - //~^ ERROR this expression will panic at runtime - //~| ERROR this expression will panic at runtime } } fn main() { - // FIXME(oli-obk): this should compile but panic at runtime - // if we change the `const_err` lint to allow this will actually compile, but then - // continue with undefined values. + // FIXME(oli-obk): this should panic at runtime + // this will actually compile, but then + // abort at runtime (not panic, hard abort). let x: &'static u8 = &(bar() + 1); let y = *x; unreachable!(); diff --git a/src/test/ui/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/const-eval/promoted_const_fn_fail.stderr deleted file mode 100644 index d805e1a27c99..000000000000 --- a/src/test/ui/const-eval/promoted_const_fn_fail.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: this expression will panic at runtime - --> $DIR/promoted_const_fn_fail.rs:25:9 - | -LL | Bar { a: &42 }.b as u8 - | ^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes - | -note: lint level defined here - --> $DIR/promoted_const_fn_fail.rs:13:9 - | -LL | #![deny(const_err)] - | ^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/promoted_const_fn_fail.rs:25:9 - | -LL | Bar { a: &42 }.b as u8 - | ^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/const-eval/promoted_errors.rs b/src/test/ui/const-eval/promoted_errors.rs index 04e9bfbc03e2..a58c4be66c42 100644 --- a/src/test/ui/const-eval/promoted_errors.rs +++ b/src/test/ui/const-eval/promoted_errors.rs @@ -18,13 +18,11 @@ fn main() { //~^ WARN const_err println!("{}", 1/(1-1)); //~^ WARN const_err - //~| WARN const_err let _x = 1/(1-1); //~^ WARN const_err //~| WARN const_err println!("{}", 1/(false as u32)); //~^ WARN const_err - //~| WARN const_err let _x = 1/(false as u32); //~^ WARN const_err //~| WARN const_err diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr index 9afe5f20af39..85b5696be947 100644 --- a/src/test/ui/const-eval/promoted_errors.stderr +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -16,44 +16,32 @@ warning: attempt to divide by zero LL | println!("{}", 1/(1-1)); | ^^^^^^^ -warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:19:20 - | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero - warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:22:14 + --> $DIR/promoted_errors.rs:21:14 | LL | let _x = 1/(1-1); | ^^^^^^^ warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:22:14 + --> $DIR/promoted_errors.rs:21:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:25:20 + --> $DIR/promoted_errors.rs:24:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ -warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:25:20 - | -LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:28:14 + --> $DIR/promoted_errors.rs:26:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:28:14 + --> $DIR/promoted_errors.rs:26:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero