@@ -29,23 +29,65 @@ private builtin_initialize notMetaExt : EnvExtension NameSet ←
2929 (replay? := some fun _ _ newEntries s => newEntries.foldl (·.insert) s)
3030
3131/-- Marks in the environment extension that the given declaration has been declared by the user as `meta`. -/
32- def addMeta (env : Environment) (declName : Name) : Environment :=
32+ def markMeta (env : Environment) (declName : Name) : Environment :=
3333 metaExt.tag env declName
3434
3535/--
3636Marks the given declaration as not being annotated with `meta` even if it could have been by the
3737user.
3838-/
39- def addNotMeta (env : Environment) (declName : Name) : Environment :=
39+ def markNotMeta (env : Environment) (declName : Name) : Environment :=
4040 if declName.isAnonymous then -- avoid panic from `modifyState` on partial input
4141 env
4242 else
4343 notMetaExt.modifyState (asyncDecl := declName) env (·.insert declName)
4444
4545/-- Returns true iff the user has declared the given declaration as `meta`. -/
46- def isMeta (env : Environment) (declName : Name) : Bool :=
46+ def isMarkedMeta (env : Environment) (declName : Name) : Bool :=
4747 metaExt.isTagged env declName
4848
49+ /--
50+ Set of IR decls that should be made available to any importer. This is a superset of `metaExt`,
51+ which is managed by the elaborator and has a different async mode. More precisely, it contains the
52+ closure of `metaExt` as well as further derived decls such as `_boxed` versions. We store this set
53+ primarily to filter exports in `declMapExt`; we persist it in `.olean.private` for the benefit of
54+ `shake`.
55+ -/
56+ private builtin_initialize declMetaExt : SimplePersistentEnvExtension Name NameSet ←
57+ registerSimplePersistentEnvExtension {
58+ addImportedFn := fun _ => {}
59+ addEntryFn := fun s n => s.insert n
60+ asyncMode := .sync
61+ replay? := some <| SimplePersistentEnvExtension.replayOfFilter (!·.contains ·) (·.insert ·)
62+ exportEntriesFnEx? := some fun env s entries => fun
63+ | .private =>
64+ let decls := entries.foldl (init := #[]) fun decls decl => decls.push decl
65+ decls.qsort Name.quickLt
66+ | _ => #[]
67+ }
68+
69+ /-- Whether a declaration should be exported for interpretation. -/
70+ def isDeclMeta (env : Environment) (declName : Name) : Bool :=
71+ if !env.header.isModule then
72+ true
73+ else
74+ -- The interpreter may call the boxed variant even if the IR does not directly reference it, so
75+ -- use same visibility as base decl.
76+ -- Note that boxed decls are created after the `inferVisibility` pass.
77+ let inferFor := match declName with
78+ | .str n "_boxed" => n
79+ | n => n
80+ match env.getModuleIdxFor? declName with
81+ | some idx => declMetaExt.getModuleEntries env idx |>.binSearchContains inferFor Name.quickLt
82+ | none => declMetaExt.getState env |>.contains inferFor
83+
84+ /-- Marks a declaration to be exported for interpretation. -/
85+ def setDeclMeta (env : Environment) (declName : Name) : Environment :=
86+ if isDeclMeta env declName then
87+ env
88+ else
89+ declMetaExt.addEntry env declName
90+
4991/--
5092Returns the IR phases of the given declaration that should be considered accessible. Does not take
5193additional IR loaded for language server purposes into account.
@@ -55,12 +97,12 @@ def getIRPhases (env : Environment) (declName : Name) : IRPhases := Id.run do
5597 return .all
5698 match env.getModuleIdxFor? declName with
5799 | some idx =>
58- if isMeta env declName then
100+ if isMarkedMeta env declName then
59101 .comptime
60102 else
61103 env.header.modules[idx]?.map (·.irPhases) |>.get!
62104 | none =>
63- if isMeta env declName then
105+ if isMarkedMeta env declName then
64106 .comptime
65107 else if notMetaExt.getState env |>.contains declName then
66108 .runtime
0 commit comments