Skip to content

Commit 41ace69

Browse files
authored
feat: lint on open statements within namespace which do not open all candidate namespaces (#14325)
This PR adds a linter which warns on `open` statements which do not in fact open all namespaces which end in the given name. Example: ```lean def A.B.a1 : Nat := 0 def B.a2 : Nat := 0 namespace A open B #check a2 ``` Here, we lint on `open B` since `_root_.B` is not actually opened. This will help with fixing downstream fallout from adding new namespaces. Suppose we have just ```lean def B.a2 : Nat := 0 namespace A open B #check a2 ``` This compiles. Now suppose upstream adds `def A.B.a1 : Nat := 0`. Then the above snippet no longer compiles, with only an `unknown identifier` error on `a2`. With the new linter, we now also get a warning on the `open B` which warns us that `_root_.B` is no longer imported, which should help with understanding the `unknown identifier` error (because usually from the context of the file it is quite clear that we want `_root_.B`, not `_root_.A.B`!).
1 parent e599b3e commit 41ace69

61 files changed

Lines changed: 391 additions & 69 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Init/Data/Fin/Lemmas.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ attribute [scoped instance] instIntCast
152152

153153
end IntCast
154154

155-
open IntCast in
155+
open Fin.IntCast in
156156
theorem intCast_def {n : Nat} [NeZero n] (x : Int) :
157157
(x : Fin n) = if 0 ≤ x then Fin.ofNat n x.natAbs else -Fin.ofNat n x.natAbs := rfl
158158

src/Lean/Compiler/LCNF/ToExpr.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ where
7878

7979
end ToExpr
8080

81-
open ToExpr
81+
open Lean.Compiler.LCNF.ToExpr
8282

8383
private def Arg.toExprM (arg : Arg pu) : ToExprM Expr :=
8484
return arg.toExpr.abstract' (← read) (← get)

src/Lean/Elab/Open.lean

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ prelude
99
public import Lean.Elab.Util
1010
public import Lean.Parser.Command
1111
meta import Lean.Parser.Command
12+
public import Lean.Linter.AmbiguousOpen
1213
import Init.Omega
1314

1415
public section
@@ -75,31 +76,38 @@ def elabOpenDecl [MonadOptions m] [MonadResolveName m] [MonadInfoTree m] (stx :
7576
match stx with
7677
| `(Parser.Command.openDecl| $nss*) =>
7778
for ns in nss do
78-
for ns in (← resolveNamespace ns) do
79+
let resolved ← resolveNamespace ns
80+
Linter.checkAmbiguousOpen ns resolved
81+
for ns in resolved do
7982
addOpenDecl (OpenDecl.simple ns [])
8083
activateScoped ns
8184
| `(Parser.Command.openDecl| scoped $nss*) =>
8285
for ns in nss do
83-
for ns in (← resolveNamespace ns) do
86+
let resolved ← resolveNamespace ns
87+
Linter.checkAmbiguousOpen ns resolved
88+
for ns in resolved do
8489
activateScoped ns
8590
| `(Parser.Command.openDecl| $ns ($ids*)) =>
8691
let nss ← resolveNamespace ns
92+
Linter.checkAmbiguousOpen ns nss
8793
for idStx in ids do
8894
let declName ← resolveNameUsingNamespacesCore nss idStx
8995
if (← getInfoState).enabled then
9096
addConstInfo idStx declName
9197
addOpenDecl (OpenDecl.explicit idStx.getId declName)
92-
| `(Parser.Command.openDecl| $ns hiding $ids*) =>
93-
let ns ← resolveUniqueNamespace ns
98+
| `(Parser.Command.openDecl| $nsStx hiding $ids*) =>
99+
let ns ← resolveUniqueNamespace nsStx
100+
Linter.checkAmbiguousOpen nsStx [ns]
94101
activateScoped ns
95102
for id in ids do
96103
let declName ← resolveId ns id
97104
if (← getInfoState).enabled then
98105
addConstInfo id declName
99106
let ids := ids.map (·.getId) |>.toList
100107
addOpenDecl (OpenDecl.simple ns ids)
101-
| `(Parser.Command.openDecl| $ns renaming $[$froms -> $tos],*) =>
102-
let ns ← resolveUniqueNamespace ns
108+
| `(Parser.Command.openDecl| $nsStx renaming $[$froms -> $tos],*) =>
109+
let ns ← resolveUniqueNamespace nsStx
110+
Linter.checkAmbiguousOpen nsStx [ns]
103111
forfrom», to) in froms.zip tos do
104112
let declName ← resolveId ns «from»
105113
if (← getInfoState).enabled then

src/Lean/Elab/Tactic/Do/Internal/VCGen/SpecDB.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ side of `@[spec]` into the same database, and looking up the specs matching a pr
2424

2525
namespace Lean.Elab.Tactic.Do.Internal
2626

27-
open SpecAttr
27+
open Lean.Elab.Tactic.Do.Internal.SpecAttr
2828

2929
/-- Returns `true` if `e` is already internalized into the current `SymM` share table, in which case
3030
`shareCommon e` returns `e` unchanged. -/

src/Lean/Elab/Tactic/Grind/Anchor.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module
77
prelude
88
public import Lean.Meta.Tactic.Grind.Types
99
namespace Lean.Elab.Tactic.Grind
10-
open Meta Grind
10+
open Meta Lean.Meta.Grind
1111

1212
public def elabAnchorRef (anchor : TSyntax `hexnum) : CoreM AnchorRef := do
1313
let numDigits := anchor.getHexNumSize

src/Lean/Elab/Tactic/Grind/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ def tryTactic (tac : GrindTacticM α) : GrindTacticM Bool := do
324324
catch _ =>
325325
pure false
326326

327-
open Grind
327+
open Lean.Meta.Grind
328328

329329
/-
330330
**Note**: Recall that `grind` uses the reducibility specified at `Config.reducible`

src/Lean/Elab/Tactic/Grind/BuiltinTactic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def evalGrindSeq : GrindTactic := fun stx =>
8383
@[builtin_grind_tactic paren] def evalParen : GrindTactic := fun stx =>
8484
evalGrindTactic stx[1]
8585

86-
open Meta Grind
86+
open Meta Lean.Meta.Grind
8787

8888
@[builtin_grind_tactic finish] def evalFinish : GrindTactic := fun stx => withMainContext do
8989
let `(grind| finish $[$configItems]* $[only%$only]? $[[$params?,*]]?) := stx | throwUnsupportedSyntax

src/Lean/Elab/Tactic/Grind/Cbv.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ prelude
88
import Lean.Elab.Tactic.Grind.Basic
99
import Lean.Meta.Tactic.Cbv.Main
1010
namespace Lean.Elab.Tactic.Grind
11-
open Meta Grind
11+
open Meta
1212

1313
@[builtin_grind_tactic Parser.Tactic.Grind.symCbv] def evalSymCbv : GrindTactic := fun _ => withMainContext do
1414
ensureSym

src/Lean/Elab/Tactic/Grind/DSimp.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Lean.Meta.Sym.DSimp.Variant
1111
import Lean.Meta.Sym.DSimp.Reduce
1212
import Lean.Meta.Sym.DSimp.DSimproc
1313
namespace Lean.Elab.Tactic.Grind
14-
open Meta Grind
14+
open Meta
1515
open Sym.DSimp
1616

1717
def elabDSimpArgs (args? : Option (Array (TSyntax [`token.«*», `ident]))) : GrindTacticM DSimpArgs := do

src/Lean/Elab/Tactic/Grind/Filter.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ prelude
88
public import Lean.Elab.Tactic.Grind.Basic
99
public import Lean.Meta.Tactic.Grind.Filter
1010
namespace Lean.Elab.Tactic.Grind
11-
open Meta Grind
11+
open Meta Lean.Meta.Grind
1212

1313
public partial def elabFilter (filter? : Option (TSyntax `grind_filter)) : GrindTacticM Filter := do
1414
let some filter := filter? | return .true

0 commit comments

Comments
 (0)