about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-09 22:43:58 +0000
committerbors <bors@rust-lang.org>2023-06-09 22:43:58 +0000
commit993299ee3f0b8650101bf59d0341da6448d9bc21 (patch)
treefc2bf592f8750ba7e8b7896bf8a9bffd6b03970b
parent60d952e9027c554856c365c3bf3daf2396a00bcf (diff)
parent6fbf6ef514876e68d98211051ef54d0dcd2b8550 (diff)
downloadrust-993299ee3f0b8650101bf59d0341da6448d9bc21.tar.gz
rust-993299ee3f0b8650101bf59d0341da6448d9bc21.zip
Auto merge of #15019 - HKalbasi:nightly-mir-eval-panic, r=HKalbasi
Fix panic in displaying const trait objects

I hope this fixes the panic on recent nightly stdlib, but I didn't test it locally.
-rw-r--r--crates/hir-ty/src/display.rs16
-rw-r--r--crates/hir-ty/src/mir/eval.rs18
-rw-r--r--crates/ide/src/hover/tests.rs23
3 files changed, 52 insertions, 5 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index f90e025c7cc..9d5cf47da8d 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -536,6 +536,22 @@ fn render_const_scalar(
                 }
                 f.write_str("]")
             }
+            TyKind::Dyn(_) => {
+                let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
+                let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
+                let Ok(t) = memory_map.vtable.ty(ty_id) else {
+                    return f.write_str("<ty-missing-in-vtable-map>");
+                };
+                let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
+                    return f.write_str("<layout-error>");
+                };
+                let size = layout.size.bytes_usize();
+                let Some(bytes) = memory_map.get(addr, size) else {
+                    return f.write_str("<ref-data-not-available>");
+                };
+                f.write_str("&")?;
+                render_const_scalar(f, bytes, memory_map, t)
+            }
             _ => {
                 let addr = usize::from_le_bytes(b.try_into().unwrap());
                 let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index ce14f6dbad5..9acf9d39e56 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -77,7 +77,7 @@ impl VTableMap {
         id
     }
 
-    fn ty(&self, id: usize) -> Result<&Ty> {
+    pub(crate) fn ty(&self, id: usize) -> Result<&Ty> {
         self.id_to_ty.get(id).ok_or(MirEvalError::InvalidVTableId(id))
     }
 
@@ -1571,16 +1571,24 @@ impl Evaluator<'_> {
                         }
                         None => {
                             let mut check_inner = None;
+                            let (addr, meta) = bytes.split_at(bytes.len() / 2);
                             let element_size = match t.kind(Interner) {
                                 TyKind::Str => 1,
                                 TyKind::Slice(t) => {
                                     check_inner = Some(t);
                                     this.size_of_sized(t, locals, "slice inner type")?
                                 }
-                                _ => return Ok(()), // FIXME: support other kind of unsized types
+                                TyKind::Dyn(_) => {
+                                    let t = this.vtable_map.ty_of_bytes(meta)?;
+                                    check_inner = Some(t);
+                                    this.size_of_sized(t, locals, "dyn concrete type")?
+                                }
+                                _ => return Ok(()),
+                            };
+                            let count = match t.kind(Interner) {
+                                TyKind::Dyn(_) => 1,
+                                _ => from_bytes!(usize, meta),
                             };
-                            let (addr, meta) = bytes.split_at(bytes.len() / 2);
-                            let count = from_bytes!(usize, meta);
                             let size = element_size * count;
                             let addr = Address::from_bytes(addr)?;
                             let b = this.read_memory(addr, size)?;
@@ -1588,7 +1596,7 @@ impl Evaluator<'_> {
                             if let Some(ty) = check_inner {
                                 for i in 0..count {
                                     let offset = element_size * i;
-                                    rec(this, &b[offset..offset + element_size], ty, locals, mm)?;
+                                    rec(this, &b[offset..offset + element_size], &ty, locals, mm)?;
                                 }
                             }
                         }
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index a2f96977581..22bbdf37a8e 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -4423,6 +4423,29 @@ const FOO$0: Option<&i32> = Some(2).as_ref();
 }
 
 #[test]
+fn hover_const_eval_dyn_trait() {
+    check(
+        r#"
+//- minicore: fmt, coerce_unsized, builtin_impls
+use core::fmt::Debug;
+
+const FOO$0: &dyn Debug = &2i32;
+"#,
+        expect![[r#"
+            *FOO*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            const FOO: &dyn Debug = &2
+            ```
+        "#]],
+    );
+}
+
+#[test]
 fn hover_const_eval_slice() {
     check(
         r#"