Skip to content

Commit a164ae5

Browse files
authored
chore: overhaul meta error messages (#10569)
1 parent 2c54386 commit a164ae5

File tree

5 files changed

+62
-9
lines changed

5 files changed

+62
-9
lines changed

src/Lean/Compiler/LCNF/Visibility.lean

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,44 @@ where go (isMeta isPublic : Bool) (decl : Decl) : StateT NameSet CompilerM Unit
7474
if (← get).contains ref then
7575
continue
7676
modify (·.insert ref)
77+
let env ← getEnv
7778
if isMeta && isPublic then
78-
if let some modIdx := (← getEnv).getModuleIdxFor? ref then
79-
if (← getEnv).header.modules[modIdx]?.any (!·.isExported) then
80-
throwError "Invalid `meta` definition `{.ofConstName origDecl.name}`, `{.ofConstName ref}` not publicly marked or imported as `meta`"
81-
match getIRPhases (← getEnv) ref, isMeta with
79+
if let some modIdx := env.getModuleIdxFor? ref then
80+
if Lean.isMeta env ref then
81+
if env.header.modules[modIdx]?.any (!·.isExported) then
82+
throwError "Invalid public `meta` definition `{.ofConstName origDecl.name}`, \
83+
`{.ofConstName ref}` is not accessible here; consider adding \
84+
`public import {env.header.moduleNames[modIdx]!}`"
85+
else
86+
-- TODO: does not account for `public import` + `meta import`, which is not the same
87+
if env.header.modules[modIdx]?.any (!·.isExported) then
88+
throwError "Invalid public `meta` definition `{.ofConstName origDecl.name}`, \
89+
`{.ofConstName ref}` is not accessible here; consider adding \
90+
`public meta import {env.header.moduleNames[modIdx]!}`"
91+
match getIRPhases env ref, isMeta with
8292
| .runtime, true =>
83-
throwError "Invalid `meta` definition `{.ofConstName origDecl.name}`, may not access declaration `{.ofConstName ref}` not marked or imported as `meta`"
93+
if let some modIdx := env.getModuleIdxFor? ref then
94+
throwError "Invalid `meta` definition `{.ofConstName origDecl.name}`, \
95+
`{.ofConstName ref}` is not accessible here; consider adding \
96+
`meta import {env.header.moduleNames[modIdx]!}`"
97+
else
98+
throwError "Invalid `meta` definition `{.ofConstName origDecl.name}`, \
99+
`{.ofConstName ref}` not marked `meta`"
84100
| .comptime, false =>
85-
throwError "Invalid definition `{.ofConstName origDecl.name}`, may not access declaration `{.ofConstName ref}` marked or imported as `meta`"
86-
| _, _ =>
101+
if let some modIdx := env.getModuleIdxFor? ref then
102+
if !Lean.isMeta env ref then
103+
throwError "Invalid definition `{.ofConstName origDecl.name}`, may not access \
104+
declaration `{.ofConstName ref}` imported as `meta`; consider adding \
105+
`import {env.header.moduleNames[modIdx]!}`"
106+
throwError "Invalid definition `{.ofConstName origDecl.name}`, may not access \
107+
declaration `{.ofConstName ref}` marked as `meta`"
108+
| irPhases, _ =>
87109
-- We allow auxiliary defs to be used in either phase but we need to recursively check
88110
-- *their* references in this case. We also need to do this for non-auxiliary defs in case a
89111
-- public meta def tries to use a private meta import via a local private meta def :/ .
90-
if let some refDecl ← getLocalDecl? ref then
91-
go isMeta isPublic refDecl
112+
if irPhases == .all || isPublic && isPrivateName ref then
113+
if let some refDecl ← getLocalDecl? ref then
114+
go isMeta isPublic refDecl
92115

93116
/--
94117
Checks meta availability just before `evalConst`. This is a "last line of defense" as accesses

tests/pkg/module/Module.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Module.ImportedPrivateImported
66
import Module.PrivateImported
77
import Module.ImportedAllPrivateImported
88
import Module.NonModule
9+
import Module.MetaImported
910

1011
/-! # Module system basic tests -/
1112

tests/pkg/module/Module/Basic.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ inst✝
408408
#guard_msgs in
409409
#print instTypeNameFoo
410410

411+
public meta def pubMeta := 1
412+
411413
/-! Prop `instance`s should have direct access to the private scope. -/
412414

413415
public class PropClass : Prop where

tests/pkg/module/Module/Imported.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,9 @@ info: f_exp_wfrec.induct_unfolding (motive : Nat → Nat → Nat → Prop) (case
147147
-/
148148
#guard_msgs(pass trace, all) in
149149
#check f_exp_wfrec.induct_unfolding
150+
151+
/-! Basic non-`meta` check. -/
152+
153+
/-- error: Invalid definition `nonMeta`, may not access declaration `pubMeta` marked as `meta` -/
154+
#guard_msgs in
155+
def nonMeta := pubMeta
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module
2+
3+
prelude
4+
meta import Module.Basic
5+
6+
/-! Basic phase restriction tests. -/
7+
/--
8+
error: Invalid definition `nonMeta`, may not access declaration `f` imported as `meta`; consider adding `import Module.Basic`
9+
-/
10+
#guard_msgs in
11+
def nonMeta := f
12+
13+
/-- error: Invalid `meta` definition `veryMeta`, `nonMeta` not marked `meta` -/
14+
#guard_msgs in
15+
meta def veryMeta := nonMeta
16+
17+
/--
18+
error: Invalid public `meta` definition `pubMetaImp`, `pubMeta` is not accessible here; consider adding `public import Module.Basic`
19+
-/
20+
#guard_msgs in
21+
public meta def pubMetaImp := pubMeta

0 commit comments

Comments
 (0)