Unnamed repository; edit this file 'description' to name the repository.
Fix panic in displaying const trait objects
hkalbasi 2023-06-10
parent 2796851 · commit 6fbf6ef
-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 f90e025c7c..9d5cf47da8 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 ce14f6dbad..9acf9d39e5 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 a2f9697758..22bbdf37a8 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#"