Why can't I have a local class with the same name as an imported reference in EK9?
← Code Quality · Ref: Q832
EK9 prevents any name collision between locally-defined constructs and imported references. Neither takes priority — the compiler rejects the ambiguity immediately with E03010.
THE RULE
If you reference (import) a symbol like 'Helper' from another module, you cannot also define a local class, function, or record called 'Helper' in the same module. The compiler cannot know which one you mean when you write 'Helper()'.
WHY NO PRIORITY RULES
Some languages let local definitions shadow imports (C#) or let wildcard imports shadow locals (Python's 'from module import *'). Both create subtle bugs where the wrong type is silently used. Java's 'import java.util.*' can silently resolve to the wrong List. EK9 forces you to choose explicitly.
HOW TO FIX
- Rename your local construct to a unique name
- Remove the reference if you only need the local version
- Use fully qualified module::TypeName if both are truly needed
THIS EXAMPLE
Shows proper module naming with distinct local class names. When importing from another module, always ensure your local constructs have unique names.
See Q741 for reference conflict overview. See Q119 for constructs overview. See Q13 for package vs module.
Example
defines module qa.quality.reference.collision defines class <?- When importing from another module, always use distinct names. If another module exports 'Formatter', name your local version differently to avoid E03010 CONSTRUCT_REFERENCE_CONFLICT. -?> LocalFormatter prefix <- "[" suffix <- "]" default LocalFormatter() LocalFormatter() -> p as String s as String prefix :=: p suffix :=: s formatText() -> text as String <- rtn as String: `${prefix}${text}${suffix}` default operator ? defines function <?- Similarly, local functions must not share names with imported references. -?> localTransform() as pure -> input as String <- rtn as String: `<${input}>` defines program ReferenceCollisionDemo() stdout <- Stdout() formatter <- LocalFormatter("[", "]") if formatter? stdout.println(formatter.formatText("hello")) stdout.println(localTransform("world"))
Common mistakes
E01040 — Renaming a function to the same name as an existing class creates a duplicate symbol. EK9 rejects any ambiguity between constructs sharing the same name. See ek9 -h E01030 for details.
Incorrect:
LocalFormatter() as pure
Correct:
localTransform() as pure
Other ways to ask this
- What is E03010 CONSTRUCT_REFERENCE_CONFLICT?
- Why does EK9 reject my class when I also import the same name?
- How do I fix a name collision between a local construct and a referenced import?
Coming from another language?
Java: wildcard imports ('import java.util.*') silently shadow local types — 'which List?' confusion surfaces late in production. Python: 'from module import *' can overwrite locals silently. C#: local types take priority over 'using' imports, masking bugs. Rust: 'use' aliases prevent collisions. EK9: any collision between local and imported is E03010, no shadowing permitted.
Keywords: conflict, local, ambiguity, E03010, construct, module, import, shadow, collision, reference