From: Utkarsh Bahuguna <[email protected]>
Const eval reserved a slot in the call cache even past the depth where it
stops caching, and never filled it, so a deep enough recursion tripped a
hash table check. Only ask for an insertion when we're going to cache the
call, like the C++ front end does.
Fixes Rust-GCC/gccrs#3949
Assisted-by: Claude Opus 5.5 (Anthropic)
gcc/rust/ChangeLog:
* backend/rust-constexpr.cc (eval_call_expression): Only request an
insertion in the call table when the call will be cached.
gcc/testsuite/ChangeLog:
* rust/compile/issues/issue-3949.rs: New test.
* rust/execute/torture/const-fn-recursion.rs: New test.
Signed-off-by: Utkarsh Bahuguna <[email protected]>
Tested on x86_64-pc-linux-gnu.
---
gcc/rust/backend/rust-constexpr.cc | 8 ++++---
.../rust/compile/issues/issue-3949.rs | 14 +++++++++++
.../execute/torture/const-fn-recursion.rs | 24 +++++++++++++++++++
3 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issues/issue-3949.rs
create mode 100644 gcc/testsuite/rust/execute/torture/const-fn-recursion.rs
diff --git a/gcc/rust/backend/rust-constexpr.cc
b/gcc/rust/backend/rust-constexpr.cc
index 33a7d2ad719..15b705e3b9c 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -3715,13 +3715,15 @@ eval_call_expression (const constexpr_ctx *ctx, tree t,
bool lval,
/* If we have seen this call before, we are done. */
maybe_initialize_constexpr_call_table ();
+ bool insert = depth_ok < constexpr_cache_depth;
rust_constexpr_call **slot
- = constexpr_call_table->find_slot (&new_call, INSERT);
- entry = *slot;
+ = constexpr_call_table->find_slot (&new_call,
+ insert ? INSERT : NO_INSERT);
+ entry = slot ? *slot : NULL;
if (entry == NULL)
{
/* Only cache up to constexpr_cache_depth to limit memory use. */
- if (depth_ok < constexpr_cache_depth)
+ if (insert)
{
/* We need to keep a pointer to the entry, not just the slot, as
the slot can move during evaluation of the body. */
diff --git a/gcc/testsuite/rust/compile/issues/issue-3949.rs
b/gcc/testsuite/rust/compile/issues/issue-3949.rs
new file mode 100644
index 00000000000..aa9f97681a4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issues/issue-3949.rs
@@ -0,0 +1,14 @@
+#![feature(no_core)]
+#![no_core]
+
+const fn a() -> usize {
+ b()
+}
+
+const fn b() -> usize {
+ a()
+}
+
+const ARR: [i32; a()] = [5; 6];
+// { dg-error "mismatched types" "" { target *-*-* } .-1 }
+// { dg-error "evaluation depth exceeds maximum" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/rust/execute/torture/const-fn-recursion.rs
b/gcc/testsuite/rust/execute/torture/const-fn-recursion.rs
new file mode 100644
index 00000000000..a898eb0e3c6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const-fn-recursion.rs
@@ -0,0 +1,24 @@
+// { dg-additional-options "-w" }
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+const fn fib(n: i32) -> i32 {
+ if n < 2 {
+ n
+ } else {
+ fib(n - 1) + fib(n - 2)
+ }
+}
+
+const X: i32 = fib(20);
+
+fn main() -> i32 {
+ if X == 6765 {
+ 0
+ } else {
+ 1
+ }
+}
--
2.55.0