This didn't work before ``` def f (n : Nat) : Nat := match n with | 0 => 0 | n + 1 => (f) n ``` because the `RecApp` metadata marker gets in the way. More practically relevant, such code is to be produced when using `rw` or `simp` in recursive theorems (see included test case). We can fix this by preprocessing the definitions and floating the `.mdata` marker out of applications. For structural recursion, there already exists a `preprocess` function; this now also floats out `.mdata` markers. For well-founded recursion, this introduces an analogous `preprocess` function. Fixes #2810. One test case output changes: With the `.mdata` out of the way, we get a different error message. Seems fine. Alternative approaches are: * Leaving the `.mdata` marker where it is, and looking around it. Tried in #2813, but not nice (many many places where `withApp` etc. need to be adjusted). * Moving the `.mdata` _inside_ the application, so that `withApp` still works. Tried in #2814. Also not nice, the invariant that the `.mdata` is around the `.const` is tedious to maintain.
36 lines
957 B
Text
36 lines
957 B
Text
/-
|
|
Copyright (c) 2021 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
import Lean.Expr
|
|
|
|
namespace Lean
|
|
|
|
private def recAppKey := `_recApp
|
|
|
|
/--
|
|
We store the syntax at recursive applications to be able to generate better error messages
|
|
when performing well-founded and structural recursion.
|
|
-/
|
|
def mkRecAppWithSyntax (e : Expr) (stx : Syntax) : Expr :=
|
|
mkMData (KVMap.empty.insert recAppKey (DataValue.ofSyntax stx)) e
|
|
|
|
/--
|
|
Retrieve (if available) the syntax object attached to a recursive application.
|
|
-/
|
|
def getRecAppSyntax? (e : Expr) : Option Syntax :=
|
|
match e with
|
|
| Expr.mdata d _ =>
|
|
match d.find recAppKey with
|
|
| some (DataValue.ofSyntax stx) => some stx
|
|
| _ => none
|
|
| _ => none
|
|
|
|
/--
|
|
Checks if the `MData` is for a recursive applciation.
|
|
-/
|
|
def MData.isRecApp (d : MData) : Bool :=
|
|
d.contains recAppKey
|
|
|
|
end Lean
|