diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8424c096e88c..22c0f0e5c394 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -35,6 +35,7 @@ use crate::ty::{ UserTypeAnnotationIndex, }; use crate::ty::print::{FmtPrinter, Printer}; +use crate::ty::adjustment::{PointerCast}; pub use crate::mir::interpret::AssertMessage; @@ -2248,29 +2249,11 @@ pub enum Rvalue<'tcx> { Aggregate(Box>, Vec>), } + #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub enum CastKind { Misc, - - /// Converts unique, zero-sized type for a fn to fn() - ReifyFnPointer, - - /// Converts non capturing closure to fn() or unsafe fn(). - /// It cannot convert a closure that requires unsafe. - ClosureFnPointer(hir::Unsafety), - - /// Converts safe fn() to unsafe fn() - UnsafeFnPointer, - - /// Coerces *mut T to *const T, preserving T. - MutToConstPointer, - - /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer. - /// codegen must figure out the details once full monomorphization - /// is known. For example, this could be used to cast from a - /// `&[i32;N]` to a `&[i32]`, or a `Box` to a `Box` - /// (presuming `T: Trait`). - Unsize, + Pointer(PointerCast), } #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index c2ef08c4c40f..7b81f7c69790 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -5,6 +5,15 @@ use crate::ty::subst::SubstsRef; use rustc_macros::HashStable; +#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] +pub enum PointerCast { + ReifyFnPointer, + UnsafeFnPointer, + ClosureFnPointer(hir::Unsafety), + MutToConstPointer, + Unsize, +} + /// Represents coercing a value to a different type of value. /// /// We transform values by following a number of `Adjust` steps in order. diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 53640284a2ca..35e9d918aa6f 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -1,4 +1,4 @@ -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Ty, adjustment::{PointerCast}}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::mir; @@ -37,7 +37,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx } - mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, _) => { + mir::Rvalue::Cast(mir::CastKind::Pointer(PointerCast::Unsize), ref source, _) => { // The destination necessarily contains a fat pointer, so if // it's a scalar pair, it's a fat pointer or newtype thereof. if bx.cx().is_backend_scalar_pair(dest.layout) { @@ -178,7 +178,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cast = bx.cx().layout_of(self.monomorphize(&mir_cast_ty)); let val = match *kind { - mir::CastKind::ReifyFnPointer => { + mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => { match operand.layout.ty.sty { ty::FnDef(def_id, substs) => { if bx.cx().tcx().has_attr(def_id, "rustc_args_required_const") { @@ -193,7 +193,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } - mir::CastKind::ClosureFnPointer(_) => { + mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)) => { match operand.layout.ty.sty { ty::Closure(def_id, substs) => { let instance = monomorphize::resolve_closure( @@ -205,11 +205,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } - mir::CastKind::UnsafeFnPointer => { + mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => { // this is a no-op at the LLVM level operand.val } - mir::CastKind::Unsize => { + mir::CastKind::Pointer(PointerCast::Unsize) => { assert!(bx.cx().is_backend_scalar_pair(cast)); match operand.val { OperandValue::Pair(lldata, llextra) => { @@ -236,7 +236,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } - mir::CastKind::MutToConstPointer + mir::CastKind::Pointer(PointerCast::MutToConstPointer) | mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => { if let OperandValue::Pair(data_ptr, meta) = operand.val { if bx.cx().is_backend_scalar_pair(cast) { @@ -254,7 +254,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("Unexpected non-Pair operand") } } - mir::CastKind::MutToConstPointer + mir::CastKind::Pointer(PointerCast::MutToConstPointer) | mir::CastKind::Misc => { assert!(bx.cx().is_backend_immediate(cast)); let ll_t_out = bx.cx().immediate_backend_type(cast); diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index e30938bc3265..5ad54080c5a6 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -10,6 +10,7 @@ use rustc::mir::{ Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc::ty::{self, TyCtxt}; +use rustc::ty::adjustment::{PointerCast}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; @@ -580,7 +581,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }, // If we see a unsized cast, then if it is our data we should check // whether it is being cast to a trait object. - Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand { + Rvalue::Cast( + CastKind::Pointer(PointerCast::Unsize), operand, ty + ) => match operand { Operand::Copy(Place::Base(PlaceBase::Local(from))) | Operand::Move(Place::Base(PlaceBase::Local(from))) if *from == target => 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 ec5637d17072..d123f3e40593 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -36,6 +36,7 @@ use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; +use rustc::ty::adjustment::{PointerCast}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts}; use rustc::ty::{ @@ -1972,7 +1973,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { Rvalue::Cast(cast_kind, op, ty) => { match cast_kind { - CastKind::ReifyFnPointer => { + CastKind::Pointer(PointerCast::ReifyFnPointer) => { let fn_sig = op.ty(mir, tcx).fn_sig(tcx); // The type that we see in the fcx is like @@ -2001,7 +2002,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - CastKind::ClosureFnPointer(unsafety) => { + CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { let sig = match op.ty(mir, tcx).sty { ty::Closure(def_id, substs) => { substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) @@ -2027,7 +2028,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - CastKind::UnsafeFnPointer => { + CastKind::Pointer(PointerCast::UnsafeFnPointer) => { let fn_sig = op.ty(mir, tcx).fn_sig(tcx); // The type that we see in the fcx is like @@ -2056,7 +2057,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - CastKind::Unsize => { + CastKind::Pointer(PointerCast::Unsize) => { let &ty = ty; let trait_ref = ty::TraitRef { def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), @@ -2070,7 +2071,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } - CastKind::MutToConstPointer => { + CastKind::Pointer(PointerCast::MutToConstPointer) => { let ty_from = match op.ty(mir, tcx).sty { ty::RawPtr(ty::TypeAndMut { ty: ty_from, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7289dd96edb8..565524247174 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -10,6 +10,7 @@ use rustc::middle::region; use rustc::mir::interpret::InterpError; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts}; +use rustc::ty::adjustment::{PointerCast}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { @@ -156,23 +157,33 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } ExprKind::ReifyFnPointer { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty)) + block.and(Rvalue::Cast( + CastKind::Pointer(PointerCast::ReifyFnPointer), source, expr.ty) + ) } ExprKind::UnsafeFnPointer { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::UnsafeFnPointer, source, expr.ty)) + block.and(Rvalue::Cast( + CastKind::Pointer(PointerCast::UnsafeFnPointer), source, expr.ty) + ) } ExprKind::ClosureFnPointer { source, unsafety } => { let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::ClosureFnPointer(unsafety), source, expr.ty)) + block.and(Rvalue::Cast( + CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)), source, expr.ty) + ) } ExprKind::MutToConstPointer { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::MutToConstPointer, source, expr.ty)) + block.and(Rvalue::Cast( + CastKind::Pointer(PointerCast::MutToConstPointer), source, expr.ty) + ) } ExprKind::Unsize { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty)) + block.and(Rvalue::Cast( + CastKind::Pointer(PointerCast::Unsize), source, expr.ty) + ) } ExprKind::Array { fields } => { // (*) We would (maybe) be closer to codegen if we diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index b06022196106..1eaf3d7ba998 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -11,7 +11,7 @@ use crate::hair::*; use crate::hair::pattern::compare_const_vals; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Ty, adjustment::{PointerCast}}; use rustc::ty::util::IntTypeExt; use rustc::ty::layout::VariantIdx; use rustc::mir::*; @@ -280,8 +280,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ty = tcx.mk_imm_ref(region, tcx.mk_slice(elem_ty)); if opt_ref_ty.is_some() { place = self.temp(ty, test.span); - self.cfg.push_assign(block, source_info, &place, - Rvalue::Cast(CastKind::Unsize, val, ty)); + self.cfg.push_assign( + block, source_info, &place, Rvalue::Cast( + CastKind::Pointer(PointerCast::Unsize), val, ty + ) + ); } if opt_ref_test_ty.is_some() { let array = self.literal_operand( @@ -291,8 +294,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let slice = self.temp(ty, test.span); - self.cfg.push_assign(block, source_info, &slice, - Rvalue::Cast(CastKind::Unsize, array, ty)); + self.cfg.push_assign( + block, source_info, &slice, Rvalue::Cast( + CastKind::Pointer(PointerCast::Unsize), array, ty + ) + ); expect = Operand::Move(slice); } }, diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 5056d79bec4b..32f218d49cea 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,5 +1,6 @@ use rustc::ty::{self, Ty, TypeAndMut}; use rustc::ty::layout::{self, TyLayout, Size}; +use rustc::ty::adjustment::{PointerCast}; use syntax::ast::{FloatTy, IntTy, UintTy}; use rustc_apfloat::ieee::{Single, Double}; @@ -29,11 +30,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ) -> EvalResult<'tcx> { use rustc::mir::CastKind::*; match kind { - Unsize => { + Pointer(PointerCast::Unsize) => { self.unsize_into(src, dest)?; } - Misc | MutToConstPointer => { + Misc | Pointer(PointerCast::MutToConstPointer) => { let src = self.read_immediate(src)?; if self.type_is_fat_ptr(src.layout.ty) { @@ -72,7 +73,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> } } - ReifyFnPointer => { + Pointer(PointerCast::ReifyFnPointer) => { // The src operand does not matter, just its type match src.layout.ty.sty { ty::FnDef(def_id, substs) => { @@ -93,7 +94,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> } } - UnsafeFnPointer => { + Pointer(PointerCast::UnsafeFnPointer) => { let src = self.read_immediate(src)?; match dest.layout.ty.sty { ty::FnPtr(_) => { @@ -104,7 +105,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> } } - ClosureFnPointer(_) => { + Pointer(PointerCast::ClosureFnPointer(_)) => { // The src operand does not matter, just its type match src.layout.ty.sty { ty::Closure(def_id, substs) => { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index af875c2f9e8a..2f4b3fa6ca8f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -182,7 +182,7 @@ use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; -use rustc::ty::adjustment::CustomCoerceUnsized; +use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; @@ -529,7 +529,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // When doing an cast from a regular pointer to a fat pointer, we // have to instantiate all methods of the trait being cast to, so we // can build the appropriate vtable. - mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, target_ty) => { + mir::Rvalue::Cast( + mir::CastKind::Pointer(PointerCast::Unsize), ref operand, target_ty + ) => { let target_ty = self.tcx.subst_and_normalize_erasing_regions( self.param_substs, ty::ParamEnv::reveal_all(), @@ -554,7 +556,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output); } } - mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => { + mir::Rvalue::Cast( + mir::CastKind::Pointer(PointerCast::ReifyFnPointer), ref operand, _ + ) => { let fn_ty = operand.ty(self.mir, self.tcx); let fn_ty = self.tcx.subst_and_normalize_erasing_regions( self.param_substs, @@ -563,7 +567,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { ); visit_fn_use(self.tcx, fn_ty, false, &mut self.output); } - mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer(_), ref operand, _) => { + mir::Rvalue::Cast( + mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)), ref operand, _ + ) => { let source_ty = operand.ty(self.mir, self.tcx); let source_ty = self.tcx.subst_and_normalize_erasing_regions( self.param_substs, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1faa9ad0d0da..111f54439962 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -12,7 +12,7 @@ use rustc_target::spec::abi::Abi; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::traits::{self, TraitEngine}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; +use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, adjustment::{PointerCast}}; use rustc::ty::cast::CastTy; use rustc::ty::query::Providers; use rustc::mir::*; @@ -1106,11 +1106,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { Rvalue::UnaryOp(UnOp::Not, _) | Rvalue::NullaryOp(NullOp::SizeOf, _) | Rvalue::CheckedBinaryOp(..) | - Rvalue::Cast(CastKind::ReifyFnPointer, ..) | - Rvalue::Cast(CastKind::UnsafeFnPointer, ..) | - Rvalue::Cast(CastKind::ClosureFnPointer(_), ..) | - Rvalue::Cast(CastKind::Unsize, ..) | - Rvalue::Cast(CastKind::MutToConstPointer, ..) | + Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), ..) | + Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), ..) | + Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), ..) | + Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), ..) | + Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), ..) | Rvalue::Discriminant(..) | Rvalue::Len(_) | Rvalue::Ref(..) | diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 87459571b529..201dac1524e4 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -1,7 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::mir::*; -use rustc::ty::{self, Predicate, TyCtxt}; +use rustc::ty::{self, Predicate, TyCtxt, adjustment::{PointerCast}}; use rustc_target::spec::abi; use std::borrow::Cow; use syntax_pos::Span; @@ -152,16 +152,16 @@ fn check_rvalue( _ => check_operand(tcx, mir, operand, span), } } - Rvalue::Cast(CastKind::MutToConstPointer, operand, _) => { + Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => { check_operand(tcx, mir, operand, span) } - Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) | - Rvalue::Cast(CastKind::ClosureFnPointer(_), _, _) | - Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err(( + Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) | + Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), _, _) | + Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), _, _) => Err(( span, "function pointer casts are not allowed in const fn".into(), )), - Rvalue::Cast(CastKind::Unsize, _, _) => Err(( + Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => Err(( span, "unsizing casts are not allowed in const fn".into(), )),