fix: auxiliary matcher definitions should be treated as abbreviations
The motivation is to prevent performance problems such as the one described at issue #854. Fixes #854 after a update stage0
This commit is contained in:
parent
b0fe1e5d10
commit
41040a81de
3 changed files with 30 additions and 9 deletions
|
|
@ -1035,14 +1035,18 @@ private def tryHeuristic (t s : Expr) : MetaM Bool := do
|
|||
let tFn := t.getAppFn
|
||||
let sFn := s.getAppFn
|
||||
let info ← getConstInfo tFn.constName!
|
||||
/- We only use the heuristic when `f` is a regular definition. That is, it is marked an abbreviation
|
||||
(e.g., a user-facing projection) or as opaque (e.g., proof).
|
||||
/- We only use the heuristic when `f` is a regular definition or an auxiliary `match` application.
|
||||
That is, it is not marked an abbreviation (e.g., a user-facing projection) or as opaque (e.g., proof).
|
||||
We check whether terms contain metavariables to make sure we can solve constraints such
|
||||
as `S.proj ?x =?= S.proj t` without performing delta-reduction.
|
||||
That is, we are assuming the heuristic implemented by this method is seldom effective
|
||||
when `t` and `s` do not have metavariables, are not structurally equal, and `f` is an abbreviation.
|
||||
On the other hand, by unfolding `f`, we often produce smaller terms. -/
|
||||
unless info.hints.isRegular do
|
||||
On the other hand, by unfolding `f`, we often produce smaller terms.
|
||||
|
||||
Recall that auxiliary `match` definitions are marked as abbreviations, but we must use the heuristic on
|
||||
them since they will not be unfolded when smartUnfolding is turned on. The abbreviation annotation in this
|
||||
case is used to help the kernel type checker. -/
|
||||
unless info.hints.isRegular || isMatcherCore (← getEnv) tFn.constName! do
|
||||
unless t.hasExprMVar || s.hasExprMVar do
|
||||
return false
|
||||
traceCtx `Meta.isDefEq.delta do
|
||||
|
|
|
|||
|
|
@ -715,11 +715,11 @@ def mkMatcherAuxDefinition (name : Name) (type : Expr) (value : Expr) : MetaM (E
|
|||
| some nameNew => (mkMatcherConst nameNew, none)
|
||||
| none =>
|
||||
let decl := Declaration.defnDecl {
|
||||
name := name,
|
||||
levelParams := result.levelParams.toList,
|
||||
type := result.type,
|
||||
value := result.value,
|
||||
hints := ReducibilityHints.regular (getMaxHeight env result.value + 1),
|
||||
name
|
||||
levelParams := result.levelParams.toList
|
||||
type := result.type
|
||||
value := result.value
|
||||
hints := ReducibilityHints.abbrev
|
||||
safety := if env.hasUnsafe result.type || env.hasUnsafe result.value then DefinitionSafety.unsafe else DefinitionSafety.safe
|
||||
}
|
||||
trace[Meta.debug] "{name} : {result.type} := {result.value}"
|
||||
|
|
|
|||
17
tests/lean/run/854.lean
Normal file
17
tests/lean/run/854.lean
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
example (a : Nat) : (a - 8000) + 1 = Nat.succ (a - 8000) := by
|
||||
rfl
|
||||
|
||||
theorem mwe (a : Nat) : (a - 100000000) + 1 <= 1 := by
|
||||
apply Nat.succ_le_succ
|
||||
sorry
|
||||
|
||||
@[irreducible]
|
||||
def someConstant : Nat := 100000000
|
||||
|
||||
theorem mwe' (a : Nat) : (a - someConstant) + 1 <= someConstant + 1 := by
|
||||
apply Nat.succ_le_succ
|
||||
sorry
|
||||
|
||||
theorem mwe'' (a : Nat) : Nat.add (a - 100000000) 1 <= Nat.zero.succ := by
|
||||
apply Nat.succ_le_succ
|
||||
sorry
|
||||
Loading…
Add table
Reference in a new issue