Skip to content

fix: fun_cases when a goal variable depends on a match discriminant - #15737

Merged
sgraf812 merged 1 commit into
leanprover:masterfrom
sgraf812:sg/fun-cases-index-match
Oct 20, 2026
Merged

sgraf812 merged 1 commit into
leanprover:masterfrom
sgraf812:sg/fun-cases-index-match

Conversation

@sgraf812

@sgraf812 sgraf812 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes fun_cases and fun_induction for a match whose discriminant appears in the type of another variable in the goal.

Example:

inductive W where | a | b

inductive Op : W → Type where
  | y : Fin w.ctorIdx → Op w

def Op.f {w} (i : Op w) : Nat :=
  match (generalizing := false) (motive := Op w → Nat) i with
  | .y _ =>
    match (generalizing := false) (motive := W → Nat) w with
    | .a => 1
    | _ => 2

#check Op.f.fun_cases_unfolding
-- failed to transform matcher, type error when constructing new pre-splitter motive

The functional cases construction splits the inner match with a motive that abstracts the discriminant w from the goal motive (Op.y x) (match w with ...). The variable x : Fin w.ctorIdx stays free, so fun w' => motive (Op.y x) ... is type-incorrect.

For the motive of a match, mkLambdaFVarsMasked now abstracts a discriminant only if the result is type-correct (checkTypeCorrect := true). It checks the abstraction over all discriminants once, and only if that check fails does it check each discriminant. An unabstracted discriminant still gets the equality w = pattern from MatcherApp.transform, and rwMatcher uses this equality to reduce the match in each alternative. The default match was not affected, because it generalizes x together with w.

Closes #8213

@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Oct 16, 2026
@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar

leanprover-radar commented Oct 16, 2026 •

Copy link
Copy Markdown

Benchmark results for 87980ca against 8853987 are in. There are significant results. @sgraf812

  • 🟥 build//instructions: +11.4G (+0.11%)

Medium changes (2🟥)

  • 🟥 build/module/Std.Data.DTreeMap.Internal.Balancing//instructions: +4.5G (+8.22%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Std.Data.DTreeMap.Internal.Model//instructions: +1.5G (+2.76%) (reduced significance based on absolute threshold)

Small changes (1✅, 36🟥)

  • 🟥 build/module/Init.Data.Array.Sort.Lemmas//instructions: +307.5M (+10.51%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.Dyadic.Basic//instructions: +38.6M (+0.30%)
  • 🟥 build/module/Init.Data.Float.Model.Unpacked.Pack.Lemmas//instructions: +15.6M (+1.56%)
  • 🟥 build/module/Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop//instructions: +429.5M (+4.03%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.List.ControlImpl//instructions: +41.9M (+5.14%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.List.MinMaxOn//instructions: +41.7M (+0.73%)
  • 🟥 build/module/Init.Data.List.Monadic//instructions: +154.7M (+1.91%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.List.Nat.Basic//instructions: +14.1M (+0.24%)
  • 🟥 build/module/Init.Data.List.SplitOn.Lemmas//instructions: +18.5M (+0.99%)
  • 🟥 build/module/Init.Data.Nat.PowMod//instructions: +12.3M (+1.19%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.Nat.Power2.Lemmas//instructions: +6.7M (+0.82%)
  • 🟥 build/module/Init.Data.Ord.Array//instructions: +23.6M (+0.84%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.Range.Polymorphic.RangeIterator//instructions: +977.8M (+5.55%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.String.Decode//instructions: +189.1M (+0.80%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.String.Defs//instructions: +14.4M (+0.60%)
  • 🟥 build/module/Init.Data.String.Lemmas.FindPos//instructions: +19.0M (+0.53%)
  • 🟥 build/module/Init.Data.String.Lemmas.Pattern.Char//instructions: +44.3M (+1.14%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.String.Lemmas.Pattern.Memcmp//instructions: +46.1M (+3.43%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.String.Lemmas.Pattern.Pred//instructions: +44.0M (+0.86%)
  • 🟥 build/module/Init.Data.String.Lemmas.Pattern.Split.Char//instructions: +145.6M (+9.10%) (reduced significance based on absolute threshold)
  • and 17 more

