Zulip Chat Archive

Stream: general

Topic: (Bug?) LEAN4 unresolvable termination error


Aniket Mishra (Sati) (Sep 15 2025 at 19:50):

The error is in the Basic.lean file at https://github.com/satiscugcat/assertion-insecurity-lean/tree/error-showcase (the file currently takes a non insignificant while to typecheck, so it may take some time for the errors to pop up).

The error comes from LEAN trying to prove termination for the "recursor" functions, but apparently in trying to do so it encounters a type application mismatch. I do not understand how. Adding "decreasing_by (all_goals sorry)" results in a weirder kernel error that looks like this. I cannot understand what is going on.
image.png

Aaron Liu (Sep 15 2025 at 19:54):

that's not good

Aaron Liu (Sep 15 2025 at 19:56):

you linked to a 3000 line file, so it will be difficult to go through all that

Aaron Liu (Sep 15 2025 at 19:56):

it'd be a lot easier if you had a #mwe

Aniket Mishra (Sati) (Sep 15 2025 at 20:16):

Aaron Liu said:

you linked to a 3000 line file, so it will be difficult to go through all that

Right, sorry for that. Branch has been updated to serve as a minimum working example (now about 300 lines)

Robin Arnez (Sep 15 2025 at 20:35):

Just to clarify; I get the same kind of error for all "recursors". If you're talking about that error, here's a reproducer:

inductive EX {A : Type} (P : A  Type) : Type
  | intro (w : A) (h : P w)

inductive EQ {A : Type} : A  A  Type
  | refl (r : A) : EQ r r

inductive Term : Type
  | pair (t1 t2 : Term)
deriving DecidableEq

def Set (α : Type u) := α  Prop

@[instance]
axiom instSingletonSet : Singleton α (Set α)

@[instance]
axiom instUnionSet : Union (Set α)

@[instance]
axiom instEmptyCollectionSet : EmptyCollection (Set α)

abbrev TermSet := Set Term

inductive dy : TermSet  Term  Type
  | something {x y} : dy x y

inductive Assertion : Type
  | eq (t u : Term)
  | member (t₀ : Term) (tlist : List Term)
deriving DecidableEq

abbrev AssertionSet := Set Assertion

axiom intersection {A : Type} [DecidableEq A] : List A  List A  List A

mutual
inductive eq_ady : TermSet  AssertionSet  Assertion  Type
  | cons_pair {S : TermSet} {A : AssertionSet} {t1 t2 u1 u2 : Term} (p1 : eq_ady S A (Assertion.eq t1 u1)) (p2 : eq_ady S A (Assertion.eq t2 u2)) : eq_ady S A (Assertion.eq (Term.pair t1 t2) (Term.pair u1 u2))
  | irrelevant {S A B} : eq_ady S A B
inductive Eq_Trans : TermSet  AssertionSet  Term  Term  Type
  | two_trans {S : TermSet} {A : AssertionSet} {t1 t2 t3 : Term} (p1 : eq_ady S A (Assertion.eq t1 t2)) (p2 : eq_ady S A (Assertion.eq t2 t3)) : Eq_Trans S A t1 t3
  | trans_trans {S : TermSet} {A : AssertionSet} {t1 tk tk' : Term} (phead : eq_ady S A (Assertion.eq t1 tk)) (plist : Eq_Trans S A tk tk') : Eq_Trans S A t1 tk'
inductive Eq_Int : TermSet  AssertionSet  Term  List Term  Type
  | two_lists {S : TermSet} {A : AssertionSet} {t : Term} {l1 l2 : List Term}  (proof1 : eq_ady S A (Assertion.member t l1)) (proof2 : eq_ady S A (Assertion.member t l2)) : Eq_Int S A t (intersection l1 l2)
  | new_list {S : TermSet} {A : AssertionSet} {t : Term} {l l' : List Term} (proof1 : eq_ady S A (Assertion.member t l)) (proof2 : Eq_Int S A t l') : Eq_Int S A t (intersection l l')
inductive Eq_Wk : TermSet  List Term  Type
  | single {S : TermSet} {t : Term} (proof : dy S t) : Eq_Wk S [t]
  | new {S : TermSet} {t : Term} {tlist : List Term} (proofNew : dy S t) (proofList : Eq_Wk S tlist) : Eq_Wk S (t :: tlist)
end

def pairLeftRecursor {S A t u} : Eq_Trans S A t u 
        Option (
          (EX fun t1  => EX fun x1 => EX fun x2 =>
              eq_ady S A (Assertion.eq t1 x1) × (eq_ady S A (Assertion.eq (x1.pair x2) u)) × (EX fun t2 => EQ t (t1.pair t2)))
        ) := by
  intros p
  cases p with
  | @two_trans _ _ x _ p1 p2 => apply Option.none
  | trans_trans phead plist =>
    match phead with
    | @eq_ady.cons_pair _ _ t1 t2 x1 x2 a b => apply Option.none
    | phead =>
      match (pairLeftRecursor plist) with
      | Option.none => apply Option.none
      | Option.some p => apply Option.none

Robin Arnez (Sep 15 2025 at 20:36):

The error in question being:

fail to show termination for
  pkRecursor
with errors
failed to infer structural recursion:
Not considering parameter S of pkRecursor:
  it is unchanged in the recursive calls
Not considering parameter A of pkRecursor:
  it is unchanged in the recursive calls
Not considering parameter u of pkRecursor:
  it is unchanged in the recursive calls
Cannot use parameter p:
  failed to eliminate recursive application
    pkRecursor ptail
Cannot use parameter u:
  failed to eliminate recursive application
    pkRecursor ptail


Application type mismatch: The argument
  Eq_Trans.trans_trans phead✝² plist
has type
  Eq_Trans S A t1 tk'
but is expected to have type
  Eq_Trans S A t1 u
in the application
  sizeOf (Eq_Trans.trans_trans phead✝² plist)

Aniket Mishra (Sati) (Sep 23 2025 at 12:36):

@Robin Arnez thanks for the better minimal example, would you have any idea on why it's happening?


Last updated: Dec 20 2025 at 21:32 UTC