Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: Current namespace in declaration elaborator
Christian Merten (Jan 11 2026 at 17:26):
How do I access the current surrounding namespace of a declaration at elaboration time? For example, in
namespace Foo
def Baz.bla : Nat := 3
end Foo
I would like the output to be Foo. The naive
import Lean
open Lean Elab Command
@[command_elab declaration]
def foo : CommandElab := fun stx => do
logInfo s!"Namespace in elab: {← getCurrNamespace}"
elabDeclaration stx
namespace Foo
-- I would like to get `Foo` instead.
/-- info: Namespace in elab: Foo.Baz -/
#guard_msgs in
def Baz.bla : Nat := 3
end Foo
yields Foo.Baz instead. The reason is that before the declaration is elaborated, the macro docs#Lean.Elab.Command.expandNamespacedDeclaration wraps the declaration in a namespace Baz block.
Edward van de Meent (Jan 11 2026 at 18:29):
i think there isn't really a way to fix this, since it happens after expanding a macro for the syntax you're (presumably?) trying to modify elaboration of.
I think you should check if elaborating an attribute has the same issue (i'm presuming not, since to_additive manages to change namespaces)
Also, let me #xy you need this functionality, just in case
Christian Merten (Jan 11 2026 at 18:43):
I want to extract the source code for a declaration from a .lean source file while preserving the relevant context, which is in particular the necessary namespace ... commands. The way I am currently doing that is by adding an environment extension that stores the current docs#Lean.Elab.Command.Scope when elaborating the declaration. But this contains the "wrong" namespace in the sense that
namespace {extracted namespace}
-- extracted original source code of declaration
end {extracted namespace}
repeats the Baz (in the Baz.bla example from above).
Aaron Liu (Jan 11 2026 at 18:47):
do you know about #where
Aaron Liu (Jan 11 2026 at 18:48):
docs#Lean.Parser.Command.where
Christian Merten (Jan 11 2026 at 18:48):
Edward van de Meent said:
I think you should check if elaborating an attribute has the same issue (i'm presuming not, since
to_additivemanages to change namespaces)
It does have the same issue (can't post a nice mwe in the live editor because of initialization).
Christian Merten (Jan 11 2026 at 18:52):
Aaron Liu said:
do you know about
#where
Yes, but I am not sure how that helps: If you look at the source code of docs#Lean.Elab.Command.elabWhere, it also just gets the current docs#Lean.Elab.Command.Scope. So I would need a way to run this just before elaborating the declaration I want to extract.
Christian Merten (Jan 12 2026 at 09:57):
For the record, I found a hack around this:
import Lean
import Batteries.Tactic.OpenPrivate
open private getDeclName? from Lean.Elab.Declaration
open Lean Elab Command
elab "update_decl_context" decl:ident : command => do
let scope ← getScope
let resolvedName : Name := scope.currNamespace ++ decl.getId
logInfo s!"updating env extension for {resolvedName} in namespace {scope.currNamespace}"
@[macro Lean.Parser.Command.declaration]
def prependUpdateDeclContext : Macro := fun stx => do
if let some declName := getDeclName? stx then
`(update_decl_context $(mkIdent (declName))
$(⟨← expandNamespacedDeclaration stx⟩))
else
expandNamespacedDeclaration stx
namespace Foo
/-- info: updating env extension for Foo.Baz.bla in namespace Foo -/
#guard_msgs in
def Baz.bla : Nat := 3
end Foo
The reason I need the update_decl_context helper command is to get access to the environment in my application (to store the scope in an environment extension).
This is also only half the fix, to also still cover unnamespaced declarations, I also had to change the actual command elaborator.
Last updated: Feb 28 2026 at 14:05 UTC