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.
Alexis Sellier committed ago 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