Skip to content

Commit b318bcf

Browse files
committed
refactor cast_immediate to dispatch on the type first, and on the value second
1 parent ec1e718 commit b318bcf

File tree

1 file changed

+46
-64
lines changed

1 file changed

+46
-64
lines changed

src/librustc_mir/interpret/cast.rs

Lines changed: 46 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,6 @@ use rustc::mir::CastKind;
1414
use super::{InterpCx, Machine, PlaceTy, OpTy, ImmTy, Immediate, FnVal};
1515

1616
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
17-
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
18-
match ty.sty {
19-
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
20-
ty::Ref(_, ty, _) => !self.type_is_sized(ty),
21-
ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
22-
_ => false,
23-
}
24-
}
25-
2617
pub fn cast(
2718
&mut self,
2819
src: OpTy<'tcx, M::PointerTag>,
@@ -99,68 +90,59 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9990
src: ImmTy<'tcx, M::PointerTag>,
10091
dest_layout: TyLayout<'tcx>,
10192
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
102-
if self.type_is_fat_ptr(src.layout.ty) {
103-
return match (*src, self.type_is_fat_ptr(dest_layout.ty)) {
104-
// pointers to extern types
105-
(Immediate::Scalar(_),_) |
106-
// slices and trait objects to other slices/trait objects
107-
(Immediate::ScalarPair(..), true) => {
108-
// No change to immediate
109-
Ok(*src)
110-
}
111-
// slices and trait objects to thin pointers (dropping the metadata)
112-
(Immediate::ScalarPair(data, _), false) => {
113-
Ok(data.into())
114-
}
115-
};
116-
} else {
117-
match src.layout.variants {
118-
layout::Variants::Single { index } => {
119-
if let Some(discr) =
120-
src.layout.ty.discriminant_for_variant(*self.tcx, index)
121-
{
122-
// Cast from a univariant enum
123-
assert!(src.layout.is_zst());
124-
return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
125-
}
126-
}
127-
layout::Variants::Multiple { .. } => {},
128-
}
129-
130-
return Ok(self.cast_scalar(src.to_scalar()?, src.layout, dest_layout)?.into());
131-
}
132-
}
133-
134-
fn cast_scalar(
135-
&self,
136-
val: Scalar<M::PointerTag>,
137-
src_layout: TyLayout<'tcx>,
138-
dest_layout: TyLayout<'tcx>,
139-
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
14093
use rustc::ty::TyKind::*;
141-
trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
94+
trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, dest_layout.ty);
14295

143-
match src_layout.ty.sty {
96+
match src.layout.ty.sty {
14497
// Floating point
145-
Float(FloatTy::F32) => self.cast_from_float(val.to_f32()?, dest_layout.ty),
146-
Float(FloatTy::F64) => self.cast_from_float(val.to_f64()?, dest_layout.ty),
147-
// Integer(-like), including fn ptr casts and casts from enums that
148-
// are represented as integers (this excludes univariant enums, which
149-
// are handled in `cast` directly).
150-
_ => {
98+
Float(FloatTy::F32) =>
99+
return Ok(self.cast_from_float(src.to_scalar()?.to_f32()?, dest_layout.ty)?.into()),
100+
Float(FloatTy::F64) =>
101+
return Ok(self.cast_from_float(src.to_scalar()?.to_f64()?, dest_layout.ty)?.into()),
102+
// The rest is integer/pointer-"like", including fn ptr casts and casts from enums that
103+
// are represented as integers.
104+
_ =>
151105
assert!(
152-
src_layout.ty.is_bool() || src_layout.ty.is_char() ||
153-
src_layout.ty.is_enum() || src_layout.ty.is_integral() ||
154-
src_layout.ty.is_unsafe_ptr() || src_layout.ty.is_fn_ptr() ||
155-
src_layout.ty.is_region_ptr(),
156-
"Unexpected cast from type {:?}", src_layout.ty
157-
);
158-
match val.to_bits_or_ptr(src_layout.size, self) {
159-
Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
160-
Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
106+
src.layout.ty.is_bool() || src.layout.ty.is_char() ||
107+
src.layout.ty.is_enum() || src.layout.ty.is_integral() ||
108+
src.layout.ty.is_unsafe_ptr() || src.layout.ty.is_fn_ptr() ||
109+
src.layout.ty.is_region_ptr(),
110+
"Unexpected cast from type {:?}", src.layout.ty
111+
)
112+
}
113+
114+
// Handle cast the metadata away from a fat pointer.
115+
if dest_layout.size != src.layout.size {
116+
assert_eq!(dest_layout.size, self.memory.pointer_size());
117+
return match *src {
118+
Immediate::ScalarPair(data, _) => Ok(data.into()),
119+
Immediate::Scalar(..) =>
120+
bug!(
121+
"{:?} input to a fat-to-thin cast ({:?} -> {:?})",
122+
*src, src.layout.ty, dest_layout.ty
123+
),
124+
};
125+
}
126+
127+
// Handle cast from a univariant (ZST) enum
128+
match src.layout.variants {
129+
layout::Variants::Single { index } => {
130+
if let Some(discr) =
131+
src.layout.ty.discriminant_for_variant(*self.tcx, index)
132+
{
133+
assert!(src.layout.is_zst());
134+
return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
161135
}
162136
}
137+
layout::Variants::Multiple { .. } => {},
163138
}
139+
140+
// Handle all the rest.
141+
let val = src.to_scalar()?;
142+
Ok(match val.to_bits_or_ptr(src.layout.size, self) {
143+
Err(ptr) => self.cast_from_ptr(ptr, src.layout, dest_layout)?,
144+
Ok(data) => self.cast_from_int(data, src.layout, dest_layout)?,
145+
}.into())
164146
}
165147

166148
fn cast_from_int(

0 commit comments

Comments
 (0)