File: .lake/packages/lean4/src/lean/Lean/Meta/ExprDefEq.lean

full_name: Lean.Meta.backward.isDefEq.lazyProjDelta
code: register_builtin_option backward.isDefEq.lazyProjDelta : Bool := {
  defValue := true
  group    := "backward compatibility"
  descr    := "use lazy delta reduction when solving unification constrains of the form `(f a).i =?= (g b).i`"
}
goal: Lean.Option Bool

full_name: Lean.Meta.initFn._@..lake.packages.lean4.src.lean.Lean.Meta.ExprDefEq._hyg.6
code: register_builtin_option backward.isDefEq.lazyProjDelta : Bool := {
  defValue := true
  group    := "backward compatibility"
  descr    := "use lazy delta reduction when solving unification constrains of the form `(f a).i =?= (g b).i`"
}
goal: IO (Lean.Option Bool)

full_name: Lean.Meta.backward.isDefEq.lazyWhnfCore
code: register_builtin_option backward.isDefEq.lazyWhnfCore : Bool := {
  defValue := true
  group    := "backward compatibility"
  descr    := "specifies transparency mode when normalizing constraints of the form `(f a).i =?= s`, if `true` only reducible definitions and instances are unfolded when reducing `f a`. Otherwise, the default setting is used"
}
goal: Lean.Option Bool

full_name: Lean.Meta.initFn._@..lake.packages.lean4.src.lean.Lean.Meta.ExprDefEq._hyg.48
code: register_builtin_option backward.isDefEq.lazyWhnfCore : Bool := {
  defValue := true
  group    := "backward compatibility"
  descr    := "specifies transparency mode when normalizing constraints of the form `(f a).i =?= s`, if `true` only reducible definitions and instances are unfolded when reducing `f a`. Otherwise, the default setting is used"
}
goal: IO (Lean.Option Bool)

full_name: Lean.Meta.isAbstractedUnassignedMVar
code: /--
  Return `true` if `e` is of the form `fun (x_1 ... x_n) => ?m y_1 ... y_k)`, and `?m` is unassigned.
  Remark: `n`, `k` may be 0.
  This function is used to filter unification problems in
  `isDefEqArgs`/`isDefEqEtaStruct` where we can assign proofs.
  If one side is of the form described above, then we can likely assign `?m`.
  But it it's not, we would most likely apply proof irrelevance, which is
  usually very expensive since it needs to unify the types as well.
-/
def isAbstractedUnassignedMVar : Expr → MetaM Bool
  
goal: Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqEtaStruct.go
code: /--
  Return true if `b` is of the form `mk a.1 ... a.n`, and `a` is not a constructor application.

  If `a` and `b` are constructor applications, the method returns `false` to force `isDefEq` to use `isDefEqArgs`.
  For example, suppose we are trying to solve the constraint
  ```
  Fin.mk ?n ?h =?= Fin.mk n h
  ```
  If this method is applied, the constraints are reduced to
  ```
  n =?= (Fin.mk ?n ?h).1
  h =?= (Fin.mk ?n ?h).2
  ```
  The first constraint produces the assignment `?n := n`. Then, the second constraint is solved using proof irrelevance without
  assigning `?h`.
  TODO: investigate better solutions for the proof irrelevance issue. The problem above can happen is other scenarios.
  That is, proof irrelevance may prevent us from performing desired mvar assignments.
