Skip to content

Commit 64b2f32

Browse files
committed
unique -> labeled sorries. Turns out using unique sorries for elaboration errors can compound the issues. In any case, they can still be labeled.
improves addPPExplicitToExposeDiff when functions are overapplied fixes mdata bugs in location RPC handler fixes #4972
1 parent 3e91655 commit 64b2f32

File tree

15 files changed

+132
-81
lines changed

15 files changed

+132
-81
lines changed

src/Lean/Elab/BuiltinNotation.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ private def elabTParserMacroAux (prec lhsPrec e : Term) : TermElabM Syntax := do
214214

215215
@[builtin_term_elab «sorry»] def elabSorry : TermElab := fun _ expectedType? => do
216216
let type ← expectedType?.getDM mkFreshTypeMVar
217-
mkUniqueSorry type (synthetic := false)
217+
mkLabeledSorry type (synthetic := false) (unique := true)
218218

219219
/-- Return syntax `Prod.mk elems[0] (Prod.mk elems[1] ... (Prod.mk elems[elems.size - 2] elems[elems.size - 1])))` -/
220220
partial def mkPairs (elems : Array Term) : MacroM Term :=

src/Lean/Elab/Extra.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ def elabDefaultOrNonempty : TermElab := fun stx expectedType? => do
578578
else
579579
-- It is in the context of an `unsafe` constant. We can use sorry instead.
580580
-- Another option is to make a recursive application since it is unsafe.
581-
mkUniqueSorry expectedType false
581+
mkLabeledSorry expectedType false (unique := true)
582582

