lean4-htt/src/Lean/Elab/PreDefinition/Structural/IndGroupInfo.lean
Paul Reichert 6e538c35dd
refactor: migrate all usages of old slice notation (#9000)
This PR replaces all usages of `[:]` slice notation in `src` with the
new `[...]` notation in production code, tests and comments. The
underlying implementation of the `Subarray` functions stays the same.

Notation cheat sheet:

* `*...*` is the doubly-unbounded range.
* `*...a` or `*...<a` contains all elements that are less than `a`.
* `*...=a` contains all elements that are less than or equal to `a`.
* `a...*` contains all elements that are greater than or equal to `a`.
* `a...b` or `a...<b` contains all elements that are greater than or
equal to `a` and less than `b`.
* `a...=b` contains all elements that are greater than or equal to `a`
and less than or equal to `b`.
* `a<...*` contains all elements that are greater than `a`.
* `a<...b` or `a<...<b` contains all elements that are greater than `a`
and less than `b`.
* `a<...=b` contains all elements that are greater than `a` and less
than or equal to `b`.

Benchmarks have shown that importing the iterator-backed parts of the
polymorphic slice library in `Init` impacts build performance. This PR
avoids this problem by separating those parts of the library that do not
rely on iterators from those those that do. Whereever the new slice
notation is used, only the iterator-independent files are imported.
2025-06-27 18:52:07 +00:00

109 lines
3.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joachim Breitner
-/
prelude
import Lean.Meta.InferType
/-!
This module contains the types
* `IndGroupInfo`, a variant of `InductiveVal` with information that
applies to a whole group of mutual inductives and
* `IndGroupInst` which extends `IndGroupInfo` with levels and parameters
to indicate a instantiation of the group.
One purpose of this abstraction is to make it clear when a function operates on a group as
a whole, rather than a specific inductive within the group.
-/
namespace Lean.Elab.Structural
open Lean Meta
/--
A mutually inductive group, identified by the `all` array of the `InductiveVal` of its
constituents.
-/
structure IndGroupInfo where
all : Array Name
numNested : Nat
deriving BEq, Inhabited, Repr
def IndGroupInfo.ofInductiveVal (indInfo : InductiveVal) : IndGroupInfo where
all := indInfo.all.toArray
numNested := indInfo.numNested
def IndGroupInfo.numMotives (group : IndGroupInfo) : Nat :=
group.all.size + group.numNested
/-- Instantiates the right `.brecOn` for the given type former index,
including universe parameters and fixed prefix. -/
partial def IndGroupInfo.brecOnName (info : IndGroupInfo) (idx : Nat) : Name :=
if let .some n := info.all[idx]? then
mkBRecOnName n
else
let j := idx - info.all.size + 1
info.brecOnName 0 |>.appendIndexAfter j
/--
An instance of an mutually inductive group of inductives, identified by the `all` array
and the level and expressions parameters.
For example this distinguishes between `List α` and `List β` so that we will not even attempt
mutual structural recursion on such incompatible types.
-/
structure IndGroupInst extends IndGroupInfo where
levels : List Level
params : Array Expr
deriving Inhabited, Repr
def IndGroupInst.toMessageData (igi : IndGroupInst) : MessageData :=
mkAppN (.const igi.all[0]! igi.levels) igi.params
instance : ToMessageData IndGroupInst where
toMessageData := IndGroupInst.toMessageData
def IndGroupInst.isDefEq (igi1 igi2 : IndGroupInst) : MetaM Bool := do
unless igi1.toIndGroupInfo == igi2.toIndGroupInfo do return false
unless igi1.levels.length = igi2.levels.length do return false
unless (igi1.levels.zip igi2.levels).all (fun (l₁, l₂) => Level.isEquiv l₁ l₂) do return false
unless igi1.params.size = igi2.params.size do return false
unless (← (igi1.params.zip igi2.params).allM (fun (e₁, e₂) => Meta.isDefEqGuarded e₁ e₂)) do return false
return true
/-- Instantiates the right `.brecOn` for the given type former index,
including universe parameters and fixed prefix. -/
def IndGroupInst.brecOn (group : IndGroupInst) (lvl : Level) (idx : Nat) : Expr :=
let n := group.brecOnName idx
let us := lvl :: group.levels
mkAppN (.const n us) group.params
/--
Figures out the nested type formers of an inductive group, with parameters instantiated
and indices still forall-abstracted.
For example given a nested inductive
```
inductive Tree α where | node : α → Vector (Tree α) n → Tree α
```
(where `n` is an index of `Vector`) and the instantiation `Tree Int` it will return
```
#[(n : Nat) → Vector (Tree Int) n]
```
-/
def IndGroupInst.nestedTypeFormers (igi : IndGroupInst) : MetaM (Array Expr) := do
if igi.numNested = 0 then return #[]
-- We extract this information from the motives of the recursor
let recName := mkRecName igi.all[0]!
let recInfo ← getConstInfoRec recName
assert! recInfo.numMotives = igi.numMotives
let aux := mkAppN (.const recName (0 :: igi.levels)) igi.params
let motives ← inferArgumentTypesN recInfo.numMotives aux
let auxMotives : Array Expr := motives[igi.all.size...*]
auxMotives.mapM fun motive =>
forallTelescopeReducing motive fun xs _ => do
assert! xs.size > 0
mkForallFVars xs.pop (← inferType xs.back!)
end Lean.Elab.Structural