@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar

leanprover-radar commented Oct 19, 2026 •

Copy link
Copy Markdown

Benchmark results for 0352305 against 8853987 are in. There are significant results. @sgraf812

  • 🟥 build exited with code -1
  • 🟥 other exited with code -1

No significant changes detected.

@sgraf812
sgraf812 force-pushed the sg/fun-cases-index-match branch from 0352305 to 44bed7e Compare October 19, 2026 13:37
@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar

leanprover-radar commented Oct 19, 2026 •

Copy link
Copy Markdown

Benchmark results for 44bed7e against 8853987 are in. There are significant results. @sgraf812

  • 🟥 build exited with code -1
  • 🟥 other exited with code -1

No significant changes detected.

@sgraf812
sgraf812 force-pushed the sg/fun-cases-index-match branch from 44bed7e to c45c172 Compare October 19, 2026 13:41
@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar

leanprover-radar commented Oct 19, 2026 •

Copy link
Copy Markdown

Benchmark results for c45c172 against 8853987 are in. There are significant results. @sgraf812

  • 🟥 build exited with code -1
  • 🟥 other exited with code -1

No significant changes detected.

When the functional induction construction splits a `match`, it abstracts
the discriminants from the goal to form the new motive. If another free
variable in the goal has a type that mentions a discriminant, the
abstraction is type-incorrect. Example: `match (generalizing := false) w`
inside an alternative that binds `x : Fin w.ctorIdx`.

For the motive of a `match`, `mkLambdaFVarsMasked` now keeps such a
discriminant unabstracted (`checkTypeCorrect := true`). It checks the
abstraction over all discriminants once, and only if that check fails does
it check each discriminant. The equality `w = pattern` that
`MatcherApp.transform` adds lets `rwMatcher` reduce the match in each
alternative. The abstraction of the parameters of the principles checks
nothing.
@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@sgraf812
sgraf812 force-pushed the sg/fun-cases-index-match branch from c45c172 to a82fd40 Compare October 19, 2026 13:45
@leanprover-radar

Copy link
Copy Markdown

Failed to find a commit to compare against.

You can edit the original message until the command succeeds.

@sgraf812

Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar

leanprover-radar commented Oct 19, 2026 •

Copy link
Copy Markdown

Benchmark results for a82fd40 against 8853987 are in. No significant results found. @sgraf812

  • 🟥 build//instructions: +563.1M (+0.01%)

Small changes (1✅, 6🟥)

  • 🟥 build/module/Init.Data.Array.Sort.Lemmas//instructions: +35.6M (+1.22%) (reduced significance based on absolute threshold)
  • 🟥 build/module/Init.Data.Nat.PowMod//instructions: +2.1M (+0.21%)
  • 🟥 build/module/Init.Data.Vector.OfFn//instructions: +10.1M (+0.29%)
  • 🟥 build/module/Lean.Data.RArray//instructions: +13.6M (+0.34%)
  • 🟥 build/module/Lean.Meta.Tactic.FunInd//instructions: +105.8M (+0.32%)
  • 🟥 build/module/Std.Data.DTreeMap.Internal.Balancing//instructions: +191.7M (+0.35%)
  • ✅ compiled/server_startup//instructions: -2.0M (-0.57%)

@sgraf812 sgraf812 added downstream Request a downstream-lean4 adaptation PR. and removed downstream Request a downstream-lean4 adaptation PR. labels Oct 20, 2026
@sgraf812
sgraf812 marked this pull request as ready for review October 20, 2026 13:49
@sgraf812
sgraf812 requested a review from leodemoura as a code owner October 20, 2026 13:49
@sgraf812
sgraf812 enabled auto-merge October 20, 2026 13:49
@sgraf812 sgraf812 added the changelog-language Language features and metaprograms label Oct 20, 2026
@sgraf812
sgraf812 added this pull request to the merge queue Oct 20, 2026
Merged via the queue into leanprover:master with commit d2fb769 Oct 20, 2026
37 of 39 checks passed
@sgraf812
sgraf812 deleted the sg/fun-cases-index-match branch October 20, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-language Language features and metaprograms toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fun_cases: fails with dependent match

3 participants