Skip to content

Commit bf8e2b5

Browse files
committed
feat: prop instance yields theorems
Adds a feature to the the mutual def elaborator where the `instance` command yields theorems instead of definitions when the class is a `Prop`. Closes #5672
1 parent c779f3a commit bf8e2b5

File tree

4 files changed

+50
-19
lines changed

4 files changed

+50
-19
lines changed

src/Lean/Elab/DefView.lean

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ import Lean.Elab.DeclUtil
1111
namespace Lean.Elab
1212

1313
inductive DefKind where
14-
| def | theorem | example | opaque | abbrev
14+
| def | instance | theorem | example | opaque | abbrev
1515
deriving Inhabited, BEq
1616

1717
def DefKind.isTheorem : DefKind → Bool
1818
| .theorem => true
1919
| _ => false
2020

2121
def DefKind.isDefOrAbbrevOrOpaque : DefKind → Bool
22-
| .def => true
23-
| .opaque => true
24-
| .abbrev => true
25-
| _ => false
22+
| .def => true
23+
| .instance => true
24+
| .opaque => true
25+
| .abbrev => true
26+
| _ => false
2627

2728
def DefKind.isExample : DefKind → Bool
2829
| .example => true
@@ -171,7 +172,7 @@ def mkDefViewOfInstance (modifiers : Modifiers) (stx : Syntax) : CommandElabM De
171172
trace[Elab.instance.mkInstanceName] "generated {(← getCurrNamespace) ++ id}"
172173
pure <| mkNode ``Parser.Command.declId #[mkIdentFrom stx id, mkNullNode]
173174
return {
174-
ref := stx, headerRef := mkNullNode stx.getArgs[:5], kind := DefKind.def, modifiers := modifiers,
175+
ref := stx, headerRef := mkNullNode stx.getArgs[:5], kind := DefKind.instance, modifiers := modifiers,
175176
declId := declId, binders := binders, type? := type, value := stx[5]
176177
}
177178

src/Lean/Elab/PreDefinition/Basic.lean

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,21 @@ private def reportTheoremDiag (d : TheoremVal) : TermElabM Unit := do
132132
private def addNonRecAux (preDef : PreDefinition) (compile : Bool) (all : List Name) (applyAttrAfterCompilation := true) : TermElabM Unit :=
133133
withRef preDef.ref do
134134
let preDef ← abstractNestedProofs preDef
135+
let mkDefDecl : TermElabM Declaration :=
136+
return Declaration.defnDecl {
137+
name := preDef.declName, levelParams := preDef.levelParams, type := preDef.type, value := preDef.value
138+
hints := ReducibilityHints.regular (getMaxHeight (← getEnv) preDef.value + 1)
139+
safety := if preDef.modifiers.isUnsafe then DefinitionSafety.unsafe else DefinitionSafety.safe,
140+
all }
141+
let mkThmDecl : TermElabM Declaration := do
142+
let d := {
143+
name := preDef.declName, levelParams := preDef.levelParams, type := preDef.type, value := preDef.value, all
144+
}
145+
reportTheoremDiag d
146+
return Declaration.thmDecl d
135147
let decl ←
136148
match preDef.kind with
137-
| DefKind.«theorem» =>
138-
let d := {
139-
name := preDef.declName, levelParams := preDef.levelParams, type := preDef.type, value := preDef.value, all
140-
}
141-
reportTheoremDiag d
142-
pure <| Declaration.thmDecl d
149+
| DefKind.«theorem» => mkThmDecl
143150
| DefKind.«opaque» =>
144151
pure <| Declaration.opaqueDecl {
145152
name := preDef.declName, levelParams := preDef.levelParams, type := preDef.type, value := preDef.value
@@ -151,12 +158,8 @@ private def addNonRecAux (preDef : PreDefinition) (compile : Bool) (all : List N
151158
hints := ReducibilityHints.«abbrev»
152159
safety := if preDef.modifiers.isUnsafe then DefinitionSafety.unsafe else DefinitionSafety.safe,
153160
all }
154-
| _ => -- definitions and examples
155-
pure <| Declaration.defnDecl {
156-
name := preDef.declName, levelParams := preDef.levelParams, type := preDef.type, value := preDef.value
157-
hints := ReducibilityHints.regular (getMaxHeight (← getEnv) preDef.value + 1)
158-
safety := if preDef.modifiers.isUnsafe then DefinitionSafety.unsafe else DefinitionSafety.safe,
159-
all }
161+
| DefKind.def | DefKind.example => mkDefDecl
162+
| DefKind.«instance» => if ← Meta.isProp preDef.type then mkThmDecl else mkDefDecl
160163
addDecl decl
161164
withSaveInfoContext do -- save new env
162165
addTermInfo' preDef.ref (← mkConstWithLevelParams preDef.declName) (isBinder := true)

src/Lean/Elab/PreDefinition/Main.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def addPreDefinitions (preDefs : Array PreDefinition) : TermElabM Unit := withLC
267267
logException ex
268268
let s ← saveState
269269
try
270-
if preDefs.all fun preDef => preDef.kind == DefKind.def || preDefs.all fun preDef => preDef.kind == DefKind.abbrev then
270+
if preDefs.all fun preDef => (preDef.kind matches DefKind.def | DefKind.instance) || preDefs.all fun preDef => preDef.kind == DefKind.abbrev then
271271
-- try to add as partial definition
272272
try
273273
addAndCompilePartial preDefs (useSorry := true)

tests/lean/run/5672.lean

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/-!
2+
# `instance` creates a theorem if the class is a `Prop`
3+
4+
https://github.com/leanprover/lean4/issues/5672
5+
-/
6+
7+
class A : Prop
8+
9+
instance a : A where
10+
11+
/--
12+
info: theorem a : A :=
13+
{ }
14+
-/
15+
#guard_msgs in #print a
16+
17+
18+
/-!
19+
Uses `def` variable inclusion rules
20+
-/
21+
section
22+
variable (x : Nat)
23+
instance b : A := by
24+
cases x <;> exact {}
25+
/-- info: b (x : Nat) : A -/
26+
#guard_msgs in #check b
27+
end

0 commit comments

Comments
 (0)