Why can't a local construct share a name with a referenced (imported) type in EK9?
← Syntax and Structure Rules · Ref: Q1306
EK9 refuses to pick a winner when a locally-defined construct (class, record, trait, function) shares its name with a type brought in via a 'references' block. Both the import and the local definition want the same short name, so any later use of that name is ambiguous - the compiler rejects it immediately with E03010 rather than silently choosing one.
Fix: rename the local construct to a distinct name (e.g. ItemList instead of List). The referenced type keeps its short name, the local type gets its own, and every use resolves to exactly one symbol.
Note that a local construct named after a BUILT-IN type (a class called List, say) is refused earlier, with E01090 (the name of a built-in construct cannot be given a second meaning), before references are even checked. E03010 is for the names of types that come from another module; a single file can show it only by referencing a type of its own module (references qa.syntaxrules.referencecollision::ItemList while also defining ItemList). Alternatively, drop the reference and use the fully qualified 'module::Type' form inline when the imported type is needed.
See Q726 for references block syntax. See Q832 for the design rationale.
Example
defines module qa.syntaxrules.referencecollision //'List' is imported via references and keeps that short name. references org.ek9.lang::List //THE FIX: the local construct is named distinctly (ItemList), so it does //NOT collide with the referenced 'List'. Also referencing a type called //ItemList (from another module) would trigger E03010 CONSTRUCT_REFERENCE_CONFLICT; //naming this class 'List' is E01090 instead, because List is built in. defines class ItemList items as List of String? ItemList() items: List() of String ItemList() -> initial as String items: List() of String items += initial add() -> item as String items += item size() <- rtn as Integer: length items default operator ? defines program ReferenceCollisionDemo() stdout <- Stdout() //'List' resolves unambiguously to the referenced org.ek9.lang::List. basket <- ItemList("apple") basket.add("pear") stdout.println(`Basket holds ${basket.size()} items`)
Common mistakes
E03010 — Referencing 'ItemList' via references and then defining a local class also named 'ItemList' makes the short name ambiguous - neither the reference nor the local definition takes priority, so EK9 raises E03010 (here the referenced type stands in for one from another module). Rename the local construct so each name resolves to exactly one symbol, or drop the reference and use the fully qualified name inline. See ek9 -h E03010 for details.
Incorrect:
references org.ek9.lang::List qa.syntaxrules.referencecollision::ItemList
Correct:
references org.ek9.lang::List
Other ways to ask this
- What triggers E03010 CONSTRUCT_REFERENCE_CONFLICT?
- Why does referencing a type and then defining a local class with the same name fail to compile?
- How do I resolve a name collision between a references import and a local type?
Coming from another language?
Java: wildcard imports (import java.util.*) silently shadow local types; the conflict surfaces only when two imports expose the same name. Python: 'from module import *' overwrites local names with no warning. C#: 'using' directives let a local type silently win over an imported one. EK9: neither the reference nor the local takes priority - the collision is a compile-time error (E03010) and the developer must choose a distinct name.
Keywords: E03010, name, collision, rename, references, import, conflict, local, syntax