about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs12
-rw-r--r--src/librustc_mir/interpret/intrinsics/type_name.rs17
-rw-r--r--src/test/run-pass/ctfe/const-fn-type-name.rs37
3 files changed, 60 insertions, 6 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 3f3651fd817..4de2bd48eeb 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -11,7 +11,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    Machine, PlaceTy, OpTy, InterpretCx,
+    Machine, PlaceTy, OpTy, InterpretCx, Immediate,
 };
 
 mod type_name;
@@ -78,6 +78,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                 let id_val = Scalar::from_uint(type_id, dest.layout.size);
                 self.write_scalar(id_val, dest)?;
             }
+
+            "type_name" => {
+                let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
+                let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
+                let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
+                let alloc_len = alloc.bytes.len() as u64;
+                let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
+                self.write_immediate(name_val, dest)?;
+            }
+
             | "ctpop"
             | "cttz"
             | "cttz_nonzero"
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 456fc70fc0d..1270b35ebb9 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -213,16 +213,23 @@ impl Write for AbsolutePathPrinter<'_, '_> {
 /// Produces an absolute path representation of the given type. See also the documentation on
 /// `std::any::type_name`
 pub fn type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
-    let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
-    let len = path.len();
-    let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
-    let alloc = tcx.intern_const_alloc(alloc);
+    let alloc = alloc_type_name(tcx, ty);
     tcx.mk_const(ty::Const {
         val: ConstValue::Slice {
             data: alloc,
             start: 0,
-            end: len,
+            end: alloc.bytes.len(),
         },
         ty: tcx.mk_static_str(),
     })
 }
+
+/// Directly returns an `Allocation` containing an absolute path representation of the given type.
+pub(super) fn alloc_type_name<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ty: Ty<'tcx>
+) -> &'tcx Allocation {
+    let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
+    let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
+    tcx.intern_const_alloc(alloc)
+}
diff --git a/src/test/run-pass/ctfe/const-fn-type-name.rs b/src/test/run-pass/ctfe/const-fn-type-name.rs
new file mode 100644
index 00000000000..2ee6415aa68
--- /dev/null
+++ b/src/test/run-pass/ctfe/const-fn-type-name.rs
@@ -0,0 +1,37 @@
+// run-pass
+
+#![feature(core_intrinsics)]
+#![feature(const_fn)]
+#![allow(dead_code)]
+
+const fn type_name_wrapper<T>(_: &T) -> &'static str {
+    unsafe { core::intrinsics::type_name::<T>() }
+}
+
+struct Struct<TA, TB, TC> {
+    a: TA,
+    b: TB,
+    c: TC,
+}
+
+type StructInstantiation = Struct<i8, f64, bool>;
+
+const CONST_STRUCT: StructInstantiation = StructInstantiation {
+    a: 12,
+    b: 13.7,
+    c: false,
+};
+
+const CONST_STRUCT_NAME: &'static str = type_name_wrapper(&CONST_STRUCT);
+
+fn main() {
+    let non_const_struct = StructInstantiation {
+        a: 87,
+        b: 65.99,
+        c: true,
+    };
+
+    let non_const_struct_name = type_name_wrapper(&non_const_struct);
+
+    assert_eq!(CONST_STRUCT_NAME, non_const_struct_name);
+}