583583
builtin_initialize
584584
registerTraceClass `Elab.binop

src/Lean/Elab/MutualDef.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ where
978978
values.mapM (instantiateMVarsProfiling ·)
979979
catch ex =>
980980
logException ex
981-
headers.mapM fun header => withRef header.declId <| mkUniqueSorry header.type (synthetic := true)
981+
headers.mapM fun header => withRef header.declId <| mkLabeledSorry header.type (synthetic := true) (unique := false)
982982
let headers ← headers.mapM instantiateMVarsAtHeader
983983
let letRecsToLift ← getLetRecsToLift
984984
let letRecsToLift ← letRecsToLift.mapM instantiateMVarsAtLetRecToLift

src/Lean/Elab/PreDefinition/Main.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ private def addAndCompilePartial (preDefs : Array PreDefinition) (useSorry := fa
2020
let all := preDefs.toList.map (·.declName)
2121
forallTelescope preDef.type fun xs type => do
2222
let value ← if useSorry then
23-
mkLambdaFVars xs (← withRef preDef.ref <| mkUniqueSorry type (synthetic := true))
23+
mkLambdaFVars xs (← withRef preDef.ref <| mkLabeledSorry type (synthetic := true) (unique := true))
2424
else
2525
liftM <| mkInhabitantFor preDef.declName xs type
2626
addNonRec { preDef with
@@ -114,7 +114,7 @@ private partial def ensureNoUnassignedLevelMVarsAtPreDef (preDef : PreDefinition
114114
private def ensureNoUnassignedMVarsAtPreDef (preDef : PreDefinition) : TermElabM PreDefinition := do
115115
let pendingMVarIds ← getMVarsAtPreDef preDef
116116
if (← logUnassignedUsingErrorInfos pendingMVarIds) then
117-
let preDef := { preDef with value := (← withRef preDef.ref <| mkUniqueSorry preDef.type (synthetic := true)) }
117+
let preDef := { preDef with value := (← withRef preDef.ref <| mkLabeledSorry preDef.type (synthetic := true) (unique := true)) }
118118
if (← getMVarsAtPreDef preDef).isEmpty then
119119
return preDef
120120
else

src/Lean/Elab/Tactic/Basic.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ open Meta
1414
def admitGoal (mvarId : MVarId) : MetaM Unit :=
1515
mvarId.withContext do
1616
let mvarType ← inferType (mkMVar mvarId)
17-
mvarId.assign (← mkUniqueSorry mvarType (synthetic := true))
17+
mvarId.assign (← mkLabeledSorry mvarType (synthetic := true) (unique := true))
1818

1919
def goalsToMessageData (goals : List MVarId) : MessageData :=
2020
MessageData.joinSep (goals.map MessageData.ofGoal) m!"\n\n"

src/Lean/Elab/Tactic/LibrarySearch.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def elabExact?Term : TermElab := fun stx expectedType? => do
7070
if let some suggestions ← librarySearch introdGoal then
7171
if suggestions.isEmpty then logError "`exact?%` didn't find any relevant lemmas"
7272
else logError "`exact?%` could not close the goal. Try `by apply` to see partial suggestions."
73-
mkUniqueSorry expectedType (synthetic := true)
73+
mkLabeledSorry expectedType (synthetic := true) (unique := true)
7474
else
7575
addTermSuggestion stx (← instantiateMVars goal).headBeta
7676
instantiateMVars goal

src/Lean/Elab/Term.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ private def mkSyntheticSorryFor (expectedType? : Option Expr) : TermElabM Expr :
11091109
let expectedType ← match expectedType? with
11101110
| none => mkFreshTypeMVar
11111111
| some expectedType => pure expectedType
1112-
mkUniqueSorry expectedType (synthetic := true)
1112+
mkLabeledSorry expectedType (synthetic := true) (unique := false)
11131113

11141114
/--
11151115
Log the given exception, and create a synthetic sorry for representing the failed
@@ -1215,7 +1215,7 @@ The `tacticCode` syntax is the full `by ..` syntax.
12151215
-/
12161216
def mkTacticMVar (type : Expr) (tacticCode : Syntax) (kind : TacticMVarKind) : TermElabM Expr := do
12171217
if ← pure (debug.byAsSorry.get (← getOptions)) <&&> isProp type then
1218-
withRef tacticCode <| mkUniqueSorry type false
1218+
withRef tacticCode <| mkLabeledSorry type false (unique := true)
12191219
else
12201220
let mvar ← mkFreshExprMVar type MetavarKind.syntheticOpaque
12211221
let mvarId := mvar.mvarId!

src/Lean/Meta/AppBuilder.lean

+30-24
Original file line numberDiff line numberDiff line change
@@ -520,51 +520,57 @@ def mkSorry (type : Expr) (synthetic : Bool) : MetaM Expr := do
520520
let u ← getLevel type
521521
return mkApp2 (mkConst ``sorryAx [u]) type (toExpr synthetic)
522522

523-
structure UniqueSorryView where
524-
module? : Option Name := none
525-
range? : Option Lsp.Range := none
523+
structure SorryLabelView where
524+
module? : Option (Name × Lsp.Range) := none
526525

527-
def UniqueSorryView.encode (view : UniqueSorryView) : CoreM Name :=
528-
let name := view.module?.getD .anonymous
526+
def SorryLabelView.encode (view : SorryLabelView) : CoreM Name :=
529527
let name :=
530-
if let some range := view.range? then
531-
name |>.num range.start.line |>.num range.start.character |>.num range.end.line |>.num range.end.character
528+
if let some (mod, range) := view.module? then
529+
mod |>.num range.start.line |>.num range.start.character |>.num range.end.line |>.num range.end.character
532530
else
533-
name
531+
.anonymous
534532
mkFreshUserName (name.str "_unique_sorry")
535533

536-
def UniqueSorryView.decode? (name : Name) : Option UniqueSorryView := do
534+
def SorryLabelView.decode? (name : Name) : Option SorryLabelView := do
537535
guard <| name.hasMacroScopes
538536
let .str name "_unique_sorry" := name.eraseMacroScopes | failure
539537
if let .num (.num (.num (.num name startLine) startChar) endLine) endChar := name then
540-
return { module? := name, range? := some ⟨⟨startLine, startChar⟩, ⟨endLine, endChar⟩⟩ }
541-
else if name.isAnonymous then
542-
return { module? := none, range? := none }
538+
return { module? := some (name, ⟨⟨startLine, startChar⟩, ⟨endLine, endChar⟩⟩) }
543539
else
544540
failure
545541

546542
/--
547-
Makes a `sorryAx` that is unique, in the sense that it is not defeq to any other `sorry` created by `mkUniqueSorry`.
548-
549-
Encodes the source position of the current ref into the term.
543+
Makes a `sorryAx` that encodes the current ref into the term to support "go to definition" for the `sorry`.
544+
If `unique` is true, the `sorry` is unique, in the sense that it is not defeq to any other `sorry` created by `mkLabeledSorry`.
550545
-/
551-
def mkUniqueSorry (type : Expr) (synthetic : Bool) : MetaM Expr := do
546+
def mkLabeledSorry (type : Expr) (synthetic : Bool) (unique : Bool) : MetaM Expr := do
552547
let tag ←
553548
if let (some pos, some endPos) := ((← getRef).getPos?, (← getRef).getTailPos?) then
554549
let range := (← getFileMap).utf8RangeToLspRange ⟨pos, endPos⟩
555-
UniqueSorryView.encode { module? := (← getMainModule), range? := range }
550+
SorryLabelView.encode { module? := (← getMainModule, range) }
556551
else
557-
UniqueSorryView.encode {}
558-
let e ← mkSorry (mkForall `tag .default (mkConst ``Lean.Name) type) synthetic
559-
return .app e (toExpr tag)
552+
SorryLabelView.encode {}
553+
if unique then
554+
let e ← mkSorry (mkForall `tag .default (mkConst ``Lean.Name) type) synthetic
555+
return .app e (toExpr tag)
556+
else
557+
let e ← mkSorry (mkForall `tag .default (mkConst ``Unit) type) synthetic
558+
return .app e (mkApp4 (mkConst ``Function.const [levelOne, levelOne])
559+
(mkConst ``Unit) (mkConst ``Lean.Name) (mkConst ``Unit.unit) (toExpr tag))
560560

