Skip to content

Commit 6a75ad1

Browse files
committed
cleanups
1 parent 07257c8 commit 6a75ad1

File tree

6 files changed

+74
-34
lines changed

6 files changed

+74
-34
lines changed

src/Lean/Elab/InfoTree/Main.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,10 @@ def withMacroExpansionInfo [MonadFinally m] [Monad m] [MonadInfoTree m] [MonadLC
489489
}
490490
withInfoContext x mkInfo
491491

492+
/--
493+
Runs `x`. The last info tree that is pushed while running `x` is assigned to `mvarId`. All other
494+
pushed info trees are silently discarded.
495+
-/
492496
@[inline] def withInfoHole [MonadFinally m] [Monad m] [MonadInfoTree m] (mvarId : MVarId) (x : m α) : m α := do
493497
if (← getInfoState).enabled then
494498
let treesSaved ← getResetInfoTrees

src/Lean/Elab/SyntheticMVars.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ private def resumePostponed (savedContext : SavedContext) (stx : Syntax) (mvarId
3737
let mvarDecl ← getMVarDecl mvarId
3838
let expectedType ← instantiateMVars mvarDecl.type
3939
withInfoHole mvarId do
40+
/-
41+
NOTE: `withInfoTree` discards all but the last info tree pushed inside this `do` block.
42+
`resumeElabTerm` usually pushes the term info node and `ensureHasType` sometimes
43+
pushes a custom info node with information about the coercions that were applied.
44+
45+
In order for both trees to be preserved, we use `withTermInfoContext'` to wrap these
46+
trees into a single node. Although this results in two nested term nodes for the same
47+
syntax element, this should be unproblematic. For example, `hoverableInfoAtM?` selects
48+
the innermost info tree.
49+
-/
4050
let result ← withTermInfoContext' .anonymous stx do
4151
let result ← resumeElabTerm stx expectedType (!postponeOnError)
4252
/- We must ensure `result` has the expected type because it is the one expected by the method that postponed stx.

src/Lean/Elab/Term/TermElabM.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ depend on them (i.e. they should not be inspected beforehand).
482482
def withNarrowedArgTacticReuse [Monad m] [MonadReaderOf Context m] [MonadLiftT BaseIO m]
483483
[MonadWithReaderOf Core.Context m] [MonadWithReaderOf Context m] [MonadOptions m]
484484
(argIdx : Nat) (act : Syntax → m α) (stx : Syntax) : m α :=
485-
withNarrowedTacticReuse (fun stx => (mkNullNode stx.getArgs[*...argIdx].copy, stx[argIdx])) act stx
485+
withNarrowedTacticReuse (fun stx => (mkNullNode stx.getArgs[*...argIdx], stx[argIdx])) act stx
486486

487487
/--
488488
Disables incremental tactic reuse *and* reporting for `act` if `cond` is true by setting `tacSnap?`

src/Lean/Linter/Coe.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def coeLinter : Linter where
5252
logWarningAt ci.stx m!"This term uses the coercion `{coeDecl}`, which is banned in Lean's core library."
5353
if shouldWarnOnDeprecated then
5454
let some attr := deprecatedAttr.getParam? (← getEnv) coeDecl | pure ()
55-
logWarningAt ci.stx <| .tagged ``deprecatedAttr <|
55+
logLint linter.deprecatedCoercions ci.stx <| .tagged ``deprecatedAttr <|
5656
m!"This term uses the deprecated coercion `{.ofConstName coeDecl true}`."
5757
| _ => pure ()
5858
return true) (fun _ _ _ _ => return)

