This PR makes it harder to create "fake" theorems about definitions that are stubbed-out with `sorry` by ensuring that each `sorry` is not definitionally equal to any other. For example, this now fails: ```lean example : (sorry : Nat) = sorry := rfl -- fails ``` However, this still succeeds, since the `sorry` is a single indeterminate `Nat`: ```lean def f (n : Nat) : Nat := sorry example : f 0 = f 1 := rfl -- succeeds ``` One can be more careful by putting parameters to the right of the colon: ```lean def f : (n : Nat) → Nat := sorry example : f 0 = f 1 := rfl -- fails ``` Most sources of synthetic sorries (recall: a sorry that originates from the elaborator) are now unique, except for elaboration errors, since making these unique tends to cause a confusing cascade of errors. In general, however, such sorries are labeled. This enables "go to definition" on `sorry` in the Infoview, which brings you to its origin. The option `set_option pp.sorrySource true` causes the pretty printer to show source position information on sorries. **Details:** * Adds `Lean.Meta.mkLabeledSorry`, which creates a sorry that is labeled with its source position. For example, `(sorry : Nat)` might elaborate to ``` sorryAx (Lean.Name → Nat) false `lean.foo.12.8.12.13.8.13._sorry._@.lean.foo._hyg.153 ``` It can either be made unique (like the above) or merely labeled. Labeled sorries use an encoding that does not impact defeq: ``` sorryAx (Unit → Nat) false (Function.const Lean.Name () `lean.foo.14.7.13.7.13.69._sorry._@.lean.foo._hyg.174) ``` * Makes the `sorry` term, the `sorry` tactic, and every elaboration failure create labeled sorries. Most are unique sorries, but some elaboration errors are labeled sorries. * Renames `OmissionInfo` to `DelabTermInfo` and adds configuration options to control LSP interactions. One field is a source position to use for "go to definition". This is used to implement "go to definition" on labeled sorries. * Makes hovering over a labeled `sorry` show something friendlier than that full `sorryAx` expression. Instead, the first hover shows the simplified ``sorry `«lean.foo:48:11»``. Hovering over that hover shows the full `sorryAx`. Setting `set_option pp.sorrySource true` makes `sorry` always start with printing with this source position information. * Removes `Lean.Meta.mkSyntheticSorry` in favor of `Lean.Meta.mkSorry` and `Lean.Meta.mkLabeledSorry`. * Changes `sorryAx` so that the `synthetic` argument is no longer optional. * Gives `addPPExplicitToExposeDiff` awareness of labeled sorries. It can set `pp.sorrySource` when source positions differ. * Modifies the delaborator framework so that delaborators can set Info themselves without it being overwritten. Incidentally closes #4972. Inspired by [this Zulip thread](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Is.20a.20.60definition_wanted.60.20keyword.20possible.3F/near/477260277).
39 lines
1.3 KiB
Text
39 lines
1.3 KiB
Text
/-
|
|
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Leonardo de Moura
|
|
-/
|
|
prelude
|
|
import Lean.Util.FindExpr
|
|
import Lean.Declaration
|
|
|
|
namespace Lean
|
|
|
|
/-- Returns `true` if the expression is an application of `sorryAx`. -/
|
|
def Expr.isSorry (e : Expr) : Bool :=
|
|
e.isAppOf ``sorryAx
|
|
|
|
/-- Returns `true` if the expression is of the form `sorryAx _ true ..`. -/
|
|
def Expr.isSyntheticSorry (e : Expr) : Bool :=
|
|
e.isAppOf ``sorryAx && e.getAppNumArgs ≥ 2 && (e.getArg! 1).isConstOf ``Bool.true
|
|
|
|
/-- Returns `true` if the expression is of the form `sorryAx _ false ..`. -/
|
|
def Expr.isNonSyntheticSorry (e : Expr) : Bool :=
|
|
e.isAppOf ``sorryAx && e.getAppNumArgs ≥ 2 && (e.getArg! 1).isConstOf ``Bool.false
|
|
|
|
def Expr.hasSorry (e : Expr) : Bool :=
|
|
Option.isSome <| e.find? (·.isConstOf ``sorryAx)
|
|
|
|
def Expr.hasSyntheticSorry (e : Expr) : Bool :=
|
|
Option.isSome <| e.find? (·.isSyntheticSorry)
|
|
|
|
def Expr.hasNonSyntheticSorry (e : Expr) : Bool :=
|
|
Option.isSome <| e.find? (·.isNonSyntheticSorry)
|
|
|
|
def Declaration.hasSorry (d : Declaration) : Bool := Id.run do
|
|
d.foldExprM (fun r e => r || e.hasSorry) false
|
|
|
|
def Declaration.hasNonSyntheticSorry (d : Declaration) : Bool := Id.run do
|
|
d.foldExprM (fun r e => r || e.hasNonSyntheticSorry) false
|
|
|
|
end Lean
|