561561
/--
562-
Returns a `UniqueSorryView` if `e` is an application of an expression returned by `mkUniqueSorry`.
562+
Returns a `SorryLabelView` if `e` is an application of an expression returned by `mkLabeledSorry`.
563563
-/
564-
def isUniqueSorry? (e : Expr) : Option UniqueSorryView := do
564+
def isLabeledSorry? (e : Expr) : Option SorryLabelView := do
565565
guard <| e.isAppOf ``sorryAx && e.getAppNumArgs ≥ 3
566-
let some tag := (e.getArg! 2).name? | failure
567-
UniqueSorryView.decode? tag
566+
let arg := e.getArg! 2
567+
if let some tag := arg.name? then
568+
SorryLabelView.decode? tag
569+
else
570+
guard <| arg.isAppOfArity ``Function.const 4
571+
guard <| arg.appFn!.appArg!.isAppOfArity ``Unit.unit 0
572+
let some tag := arg.appArg!.name? | failure
573+
SorryLabelView.decode? tag
568574

569575
/-- Return `Decidable.decide p` -/
570576
def mkDecide (p : Expr) : MetaM Expr :=

src/Lean/Meta/Check.lean

+38-27
Original file line numberDiff line numberDiff line change
@@ -78,40 +78,51 @@ partial def addPPExplicitToExposeDiff (a b : Expr) : MetaM (Expr × Expr) := do
7878
where
7979
visit (a b : Expr) : MetaM (Expr × Expr) := do
8080
try
81-
if !a.isApp || !b.isApp then
81+
if ← isDefEq a b then
8282
return (a, b)
83-
else if a.getAppNumArgs != b.getAppNumArgs then
83+
else if !a.isApp || !b.isApp || a.getAppNumArgs != b.getAppNumArgs then
8484
return (a, b)
8585
else if !(← isDefEq a.getAppFn b.getAppFn) then
86-
return (a, b)
86+
let (fa, fb) ← visit a.getAppFn b.getAppFn
87+
return (mkAppN fa a.getAppArgs, mkAppN fb b.getAppArgs)
8788
else
88-
let fType ← inferType a.getAppFn
89-
forallBoundedTelescope fType a.getAppNumArgs fun xs _ => do
90-
let mut as := a.getAppArgs
91-
let mut bs := b.getAppArgs
92-
if let some (as', bs') ← hasExplicitDiff? xs as bs then
93-
return (mkAppN a.getAppFn as', mkAppN b.getAppFn bs')
94-
else
95-
for i in [:as.size] do
96-
unless (← isDefEq as[i]! bs[i]!) do
97-
let (ai, bi) ← visit as[i]! bs[i]!
98-
as := as.set! i ai
99-
bs := bs.set! i bi
100-
let a := mkAppN a.getAppFn as
101-
let b := mkAppN b.getAppFn bs
102-
return (a.setAppPPExplicit, b.setAppPPExplicit)
89+
-- Note: this isn't using forallBoundedTelescope because the function might be "overapplied".
90+
-- That is to say, the arity might depend on the values of the arguments.
91+
let mut as := a.getAppArgs
92+
let mut bs := b.getAppArgs
93+
let mut aFnType ← inferType a.getAppFn
94+
let mut bFnType ← inferType b.getAppFn
95+
let mut firstDiff? := none
96+
for i in [0:as.size] do
97+
unless aFnType.isForall do aFnType ← withTransparency .all <| whnf aFnType
98+
unless bFnType.isForall do bFnType ← withTransparency .all <| whnf bFnType
99+
-- These pattern matches are expected to succeed:
100+
let .forallE _ _ abody abi := aFnType | return (a, b)
101+
let .forallE _ _ bbody bbi := aFnType | return (a, b)
102+
aFnType := abody.instantiate1 as[i]!
103+
bFnType := bbody.instantiate1 bs[i]!
104+
let explicit := abi.isExplicit && bbi.isExplicit
105+
unless (← isDefEq as[i]! bs[i]!) do
106+
if explicit then
107+
let (ai, bi) ← visit as[i]! bs[i]!
108+
let a := mkAppN a.getAppFn (as.set! i ai)
109+
let b := mkAppN b.getAppFn (bs.set! i bi)
110+
if a.isAppOf ``sorryAx then
111+
-- Special case: if this is a `sorry` with source position, make sure the delaborator shows the position.
112+
return (a.setOption `pp.sorrySource true, b.setOption `pp.sorrySource true)
113+
return (a, b)
114+
else
115+
firstDiff? := firstDiff? <|> some i
116+
if let some i := firstDiff? then
117+
let (ai, bi) ← visit as[i]! bs[i]!
118+
as := as.set! i ai
119+
bs := bs.set! i bi
120+
let a := mkAppN a.getAppFn as
121+
let b := mkAppN b.getAppFn bs
122+
return (a.setPPExplicit true, b.setPPExplicit true)
103123
catch _ =>
104124
return (a, b)
105125

