Auto merge of #16935 - Nilstrieb:dont-panic, r=HKalbasi
Handle panicking like rustc CTFE does
Instead of using `core::fmt::format` to format panic messages, which may in turn panic too and cause recursive panics and other messy things, redirect `panic_fmt` to `const_panic_fmt` like CTFE, which in turn goes to `panic_display` and does the things normally. See the tests for the full call stack.
The tests don't work yet, I probably missed something in minicore.
fixes #16907 in my local testing, I also need to add a test for it
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 98384c4..d1ffd50 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2825,3 +2825,30 @@
|e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))),
);
}
+
+#[test]
+fn recursive_adt() {
+ check_fail(
+ r#"
+ //- minicore: coerce_unsized, index, slice
+ pub enum TagTree {
+ Leaf,
+ Choice(&'static [TagTree]),
+ }
+ const GOAL: TagTree = {
+ const TAG_TREE: TagTree = TagTree::Choice(&[
+ {
+ const VARIANT_TAG_TREE: TagTree = TagTree::Choice(
+ &[
+ TagTree::Leaf,
+ ],
+ );
+ VARIANT_TAG_TREE
+ },
+ ]);
+ TAG_TREE
+ };
+ "#,
+ |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
+ );
+}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 7799c03..045ffb4 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1931,7 +1931,11 @@
ty: &Ty,
locals: &Locals,
mm: &mut ComplexMemoryMap,
+ stack_depth_limit: usize,
) -> Result<()> {
+ if stack_depth_limit.checked_sub(1).is_none() {
+ return Err(MirEvalError::StackOverflow);
+ }
match ty.kind(Interner) {
TyKind::Ref(_, _, t) => {
let size = this.size_align_of(t, locals)?;
@@ -1970,7 +1974,14 @@
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,
+ stack_depth_limit - 1,
+ )?;
}
}
}
@@ -1984,7 +1995,14 @@
let size = this.size_of_sized(inner, locals, "inner of array")?;
for i in 0..len {
let offset = i * size;
- rec(this, &bytes[offset..offset + size], inner, locals, mm)?;
+ rec(
+ this,
+ &bytes[offset..offset + size],
+ inner,
+ locals,
+ mm,
+ stack_depth_limit - 1,
+ )?;
}
}
chalk_ir::TyKind::Tuple(_, subst) => {
@@ -1993,7 +2011,14 @@
let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
let offset = layout.fields.offset(id).bytes_usize();
let size = this.layout(ty)?.size.bytes_usize();
- rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+ rec(
+ this,
+ &bytes[offset..offset + size],
+ ty,
+ locals,
+ mm,
+ stack_depth_limit - 1,
+ )?;
}
}
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
@@ -2008,7 +2033,14 @@
.bytes_usize();
let ty = &field_types[f].clone().substitute(Interner, subst);
let size = this.layout(ty)?.size.bytes_usize();
- rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+ rec(
+ this,
+ &bytes[offset..offset + size],
+ ty,
+ locals,
+ mm,
+ stack_depth_limit - 1,
+ )?;
}
}
AdtId::EnumId(e) => {
@@ -2027,7 +2059,14 @@
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
let ty = &field_types[f].clone().substitute(Interner, subst);
let size = this.layout(ty)?.size.bytes_usize();
- rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+ rec(
+ this,
+ &bytes[offset..offset + size],
+ ty,
+ locals,
+ mm,
+ stack_depth_limit - 1,
+ )?;
}
}
}
@@ -2038,7 +2077,7 @@
Ok(())
}
let mut mm = ComplexMemoryMap::default();
- rec(self, bytes, ty, locals, &mut mm)?;
+ rec(self, bytes, ty, locals, &mut mm, self.stack_depth_limit - 1)?;
Ok(mm)
}