src/Lean/Meta/Coe.lean

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,29 +40,11 @@ private partial def recProjTarget (e : Expr) (nm : Name := e.getAppFn.constName!
4040
else
4141
return nm
4242

43-
/-- Expand coercions occurring in `e` -/
44-
partial def expandCoe (e : Expr) : MetaM Expr :=
45-
withReducibleAndInstances do
46-
transform e fun e => do
47-
let f := e.getAppFn
48-
if f.isConst then
49-
let declName := f.constName!
50-
if isCoeDecl (← getEnv) declName then
51-
/-
52-
Unfolding an instance projection corresponds to unfolding the target of the projection
53-
(and then reducing the projection). Thus we can recursively visit projections before
54-
recording the declaration. We shouldn't need to record any other arguments because they
55-
should still appear after unfolding (unless there are unused variables in the instances).
56-
-/
57-
recordExtraModUseFromDecl (isMeta := false) (← recProjTarget e)
58-
if let some e ← unfoldDefinition? e then
59-
return .visit e.headBeta
60-
return .continue
61-
62-
63-
64-
/-- Expand coercions occurring in `e` -/
65-
partial def expandCoe' (e : Expr) : MetaM (Expr × List Name) := StateT.run (s := ([] : List Name)) do
43+
/--
44+
Expands coercions occurring in `e` and return the result together with a list of applied
45+
`Coe` instances.
46+
-/
47+
partial def expandCoe (e : Expr) : MetaM (Expr × List Name) := StateT.run (s := ([] : List Name)) do
6648
withReducibleAndInstances do
6749
transform e fun e => do
6850
let f := e.getAppFn
@@ -77,6 +59,10 @@ partial def expandCoe' (e : Expr) : MetaM (Expr × List Name) := StateT.run (s :
7759
-/
7860
recordExtraModUseFromDecl (isMeta := false) (← recProjTarget e)
7961
if let some e' ← unfoldDefinition? e then
62+
/-
63+
If the unfolded coercion is an application of `Coe.coe` and its third argument is
64+
an application of a constant, record this constant's name.
65+
-/
8066
if declName = ``Coe.coe then
8167
if let some inst := e.getAppArgs[2]? then
8268
let g := inst.getAppFn
@@ -99,7 +85,7 @@ def coerceSimple? (expr expectedType : Expr) : MetaM (LOption (Expr × List Name
9985
let coeTInstType := mkAppN (mkConst ``CoeT [u, v]) #[eType, expr, expectedType]
10086
match ← trySynthInstance coeTInstType with
10187
| .some inst =>
102-
let result ← expandCoe' (mkAppN (mkConst ``CoeT.coe [u, v]) #[eType, expr, expectedType, inst])
88+
let result ← expandCoe (mkAppN (mkConst ``CoeT.coe [u, v]) #[eType, expr, expectedType, inst])
10389
unless ← isDefEq (← inferType result.1) expectedType do
10490
throwError "Could not coerce{indentExpr expr}\nto{indentExpr expectedType}\ncoerced expression has wrong type:{indentExpr result.1}"
10591
return .some result
@@ -114,7 +100,7 @@ def coerceToFunction? (expr : Expr) : MetaM (Option Expr) := do
114100
let v ← mkFreshLevelMVar
115101
let γ ← mkFreshExprMVar (← mkArrow α (mkSort v))
116102
let .some inst ← trySynthInstance (mkApp2 (.const ``CoeFun [u,v]) α γ) | return none
117-
let expanded ← expandCoe (mkApp4 (.const ``CoeFun.coe [u,v]) α γ inst expr)
103+
let (expanded, _) ← expandCoe (mkApp4 (.const ``CoeFun.coe [u,v]) α γ inst expr)
118104
unless (← whnf (← inferType expanded)).isForall do
119105
throwError m!"Failed to coerce{indentExpr expr}\nto a function: After applying `CoeFun.coe`, result is still not a function{indentExpr expanded}"
120106
++ .hint' m!"This is often due to incorrect `CoeFun` instances; the synthesized instance was{indentExpr inst}"
@@ -128,7 +114,7 @@ def coerceToSort? (expr : Expr) : MetaM (Option Expr) := do
128114
let v ← mkFreshLevelMVar
129115
let β ← mkFreshExprMVar (mkSort v)
130116
let .some inst ← trySynthInstance (mkApp2 (.const ``CoeSort [u,v]) α β) | return none
131-
let expanded ← expandCoe (mkApp4 (.const ``CoeSort.coe [u,v]) α β inst expr)
117+
let (expanded, _) ← expandCoe (mkApp4 (.const ``CoeSort.coe [u,v]) α β inst expr)
132118
unless (← whnf (← inferType expanded)).isSort do
133119
throwError m!"Failed to coerce{indentExpr expr}\nto a type: After applying `CoeSort.coe`, result is still not a type{indentExpr expanded}"
134120
++ .hint' m!"This is often due to incorrect `CoeSort` instances; the synthesized instance was{indentExpr inst}"
@@ -217,7 +203,10 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
217203
let saved ← saveState
218204
if (← isDefEq m n) then
219205
let some monadInst ← isMonad? n | restoreState saved; return none
220-
try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => restoreState saved; return none
206+
try
207+
let (result, _) ← expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e])
208+
pure result
209+
catch _ => restoreState saved; return none
221210
else if autoLift.get (← getOptions) then
222211
try
223212
-- Construct lift from `m` to `n`
@@ -244,7 +233,7 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
244233
let v ← getLevel β
245234
let coeTInstType := Lean.mkForall `a BinderInfo.default α <| mkAppN (mkConst ``CoeT [u, v]) #[α, mkBVar 0, β]
246235
let .some coeTInstVal ← trySynthInstance coeTInstType | return none
247-
let eNew ← expandCoe (mkAppN (Lean.mkConst ``Lean.Internal.liftCoeM [u_1, u_2, u_3]) #[m, n, α, β, monadLiftVal, coeTInstVal, monadInst, e])
236+
let (eNew, _) ← expandCoe (mkAppN (Lean.mkConst ``Lean.Internal.liftCoeM [u_1, u_2, u_3]) #[m, n, α, β, monadLiftVal, coeTInstVal, monadInst, e])
248237
let eNewType ← inferType eNew
249238
unless (← isDefEq expectedType eNewType) do return none
250239
return some eNew -- approach 3 worked
@@ -254,10 +243,15 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
254243
else
255244
return none
256245

257-
/-- Coerces `expr` to the type `expectedType`.
258-
Returns `.some coerced` on successful coercion,
246+
/--
247+
Coerces `expr` to the type `expectedType`.
248+
Returns `.some (coerced, appliedCoeDecls)` on successful coercion,
259249
`.none` if the expression cannot by coerced to that type,
260-
or `.undef` if we need more metavariable assignments. -/
250+
or `.undef` if we need more metavariable assignments.
251+
252+
`appliedCoeDecls` is a list of names representing the names of the `Coe` instances that were
253+
applied.
254+
-/
261255
def coerce? (expr expectedType : Expr) : MetaM (LOption (Expr × List Name)) := do
262256
if let some lifted ← coerceMonadLift? expr expectedType then
263257
return .some (lifted, [])

tests/lean/run/coeLinter.lean

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ structure Y
99
@[deprecated "" (since := "")]
1010
instance mycoe : Coe X Y where coe _ := ⟨⟩
1111

12+
/-- warning: This term uses the coercion `optionCoe`, which is banned in Lean's core library. -/
13+
#guard_msgs in
1214
def f : Option String := "hi"
1315

1416
/--
@@ -17,9 +19,39 @@ warning: This term uses the coercion `instCoeSubarrayArray`, which is banned in
1719
#guard_msgs in
1820
def g : Array Nat := #[1, 2, 3][*...*]
1921

20-
set_option trace.Elab.info true
22+
/--
23+
warning: This term uses the deprecated coercion `mycoe`.
24+
25+
Note: This linter can be disabled with `set_option linter.deprecatedCoercions false`
26+
-/
27+
#guard_msgs in
2128
def h (foo : X) : Y := foo
2229

30+
notation a " +' " b => a + b
31+
32+
@[deprecated "" (since := "")]
33+
instance : Coe X Int where
34+
coe _ := 0
35+
36+
/--
37+
@ +1:31...32
38+
warning: This term uses the deprecated coercion `instCoeXInt`.
39+
40+
Note: This linter can be disabled with `set_option linter.deprecatedCoercions false`
41+
---
42+
@ +1:36...37
43+
warning: This term uses the deprecated coercion `instCoeXInt`.
44+
45+
Note: This linter can be disabled with `set_option linter.deprecatedCoercions false`
46+
---
47+
@ +1:41...42
48+
warning: This term uses the deprecated coercion `instCoeXInt`.
49+
50+
Note: This linter can be disabled with `set_option linter.deprecatedCoercions false`
51+
-/
52+
#guard_msgs(positions := true) in
53+
example := fun (n m l : X) => (n + (m +' l) : Int)
54+
2355
set_option linter.deprecatedCoercions false
2456

2557
#guard_msgs in

0 commit comments

Comments
 (0)