fix: extended coe notation and delaborator (#3295)

This commit is contained in:
Leonardo de Moura 2024-02-09 20:58:28 -08:00 committed by GitHub
parent 488bfe2128
commit 02d1ebb564
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 23 deletions

View file

@ -22,14 +22,14 @@ open Meta
ensureHasType expectedType? e
@[builtin_term_elab coeFunNotation] def elabCoeFunNotation : TermElab := fun stx _ => do
let x ← elabTerm stx none
let x ← elabTerm stx[1] none
if let some ty ← coerceToFunction? x then
return ty
else
throwError "cannot coerce to function{indentExpr x}"
@[builtin_term_elab coeSortNotation] def elabCoeSortNotation : TermElab := fun stx _ => do
let x ← elabTerm stx none
let x ← elabTerm stx[1] none
if let some ty ← coerceToSort? x then
return ty
else

View file

@ -341,27 +341,6 @@ def withOverApp (arity : Nat) (x : Delab) : Delab := do
else
delabAppCore (n - arity) x
/--
This delaborator tries to elide functions which are known coercions.
For example, `Int.ofNat` is a coercion, so instead of printing `ofNat n` we just print `↑n`,
and when re-parsing this we can (usually) recover the specific coercion being used.
-/
@[builtin_delab app]
def coeDelaborator : Delab := whenPPOption getPPCoercions do
let e ← getExpr
let .const declName _ := e.getAppFn | failure
let some info ← Meta.getCoeFnInfo? declName | failure
let n := e.getAppNumArgs
withOverApp info.numArgs do
match info.type with
| .coe => `(↑$(← withNaryArg info.coercee delab))
| .coeFun =>
if n = info.numArgs then
`(⇑$(← withNaryArg info.coercee delab))
else
withNaryArg info.coercee delab
| .coeSort => `(↥$(← withNaryArg info.coercee delab))
/-- State for `delabAppMatch` and helpers. -/
structure AppMatchState where
info : MatcherInfo
@ -832,6 +811,27 @@ def delabProjectionApp : Delab := whenPPOption getPPStructureProjections $ do
let appStx ← withAppArg delab
`($(appStx).$(mkIdent f):ident)
/--
This delaborator tries to elide functions which are known coercions.
For example, `Int.ofNat` is a coercion, so instead of printing `ofNat n` we just print `↑n`,
and when re-parsing this we can (usually) recover the specific coercion being used.
-/
@[builtin_delab app]
def coeDelaborator : Delab := whenPPOption getPPCoercions do
let e ← getExpr
let .const declName _ := e.getAppFn | failure
let some info ← Meta.getCoeFnInfo? declName | failure
let n := e.getAppNumArgs
withOverApp info.numArgs do
match info.type with
| .coe => `(↑$(← withNaryArg info.coercee delab))
| .coeFun =>
if n = info.numArgs then
`(⇑$(← withNaryArg info.coercee delab))
else
withNaryArg info.coercee delab
| .coeSort => `(↥$(← withNaryArg info.coercee delab))
@[builtin_delab app.dite]
def delabDIte : Delab := whenPPOption getPPNotation <| withOverApp 5 do
-- Note: we keep this as a delaborator for now because it actually accesses the expression.

53
tests/lean/coe.lean Normal file
View file

@ -0,0 +1,53 @@
import Lean
structure WrappedNat where
val : Nat
structure WrappedFun (α) where
fn : Nat → α
structure WrappedType where
typ : Type
attribute [coe] WrappedNat.val
instance : Coe WrappedNat Nat where coe := WrappedNat.val
#eval Lean.Meta.registerCoercion ``WrappedFun.fn (some ⟨2, 1, .coeFun⟩)
instance : CoeFun (WrappedFun α) (fun _ => Nat → α) where coe := WrappedFun.fn
#eval Lean.Meta.registerCoercion ``WrappedType.typ (some ⟨1, 0, .coeSort⟩)
instance : CoeSort WrappedType Type where coe := WrappedType.typ
section coe
variable (n : WrappedNat)
#check (↑n : Nat)
#check n.val
end coe
section coeFun
variable (f : WrappedFun Nat) (g : Nat → WrappedFun Nat) (h : WrappedFun (WrappedFun Nat))
#check f.fn
#check ⇑f
#check ⇑f 1
#check ⇑(g 1)
#check g 1 2
#check ⇑h
end coeFun
section coeSort
variable (t : WrappedType)
#check t.typ
#check ↥t
end coeSort

View file

@ -0,0 +1,12 @@
↑n : Nat
↑n : Nat
⇑f : Nat → Nat
⇑f : Nat → Nat
f 1 : Nat
⇑(g 1) : Nat → Nat
(g 1) 2 : Nat
⇑h : Nat → WrappedFun Nat
↥t : Type
↥t : Type