Zulip Chat Archive

Stream: lean4

Topic: env using withImportModules


Adam Topaz (Jun 19 2024 at 04:09):

I came across something the following today:
Compare the following two pieces of code.

import Batteries.Lean.Util.Path
import Mathlib.Lean.CoreM

open Lean
def main : IO Unit := do
  searchPathRef.set compile_time_search_path%
  CoreM.withImportModules #[`Mathlib] do
    let env  getEnv
    println! env.constants.toList.length

vs. the following:

import Batteries.Lean.Util.Path
import Mathlib.Lean.CoreM

open Lean
def main : IO Unit := do
  searchPathRef.set compile_time_search_path%
  let env  CoreM.withImportModules #[`Mathlib] getEnv
  println! env.constants.toList.length

The first one works as expected, but the second gives a nonzero exit code and doesn't print anything. The thing is, in my mental model these two programs are equivalent, so I'm interested in understanding why they're behaving differently.

Sebastian Ullrich (Jun 19 2024 at 08:42):

This is a bug in Mathlib, that function must be unsafe. Please read docs#Lean.withImportModules.

Eric Wieser (Jun 19 2024 at 09:24):

Marking it unsafe wouldn't change anything here, right?

Sebastian Ullrich (Jun 19 2024 at 09:27):

It would hopefully make you think twice whether you've used unsafe correctly, which is not possible in the second code block

Adam Topaz (Jun 19 2024 at 12:39):

Thanks. What’s the preferred way to get an env in IO from an import while still allowing references to it?

Eric Wieser (Jun 19 2024 at 12:51):

I think you're expect to do all the work inside the withImportModules?

Adam Topaz (Jun 19 2024 at 13:02):

The thing is, I’m getting some unexpected stack overflow if I try to do my computation inside of the withImportModules so I explicitly want to try to do it in IO to diagnose the issue

Henrik Böving (Jun 19 2024 at 13:28):

You can run the binary in gdb until it stack overflows and take a look at the back trace for a first clue as to what is going wrong.

Adam Topaz (Jun 19 2024 at 13:32):

What is gdb?

Henrik Böving (Jun 19 2024 at 13:34):

Okay if you don't already know GDB my suggestion is probably not useful for you. If you still want to try: its a CLI based C debugger (the GNU debugger) that you can use to....well debug compiled lean projects. You would run gdb <binary> and then in the gdb shell run to execute the program and then when it crashes bt to get a backtrace.

Adam Topaz (Jun 19 2024 at 13:57):

Okay, I have it figured out now. Thanks all for the help! FWIW, the issue arose from the toJson instance for lists. Here is a minimized main function illustrating the issue:

def main : IO Unit := do
  println! toJson <| List.range 100000

Kim Morrison (Jun 20 2024 at 04:52):

@Adam Topaz, could you make an issue for that?

Adam Topaz (Jun 20 2024 at 14:10):

Will do. I'll do some more digging first (e.g. the same issue happens for Array, and the list instance uses that one)

Eric Wieser (Jun 20 2024 at 14:38):

I think the issue is the Json to string instance

Adam Topaz (Jun 20 2024 at 14:38):

Yeah I think you’re right

Eric Wieser (Jun 20 2024 at 14:39):

In fact, its the format to string one

Eric Wieser (Jun 20 2024 at 14:39):

run_cmd do
  let x := Lean.toJson <| List.range 100000
  pure (toString x).length

is fine

Adam Topaz (Jun 20 2024 at 14:54):

I'm not so sure... this still gives a stack overflow:

run_cmd do
  let x := Lean.toJson <| List.range 100000
  let e := (toString x).length
  println! e

Adam Topaz (Jun 20 2024 at 15:06):

I can't come up with an example that doesn't use Json, and only uses some large term of Format.


Last updated: May 02 2025 at 03:31 UTC