Fix an issue with module declaration order

326c599dec28d013d4b4aaba5a7e107bdb328c7276286ed8d8ea1cbf89b539bf
Alexis Sellier committed ago 1 parent a74c66b8
lib/std.rad +1 -5
1 1
//! The Radiance Standard Library.
2 -
// TODO: The order of these module declarations matter, but they shouldn't.
3 -
4 -
// Nb: `testing` must come before all other modules so that `@test mod`
5 -
// submodules can `use std::testing` during resolution.
6 -
@test pub mod testing;
7 2
8 3
pub mod io;
9 4
pub mod collections;
10 5
pub mod lang;
11 6
pub mod sys;
15 10
pub mod mem;
16 11
pub mod vec;
17 12
pub mod intrinsics;
18 13
19 14
// Test modules.
15 +
@test pub mod testing;
20 16
@test pub mod tests;
lib/std/lang/resolver.rad +13 -11
5363 5363
    try setNodeType(self, root, Type::Void);
5364 5364
5365 5365
    return Diagnostics { errors: self.errors };
5366 5366
}
5367 5367
5368 -
/// Analyze the module graph. This pass doesn't process function, type or variable declarations,
5369 -
/// it only processes `mod` statements, creating symbols and scopes for them.
5368 +
/// Analyze the module graph. This pass processes `mod` statements, creating symbols
5369 +
/// and scopes for them, and also binds type names in each module so that cross-module
5370 +
/// type references work regardless of declaration order.
5370 5371
fn resolveModuleGraph(self: *mut Resolver, block: *ast::Block) throws (ResolveError) {
5372 +
    try bindTypeNames(self, block);
5373 +
5371 5374
    for i in 0..block.statements.len {
5372 5375
        let node = block.statements.list[i];
5373 5376
        if let case ast::NodeValue::Mod(decl) = node.value {
5374 5377
            try resolveModGraph(self, node, decl);
5375 5378
        }
5376 5379
    }
5377 5380
}
5378 5381
5379 5382
/// Bind all type names in a module.
5383 +
/// Skips declarations that have already been bound.
5380 5384
fn bindTypeNames(self: *mut Resolver, block: *ast::Block) throws (ResolveError) {
5381 5385
    for i in 0..block.statements.len {
5382 5386
        let node = block.statements.list[i];
5383 5387
        match node.value {
5384 5388
            case ast::NodeValue::RecordDecl(decl) => {
5385 -
                try bindTypeName(self, node, decl.name, decl.attrs) catch {
5386 -
                    // Continue binding other types even if one fails.
5387 -
                };
5389 +
                if symbolFor(self, node) == nil {
5390 +
                    try bindTypeName(self, node, decl.name, decl.attrs) catch {};
5391 +
                }
5388 5392
            }
5389 5393
            case ast::NodeValue::UnionDecl(decl) => {
5390 -
                try bindTypeName(self, node, decl.name, decl.attrs) catch {
5391 -
                    // Continue binding other types even if one fails.
5392 -
                };
5393 -
            }
5394 -
            else => {
5395 -
                // Ignore other declarations.
5394 +
                if symbolFor(self, node) == nil {
5395 +
                    try bindTypeName(self, node, decl.name, decl.attrs) catch {};
5396 +
                }
5396 5397
            }
5398 +
            else => {}
5397 5399
        }
5398 5400
    }
5399 5401
}
5400 5402
5401 5403
/// Resolve all type bodies in a module.