Zulip Chat Archive

Stream: lean4

Topic: lean-auto with structure


Kaushik Raghavan (Nov 20 2025 at 17:30):

Hi everyone,

I was trying this simple example to use lean-auto to find sat/unsat for a trivial case:

set_option auto.smt true
set_option trace.auto.smt.printCommands true
set_option trace.auto.smt.result true
set_option trace.auto.smt.unsatCore.leanExprs true

structure st where
  x : Int

def unfoldedTestRec (p: Int) (a b : st) : st :=
  if p = a.x then a else if p = b.x then b else { x := -1 }

example {a b : st} (h : (unfoldedTestRec 1 a b).x = 1) : False := by
  simp [unfoldedTestRec] at h
  auto

which gives the following error _private.Auto.Translation.LamFOL2SMT.0.Auto.SMT.lamTerm2STermAux :: Unexpected head term Auto.Embedding.Lam.LamTerm.lam (.atom 1) (.bvar 2). I was expecting the auto tactic to return Sat.

Could someone please help me understand what is causing this error for cases like this?

Abdalrhman M Mohamed (Nov 21 2025 at 07:19):

It appears that in Lean-auto's quest to identify definitional equalities between constants, it ends up unfolding Auto.Bool.ite' (auto's own version of ite). That unfolding introduces a higher-order lambda term, which cannot be translated to SMT-LIB. (Higher-order constructs were recently added in SMT-LIB 2.7, which no solver fully supports yet.)

I see three possible ways to work around this:

  1. Mark Auto.Bool.ite' as @[irreducible]. Lean-auto does not unfold irreducible constants by default, so this avoids introducing the higher-order lambda. This would require a small change on Lean-auto's side (ping @Yicheng Qian).

  2. Restrict Lean-auto's transparency mode to unfold only reducible constants. This prevents unfolding Auto.Bool.ite', but may cause Lean-auto to miss some otherwise obvious equalities. If you use this approach, you may also want to set auto.mono.termLikeDefEq.mode to "reducible":

set_option auto.mono.ciInstDefEq.mode "reducible"

example {a b : st} (h : (unfoldedTestRec 1 a b).x = 1) : False := by
  auto u[unfoldedTestRec]

example {a b : st} : (unfoldedTestRec (-1) a b).x = -1 := by
  auto u[unfoldedTestRec]
  1. Keep the default transparency mode but force Lean-auto to reduce the goal to FOL. By default Lean-auto supports higher-order reasoning with duper; switching to FOL mode can avoid the problematic lambda term. Since this reduction may fail (and does fail here), you should also tell Lean-auto to ignore hints it cannot reduce to FOL:
set_option auto.mono.mode "fol"
set_option auto.mono.ignoreNonQuasiHigherOrder true

example {a b : st} (h : (unfoldedTestRec 1 a b).x = 1) : False := by
  auto u[unfoldedTestRec]

example {a b : st} : (unfoldedTestRec (-1) a b).x = -1 := by
  auto u[unfoldedTestRec]

Yicheng Qian (Nov 21 2025 at 10:09):

@Abdalrhman M Mohamed Thanks for looking into the issue! I have marked Auto.Bool.ite' and Auto.Bool.ofProp as irreducible.

Kaushik Raghavan (Nov 21 2025 at 17:18):

Thanks a lot for the detailed response and the quick fix @Abdalrhman M Mohamed and @Yicheng Qian !


Last updated: Dec 20 2025 at 21:32 UTC