-/
private def isDefEqEtaStruct (a b : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqEtaStruct
code: /--
  Return true if `b` is of the form `mk a.1 ... a.n`, and `a` is not a constructor application.

  If `a` and `b` are constructor applications, the method returns `false` to force `isDefEq` to use `isDefEqArgs`.
  For example, suppose we are trying to solve the constraint
  ```
  Fin.mk ?n ?h =?= Fin.mk n h
  ```
  If this method is applied, the constraints are reduced to
  ```
  n =?= (Fin.mk ?n ?h).1
  h =?= (Fin.mk ?n ?h).2
  ```
  The first constraint produces the assignment `?n := n`. Then, the second constraint is solved using proof irrelevance without
  assigning `?h`.
  TODO: investigate better solutions for the proof irrelevance issue. The problem above can happen is other scenarios.
  That is, proof irrelevance may prevent us from performing desired mvar assignments.
-/
private def isDefEqEtaStruct (a b : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqEta
code: /--
  Try to solve `a := (fun x => t) =?= b` by eta-expanding `b`,
  resulting in `t =?= b x` (with a fresh free variable `x`).

  Remark: eta-reduction is not a good alternative even in a system without universe cumulativity like Lean.
  Example:
    ```
    (fun x : A => f ?m) =?= f
    ```
    The left-hand side of the constraint above it not eta-reduced because `?m` is a metavariable.

  Note: we do not backtrack after applying η-expansion anymore.
  There is no case where `(fun x => t) =?= b` unifies, but `t =?= b x` does not.
  Backtracking after η-expansion results in lots of duplicate δ-reductions,
  because we can δ-reduce `a` before and after the η-expansion.
  The fresh free variable `x` also busts the cache.
  See https://github.com/leanprover/lean4/pull/2002 -/
private def isDefEqEta (a b : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: Lean.Meta.isDefEqNative
code: /-- Support for `Lean.reduceBool` and `Lean.reduceNat` -/
def isDefEqNative (s t : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: Lean.Meta.isDefEqNat
code: /-- Support for reducing Nat basic operations. -/
def isDefEqNat (s t : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: Lean.Meta.isDefEqStringLit
code: /-- Support for constraints of the form `("..." =?= String.mk cs)` -/
def isDefEqStringLit (s t : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: Lean.Meta.isEtaUnassignedMVar
code: /--
  Return `true` if `e` is of the form `fun (x_1 ... x_n) => ?m x_1 ... x_n)`, and `?m` is unassigned.
  Remark: `n` may be 0. -/
def isEtaUnassignedMVar (e : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.trySynthPending
code: private def trySynthPending (e : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.DefEqArgsFirstPassResult.failed
code: /--
  Result type for `isDefEqArgsFirstPass`.
-/
inductive DefEqArgsFirstPassResult where
  /--
  Failed to establish that explicit arguments are def-eq.
  Remark: higher output parameters, and parameters that depend on them
  are postponed.
  -/
  | failed
  /--
  Succeeded. The array `postponedImplicit` contains the position
  of the implicit arguments for which def-eq has been postponed.
  `postponedHO` contains the higher order output parameters, and parameters
  that depend on them. They should be processed after the implicit ones.
  `postponedHO` is used to handle applications involving functions that
  contain higher order output parameters. Example:
  ```lean
  getElem :
    {cont : Type u_1} → {idx : Type u_2} → {elem : Type u_3} →
    {dom : cont → idx → Prop} → [self : GetElem cont idx elem dom] →
    (xs : cont) → (i : idx) → (h : dom xs i) → elem
  ```
  The arguments `dom` and `h` must be processed after all implicit arguments
  otherwise higher-order unification problems are generated. See issue #1299,
  when trying to solve
  ```
  getElem ?a ?i ?h =?= getElem a i (Fin.val_lt_of_le i ...)
  ```
  we have to solve the constraint
  ```
  ?dom a i.val =?= LT.lt i.val (Array.size a)
  ```
  by solving after the instance has been synthesized, we reduce this constraint to
  a simple check.
  -/
  | ok (postponedImplicit : Array Nat) (postponedHO : Array Nat)
goal: Lean.Meta.DefEqArgsFirstPassResult

full_name: Lean.Meta.DefEqArgsFirstPassResult
code: /--
  Result type for `isDefEqArgsFirstPass`.
-/
inductive DefEqArgsFirstPassResult where
  /--
  Failed to establish that explicit arguments are def-eq.
  Remark: higher output parameters, and parameters that depend on them
  are postponed.
  -/
  | failed
  /--
  Succeeded. The array `postponedImplicit` contains the position
  of the implicit arguments for which def-eq has been postponed.
  `postponedHO` contains the higher order output parameters, and parameters
  that depend on them. They should be processed after the implicit ones.
  `postponedHO` is used to handle applications involving functions that
  contain higher order output parameters. Example:
  ```lean
  getElem :
    {cont : Type u_1} → {idx : Type u_2} → {elem : Type u_3} →
    {dom : cont → idx → Prop} → [self : GetElem cont idx elem dom] →
    (xs : cont) → (i : idx) → (h : dom xs i) → elem
  ```
  The arguments `dom` and `h` must be processed after all implicit arguments
  otherwise higher-order unification problems are generated. See issue #1299,
  when trying to solve
  ```
  getElem ?a ?i ?h =?= getElem a i (Fin.val_lt_of_le i ...)
  ```
  we have to solve the constraint
  ```
  ?dom a i.val =?= LT.lt i.val (Array.size a)
  ```
  by solving after the instance has been synthesized, we reduce this constraint to
  a simple check.
  -/
  | ok (postponedImplicit : Array Nat) (postponedHO : Array Nat)
goal: Type

full_name: Lean.Meta.DefEqArgsFirstPassResult.ok
code: /--
  Result type for `isDefEqArgsFirstPass`.
-/
inductive DefEqArgsFirstPassResult where
  /--
  Failed to establish that explicit arguments are def-eq.
  Remark: higher output parameters, and parameters that depend on them
  are postponed.
  -/
  | failed
  /--
  Succeeded. The array `postponedImplicit` contains the position
  of the implicit arguments for which def-eq has been postponed.
  `postponedHO` contains the higher order output parameters, and parameters
  that depend on them. They should be processed after the implicit ones.
  `postponedHO` is used to handle applications involving functions that
  contain higher order output parameters. Example:
  ```lean
  getElem :
    {cont : Type u_1} → {idx : Type u_2} → {elem : Type u_3} →
    {dom : cont → idx → Prop} → [self : GetElem cont idx elem dom] →
    (xs : cont) → (i : idx) → (h : dom xs i) → elem
  ```
  The arguments `dom` and `h` must be processed after all implicit arguments
  otherwise higher-order unification problems are generated. See issue #1299,
  when trying to solve
  ```
  getElem ?a ?i ?h =?= getElem a i (Fin.val_lt_of_le i ...)
  ```
  we have to solve the constraint
  ```
  ?dom a i.val =?= LT.lt i.val (Array.size a)
  ```
  by solving after the instance has been synthesized, we reduce this constraint to
  a simple check.
  -/
  | ok (postponedImplicit : Array Nat) (postponedHO : Array Nat)
goal: Lean.Meta.DefEqArgsFirstPassResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqArgsFirstPass
code: /--
  First pass for `isDefEqArgs`. We unify explicit arguments, *and* easy cases
  Here, we say a case is easy if it is of the form

       ?m =?= t
       or
       t  =?= ?m

  where `?m` is unassigned.

  These easy cases are not just an optimization. When
  `?m` is a function, by assigning it to t, we make sure
  a unification constraint (in the explicit part)
  ```
  ?m t =?= f s
  ```
  is not higher-order.

  We also handle the eta-expanded cases:
  ```
  fun x₁ ... xₙ => ?m x₁ ... xₙ =?= t
  t =?= fun x₁ ... xₙ => ?m x₁ ... xₙ
  ```
  This is important because type inference often produces
  eta-expanded terms, and without this extra case, we could
  introduce counter intuitive behavior.

  Pre: `paramInfo.size <= args₁.size = args₂.size`

  See `DefEqArgsFirstPassResult` for additional information.
-/
private def isDefEqArgsFirstPass
    (paramInfo : Array ParamInfo) (args₁ args₂ : Array Expr) : MetaM DefEqArgsFirstPassResult 
goal: Lean.MetaM Lean.Meta.DefEqArgsFirstPassResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqArgs
code: private partial def isDefEqArgs (f : Expr) (args₁ args₂ : Array Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.isDefEqBindingDomain
code: /--
  Check whether the types of the free variables at `fvars` are
  definitionally equal to the types at `ds₂`.

  Pre: `fvars.size == ds₂.size`

  This method also updates the set of local instances, and invokes
  the continuation `k` with the updated set.

  We can't use `withNewLocalInstances` because the `isDeq fvarType d₂`
  may use local instances. -/
@[specialize] partial def isDefEqBindingDomain (fvars : Array Expr) (ds₂ : Array Expr) (k : MetaM Bool) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.isDefEqBindingDomain.loop
code: /--
  Check whether the types of the free variables at `fvars` are
  definitionally equal to the types at `ds₂`.

  Pre: `fvars.size == ds₂.size`

  This method also updates the set of local instances, and invokes
  the continuation `k` with the updated set.

  We can't use `withNewLocalInstances` because the `isDeq fvarType d₂`
  may use local instances. -/
@[specialize] partial def isDefEqBindingDomain (fvars : Array Expr) (ds₂ : Array Expr) (k : MetaM Bool) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqBindingAux
code: /--
Auxiliary function for `isDefEqBinding` for handling binders `forall/fun`.
It accumulates the new free variables in `fvars`, and declare them at `lctx`.
We use the domain types of `e₁` to create the new free variables.
We store the domain types of `e₂` at `ds₂`.
-/
private partial def isDefEqBindingAux (lctx : LocalContext) (fvars : Array Expr) (e₁ e₂ : Expr) (ds₂ : Array Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqBinding
code: @[inline] private def isDefEqBinding (a b : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.checkTypesAndAssign
code: private def checkTypesAndAssign (mvar : Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.collectLetDeclsFrom.visit
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MonadCacheT Lean.Expr Unit (ReaderT Nat (StateRefT' IO.RealWorld Lean.FVarIdHashSet Lean.MetaM)) Unit

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.hasLetDeclsInBetween
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.collectLetDeps
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM Lean.FVarIdHashSet

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.collectLetDeclsFrom
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: ReaderT Nat (StateRefT' IO.RealWorld Lean.FVarIdHashSet Lean.MetaM) Unit

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.addLetDeps
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM (Array Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM (Option Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkLambdaFVarsWithLetDeps.collectLetDepsAux
code: /--
Auxiliary method for solving constraints of the form `?m xs := v`.
It creates a lambda using `mkLambdaFVars ys v`, where `ys` is a superset of `xs`.
`ys` is often equal to `xs`. It is a bigger when there are let-declaration dependencies in `xs`.
For example, suppose we have `xs` of the form `#[a, c]` where
```
a : Nat
b : Nat := f a
c : b = a
```
In this scenario, the type of `?m` is `(x1 : Nat) -> (x2 : f x1 = x1) -> C[x1, x2]`,
and type of `v` is `C[a, c]`. Note that, `?m a c` is type correct since `f a = a` is definitionally equal
to the type of `c : b = a`, and the type of `?m a c` is equal to the type of `v`.
Note that `fun xs => v` is the term `fun (x1 : Nat) (x2 : b = x1) => v` which has type
`(x1 : Nat) -> (x2 : b = x1) -> C[x1, x2]` which is not definitionally equal to the type of `?m`,
and may not even be type correct.
The issue here is that we are not capturing the `let`-declarations.

This method collects let-declarations `y` occurring between `xs[0]` and `xs.back` s.t.
some `x` in `xs` depends on `y`.
`ys` is the `xs` with these extra let-declarations included.

In the example above, `ys` is `#[a, b, c]`, and `mkLambdaFVars ys v` produces
`fun a => let b := f a; fun (c : b = a) => v` which has a type definitionally equal to the type of `?m`.

Recall that the method `checkAssignment` ensures `v` does not contain offending `let`-declarations.

This method assumes that for any `xs[i]` and `xs[j]` where `i < j`, we have that `index of xs[i]` < `index of xs[j]`.
where the index is the position in the local context.
-/
private partial def mkLambdaFVarsWithLetDeps (xs : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Nat → ReaderT Nat (StateRefT' IO.RealWorld Lean.FVarIdHashSet Lean.MetaM) Unit

full_name: Lean.Meta.mkAuxMVar
code: def mkAuxMVar (lctx : LocalContext) (localInsts : LocalInstances) (type : Expr) (numScopeArgs : Nat := 0) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Lean.Meta.CheckAssignment.initFn._@..lake.packages.lean4.src.lean.Lean.Meta.ExprDefEq._hyg.5806
code: builtin_initialize checkAssignmentExceptionId : InternalExceptionId ← registerInternalExceptionId `checkAssignment
goal: IO Lean.InternalExceptionId

full_name: Lean.Meta.CheckAssignment.checkAssignmentExceptionId
code: builtin_initialize checkAssignmentExceptionId : InternalExceptionId ← registerInternalExceptionId `checkAssignment
goal: Lean.InternalExceptionId

full_name: Lean.Meta.CheckAssignment.initFn._@..lake.packages.lean4.src.lean.Lean.Meta.ExprDefEq._hyg.5827
code: builtin_initialize outOfScopeExceptionId : InternalExceptionId ← registerInternalExceptionId `outOfScope
goal: IO Lean.InternalExceptionId

full_name: Lean.Meta.CheckAssignment.outOfScopeExceptionId
code: builtin_initialize outOfScopeExceptionId : InternalExceptionId ← registerInternalExceptionId `outOfScope
goal: Lean.InternalExceptionId

full_name: Lean.Meta.CheckAssignment.State
code: structure State where
  cache : ExprStructMap Expr := {}
goal: Type

full_name: Lean.Meta.CheckAssignment.State.cache
code: structure State where
  cache : ExprStructMap Expr := {}
goal: Lean.ExprStructMap Lean.Expr

full_name: Lean.Meta.CheckAssignment.Context.rhs
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Lean.Expr

full_name: Lean.Meta.CheckAssignment.Context.hasCtxLocals
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Bool

full_name: Lean.Meta.CheckAssignment.Context.mvarDecl
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Lean.MetavarDecl

full_name: Lean.Meta.CheckAssignment.Context.mvarId
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Lean.MVarId

full_name: Lean.Meta.CheckAssignment.Context.fvars
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Array Lean.Expr

full_name: Lean.Meta.CheckAssignment.Context
code: structure Context where
  mvarId        : MVarId
  mvarDecl      : MetavarDecl
  fvars         : Array Expr
  hasCtxLocals  : Bool
  rhs           : Expr
goal: Type

full_name: Lean.Meta.CheckAssignment.CheckAssignmentM
code: abbrev CheckAssignmentM 
goal: Type

full_name: Lean.Meta.CheckAssignment.throwCheckAssignmentFailure
code: def throwCheckAssignmentFailure : CheckAssignmentM α 
goal: Lean.Meta.CheckAssignment.CheckAssignmentM α

full_name: Lean.Meta.CheckAssignment.throwOutOfScopeFVar
code: def throwOutOfScopeFVar : CheckAssignmentM α 
goal: Lean.Meta.CheckAssignment.CheckAssignmentM α

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.CheckAssignment.findCached?
code: private def findCached? (e : Expr) : CheckAssignmentM (Option Expr) 
goal: Lean.Meta.CheckAssignment.CheckAssignmentM (Option Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.CheckAssignment.cache
code: private def cache (e r : Expr) : CheckAssignmentM Unit 
goal: Lean.Meta.CheckAssignment.CheckAssignmentM Unit

full_name: Lean.Meta.CheckAssignment.instMonadCacheExprCheckAssignmentM
code: instance : MonadCache Expr Expr CheckAssignmentM 
goal: Lean.MonadCache Lean.Expr Lean.Expr Lean.Meta.CheckAssignment.CheckAssignmentM

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.CheckAssignment.addAssignmentInfo
code: private def addAssignmentInfo (msg : MessageData) : CheckAssignmentM MessageData 
goal: Lean.Meta.CheckAssignment.CheckAssignmentM Lean.MessageData

full_name: Lean.Meta.CheckAssignment.run
code: @[inline] def run (x : CheckAssignmentM Expr) (mvarId : MVarId) (fvars : Array Expr) (hasCtxLocals : Bool) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM (Option Lean.Expr)

full_name: Lean.Meta.CheckAssignmentQuick.check
code: partial def check
    (hasCtxLocals : Bool)
    (mctx : MetavarContext) (lctx : LocalContext) (mvarDecl : MetavarDecl) (mvarId : MVarId) (fvars : Array Expr) (e : Expr) : Bool 
goal: Bool

full_name: Lean.Meta.CheckAssignmentQuick.check.visit
code: partial def check
    (hasCtxLocals : Bool)
    (mctx : MetavarContext) (lctx : LocalContext) (mvarDecl : MetavarDecl) (mvarId : MVarId) (fvars : Array Expr) (e : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.skipAtMostNumBinders
code: /--
Auxiliary function used at `typeOccursCheckImp`.
Given `type`, it tries to eliminate "dependencies". For example, suppose we are trying to
perform the assignment `?m := f (?n a b)` where
```
?n : let k := g ?m; A -> h k ?m -> C
```
If we just perform occurs check `?m` at the type of `?n`, we get a failure, but
we claim these occurrences are ok because the type `?n a b : C`.
In the example above, `typeOccursCheckImp` invokes this function with `n := 2`.
Note that we avoid using `whnf` and `inferType` at `typeOccursCheckImp` to minimize the
performance impact of this extra check.

See test `typeOccursCheckIssue.lean` for an example where this refinement is needed.
The test is derived from a Mathlib file.
-/
private partial def skipAtMostNumBinders (type : Expr) (n : Nat) : Expr 
goal: Lean.Expr

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp.alreadyVisited
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: StateM (Lean.PtrSet Lean.Expr) Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp.occursCheck
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp.visitMVar
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp.visit
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: StateM (Lean.PtrSet Lean.Expr) Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp.visitApp
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: StateM (Lean.PtrSet Lean.Expr) Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheckImp
code: /-- `typeOccursCheck` implementation using unsafe (i.e., pointer equality) features. -/
private unsafe def typeOccursCheckImp (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.typeOccursCheck
code: /--
Check whether there are invalid occurrences of `mvarId` in the type of other metavariables in `v`.
For example, suppose we have
```
?m_1 : Nat
?m_2 : Fin ?m_1
```
The assignment `?m_1 := (?m_2).1` should not be accepted.
See issue #4405 for additional examples.
-/
private def typeOccursCheck (mctx : MetavarContext) (mvarId : MVarId) (v : Expr) : Bool 
goal: Bool

full_name: Lean.Meta.checkAssignment
code: /--
  Auxiliary function for handling constraints of the form `?m a₁ ... aₙ =?= v`.
  It will check whether we can perform the assignment
  ```
  ?m := fun fvars => v
  ```
  The result is `none` if the assignment can't be performed.
  The result is `some newV` where `newV` is a possibly updated `v`. This method may need
  to unfold let-declarations. -/
def checkAssignment (mvarId : MVarId) (fvars : Array Expr) (v : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM (Option Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignmentFOApproxAux
code: private def processAssignmentFOApproxAux (mvar : Expr) (args : Array Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignmentFOApprox
code: /--
  Auxiliary method for applying first-order unification. It is an approximation.
  Remark: this method is trying to solve the unification constraint:

      ?m a₁ ... aₙ =?= v

   It is uses processAssignmentFOApproxAux, if it fails, it tries to unfold `v`.

   We have added support for unfolding here because we want to be able to solve unification problems such as

      ?m Unit =?= ITactic

   where `ITactic` is defined as

   def ITactic := Tactic Unit
-/
private partial def processAssignmentFOApprox (mvar : Expr) (args : Array Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignmentFOApprox.loop
code: /--
  Auxiliary method for applying first-order unification. It is an approximation.
  Remark: this method is trying to solve the unification constraint:

      ?m a₁ ... aₙ =?= v

   It is uses processAssignmentFOApproxAux, if it fails, it tries to unfold `v`.

   We have added support for unfolding here because we want to be able to solve unification problems such as

      ?m Unit =?= ITactic

   where `ITactic` is defined as

   def ITactic := Tactic Unit
-/
private partial def processAssignmentFOApprox (mvar : Expr) (args : Array Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.simpAssignmentArgAux
code: private partial def simpAssignmentArgAux (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.simpAssignmentArg
code: /-- Auxiliary procedure for processing `?m a₁ ... aₙ =?= v`.
   We apply it to each `aᵢ`. It instantiates assigned metavariables if `aᵢ` is of the form `f[?n] b₁ ... bₘ`,
   and then removes metadata, and zeta-expand let-decls. -/
private def simpAssignmentArg (arg : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.assignConst
code: /-- Assign `mvar := fun a_1 ... a_{numArgs} => v`.
   We use it at `processConstApprox` and `isDefEqMVarSelf` -/
private def assignConst (mvar : Expr) (numArgs : Nat) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processConstApprox.defaultCase
code: /--
  Auxiliary procedure for solving `?m args =?= v` when `args[:patternVarPrefix]` contains
  only pairwise distinct free variables.
  Let `args[:patternVarPrefix] = #[a₁, ..., aₙ]`, and `args[patternVarPrefix:] = #[b₁, ..., bᵢ]`,
  this procedure first reduces the constraint to
  ```
  ?m a₁ ... aₙ =?= fun x₁ ... xᵢ => v
  ```
  where the left-hand-side is a constant function.
  Then, it tries to find the longest prefix `#[a₁, ..., aⱼ]` of `#[a₁, ..., aₙ]` such that the following assignment is valid.
  ```
  ?m := fun y₁ ... y‌ⱼ => (fun y_{j+1} ... yₙ x₁ ... xᵢ => v)[a₁/y₁, .., aⱼ/yⱼ]
  ```
  That is, after the longest prefix is found, we solve the constraint as the lhs was a pattern. See the definition of "pattern" above.
-/
private partial def processConstApprox (mvar : Expr) (args : Array Expr) (patternVarPrefix : Nat) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processConstApprox.go
code: /--
  Auxiliary procedure for solving `?m args =?= v` when `args[:patternVarPrefix]` contains
  only pairwise distinct free variables.
  Let `args[:patternVarPrefix] = #[a₁, ..., aₙ]`, and `args[patternVarPrefix:] = #[b₁, ..., bᵢ]`,
  this procedure first reduces the constraint to
  ```
  ?m a₁ ... aₙ =?= fun x₁ ... xᵢ => v
  ```
  where the left-hand-side is a constant function.
  Then, it tries to find the longest prefix `#[a₁, ..., aⱼ]` of `#[a₁, ..., aₙ]` such that the following assignment is valid.
  ```
  ?m := fun y₁ ... y‌ⱼ => (fun y_{j+1} ... yₙ x₁ ... xᵢ => v)[a₁/y₁, .., aⱼ/yⱼ]
  ```
  That is, after the longest prefix is found, we solve the constraint as the lhs was a pattern. See the definition of "pattern" above.
-/
private partial def processConstApprox (mvar : Expr) (args : Array Expr) (patternVarPrefix : Nat) (v : Expr) : MetaM Bool 
goal: Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processConstApprox
code: /--
  Auxiliary procedure for solving `?m args =?= v` when `args[:patternVarPrefix]` contains
  only pairwise distinct free variables.
  Let `args[:patternVarPrefix] = #[a₁, ..., aₙ]`, and `args[patternVarPrefix:] = #[b₁, ..., bᵢ]`,
  this procedure first reduces the constraint to
  ```
  ?m a₁ ... aₙ =?= fun x₁ ... xᵢ => v
  ```
  where the left-hand-side is a constant function.
  Then, it tries to find the longest prefix `#[a₁, ..., aⱼ]` of `#[a₁, ..., aₙ]` such that the following assignment is valid.
  ```
  ?m := fun y₁ ... y‌ⱼ => (fun y_{j+1} ... yₙ x₁ ... xᵢ => v)[a₁/y₁, .., aⱼ/yⱼ]
  ```
  That is, after the longest prefix is found, we solve the constraint as the lhs was a pattern. See the definition of "pattern" above.
-/
private partial def processConstApprox (mvar : Expr) (args : Array Expr) (patternVarPrefix : Nat) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processConstApprox.go.cont
code: /--
  Auxiliary procedure for solving `?m args =?= v` when `args[:patternVarPrefix]` contains
  only pairwise distinct free variables.
  Let `args[:patternVarPrefix] = #[a₁, ..., aₙ]`, and `args[patternVarPrefix:] = #[b₁, ..., bᵢ]`,
  this procedure first reduces the constraint to
  ```
  ?m a₁ ... aₙ =?= fun x₁ ... xᵢ => v
  ```
  where the left-hand-side is a constant function.
  Then, it tries to find the longest prefix `#[a₁, ..., aⱼ]` of `#[a₁, ..., aₙ]` such that the following assignment is valid.
  ```
  ?m := fun y₁ ... y‌ⱼ => (fun y_{j+1} ... yₙ x₁ ... xᵢ => v)[a₁/y₁, .., aⱼ/yⱼ]
  ```
  That is, after the longest prefix is found, we solve the constraint as the lhs was a pattern. See the definition of "pattern" above.
-/
private partial def processConstApprox (mvar : Expr) (args : Array Expr) (patternVarPrefix : Nat) (v : Expr) : MetaM Bool 
goal: Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignment.process
code: /-- Tries to solve `?m a₁ ... aₙ =?= v` by assigning `?m`.
    It assumes `?m` is unassigned. -/
private partial def processAssignment (mvarApp : Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignment
code: /-- Tries to solve `?m a₁ ... aₙ =?= v` by assigning `?m`.
    It assumes `?m` is unassigned. -/
private partial def processAssignment (mvarApp : Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.processAssignment'
code: /--
  Similar to processAssignment, but if it fails, compute v's whnf and try again.
  This helps to solve constraints such as `?m =?= { α := ?m, ... }.α`
  Note this is not perfect solution since we still fail occurs check for constraints such as
  ```lean
    ?m =?= List { α := ?m, β := Nat }.β
  ```
-/
private def processAssignment' (mvarApp : Expr) (v : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDeltaCandidate?
code: private def isDeltaCandidate? (t : Expr) : MetaM (Option ConstantInfo) 
goal: Lean.MetaM (Option Lean.ConstantInfo)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isListLevelDefEq
code: /-- Auxiliary method for isDefEqDelta -/
private def isListLevelDefEq (us vs : List Level) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqLeft
code: /-- Auxiliary method for isDefEqDelta -/
private def isDefEqLeft (fn : Name) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqRight
code: /-- Auxiliary method for isDefEqDelta -/
private def isDefEqRight (fn : Name) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqLeftRight
code: /-- Auxiliary method for isDefEqDelta -/
private def isDefEqLeftRight (fn : Name) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isNonTrivialRegular.consumeDefnPreamble
code: /-- Helper predicate for `tryHeuristic`. -/
private def isNonTrivialRegular (info : DefinitionVal) : MetaM Bool 
goal: Lean.Expr

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isNonTrivialRegular
code: /-- Helper predicate for `tryHeuristic`. -/
private def isNonTrivialRegular (info : DefinitionVal) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isNonTrivialRegular.isSimple
code: /-- Helper predicate for `tryHeuristic`. -/
private def isNonTrivialRegular (info : DefinitionVal) : MetaM Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.tryHeuristic
code: /-- Try to solve `f a₁ ... aₙ =?= f b₁ ... bₙ` by solving `a₁ =?= b₁, ..., aₙ =?= bₙ`.

    Auxiliary method for isDefEqDelta -/
private def tryHeuristic (t s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfold
code: /-- Auxiliary method for isDefEqDelta -/
private abbrev unfold (e : Expr) (failK : MetaM α) (successK : Expr → MetaM α) : MetaM α 
goal: Lean.MetaM α

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldBothDefEq
code: /-- Auxiliary method for isDefEqDelta -/
private def unfoldBothDefEq (fn : Name) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.sameHeadSymbol
code: private def sameHeadSymbol (t s : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldComparingHeadsDefEq
code: /--
  - If headSymbol (unfold t) == headSymbol s, then unfold t
  - If headSymbol (unfold s) == headSymbol t, then unfold s
  - Otherwise unfold t and s if possible.

  Auxiliary method for isDefEqDelta -/
private def unfoldComparingHeadsDefEq (tInfo sInfo : ConstantInfo) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldDefEq
code: /-- If `t` and `s` do not contain metavariables, then use
    kernel definitional equality heuristics.
    Otherwise, use `unfoldComparingHeadsDefEq`.

    Auxiliary method for isDefEqDelta -/
private def unfoldDefEq (tInfo sInfo : ConstantInfo) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldReducibeDefEq
code: /--
  When `TransparencyMode` is set to `default` or `all`.
  If `t` is reducible and `s` is not ==> `isDefEqLeft  (unfold t) s`
  If `s` is reducible and `t` is not ==> `isDefEqRight t (unfold s)`

  Otherwise, use `unfoldDefEq`

  Auxiliary method for isDefEqDelta -/
private def unfoldReducibeDefEq (tInfo sInfo : ConstantInfo) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldNonProjFnDefEq.packedInstanceOf?
code: /--
  This is an auxiliary method for isDefEqDelta.
  If `t` is a (non-class) projection function application and `s` is not ==> `isDefEqRight t (unfold s)`
  If `s` is a (non-class) projection function application and `t` is not ==> `isDefEqRight (unfold t) s`
  Otherwise, use `unfoldReducibeDefEq`

  One motivation for the heuristic above is unification problems such as
  ```
  id (?m.1) =?= (a, b).1
  ```
  We want to reduce the lhs instead of the rhs, and eventually assign `?m := (a, b)`.

  Another motivation for the heuristic above is unification problems such as
  ```
  List.length (a :: as) =?= HAdd.hAdd (List.length as) 1
  ```

  However, for class projections, we also unpack them and check whether the result function is the one
  on the other side. This is relevant for unification problems such as
  ```
  Foo.pow x 256 =?= Pow.pow x 256
  ```
  where the the `Pow` instance is wrapping `Foo.pow`
  See issue #1419 for the complete example.
-/
private partial def unfoldNonProjFnDefEq (tInfo sInfo : ConstantInfo) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM (Option Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unfoldNonProjFnDefEq
code: /--
  This is an auxiliary method for isDefEqDelta.
  If `t` is a (non-class) projection function application and `s` is not ==> `isDefEqRight t (unfold s)`
  If `s` is a (non-class) projection function application and `t` is not ==> `isDefEqRight (unfold t) s`
  Otherwise, use `unfoldReducibeDefEq`

  One motivation for the heuristic above is unification problems such as
  ```
  id (?m.1) =?= (a, b).1
  ```
  We want to reduce the lhs instead of the rhs, and eventually assign `?m := (a, b)`.

  Another motivation for the heuristic above is unification problems such as
  ```
  List.length (a :: as) =?= HAdd.hAdd (List.length as) 1
  ```

  However, for class projections, we also unpack them and check whether the result function is the one
  on the other side. This is relevant for unification problems such as
  ```
  Foo.pow x 256 =?= Pow.pow x 256
  ```
  where the the `Pow` instance is wrapping `Foo.pow`
  See issue #1419 for the complete example.
-/
private partial def unfoldNonProjFnDefEq (tInfo sInfo : ConstantInfo) (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqDelta
code: /--
  isDefEq by lazy delta reduction.
  This method implements many different heuristics:
  1- If only `t` can be unfolded => then unfold `t` and continue
  2- If only `s` can be unfolded => then unfold `s` and continue
  3- If `t` and `s` can be unfolded and they have the same head symbol, then
     a) First try to solve unification by unifying arguments.
     b) If it fails, unfold both and continue.
     Implemented by `unfoldBothDefEq`
  4- If `t` is a projection function application and `s` is not => then unfold `s` and continue.
  5- If `s` is a projection function application and `t` is not => then unfold `t` and continue.
  Remark: 4&5 are implemented by `unfoldNonProjFnDefEq`
  6- If `t` is reducible and `s` is not => then unfold `t` and continue.
  7- If `s` is reducible and `t` is not => then unfold `s` and continue
  Remark: 6&7 are implemented by `unfoldReducibeDefEq`
  8- If `t` and `s` do not contain metavariables, then use heuristic used in the Kernel.
     Implemented by `unfoldDefEq`
  9- If `headSymbol (unfold t) == headSymbol s`, then unfold t and continue.
  10- If `headSymbol (unfold s) == headSymbol t`, then unfold s
  11- Otherwise, unfold `t` and `s` and continue.
  Remark: 9&10&11 are implemented by `unfoldComparingHeadsDefEq` -/
private def isDefEqDelta (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isAssigned
code: private def isAssigned : Expr → MetaM Bool
  
goal: Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.expandDelayedAssigned?
code: private def expandDelayedAssigned? (t : Expr) : MetaM (Option Expr) 
goal: Lean.MetaM (Option Lean.Expr)

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isAssignable
code: private def isAssignable : Expr → MetaM Bool
  
goal: Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.etaEq
code: private def etaEq (t s : Expr) : Bool 
goal: Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.withProofIrrelTransparency
code: /--
  Helper method for implementing `isDefEqProofIrrel`. Execute `k` with a transparency setting
  that is at least as strong as `.default`. This is important for modules that use the `.reducible`
  setting (e.g., `simp`, `rw`, etc). We added this feature to address issue #1302.
  ```lean
  @[simp] theorem get_cons_zero {as : List α} : (a :: as).get ⟨0, Nat.zero_lt_succ _⟩ = a := rfl

  example (a b c : α) : [a, b, c].get ⟨0, by simp⟩ = a := by simp
  ```
  In the example above `simp` fails to use `get_cons_zero` because it fails to establish that
  the proof objects are definitionally equal using proof irrelevance. In this example,
  the propositions are
  ```lean
  0 < Nat.succ (List.length [b, c]) =?= 0 < Nat.succ (Nat.succ (Nat.succ 0))
  ```
  So, unless we can unfold `List.length`, it fails.

  Remark: if this becomes a performance bottleneck, we should add a flag to control when it is used.
  Then, we can enable the flag only when applying `simp` and `rw` theorems.
-/
private def withProofIrrelTransparency (k : MetaM α) : MetaM α 
goal: Lean.MetaM α

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProofIrrel
code: private def isDefEqProofIrrel (t s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqMVarSelf
code: /-- Try to solve constraint of the form `?m args₁ =?= ?m args₂`.
   - First try to unify `args₁` and `args₂`, and return true if successful
   - Otherwise, try to assign `?m` to a constant function of the form `fun x_1 ... x_n => ?n`
     where `?n` is a fresh metavariable. See `assignConst`. -/
private def isDefEqMVarSelf (mvar : Expr) (args₁ args₂ : Array Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.consumeLet
code: /--
Removes unnecessary let-decls (both true `let`s and `let_fun`s).
-/
private partial def consumeLet : Expr → Expr
  
goal: Lean.Expr → Lean.Expr

full_name: Lean.Meta.whenUndefDo
code: @[inline] def whenUndefDo (x : MetaM LBool) (k : MetaM Bool) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.unstuckMVar
code: @[specialize] private def unstuckMVar (e : Expr) (successK : Expr → MetaM Bool) (failK : MetaM Bool): MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqOnFailure
code: private def isDefEqOnFailure (t s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.DeltaStepResult.unknown
code: /--
Result type for `isDefEqDelta`
-/
inductive DeltaStepResult where
  | eq | unknown
  | cont (t s : Expr)
  | diff (t s : Expr)
goal: Lean.Meta.DeltaStepResult

full_name: Lean.Meta.DeltaStepResult.cont
code: /--
Result type for `isDefEqDelta`
-/
inductive DeltaStepResult where
  | eq | unknown
  | cont (t s : Expr)
  | diff (t s : Expr)
goal: Lean.Meta.DeltaStepResult

full_name: Lean.Meta.DeltaStepResult.eq
code: /--
Result type for `isDefEqDelta`
-/
inductive DeltaStepResult where
  | eq | unknown
  | cont (t s : Expr)
  | diff (t s : Expr)
goal: Lean.Meta.DeltaStepResult

full_name: Lean.Meta.DeltaStepResult
code: /--
Result type for `isDefEqDelta`
-/
inductive DeltaStepResult where
  | eq | unknown
  | cont (t s : Expr)
  | diff (t s : Expr)
goal: Type

full_name: Lean.Meta.DeltaStepResult.diff
code: /--
Result type for `isDefEqDelta`
-/
inductive DeltaStepResult where
  | eq | unknown
  | cont (t s : Expr)
  | diff (t s : Expr)
goal: Lean.Meta.DeltaStepResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqDeltaStep
code: /--
Perform one step of lazy delta reduction. This function decides whether to perform delta-reduction on `t`, `s`, or both.
It is currently used to solve contraints of the form `(f a).i =?= (g a).i` where `i` is a numeral at `isDefEqProjDelta`.
It is also a simpler version of `isDefEqDelta`. In the future, we may decide to combine these two functions like we do
in the kernel.
-/
private def isDefEqDeltaStep (t s : Expr) : MetaM DeltaStepResult 
goal: Lean.MetaM Lean.Meta.DeltaStepResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqDeltaStep.k
code: /--
Perform one step of lazy delta reduction. This function decides whether to perform delta-reduction on `t`, `s`, or both.
It is currently used to solve contraints of the form `(f a).i =?= (g a).i` where `i` is a numeral at `isDefEqProjDelta`.
It is also a simpler version of `isDefEqDelta`. In the future, we may decide to combine these two functions like we do
in the kernel.
-/
private def isDefEqDeltaStep (t s : Expr) : MetaM DeltaStepResult 
goal: Lean.MetaM Lean.Meta.DeltaStepResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqDeltaStep.unfoldBoth
code: /--
Perform one step of lazy delta reduction. This function decides whether to perform delta-reduction on `t`, `s`, or both.
It is currently used to solve contraints of the form `(f a).i =?= (g a).i` where `i` is a numeral at `isDefEqProjDelta`.
It is also a simpler version of `isDefEqDelta`. In the future, we may decide to combine these two functions like we do
in the kernel.
-/
private def isDefEqDeltaStep (t s : Expr) : MetaM DeltaStepResult 
goal: Lean.MetaM Lean.Meta.DeltaStepResult

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProjDelta
code: /--
Helper function for solving contraints of the form `t.i =?= s.i`.
-/
private partial def isDefEqProjDelta (t s : Expr) (i : Nat) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProjDelta.loop
code: /--
Helper function for solving contraints of the form `t.i =?= s.i`.
-/
private partial def isDefEqProjDelta (t s : Expr) (i : Nat) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProjDelta.tryReduceProjs
code: /--
Helper function for solving contraints of the form `t.i =?= s.i`.
-/
private partial def isDefEqProjDelta (t s : Expr) (i : Nat) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProj
code: private def isDefEqProj : Expr → Expr → MetaM Bool
  
goal: Lean.Expr → Lean.Expr → Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProj.isDefEqSingleton
code: private def isDefEqProj : Expr → Expr → MetaM Bool
  
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqApp
code: /--
  Given applications `t` and `s` that are in WHNF (modulo the current transparency setting),
  check whether they are definitionally equal or not.
-/
private def isDefEqApp (t s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqUnitLike
code: /-- Return `true` if the type of the given expression is an inductive datatype with a single constructor with no fields. -/
private def isDefEqUnitLike (t : Expr) (s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isDefEqProjInst
code: /--
  The `whnf` procedure has support for unfolding class projections when the
  transparency mode is set to `.instances`. This method ensures the behavior
  of `whnf` and `isDefEq` is consistent in this transparency mode.
-/
private def isDefEqProjInst (t : Expr) (s : Expr) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.isExprDefEqExpensive
code: private def isExprDefEqExpensive (t : Expr) (s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.DefEqCacheKind.transient
code: inductive DefEqCacheKind where
  | transient -- problem has mvars or is using nonstandard configuration, we should use transient cache
  | permanent
goal: Lean.Meta.DefEqCacheKind

full_name: Lean.Meta.DefEqCacheKind.permanent
code: inductive DefEqCacheKind where
  | transient -- problem has mvars or is using nonstandard configuration, we should use transient cache
  | permanent
goal: Lean.Meta.DefEqCacheKind

full_name: Lean.Meta.DefEqCacheKind
code: inductive DefEqCacheKind where
  | transient -- problem has mvars or is using nonstandard configuration, we should use transient cache
  | permanent
goal: Type

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.getDefEqCacheKind
code: private def getDefEqCacheKind (t s : Expr) : MetaM DefEqCacheKind 
goal: Lean.MetaM Lean.Meta.DefEqCacheKind

full_name: Lean.Meta.DefEqCacheKeyInfo.key
code: /--
Structure for storing defeq cache key information.
-/
structure DefEqCacheKeyInfo where
  kind : DefEqCacheKind
  key  : Expr × Expr
goal: Lean.Expr × Lean.Expr

full_name: Lean.Meta.DefEqCacheKeyInfo.kind
code: /--
Structure for storing defeq cache key information.
-/
structure DefEqCacheKeyInfo where
  kind : DefEqCacheKind
  key  : Expr × Expr
goal: Lean.Meta.DefEqCacheKind

full_name: Lean.Meta.DefEqCacheKeyInfo
code: /--
Structure for storing defeq cache key information.
-/
structure DefEqCacheKeyInfo where
  kind : DefEqCacheKind
  key  : Expr × Expr
goal: Type

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.mkCacheKey
code: private def mkCacheKey (t s : Expr) : MetaM DefEqCacheKeyInfo 
goal: Lean.MetaM Lean.Meta.DefEqCacheKeyInfo

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.getCachedResult
code: private def getCachedResult (keyInfo : DefEqCacheKeyInfo) : MetaM LBool 
goal: Lean.MetaM Lean.LBool

full_name: Lean.Meta.DefEqCache.update
code: def DefEqCache.update (cache : DefEqCache) (mode : TransparencyMode) (key : Expr × Expr) (result : Bool) : DefEqCache 
goal: Lean.Meta.DefEqCache

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.cacheResult
code: private def cacheResult (keyInfo : DefEqCacheKeyInfo) (result : Bool) : MetaM Unit 
goal: Lean.MetaM Unit

full_name: _private.«.lake».packages.lean4.src.lean.Lean.Meta.ExprDefEq.0.Lean.Meta.whnfCoreAtDefEq
code: private def whnfCoreAtDefEq (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Lean.Meta.isExprDefEqAuxImpl
code: @[export lean_is_expr_def_eq]
partial def isExprDefEqAuxImpl (t : Expr) (s : Expr) : MetaM Bool 
goal: Lean.MetaM Bool

full_name: Lean.Meta.initFn._@..lake.packages.lean4.src.lean.Lean.Meta.ExprDefEq._hyg.20860
code: builtin_initialize
  registerTraceClass `Meta.isDefEq
  registerTraceClass `Meta.isDefEq.stuck
  registerTraceClass `Meta.isDefEq.stuckMVar (inherited := true)
  registerTraceClass `Meta.isDefEq.cache
  registerTraceClass `Meta.isDefEq.foApprox (inherited := true)
  registerTraceClass `Meta.isDefEq.onFailure (inherited := true)
  registerTraceClass `Meta.isDefEq.constApprox (inherited := true)
  registerTraceClass `Meta.isDefEq.delta
  registerTraceClass `Meta.isDefEq.delta.unfoldLeft (inherited := true)
  registerTraceClass `Meta.isDefEq.delta.unfoldRight (inherited := true)
  registerTraceClass `Meta.isDefEq.delta.unfoldLeftRight (inherited := true)
  registerTraceClass `Meta.isDefEq.assign
  registerTraceClass `Meta.isDefEq.assign.checkTypes (inherited := true)
  registerTraceClass `Meta.isDefEq.assign.outOfScopeFVar (inherited := true)
  registerTraceClass `Meta.isDefEq.assign.beforeMkLambda (inherited := true)
  registerTraceClass `Meta.isDefEq.assign.typeError (inherited := true)
  registerTraceClass `Meta.isDefEq.assign.occursCheck (inherited := true)
  registerTraceClass `Meta.isDefEq.assign.readOnlyMVarWithBiggerLCtx (inherited := true)
  registerTraceClass `Meta.isDefEq.eta.struct
goal: IO Unit