diff --git a/src/Lean/Elab/DeclModifiers.lean b/src/Lean/Elab/DeclModifiers.lean index 864f125098..65f7992b57 100644 --- a/src/Lean/Elab/DeclModifiers.lean +++ b/src/Lean/Elab/DeclModifiers.lean @@ -160,10 +160,20 @@ def checkIfShadowingStructureField (declName : Name) : m Unit := do | _ => pure () def mkDeclName (currNamespace : Name) (modifiers : Modifiers) (shortName : Name) : m (Name × Name) := do - let name := (extractMacroScopes shortName).name - unless name.isAtomic || isFreshInstanceName name do + let mut shortName := shortName + let mut currNamespace := currNamespace + let view := extractMacroScopes shortName + let name := view.name + let isRootName := (`_root_).isPrefixOf name + if name == `_root_ then + throwError "invalid declaration name `_root_`, `_root_` is a prefix used to refer to the 'root' namespace" + unless name.isAtomic || isFreshInstanceName name || isRootName do throwError "atomic identifier expected '{shortName}'" - let declName := currNamespace ++ shortName + let declName := if isRootName then { view with name := name.replacePrefix `_root_ Name.anonymous }.review else currNamespace ++ shortName + if isRootName then + let .str p s _ := name | throwError "invalid declaration name '{name}'" + shortName := Name.mkSimple s + currNamespace := p.replacePrefix `_root_ Name.anonymous checkIfShadowingStructureField declName let declName ← applyVisibility modifiers.visibility declName match modifiers.visibility with diff --git a/src/Lean/Elab/Declaration.lean b/src/Lean/Elab/Declaration.lean index 6f4ea6f236..320a489321 100644 --- a/src/Lean/Elab/Declaration.lean +++ b/src/Lean/Elab/Declaration.lean @@ -23,9 +23,12 @@ private def ensureValidNamespace (name : Name) : MacroM Unit := do | Name.num _ .. => Macro.throwError s!"invalid namespace '{name}', it must not contain numeric parts" | Name.anonymous => return () -/- Auxiliary function for `expandDeclNamespace?` -/ +/-- Auxiliary function for `expandDeclNamespace?` -/ private def expandDeclIdNamespace? (declId : Syntax) : MacroM (Option (Name × Syntax)) := do let (id, _) := expandDeclIdCore declId + if (`_root_).isPrefixOf id then + ensureValidNamespace (id.replacePrefix `_root_ Name.anonymous) + return none let scpView := extractMacroScopes id match scpView.name with | Name.str Name.anonymous _ _ => return none @@ -41,7 +44,10 @@ private def expandDeclIdNamespace? (declId : Syntax) : MacroM (Option (Name × S return some (pre, declId.setArg 0 id) | _ => return none -/- given declarations such as `@[...] def Foo.Bla.f ...` return `some (Foo.Bla, @[...] def f ...)` -/ +/-- + Given declarations such as `@[...] def Foo.Bla.f ...` return `some (Foo.Bla, @[...] def f ...)` + Remark: if the id starts with `_root_`, we return `none`. +-/ private def expandDeclNamespace? (stx : Syntax) : MacroM (Option (Name × Syntax)) := do if !stx.isOfKind `Lean.Parser.Command.declaration then return none diff --git a/tests/lean/490.lean b/tests/lean/490.lean index fabee75427..0023101363 100644 --- a/tests/lean/490.lean +++ b/tests/lean/490.lean @@ -1,3 +1,3 @@ namespace Foo -def _root_.bar := 1 -- Error +def _root_.bar := 1 -- ok end Foo diff --git a/tests/lean/490.lean.expected.out b/tests/lean/490.lean.expected.out index c5264fe5ef..e69de29bb2 100644 --- a/tests/lean/490.lean.expected.out +++ b/tests/lean/490.lean.expected.out @@ -1 +0,0 @@ -490.lean:2:0-2:19: error: invalid namespace '_root_', '_root_' is a reserved namespace diff --git a/tests/lean/root.lean b/tests/lean/root.lean new file mode 100644 index 0000000000..24634b275b --- /dev/null +++ b/tests/lean/root.lean @@ -0,0 +1,22 @@ +-*- mode: compilation; default-directory: "~/projects/lean4/build/release/" -*- +Compilation started at Mon Jun 13 13:56:14 + +/home/leodemoura/.elan/bin/lean /home/leodemoura/projects/lean4/build/release/root.lean +Bla.f : Nat → Nat +/home/leodemoura/projects/lean4/build/release/root.lean:21:14: error: protected declarations must be in a namespace +/home/leodemoura/projects/lean4/build/release/root.lean:29:4: error: invalid declaration name `_root_`, `_root_` is a prefix used to refer to the 'root' namespace +/home/leodemoura/projects/lean4/build/release/root.lean:31:0: error: invalid namespace '_root_', '_root_' is a reserved namespace +/home/leodemoura/projects/lean4/build/release/root.lean:33:0: error: invalid namespace 'f._root_', '_root_' is a reserved namespace +/home/leodemoura/projects/lean4/build/release/root.lean:35:14: error: protected declarations must be in a namespace +/home/leodemoura/projects/lean4/build/release/root.lean:41:7: error: unknown identifier 'h' +/home/leodemoura/projects/lean4/build/release/root.lean:43:7: error: unknown identifier 'f' +f : Nat → Nat +_private.root.0.prv : Nat -> Nat +/home/leodemoura/projects/lean4/build/release/root.lean:90:48: error: unsolved goals +x : Nat +⊢ isEven (x + 1 + 1) = isEven x +/home/leodemoura/projects/lean4/build/release/root.lean:95:48: error: unsolved goals +x : Nat +⊢ isEven (x + 1 + 1) = isEven x + +Compilation exited abnormally with code 1 at Mon Jun 13 13:56:14 diff --git a/tests/lean/root.lean.expected.out b/tests/lean/root.lean.expected.out new file mode 100644 index 0000000000..03687c7368 --- /dev/null +++ b/tests/lean/root.lean.expected.out @@ -0,0 +1,11 @@ +root.lean:1:0: error: expected command +root.lean:6:80: error: expected 'abbrev', 'axiom', 'builtin_initialize', 'class', 'constant', 'def', 'example', 'inductive', 'initialize', 'instance', 'structure' or 'theorem' +root.lean:7:0: error: expected identifier +root.lean:7:125: error: expected ':' +root.lean:8:0: error: expected identifier +root.lean:8:90: error: missing end of character literal +root.lean:9:0: error: expected identifier +root.lean:9:90: error: missing end of character literal +root.lean:10:0: error: expected identifier +root.lean:10:80: error: expected 'abbrev', 'axiom', 'builtin_initialize', 'class', 'constant', 'def', 'example', 'inductive', 'initialize', 'instance', 'structure' or 'theorem' +root.lean:11:0: error: expected identifier