Resolve wildcard types before function signatures
d5a7e016cd96d507a734193550e286fb97b353aaa8da510317bb0d1053792435
Wildcard imports were processed only after function signatures had been bound. Exported child-module types therefore remained unavailable in parameter and return annotations even though the same imports worked later in function bodies. Perform an idempotent wildcard import pass before signature resolution and retain the later pass for declarations added afterward.
1 parent
d8ccda79
lib/std/lang/resolver.rad
+8 -5
| 3956 | 3956 | if decl.wildcard { |
|
| 3957 | 3957 | // Import all public symbols from the target module. |
|
| 3958 | 3958 | for i in 0..resolved.scope.symbolsLen { |
|
| 3959 | 3959 | let sym = resolved.scope.symbols[i]; |
|
| 3960 | 3960 | if ast::hasAttribute(sym.attrs, ast::Attribute::Export) { |
|
| 3961 | + | if let existing = findSymbolInScope(self.scope, sym.name) { |
|
| 3962 | + | if existing == sym { |
|
| 3963 | + | continue; |
|
| 3964 | + | } |
|
| 3965 | + | } |
|
| 3961 | 3966 | try addSymbolToScope(self, sym, self.scope, node); |
|
| 3962 | 3967 | } |
|
| 3963 | 3968 | } |
|
| 3964 | 3969 | } else { |
|
| 3965 | 3970 | // Regular module import. |
| 6762 | 6767 | /// Phase 1: Bind all type names to allow forward references and mutual recursion. |
|
| 6763 | 6768 | /// Phase 2: Resolve type bodies, ie. field types, variant types, etc. |
|
| 6764 | 6769 | fn resolveModuleDecls(res: *mut Resolver, block: *ast::Block) throws (ResolveError) { |
|
| 6765 | 6770 | // Phase 1: Bind all type names as placeholders. |
|
| 6766 | 6771 | try bindTypeNames(res, block); |
|
| 6767 | - | // Phase 2: Process non-wildcard imports so module names are available |
|
| 6768 | - | // for submodule resolution and type lookups. |
|
| 6772 | + | // Phase 2: Process imports so names available from the module graph can |
|
| 6773 | + | // be used in function signatures. |
|
| 6769 | 6774 | for node in block.statements { |
|
| 6770 | 6775 | if let case ast::NodeValue::Use(decl) = node.value { |
|
| 6771 | - | if not decl.wildcard { |
|
| 6772 | - | try resolveUse(res, node, decl); |
|
| 6773 | - | } |
|
| 6776 | + | try resolveUse(res, node, decl); |
|
| 6774 | 6777 | } |
|
| 6775 | 6778 | } |
|
| 6776 | 6779 | // Phase 3: Bind function signatures so that function references are |
|
| 6777 | 6780 | // available in constant and static initializers. |
|
| 6778 | 6781 | for node in block.statements { |
lib/std/lang/resolver/tests.rad
+2 -2
| 3684 | 3684 | @test fn testWildcardImportPublicOnly() throws (testing::TestError) { |
|
| 3685 | 3685 | let mut a = testResolver(); |
|
| 3686 | 3686 | let mut arena = ast::nodeArena(&mut AST_ARENA[..]); |
|
| 3687 | 3687 | ||
| 3688 | 3688 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "export mod b; mod a;", &mut arena); |
|
| 3689 | - | let bId = try registerModule(&mut MODULE_GRAPH, rootId, "b", "export fn public() -> i32 { return 1; } fn private() -> i32 { return 2; }", &mut arena); |
|
| 3690 | - | let aId = try registerModule(&mut MODULE_GRAPH, rootId, "a", "use root::b::*; fn main() -> i32 { return public(); }", &mut arena); |
|
| 3689 | + | let bId = try registerModule(&mut MODULE_GRAPH, rootId, "b", "export record Value { number: i32 } export fn public() -> i32 { return 1; } fn private() -> i32 { return 2; }", &mut arena); |
|
| 3690 | + | let aId = try registerModule(&mut MODULE_GRAPH, rootId, "a", "use root::b::*; fn id(value: Value) -> Value { return value; } fn main() -> i32 { return public() + id(Value { number: 2 }).number; }", &mut arena); |
|
| 3691 | 3691 | ||
| 3692 | 3692 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 3693 | 3693 | try expectNoErrors(&result); |
|
| 3694 | 3694 | } |
|
| 3695 | 3695 |