This PR refactors match compilation, to handle “side-effect free” patterns (`.var`, `.inaccessible`, `.as`) eagerly and for each alternative separately. The idea is that there should be less interplay between different alternatives, and prepares the ground for #11105. This may cause some corner case match statements to compiler or fail compile that behaved differently before. For example, it can now use a sparse case where previously was using a full case, and pattern completeness may not be clear to lean now. On the other hand, using a sparse case can mean that match statements mixing matching in indicies with matching on the indexed datatype can work.
47 lines
1.4 KiB
Text
47 lines
1.4 KiB
Text
set_option linter.unusedVariables false
|
||
|
||
/-! A variety of matches that failed at some point during the development of the sparse match features. -/
|
||
|
||
|
||
inductive Finn : Nat → Type where
|
||
| fzero : {n : Nat} → Finn n
|
||
| fsucc : {n : Nat} → Finn n → Finn (n+1)
|
||
|
||
def Finn.min (x : Bool) {n : Nat} (m : Nat) : Finn n → (f : Finn n) → Unit
|
||
| fzero, _ => ()
|
||
| _, fzero => ()
|
||
| fsucc i, fsucc j => ()
|
||
|
||
def boo (x : Fin 3) : Nat :=
|
||
match x with
|
||
| 0 => 1
|
||
| 1 => 2
|
||
| 2 => 4
|
||
|
||
-- This only works if we do not use the sparse cases on when there are no alternatives left
|
||
def List.nth : (as : List α) → (i : Fin as.length) → α
|
||
| a::as, ⟨0, _⟩ => a
|
||
| a::as, ⟨i+1, h⟩ => nth as ⟨i, Nat.lt_of_succ_lt_succ h⟩
|
||
|
||
-- set_option trace.Meta.Match.match true
|
||
|
||
-- This, taken from the standard library, used to work, but it was
|
||
-- fragile and broke with sparse matching and refacotrings in #11695
|
||
-- and the error message is rather helpful actually
|
||
|
||
/--
|
||
error: Missing cases:
|
||
_, (Int.negSucc _), _
|
||
-/
|
||
#guard_msgs in
|
||
example : (a b : Int) → (h : a * b = 0) → a = 0 ∨ b = 0
|
||
| .ofNat 0, _, _ => by simp
|
||
| _, .ofNat 0, _ => by simp
|
||
| .ofNat (a+1), .negSucc b, h => by cases h
|
||
|
||
-- We can fix it this way:
|
||
example : (a b : Int) → (h : a * b = 0) → a = 0 ∨ b = 0
|
||
| .ofNat 0, _, _ => by simp
|
||
| _, .ofNat 0, _ => by simp
|
||
| .ofNat (a+1), .negSucc b, h => by cases h
|
||
| .negSucc _, .negSucc _, h => by cases h
|