From: Oliver Schneider Date: Wed, 18 Jul 2018 09:39:17 +0000 (+0200) Subject: Move the const casting code into its dedicated file X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=1f4e21028d34c0aeccc4c7b21e0d9ce044c5646c;p=rust.git Move the const casting code into its dedicated file --- diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index e69e7a522ab..7bcf4ef6588 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,13 +1,153 @@ -use rustc::ty::Ty; -use rustc::ty::layout::LayoutOf; +use rustc::ty::{self, Ty}; +use rustc::ty::layout::{self, LayoutOf}; use syntax::ast::{FloatTy, IntTy, UintTy}; use rustc_apfloat::ieee::{Single, Double}; use super::{EvalContext, Machine}; -use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic}; +use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic, Value, EvalErrorKind}; +use rustc::mir::CastKind; use rustc_apfloat::Float; +use interpret::eval_context::ValTy; +use interpret::Place; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { + crate fn cast( + &mut self, + src: ValTy<'tcx>, + kind: CastKind, + dest_ty: Ty<'tcx>, + dest: Place, + ) -> EvalResult<'tcx> { + use rustc::mir::CastKind::*; + match kind { + Unsize => { + let src_layout = self.layout_of(src.ty)?; + let dst_layout = self.layout_of(dest_ty)?; + self.unsize_into(src.value, src_layout, dest, dst_layout)?; + } + + Misc => { + if self.type_is_fat_ptr(src.ty) { + match (src.value, self.type_is_fat_ptr(dest_ty)) { + (Value::ByRef { .. }, _) | + // pointers to extern types + (Value::Scalar(_),_) | + // slices and trait objects to other slices/trait objects + (Value::ScalarPair(..), true) => { + let valty = ValTy { + value: src.value, + ty: dest_ty, + }; + self.write_value(valty, dest)?; + } + // slices and trait objects to thin pointers (dropping the metadata) + (Value::ScalarPair(data, _), false) => { + let valty = ValTy { + value: Value::Scalar(data), + ty: dest_ty, + }; + self.write_value(valty, dest)?; + } + } + } else { + let src_layout = self.layout_of(src.ty)?; + match src_layout.variants { + layout::Variants::Single { index } => { + if let Some(def) = src.ty.ty_adt_def() { + let discr_val = def + .discriminant_for_variant(*self.tcx, index) + .val; + let defined = self + .layout_of(dest_ty) + .unwrap() + .size + .bits() as u8; + return self.write_scalar( + dest, + Scalar::Bits { + bits: discr_val, + defined, + }, + dest_ty); + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } + + let src_val = self.value_to_scalar(src)?; + let dest_val = self.cast_scalar(src_val, src.ty, dest_ty)?; + let valty = ValTy { + value: Value::Scalar(dest_val), + ty: dest_ty, + }; + self.write_value(valty, dest)?; + } + } + + ReifyFnPointer => { + match src.ty.sty { + ty::TyFnDef(def_id, substs) => { + if self.tcx.has_attr(def_id, "rustc_args_required_const") { + bug!("reifying a fn ptr that requires \ + const arguments"); + } + let instance: EvalResult<'tcx, _> = ty::Instance::resolve( + *self.tcx, + self.param_env, + def_id, + substs, + ).ok_or_else(|| EvalErrorKind::TooGeneric.into()); + let fn_ptr = self.memory.create_fn_alloc(instance?); + let valty = ValTy { + value: Value::Scalar(fn_ptr.into()), + ty: dest_ty, + }; + self.write_value(valty, dest)?; + } + ref other => bug!("reify fn pointer on {:?}", other), + } + } + + UnsafeFnPointer => { + match dest_ty.sty { + ty::TyFnPtr(_) => { + let mut src = src; + src.ty = dest_ty; + self.write_value(src, dest)?; + } + ref other => bug!("fn to unsafe fn cast on {:?}", other), + } + } + + ClosureFnPointer => { + match src.ty.sty { + ty::TyClosure(def_id, substs) => { + let substs = self.tcx.subst_and_normalize_erasing_regions( + self.substs(), + ty::ParamEnv::reveal_all(), + &substs, + ); + let instance = ty::Instance::resolve_closure( + *self.tcx, + def_id, + substs, + ty::ClosureKind::FnOnce, + ); + let fn_ptr = self.memory.create_fn_alloc(instance); + let valty = ValTy { + value: Value::Scalar(fn_ptr.into()), + ty: dest_ty, + }; + self.write_value(valty, dest)?; + } + ref other => bug!("closure fn pointer on {:?}", other), + } + } + } + Ok(()) + } + pub(super) fn cast_scalar( &self, val: Scalar, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 96d0563c12d..fac6e8b69ef 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -770,134 +770,8 @@ pub(super) fn eval_rvalue_into_place( Cast(kind, ref operand, cast_ty) => { debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest_ty); - use rustc::mir::CastKind::*; let src = self.eval_operand(operand)?; - match kind { - Unsize => { - let src_layout = self.layout_of(src.ty)?; - let dst_layout = self.layout_of(dest_ty)?; - self.unsize_into(src.value, src_layout, dest, dst_layout)?; - } - - Misc => { - if self.type_is_fat_ptr(src.ty) { - match (src.value, self.type_is_fat_ptr(dest_ty)) { - (Value::ByRef { .. }, _) | - // pointers to extern types - (Value::Scalar(_),_) | - // slices and trait objects to other slices/trait objects - (Value::ScalarPair(..), true) => { - let valty = ValTy { - value: src.value, - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - // slices and trait objects to thin pointers (dropping the metadata) - (Value::ScalarPair(data, _), false) => { - let valty = ValTy { - value: Value::Scalar(data), - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - } - } else { - let src_layout = self.layout_of(src.ty)?; - match src_layout.variants { - layout::Variants::Single { index } => { - if let Some(def) = src.ty.ty_adt_def() { - let discr_val = def - .discriminant_for_variant(*self.tcx, index) - .val; - let defined = self - .layout_of(dest_ty) - .unwrap() - .size - .bits() as u8; - return self.write_scalar( - dest, - Scalar::Bits { - bits: discr_val, - defined, - }, - dest_ty); - } - } - layout::Variants::Tagged { .. } | - layout::Variants::NicheFilling { .. } => {}, - } - - let src_val = self.value_to_scalar(src)?; - let dest_val = self.cast_scalar(src_val, src.ty, dest_ty)?; - let valty = ValTy { - value: Value::Scalar(dest_val), - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - } - - ReifyFnPointer => { - match src.ty.sty { - ty::TyFnDef(def_id, substs) => { - if self.tcx.has_attr(def_id, "rustc_args_required_const") { - bug!("reifying a fn ptr that requires \ - const arguments"); - } - let instance: EvalResult<'tcx, _> = ty::Instance::resolve( - *self.tcx, - self.param_env, - def_id, - substs, - ).ok_or_else(|| EvalErrorKind::TooGeneric.into()); - let fn_ptr = self.memory.create_fn_alloc(instance?); - let valty = ValTy { - value: Value::Scalar(fn_ptr.into()), - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - ref other => bug!("reify fn pointer on {:?}", other), - } - } - - UnsafeFnPointer => { - match dest_ty.sty { - ty::TyFnPtr(_) => { - let mut src = src; - src.ty = dest_ty; - self.write_value(src, dest)?; - } - ref other => bug!("fn to unsafe fn cast on {:?}", other), - } - } - - ClosureFnPointer => { - match src.ty.sty { - ty::TyClosure(def_id, substs) => { - let substs = self.tcx.subst_and_normalize_erasing_regions( - self.substs(), - ty::ParamEnv::reveal_all(), - &substs, - ); - let instance = ty::Instance::resolve_closure( - *self.tcx, - def_id, - substs, - ty::ClosureKind::FnOnce, - ); - let fn_ptr = self.memory.create_fn_alloc(instance); - let valty = ValTy { - value: Value::Scalar(fn_ptr.into()), - ty: dest_ty, - }; - self.write_value(valty, dest)?; - } - ref other => bug!("closure fn pointer on {:?}", other), - } - } - } + self.cast(src, kind, dest_ty, dest)?; } Discriminant(ref place) => { @@ -1564,7 +1438,7 @@ fn unsize_into_ptr( } } - fn unsize_into( + crate fn unsize_into( &mut self, src: Value, src_layout: TyLayout<'tcx>,