This PR adds “non-branching case statements”: For each inductive
constructor `T.con` this adds a function `T.con.with` that is similar
`T.casesOn`, but has only one arm (the one for `con`), and an additional
`t.toCtorIdx = 12` assumption.
For example:
```lean
inductive Vec (α : Type) : Nat → Type where
| nil : Vec α 0
| cons {n} : α → Vec α n → Vec α (n + 1)
/--
info: @[reducible] protected def Vec.cons.elim.{u} : {α : Type} →
{motive : (a : Nat) → Vec α a → Sort u} →
{a : Nat} →
(t : Vec α a) →
t.ctorIdx = 1 → ({n : Nat} → (a : α) → (a_1 : Vec α n) → motive (n + 1) (Vec.cons a a_1)) → motive a t
-/
#guard_msgs in
#print sig Vec.cons.elim
```
This is a building block for non-quadratic implementations of `BEq` and
`DecidableEq` etc.
Builds on top of #9951.
The compiled code for a these functions could presumably, without
branching on the inductive value, directly access the fields. Achieving
this optimization (and achieving it without a quadratic compilation
cost) is not in scope for this PR.
64 lines
2.2 KiB
Text
64 lines
2.2 KiB
Text
/-!
|
||
This test tests and also explains the noConfusionType construction.
|
||
|
||
It contains copies of the definitions of the constructions, for manual experimentation with
|
||
the code, and uses `#guard_msgs` and `rfl` to compare them to the generated ones.
|
||
|
||
This also serves as documentation to the `NoConfusionLinear` module, so do not delete or remove
|
||
from this file without updating that module's docstring.
|
||
-/
|
||
|
||
-- set_option debug.skipKernelTC true
|
||
|
||
inductive Vec.{u} (α : Type) : Nat → Type u where
|
||
| nil : Vec α 0
|
||
| cons {n} : α → Vec α n → Vec α (n + 1)
|
||
|
||
@[reducible] protected def Vec.noConfusionType'.{u_1, u} : {α : Type} →
|
||
{a : Nat} → Sort u_1 → Vec.{u} α a → Vec α a → Sort u_1 :=
|
||
fun P x1 x2 =>
|
||
Vec.casesOn x1
|
||
(if h : x2.ctorIdx = 0 then
|
||
Vec.nil.elim (motive := fun _ _ => Sort u_1) x2 h (P → P)
|
||
else P)
|
||
(fun {n} a_1 a_2 => if h : x2.ctorIdx = 1 then
|
||
Vec.cons.elim (motive := fun _ _ => Sort u_1) x2 h fun {n_1} a a_3 => (n = n_1 → a_1 = a → a_2 ≍ a_3 → P) → P
|
||
else P)
|
||
|
||
/--
|
||
info: @[reducible] protected def Vec.noConfusionType.{u_1, u} : {α : Type} →
|
||
{a : Nat} → Sort u_1 → Vec α a → Vec α a → Sort u_1 :=
|
||
fun {α} {a} P x1 x2 =>
|
||
Vec.casesOn x1 (if h : x2.ctorIdx = 0 then Vec.nil.elim x2 h (P → P) else P) fun {n} a_1 a_2 =>
|
||
if h : x2.ctorIdx = 1 then Vec.cons.elim x2 h fun {n_1} a a_3 => (n = n_1 → a_1 = a → a_2 ≍ a_3 → P) → P else P
|
||
-/
|
||
#guard_msgs in
|
||
#print Vec.noConfusionType
|
||
|
||
example : @Vec.noConfusionType.{u_1,u} = @Vec.noConfusionType'.{u_1,u} := rfl
|
||
|
||
/-
|
||
run_meta do
|
||
let mut i := 0
|
||
for (n, _c) in (← getEnv).constants do
|
||
if let .str indName "noConfusion" := n then
|
||
let ConstantInfo.inductInfo _ ← getConstInfo indName | continue
|
||
logInfo m!"Looking at {.ofConstName indName}"
|
||
mkToCtorIdx' indName
|
||
mkWithCtorType indName
|
||
mkWithCtor indName
|
||
mkNoConfusionType' indName
|
||
i := i + 1
|
||
if i > 10 then
|
||
return
|
||
-/
|
||
|
||
-- inductive Enum.{u} : Type u where | a | b
|
||
-- set_option pp.universes true in
|
||
-- #print noConfusionTypeEnum
|
||
|
||
-- A possibly tricky universes case (resulting universe cannot be decremented)
|
||
|
||
inductive UnivTest.{u,v} (α : Sort v): Sort (max u v 1) where
|
||
| mk1 : UnivTest α
|
||
| mk2 : (x : α) → UnivTest α
|