|
7 | 7 | prelude |
8 | 8 | public import Lean.Meta.Tactic.Grind.Theorems |
9 | 9 | import Init.Grind.Util |
| 10 | +import Lean.Util.ForEachExpr |
10 | 11 | import Lean.Meta.Tactic.Grind.Util |
11 | 12 | import Lean.Meta.Match.Basic |
12 | 13 | import Lean.Meta.Tactic.TryThis |
@@ -580,6 +581,22 @@ private def saveSymbol (h : HeadIndex) : M Unit := do |
580 | 581 | unless (← get).symbolSet.contains h do |
581 | 582 | modify fun s => { s with symbols := s.symbols.push h, symbolSet := s.symbolSet.insert h } |
582 | 583 |
|
| 584 | +private def saveSymbolsAt (e : Expr) : M Unit := do |
| 585 | + e.forEach' fun e => do |
| 586 | + if e.isApp || e.isConst then |
| 587 | + /- **Note**: We ignore function symbols that have special handling in the internalizer. -/ |
| 588 | + if let .const declName _ := e.getAppFn then |
| 589 | + if declName == ``OfNat.ofNat || declName == ``Grind.nestedProof |
| 590 | + || declName == ``Grind.eqBwdPattern |
| 591 | + || declName == ``Grind.nestedDecidable || declName == ``ite then |
| 592 | + return false |
| 593 | + match e with |
| 594 | + | .const .. => |
| 595 | + saveSymbol e.toHeadIndex |
| 596 | + return false |
| 597 | + | _ => |
| 598 | + return true |
| 599 | + |
583 | 600 | private def foundBVar (idx : Nat) : M Bool := |
584 | 601 | return (← get).bvarsFound.contains idx |
585 | 602 |
|
@@ -672,30 +689,48 @@ private def getPatternFn? (pattern : Expr) (inSupport : Bool) (root : Bool) (arg |
672 | 689 |
|
673 | 690 | private partial def go (pattern : Expr) (inSupport : Bool) (root : Bool) : M Expr := do |
674 | 691 | if let some (e, k) := isOffsetPattern? pattern then |
675 | | - let e ← goArg e inSupport .relevant |
| 692 | + let e ← goArg e inSupport .relevant (isEqBwdParent := false) |
676 | 693 | if e == dontCare then |
677 | 694 | return dontCare |
678 | 695 | else |
679 | 696 | return mkOffsetPattern e k |
680 | 697 | let some f ← getPatternFn? pattern inSupport root .relevant |
681 | 698 | | throwError "invalid pattern, (non-forbidden) application expected{indentD (ppPattern pattern)}" |
682 | 699 | assert! f.isConst || f.isFVar |
683 | | - unless f.isConstOf ``Grind.eqBwdPattern do |
| 700 | + let isEqBwd := f.isConstOf ``Grind.eqBwdPattern |
| 701 | + unless isEqBwd do |
684 | 702 | saveSymbol f.toHeadIndex |
685 | 703 | let mut args := pattern.getAppArgs.toVector |
686 | 704 | let patternArgKinds ← getPatternArgKinds f args.size |
687 | 705 | for h : i in *...args.size do |
688 | 706 | let arg := args[i] |
689 | 707 | let argKind := patternArgKinds[i]?.getD .relevant |
690 | | - args := args.set i (← goArg arg (inSupport || argKind.isSupport) argKind) |
| 708 | + args := args.set i (← goArg arg (inSupport || argKind.isSupport) argKind isEqBwd) |
691 | 709 | return mkAppN f args.toArray |
692 | 710 | where |
693 | | - goArg (arg : Expr) (inSupport : Bool) (argKind : PatternArgKind) : M Expr := do |
| 711 | + goArg (arg : Expr) (inSupport : Bool) (argKind : PatternArgKind) (isEqBwdParent : Bool) : M Expr := do |
694 | 712 | if !arg.hasLooseBVars then |
695 | 713 | if arg.hasMVar then |
696 | 714 | pure dontCare |
| 715 | + else if (← isProof arg) then |
| 716 | + pure dontCare |
697 | 717 | else |
698 | | - return mkGroundPattern (← expandOffsetPatterns arg) |
| 718 | + let arg ← expandOffsetPatterns arg |
| 719 | + unless isEqBwdParent do |
| 720 | + /- |
| 721 | + **Note**: We ignore symbols in ground patterns if the parent is the auxiliary ``Grind.eqBwdPattern |
| 722 | + We do that because we want to sign an error in examples such as: |
| 723 | + ``` |
| 724 | + theorem dummy (x : Nat) : x = x := |
| 725 | + rfl |
| 726 | + -- error: invalid pattern for `dummy` |
| 727 | + -- [@Lean.Grind.eqBwdPattern `[Nat] #0 #0] |
| 728 | + -- the pattern does not contain constant symbols for indexing |
| 729 | + attribute [grind ←=] dummy |
| 730 | + ``` |
| 731 | + -/ |
| 732 | + saveSymbolsAt arg |
| 733 | + return mkGroundPattern arg |
699 | 734 | else match arg with |
700 | 735 | | .bvar idx => |
701 | 736 | if inSupport && (← foundBVar idx) then |
|
0 commit comments