leanprover / leanprover/lean4

Closed term extraction for large list literals produces large call stacks

Open
#6,047 0 comments 1 reaction 1 assignee View on GitHub

@zwarich is already working on this.

Since May 24, 2025.

bug P-high
Dominant language
Lean
Stars
9.2k
Forks
990
Avg merge
1d 17h
Merged PRs (30d)
175

Description

Prerequisites

Please put an X between the brackets as you perform the following steps:

Description

Closed term extraction for large list and array literals produces a linked list of functions. For example, the code

set_option trace.compiler.ir.result true
def a := [0, 0, 0, 0, 0]

yields

[result]
def a._closed_1 : obj :=
  let x_1 : obj := ctor_0[List.nil];
  let x_2 : obj := 0;
  let x_3 : obj := ctor_1[List.cons] x_2 x_1;
  ret x_3
def a._closed_2 : obj :=
  let x_1 : obj := 0;
  let x_2 : obj := a._closed_1;
  let x_3 : obj := ctor_1[List.cons] x_1 x_2;
  ret x_3
def a._closed_3 : obj :=
  let x_1 : obj := 0;
  let x_2 : obj := a._closed_2;
  let x_3 : obj := ctor_1[List.cons] x_1 x_2;
  ret x_3
def a._closed_4 : obj :=
  let x_1 : obj := 0;
  let x_2 : obj := a._closed_3;
  let x_3 : obj := ctor_1[List.cons] x_1 x_2;
  ret x_3
def a._closed_5 : obj :=
  let x_1 : obj := 0;
  let x_2 : obj := a._closed_4;
  let x_3 : obj := ctor_1[List.cons] x_1 x_2;
  ret x_3
def a : obj :=
  let x_1 : obj := a._closed_5;
  ret x_1

Large list literals have several problems (see for example #5683), but one of the problems is that they will cause the interpreter to overflow its stack when trying to access the list. Since array literals desugar to list literals, this is also true for array literals.

Context

This causes Lean to crash on a test for time zone database parsing that we wanted to add. The workaround is to use small literals instead.

Steps to Reproduce
  1. Run lean on this file.
terminate called after throwing an instance of 'lean::throwable'
  what():  deep recursion was detected at 'interpreter' (potential solution: increase stack space in your system)
interpreter stacktrace:
#1 l._closed_4522
#2 l._closed_4523
#3 l._closed_4524
#4 l._closed_4525
#5 l._closed_4526
#6 l._closed_4527
#7 l._closed_4528
#8 l._closed_4529
#9 l._closed_4530
#10 l._closed_4531
#11 l._closed_4532
#12 l._closed_4533
#13 l._closed_4534
#14 l._closed_4535
#15 l._closed_4536
#16 l._closed_4537
#17 l._closed_4538
#18 l._closed_4539
#19 l._closed_4540
#20 l._closed_4541

and so on for a few thousand lines.

Expected behavior: Interpreter can cope with the list.

Actual behavior: See error message above.

Versions
Lean (version 4.15.0-pre, commit bf2e39c2b89a, Release)
Impact

Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.