diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2022-05-31 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2022-05-31 00:00:00 +0000 |
| commit | dff602fc18be295d1b87196a6eee1c72673e6bb8 (patch) | |
| tree | 3c08934e4fe11ed94c9875185f3e61bcdd1a2484 /compiler/rustc_const_eval | |
| parent | d35d972e6974d40d30362344ea619a5b560aae20 (diff) | |
| download | rust-dff602fc18be295d1b87196a6eee1c72673e6bb8.tar.gz rust-dff602fc18be295d1b87196a6eee1c72673e6bb8.zip | |
Add a pointer to address cast kind
A pointer to address cast are often special-cased. Introduce a dedicated cast kind to make them easy distinguishable.
Diffstat (limited to 'compiler/rustc_const_eval')
3 files changed, 30 insertions, 36 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index be34a77bdba..af563c1450e 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::convert::TryFrom; use rustc_apfloat::ieee::{Double, Single}; @@ -30,6 +31,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.unsize_into(src, cast_ty, dest)?; } + PointerAddress => { + let src = self.read_immediate(src)?; + let res = self.pointer_address_cast(&src, cast_ty)?; + self.write_immediate(res, dest)?; + } + Misc => { let src = self.read_immediate(src)?; let res = self.misc_cast(&src, cast_ty)?; @@ -174,23 +181,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // # The remaining source values are scalar and "int-like". let scalar = src.to_scalar()?; + Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) + } - // If we are casting from a pointer to something - // that is not a pointer, mark the pointer as exposed - if src.layout.ty.is_any_ptr() && !cast_ty.is_any_ptr() { - let ptr = self.scalar_to_ptr(scalar)?; - - match ptr.into_pointer_or_addr() { - Ok(ptr) => { - M::expose_ptr(self, ptr)?; - } - Err(_) => { - // do nothing, exposing an invalid pointer - // has no meaning - } - }; - } + pub fn pointer_address_cast( + &mut self, + src: &ImmTy<'tcx, M::PointerTag>, + cast_ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Immediate<M::PointerTag>> { + assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_)); + assert!(cast_ty.is_integral()); + let scalar = src.to_scalar()?; + let ptr = self.scalar_to_ptr(scalar)?; + match ptr.into_pointer_or_addr() { + Ok(ptr) => M::expose_ptr(self, ptr)?, + Err(_) => {} // do nothing, exposing an invalid pointer has no meaning + }; Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index eea6e2a47a9..4ef33d62a6b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable}; @@ -543,16 +542,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // in the type of any local, which also excludes casts). } - Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { - let operand_ty = operand.ty(self.body, self.tcx); - let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); - let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); - - if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) { - self.check_op(ops::RawPtrToIntCast); - } + Rvalue::Cast(CastKind::PointerAddress, _, _) => { + self.check_op(ops::RawPtrToIntCast); } + Rvalue::Cast(CastKind::Misc, _, _) => {} + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} Rvalue::ShallowInitBox(_, _) => {} diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index fc6b8a1a723..ea23bd14d25 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -16,7 +16,6 @@ use rustc_hir as hir; use rustc_middle::mir::traversal::ReversePostorderIter; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable}; use rustc_span::Span; @@ -502,18 +501,11 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::ThreadLocalRef(_) => return Err(Unpromotable), - Rvalue::Cast(kind, operand, cast_ty) => { - if matches!(kind, CastKind::Misc) { - let operand_ty = operand.ty(self.body, self.tcx); - let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); - let cast_out = CastTy::from_ty(*cast_ty).expect("bad output type for cast"); - if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) { - // ptr-to-int casts are not possible in consts and thus not promotable - return Err(Unpromotable); - } - // int-to-ptr casts are fine, they just use the integer value at pointer type. - } + // ptr-to-int casts are not possible in consts and thus not promotable + Rvalue::Cast(CastKind::PointerAddress, _, _) => return Err(Unpromotable), + // int-to-ptr casts are fine, they just use the integer value at pointer type. + Rvalue::Cast(_, operand, _) => { self.validate_operand(operand)?; } |
