about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src/const_eval/mod.rs
diff options
context:
space:
mode:
authorb-naber <bn263@gmx.de>2022-04-08 13:09:24 +0200
committerb-naber <bn263@gmx.de>2022-04-08 15:45:14 +0200
commit82217a6587da07433c901a8b3ea0765acf288860 (patch)
tree78f5b61edba7994d7c7775d57971878d7d328290 /compiler/rustc_const_eval/src/const_eval/mod.rs
parentfcc4d8ce98ef61586fccfb7efae7563788453b73 (diff)
downloadrust-82217a6587da07433c901a8b3ea0765acf288860.tar.gz
rust-82217a6587da07433c901a8b3ea0765acf288860.zip
create leafs for slices
Diffstat (limited to 'compiler/rustc_const_eval/src/const_eval/mod.rs')
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs128
1 files changed, 57 insertions, 71 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index dad6e5e34a6..9b42910f99c 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -6,14 +6,14 @@ use rustc_hir::Mutability;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_middle::{
     mir::{self, interpret::ConstAlloc},
-    ty::{ScalarInt, Ty},
+    ty::ScalarInt,
 };
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
 use rustc_target::abi::VariantIdx;
 
 use crate::interpret::{
-    intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
-    MemPlaceMeta, Scalar,
+    intern_const_alloc_recursive, ConstValue, Immediate, InternKind, InterpCx, InterpResult,
+    MPlaceTy, MemPlaceMeta, Scalar,
 };
 
 mod error;
@@ -80,19 +80,28 @@ fn branches<'tcx>(
     Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
 }
 
+fn slice_branches<'tcx>(
+    ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
+    place: &MPlaceTy<'tcx>,
+    n: u64,
+) -> Option<ty::ValTree<'tcx>> {
+    let elems = (0..n).map(|i| {
+        let place_elem = ecx.mplace_index(place, i).unwrap();
+        const_to_valtree_inner(ecx, &place_elem)
+    });
+
+    // Need `len` for the ValTree -> ConstValue conversion
+    let len = Some(Some(ty::ValTree::Leaf(ScalarInt::from(n))));
+    let branches = len.into_iter().chain(elems);
+
+    Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
+}
+
 #[instrument(skip(ecx), level = "debug")]
 fn const_to_valtree_inner<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
     place: &MPlaceTy<'tcx>,
 ) -> Option<ty::ValTree<'tcx>> {
-    // We only want to use raw bytes in ValTrees for string slices or &[<integer_ty>]
-    let use_bytes_for_ref = |ty: Ty<'tcx>| -> bool {
-        match ty.kind() {
-            ty::Str | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Bool => true,
-            _ => false,
-        }
-    };
-
     match place.layout.ty.kind() {
         ty::FnDef(..) => Some(ty::ValTree::zst()),
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
@@ -107,75 +116,52 @@ fn const_to_valtree_inner<'tcx>(
         // agree with runtime equality tests.
         ty::FnPtr(_) | ty::RawPtr(_) => None,
 
-        ty::Ref(_, ref_ty, _) if place.layout.ty.is_slice() => {
-            match ecx.try_read_immediate_from_mplace(&place) {
-                Ok(Some(imm)) => {
-                    // `imm` is a ScalarPair. We try to get the underlying bytes behind that
-                    // fat pointer for string slices and slices of integer types. For any other
-                    // slice types we use `branches` to recursively construct the Valtree.
-
-                    if use_bytes_for_ref(*ref_ty) {
-                        let (alloc, range) = ecx.get_alloc_from_imm_scalar_pair(imm);
-                        let alloc_bytes = match alloc.get_bytes(&ecx.tcx, range) {
-                            Ok(bytes) => bytes,
-                            Err(_e) => return None,
-                        };
-                        debug!(?alloc_bytes);
-
-                        let bytes = ecx.tcx.arena.alloc_slice(alloc_bytes);
-                        let len = bytes.len();
-                        debug!(?bytes, ?len);
-
-                        let slice = ty::ValSlice { bytes};
-
-                        Some(ty::ValTree::SliceOrStr(slice))
-                    } else {
-                        let derefd = ecx.deref_operand(&imm.into()).expect(&format!("couldnt deref {:?}", imm));
-                        debug!("derefd: {:?}", derefd);
-
-                        let derefd_imm = match ecx.try_read_immediate_from_mplace(&derefd) {
-                            Ok(Some(imm)) => imm,
-                            _ => return None,
-                        };
-                        debug!(?derefd_imm);
-
-                        let tcx = ecx.tcx.tcx;
-                        let scalar_len= derefd.meta.unwrap_meta();
-                        let len = match scalar_len {
-                            Scalar::Int(int) => {
-                                int.try_to_machine_usize(tcx).expect(&format!("Expected a valid ScalarInt in {:?}", scalar_len))
-                            }
-                            _ => bug!("expected a ScalarInt in meta data for {:?}", place),
-                        };
-                        debug!(?len);
-
-                        let valtree = branches(ecx, place, len.try_into().expect("BLA"), None);
-                        debug!(?valtree);
-
-                        valtree
+        ty::Ref(_, inner_ty, _)  => {
+            match inner_ty.kind() {
+                ty::Slice(_) | ty::Str => {
+                    match ecx.try_read_immediate_from_mplace(&place) {
+                        Ok(Some(imm)) => {
+                            let mplace_ref = ecx.ref_to_mplace(&imm).unwrap();
+                            let derefd = ecx.deref_operand(&place.into()).expect(&format!("couldnt deref {:?}", imm));
+                            debug!(?mplace_ref, ?derefd);
+
+                            let len = match imm.imm {
+                                Immediate::ScalarPair(_, b) => {
+                                    let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
+                                    len
+                                }
+                                _ => bug!("expected ScalarPair for &[T] or &str"),
+                            };
+                            debug!(?len);
+
+                            let valtree = slice_branches(ecx, &derefd, len);
+                            debug!(?valtree);
+
+                            valtree
+                        }
+                        _ => {
+                            None
+                        }
                     }
                 }
                 _ => {
-                    None
-                }
-            }
-        }
+                    let imm = ecx.try_read_immediate_from_mplace(&place).unwrap_or_else(|e| bug!("couldnt read immediate from {:?}, error: {:?}", place, e));
 
-        ty::Ref(_, inner_ty, _) => {
-            debug!("Ref with inner_ty: {:?}", inner_ty);
-            let imm = ecx.try_read_immediate_from_mplace(&place).unwrap_or_else(|e| bug!("couldnt read immediate from {:?}, error: {:?}", place, e));
-            match imm {
-                Some(imm) => {
-                    debug!(?imm);
+                    match imm {
+                        Some(imm) => {
+                            debug!(?imm);
 
-                    let derefd_place = ecx.deref_mplace(place).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
-                    debug!(?derefd_place);
+                            let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
+                            debug!(?derefd_place);
 
-                    const_to_valtree_inner(ecx, &derefd_place)
+                            const_to_valtree_inner(ecx, &derefd_place)
+                        }
+                        None => bug!("couldn't read immediate from {:?}", place),
+                    }
                 }
-                None => None,
             }
         }
+
         ty::Str => {
             bug!("ty::Str should have been handled in ty::Ref branch that uses raw bytes");
         }