106-
hasExplicitDiff? (xs as bs : Array Expr) : MetaM (Option (Array Expr × Array Expr)) := do
107-
for i in [:xs.size] do
108-
let localDecl ← xs[i]!.fvarId!.getDecl
109-
if localDecl.binderInfo.isExplicit then
110-
unless (← isDefEq as[i]! bs[i]!) do
111-
let (ai, bi) ← visit as[i]! bs[i]!
112-
return some (as.set! i ai, bs.set! i bi)
113-
return none
114-
115126
/--
116127
Return error message "has type{givenType}\nbut is expected to have type{expectedType}"
117128
-/

src/Lean/Meta/Tactic/Util.lean

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def _root_.Lean.MVarId.admit (mvarId : MVarId) (synthetic := true) : MetaM Unit
6060
mvarId.withContext do
6161
mvarId.checkNotAssigned `admit
6262
let mvarType ← mvarId.getType
63-
let val ← mkUniqueSorry mvarType synthetic
63+
let val ← mkLabeledSorry mvarType synthetic (unique := true)
6464
mvarId.assign val
6565

6666
/-- Beta reduce the metavariable type head -/

src/Lean/PrettyPrinter/Delaborator/Basic.lean

+4-5
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,13 @@ def annotateTermInfo (stx : Term) : Delab := do
222222

223223
/--
224224
Annotates the term with the current expression position and registers `TermInfo`
225-
to associate the term to the current expression, unless (1) the syntax has a position and it is for the current position
226-
and (2) there is already `TermInfo` at this position.
225+
to associate the term to the current expression, unless the syntax has a synthetic position
226+
and associated `Info` already.
227227
-/
228228
def annotateTermInfoUnlessAnnotated (stx : Term) : Delab := do
229229
if let .synthetic ⟨pos⟩ ⟨pos'⟩ := stx.raw.getHeadInfo then
230-
if pos == pos' && pos == (← getPos) then
231-
if (← get).infos.contains pos then
232-
return stx
230+
if pos == pos' && (← get).infos.contains pos then
231+
return stx
233232
annotateTermInfo stx
234233

235234
/--

src/Lean/PrettyPrinter/Delaborator/Builtins.lean

+9-8
Original file line numberDiff line numberDiff line change
@@ -1014,15 +1014,15 @@ Delaborates an `OfNat.ofNat` literal.
10141014
`@OfNat.ofNat _ n _` ~> `n`.
10151015
-/
10161016
@[builtin_delab app.OfNat.ofNat]
1017-
def delabOfNat : Delab := whenPPOption getPPCoercions <| withOverApp 3 do
1017+
def delabOfNat : Delab := whenNotPPOption getPPExplicit <| whenPPOption getPPCoercions <| withOverApp 3 do
10181018
delabOfNatCore (showType := (← getPPOption getPPNumericTypes))
10191019

10201020
/--
10211021
Delaborates the negative of an `OfNat.ofNat` literal.
10221022
`[email protected] _ n _` ~> `-n`
10231023
-/
10241024
@[builtin_delab app.Neg.neg]
1025-
def delabNeg : Delab := whenPPOption getPPCoercions do
1025+
def delabNeg : Delab := whenNotPPOption getPPExplicit <| whenPPOption getPPCoercions do
10261026
delabNegIntCore (showType := (← getPPOption getPPNumericTypes))
10271027

10281028
/--
@@ -1031,12 +1031,12 @@ Delaborates a rational number literal.
10311031
and `[email protected] _ n _ / @OfNat.ofNat _ m` ~> `-n / m`
10321032
-/
10331033
@[builtin_delab app.HDiv.hDiv]
1034-
def delabHDiv : Delab := whenPPOption getPPCoercions do
1034+
def delabHDiv : Delab := whenNotPPOption getPPExplicit <| whenPPOption getPPCoercions do
10351035
delabDivRatCore (showType := (← getPPOption getPPNumericTypes))
10361036

10371037
-- `@OfDecimal.ofDecimal _ _ m s e` ~> `m*10^(sign * e)` where `sign == 1` if `s = false` and `sign = -1` if `s = true`
10381038
@[builtin_delab app.OfScientific.ofScientific]
1039-
def delabOfScientific : Delab := whenPPOption getPPCoercions <| withOverApp 5 do
1039+
def delabOfScientific : Delab := whenNotPPOption getPPExplicit <| whenPPOption getPPCoercions <| withOverApp 5 do
10401040
let expr ← getExpr
10411041
guard <| expr.getAppNumArgs == 5
10421042
let .lit (.natVal m) ← pure (expr.getArg! 2) | failure
@@ -1229,12 +1229,13 @@ def delabNameMkNum : Delab := delabNameMkStr
12291229
@[builtin_delab app.sorryAx]
12301230
def delabSorry : Delab := whenPPOption getPPNotation <| whenNotPPOption getPPExplicit do
12311231
guard <| (← getExpr).getAppNumArgs ≥ 2
1232-
-- If this is constructed by `Lean.Meta.mkUniqueSorry`, then don't print the unique tag.
1232+
let sorrySource ← getPPOption getPPSorrySource
1233+
-- If this is constructed by `Lean.Meta.mkLabeledSorry`, then don't print the unique tag.
12331234
-- But, if `pp.explicit` is false and `pp.sorrySource` is true, then print a simplified version of the tag.
1234-
if let some view := isUniqueSorry? (← getExpr) then
1235+
if let some view := isLabeledSorry? (← getExpr) then
12351236
withOverApp 3 do
1236-
if let (some module, some range) := (view.module?, view.range?) then
1237-
if ← getPPOption getPPSorrySource then
1237+
if let some (module, range) := view.module? then
1238+
ifpure sorrySource <||> getPPOption getPPSorrySource then
12381239
-- LSP line numbers start at 0, so add one to it.
12391240
-- Technically using the character as the column is incorrect since this is UTF-16 position, but we have no filemap to work with.
12401241
let posAsName := Name.mkSimple s!"{module}:{range.start.line + 1}:{range.start.character}"

src/Lean/Server/FileWorker/RequestHandling.lean

+5-4
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def locationLinksOfInfo (kind : GoToKind) (ictx : InfoWithCtx)
165165
let mut expr := ti.expr
166166
if kind == type then
167167
expr ← ci.runMetaM i.lctx do
168-
return Expr.getAppFn (← instantiateMVars (← Meta.inferType expr))
168+
return Expr.getAppFn (← instantiateMVars (← Meta.inferType expr)) |>.consumeMData
169169
match expr with
170170
| Expr.const n .. => return ← ci.runMetaM i.lctx <| locationLinksFromDecl i n
171171
| Expr.fvar id .. => return ← ci.runMetaM i.lctx <| locationLinksFromBinder i id
@@ -184,7 +184,7 @@ def locationLinksOfInfo (kind : GoToKind) (ictx : InfoWithCtx)
184184
-- go-to-definition on a projection application of a typeclass
185185
-- should return all instances generated by TC
186186
expr ← ci.runMetaM i.lctx do instantiateMVars expr
187-
if let .const n _ := expr.getAppFn then
187+
if let .const n _ := expr.getAppFn.consumeMData then
188188
-- also include constant along with instance results
189189
let mut results ← ci.runMetaM i.lctx <| locationLinksFromDecl i n
190190
if let some info := ci.env.getProjectionFnInfo? n then
@@ -201,13 +201,14 @@ def locationLinksOfInfo (kind : GoToKind) (ictx : InfoWithCtx)
201201
| .const declName _ => do
202202
if ← ci.runMetaM i.lctx do Lean.Meta.isInstance declName then pure #[declName] else pure #[]
203203
| .app fn arg => do pure $ (← extractInstances fn).append (← extractInstances arg)
204+
| .mdata _ e => extractInstances e
204205
| _ => pure #[]
205206
if let some instArg := appArgs.get? instIdx then
206207
for inst in (← extractInstances instArg) do
207208
results := results.append (← ci.runMetaM i.lctx <| locationLinksFromDecl i inst)
208209
results := results.append elaborators -- put elaborators at the end of the results
209-
if let some view := Meta.isUniqueSorry? expr then
210-
if let (some module, some range) := (view.module?, view.range?) then
210+
if let some view := Meta.isLabeledSorry? expr then
211+
if let some (module, range) := view.module? then
211212
let targetUri := (← documentUriFromModule rc.srcSearchPath module).getD doc.meta.uri
212213
let result := {
213214
targetUri, targetRange := range, targetSelectionRange := range,

src/Lean/Util/Sorry.lean

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,21 @@ import Lean.Declaration
1010
namespace Lean
1111

1212
def Expr.isSorry : Expr → Bool
13-
| app (app (.const ``sorryAx ..) ..) .. => true
13+
| mkApp2 (.const ``sorryAx ..) _ _ => true
14+
-- A unique sorry:
15+
| mkApp3 (.const ``sorryAx ..) _ _ _ => true
1416
| _ => false
1517

1618
def Expr.isSyntheticSorry : Expr → Bool
17-
| app (app (const ``sorryAx ..) ..) (const ``Bool.true ..) => true
19+
| mkApp2 (const ``sorryAx ..) _ (const ``Bool.true ..) => true
20+
-- A unique sorry:
21+
| mkApp3 (const ``sorryAx ..) _ (const ``Bool.true ..) _ => true
1822
| _ => false
1923

2024
def Expr.isNonSyntheticSorry : Expr → Bool
21-
| app (app (const ``sorryAx ..) ..) (const ``Bool.false ..) => true
25+
| mkApp2 (const ``sorryAx ..) _ (const ``Bool.false ..) => true
26+
-- A unique sorry:
27+
| mkApp3 (const ``sorryAx ..) _ (const ``Bool.false ..) _ => true
2228
| _ => false
2329

2430
def Expr.hasSorry (e : Expr) : Bool :=

0 commit comments

Comments
 (0)