Prerequisites
Description
Lean.Elab.Command.withNamespace does not call popScopes after running (the way Lean.Elab.Command.elabEnd does). This causes scoped syntax declarations to reserve keywords outside of their scope if withNamespace has been called.
Context
Was trying to programmatically declare scoped syntax declarations (so they don't reserve keywords outside of a certain namespace). Briefly discussed on Zulip here.
Steps to Reproduce
import Lean
open Lean Meta Elab Command
namespace outer
#eval do
withNamespace `inner do
logInfo "shouldn't affect anything"
scoped syntax "myterm" : term
end outer
#eval `(term|myterm) -- parses as a keyword (`outer.termMyterm) instead of an identifier
...and...
import Lean
open Lean Meta Elab Command
#eval do
withNamespace `outer do
logInfo "shouldn't affect anything"
namespace outer
scoped syntax "myterm" : term
end outer
#eval `(term|myterm) -- parses as a keyword (`outer.termMyterm) instead of an identifier
Expected behavior: Outside of the outer namespace, myterm should be parsed as an identifier, not a keyword
Actual behavior: Parses as an identifier outside theouter namespace (as happens when withNamespace isn't used anywhere)
Versions
Lean 4.30.0-nightly-2026-02-20
(on live.lean-lang.org)
Additional Information
It appears that this is due to withNamespace not calling Lean.popScope after running and removing the scopes from the Command.State; the end keyword does this and doesn't suffer from this problem. A one-line fix -- adding for _ in *...ns.getNumParts do popScope as the second-to-last line of withNamespace -- fixes the issue. If it would be helpful for me to make a PR I'd be happy to do so!
Impact
Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.
Prerequisites
https://github.com/leanprover/lean4/issues
Avoid dependencies to Mathlib or Batteries.
https://live.lean-lang.org/#project=lean-nightly
(You can also use the settings there to switch to “Lean nightly”)
Description
Lean.Elab.Command.withNamespacedoes not callpopScopesafter running (the wayLean.Elab.Command.elabEnddoes). This causesscoped syntaxdeclarations to reserve keywords outside of their scope ifwithNamespacehas been called.Context
Was trying to programmatically declare scoped syntax declarations (so they don't reserve keywords outside of a certain namespace). Briefly discussed on Zulip here.
Steps to Reproduce
...and...
Expected behavior: Outside of the
outernamespace,mytermshould be parsed as an identifier, not a keywordActual behavior: Parses as an identifier outside the
outernamespace (as happens whenwithNamespaceisn't used anywhere)Versions
Lean 4.30.0-nightly-2026-02-20
(on live.lean-lang.org)
Additional Information
It appears that this is due to
withNamespacenot callingLean.popScopeafter running and removing the scopes from theCommand.State; theendkeyword does this and doesn't suffer from this problem. A one-line fix -- addingfor _ in *...ns.getNumParts do popScopeas the second-to-last line ofwithNamespace-- fixes the issue. If it would be helpful for me to make a PR I'd be happy to do so!Impact
Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.