<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::ty::{self, Ty, TypeAndMut};
use rustc::ty::layout::{self, TyLayout, Size};
use syntax::ast::{FloatTy, IntTy, UintTy};

use rustc_apfloat::ieee::{Single, Double};
use rustc::mir::interpret::{
    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate
};
use rustc::mir::CastKind;
use rustc_apfloat::Float;

use super::{EvalContext, Machine, PlaceTy, OpTy, Value};

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
        match ty.sty {
            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
            ty::Ref(_, ty, _) => !self.type_is_sized(ty),
            ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
            _ => false,
        }
    }

    pub fn cast(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        kind: CastKind,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        let src_layout = src.layout;
        use rustc::mir::CastKind::*;
        match kind {
            Unsize => {
                self.unsize_into(src, dest)?;
            }

            Misc => {
                let src = self.read_value(src)?;

                if M::ENABLE_PTR_TRACKING_HOOKS &&
                    src.layout.ty.is_region_ptr() && dest.layout.ty.is_unsafe_ptr()
                {
                    // For the purpose of the "ptr tag hooks", treat this as creating
                    // a new, raw reference.
                    let place = self.ref_to_mplace(src)?;
                    let _val = self.create_ref(place, None)?;
                    // FIXME: The blog post said we should now also erase the tag.
                    // That would amount to using `_val` instead of `src` from here on.
                    // However, do we really want to do that?  `transmute` doesn't
                    // do it either and we have to support that, somehow.
                }

                if self.type_is_fat_ptr(src.layout.ty) {
                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                        // pointers to extern types
                        (Value::Scalar(_),_) |
                        // slices and trait objects to other slices/trait objects
                        (Value::ScalarPair(..), true) => {
                            // No change to value
                            self.write_value(*src, dest)?;
                        }
                        // slices and trait objects to thin pointers (dropping the metadata)
                        (Value::ScalarPair(data, _), false) => {
                            self.write_scalar(data, dest)?;
                        }
                    }
                } else {
                    match src_layout.variants {
                        layout::Variants::Single { index } => {
                            if let Some(def) = src_layout.ty.ty_adt_def() {
                                // Cast from a univariant enum
                                assert!(src.layout.is_zst());
                                let discr_val = def
                                    .discriminant_for_variant(*self.tcx, index)
                                    .val;
                                return self.write_scalar(
                                    Scalar::from_uint(discr_val, dest.layout.size),
                                    dest);
                            }
                        }
                        layout::Variants::Tagged { .. } |
                        layout::Variants::NicheFilling { .. } => {},
                    }

                    let src = src.to_scalar()?;
                    let dest_val = self.cast_scalar(src, src_layout, dest.layout)?;
                    self.write_scalar(dest_val, dest)?;
                }
            }

            ReifyFnPointer => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::FnDef(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,<commit_msg>turn casts-to-raw into a proper raw-reborrow; that is just cleaner<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::ty::{self, Ty, TypeAndMut};
use rustc::ty::layout::{self, TyLayout, Size};
use syntax::ast::{FloatTy, IntTy, UintTy};

use rustc_apfloat::ieee::{Single, Double};
use rustc::mir::interpret::{
    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind, truncate
};
use rustc::mir::CastKind;
use rustc_apfloat::Float;

use super::{EvalContext, Machine, PlaceTy, OpTy, Value};

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
        match ty.sty {
            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
            ty::Ref(_, ty, _) => !self.type_is_sized(ty),
            ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
            _ => false,
        }
    }

    pub fn cast(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        kind: CastKind,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        use rustc::mir::CastKind::*;
        match kind {
            Unsize => {
                self.unsize_into(src, dest)?;
            }

            Misc => {
                let src_layout = src.layout;
                let src = self.read_value(src)?;

                let src = if M::ENABLE_PTR_TRACKING_HOOKS && src_layout.ty.is_region_ptr() {
                    // The only `Misc` casts on references are those creating raw pointers.
                    assert!(dest.layout.ty.is_unsafe_ptr());
                    // For the purpose of the "ptr tag hooks", treat this as creating
                    // a new, raw reference.
                    let place = self.ref_to_mplace(src)?;
                    self.create_ref(place, None)?
                } else {
                    *src
                };

                if self.type_is_fat_ptr(src_layout.ty) {
                    match (src, self.type_is_fat_ptr(dest.layout.ty)) {
                        // pointers to extern types
                        (Value::Scalar(_),_) |
                        // slices and trait objects to other slices/trait objects
                        (Value::ScalarPair(..), true) => {
                            // No change to value
                            self.write_value(src, dest)?;
                        }
                        // slices and trait objects to thin pointers (dropping the metadata)
                        (Value::ScalarPair(data, _), false) => {
                            self.write_scalar(data, dest)?;
                        }
                    }
                } else {
                    match src_layout.variants {
                        layout::Variants::Single { index } => {
                            if let Some(def) = src_layout.ty.ty_adt_def() {
                                // Cast from a univariant enum
                                assert!(src_layout.is_zst());
                                let discr_val = def
                                    .discriminant_for_variant(*self.tcx, index)
                                    .val;
                                return self.write_scalar(
                                    Scalar::from_uint(discr_val, dest.layout.size),
                                    dest);
                            }
                        }
                        layout::Variants::Tagged { .. } |
                        layout::Variants::NicheFilling { .. } => {},
                    }

                    let src = src.to_scalar()?;
                    let dest_val = self.cast_scalar(src, src_layout, dest.layout)?;
                    self.write_scalar(dest_val, dest)?;
                }
            }

            ReifyFnPointer => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::FnDef(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,
{'fraction_non_alphanumeric': 0.1124248292732647, 'fraction_numerical': 0.0016308225461217, 'mean_word_length': 1.2776230269266482, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5982479', 'n_tokens_mistral': 2665, 'n_tokens_neox': 2581, 'n_words': 627}