Note: Type compatibility checking for LCNF #
We used to have a type compatibility relation ≃
for LCNF types.
It treated erased types/values as wildcards. Examples:
We used this relation to sanity check compiler passes, and detect
buggy transformations that broke type compatibility. For example,
given an application f a
, we would check whether a
s type as
compatible with the type expected by f
.
However, the type compatibility relation is not transitive. Example:
We tried address the issue above by adding casts, which required us
to then add cast
elimination simplifications, and generated a significant overhead in
the code generator.
Here is an example of transformation that would require the insertion of a cast operation.
def foo (g : List A → List A) (a : List B) :=
fun f (x : List ◾) :=
let _x.1 := g x
...
let _x.2 := f a
...
The code above would not trigger any type compatibility issue, but
by inlining f
without adding cast operations, we would get the
following type incorrect code.
def foo (g : List A → List A) (a : List B) :=
let _x.2 := g a -- Type error
...
We have considered using a reflexive and transitive subtype relation ≺
.
A ≺ A
(Nat × Nat) ≺ (Nat × ◾) ≺ (◾ × ◾) ≺ ◾
List Nat ≺ List ◾ ⊀ List String
(List ◾ → List Nat) ≺ (List Bool → List ◾)
Note thatA ≺ B
impliesA ≃ B
The subtype relation has better properties, but also has problems.
First, when converting to LCNF we would have to add more casts. Example:
the function takes a List ◾
, but the value has type ◾
.
Moreover, recall that (List Nat → List Nat) ⊀ (◾ → ◾)
forcing us
to add many casts operations when moving to the mono phase where
we erase type parameters.
Recall that type compatibility and subtype relationships do not help with memory layout.
We have that (UInt32 × UInt32) ≺ (◾ × ◾) ≺ ◾
but elements of these types have
different runtime representation.
Thus, we have decided to abandon the type compatibility checks and cast operations in LCNF. The only drawback is that we lose the capability of catching simple bugs at compiler passes.
In the future, we can try to add a sanity check flag that instructs the compiler to use the subtype relation in sanity checks and add the necessary casts.
- jps : Lean.FVarIdSet
Join points that are in scope.
- vars : Lean.FVarIdSet
Variables and local functions in scope
Instances For
- all : Lean.FVarIdHashSet
All free variables found
Instances For
Equations
Instances For
Equations
- Lean.Compiler.LCNF.Check.checkTypes = do let __do_lift ← liftM Lean.Compiler.LCNF.getConfig pure __do_lift.checkTypes
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Return true f
is a constructor and i
is less than its number of parameters.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Compiler.LCNF.Check.checkParams params = Array.forM Lean.Compiler.LCNF.Check.checkParam params 0 (Array.size params)
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Compiler.LCNF.Check.withFVarId fvarId x = do Lean.Compiler.LCNF.Check.addFVarId fvarId withReader (fun ctx => { jps := ctx.jps, vars := Lean.FVarIdSet.insert ctx.vars fvarId }) x
Instances For
Equations
- Lean.Compiler.LCNF.Check.withJp fvarId x = do Lean.Compiler.LCNF.Check.addFVarId fvarId withReader (fun ctx => { jps := Lean.FVarIdSet.insert ctx.jps fvarId, vars := ctx.vars }) x
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Compiler.LCNF.Decl.check decl = Lean.Compiler.LCNF.Check.run (Lean.Compiler.LCNF.Check.checkFunDeclCore decl.name decl.params decl.type decl.value)
Instances For
Check whether every local declaration in the local context is used in one of given decls
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Compiler.LCNF.checkDeadLocalDecls.visitFVar fvarId = modify fun x => Lean.HashSet.insert x fvarId