compiler: Skip completed nominal application suffixes

1de5c499b6e6007fa23216913cf31178ea0fa5df0bebbbe316980061495f664c
Alexis Sellier committed ago 1 parent 68c2ad57
lib/std/lang/resolver.rad +6 -1
1061 1061
    symbolCount: u32,
1062 1062
    /// Active region names for source type checking.
1063 1063
    regionScope: ?*RegionScope,
1064 1064
    /// Interned applications of nominal region parameters.
1065 1065
    applications: ?*unsafe NominalApplication,
1066 +
    /// First entry in the fully resolved suffix of the application list.
1067 +
    completedApplications: ?*unsafe NominalApplication,
1066 1068
    /// Current scope.
1067 1069
    scope: *unsafe mut Scope,
1068 1070
    /// Package scope containing package roots and top-level symbols.
1069 1071
    pkgScope: *unsafe mut Scope,
1070 1072
    /// Stack of loop contexts for nested loops.
1435 1437
    }
1436 1438
}
1437 1439
1438 1440
/// Complete all applied member views before semantic metadata reaches lowering.
1439 1441
unsafe fn resolveNominalApplications 'arena (self: &mut Resolver 'arena, site: *ast::Node) throws (ResolveError) {
1440 -
    let mut end: ?*unsafe NominalApplication = nil;
1442 +
    let mut end = self.completedApplications;
1441 1443
    loop {
1442 1444
        let first = self.applications;
1443 1445
        let mut cursor = first;
1444 1446
        while cursor <> end {
1445 1447
            let applied = cursor else panic "resolveNominalApplications: invalid frontier";
1446 1448
            try ensureNominalResolved(self, applied.view, site);
1447 1449
            set cursor = applied.next;
1448 1450
        }
1449 1451
        if self.applications == first {
1452 +
            set self.completedApplications = first;
1450 1453
            return;
1451 1454
        }
1452 1455
        set end = first;
1453 1456
    }
1454 1457
}
1455 1458
1459 +
1456 1460
/// Allocate a function type descriptor and return a pointer to it.
1457 1461
unsafe fn allocFnType 'arena (self: &mut Resolver 'arena, info: FnType) -> *FnType {
1458 1462
    let entry = try! alloc::alloc(
1459 1463
        &mut *self.arena, @sizeOf(FnType), @alignOf(FnType)
1460 1464
    ) as *mut FnType;
1537 1541
    }
1538 1542
    return Resolver 'arena {
1539 1543
        symbolCount: 0,
1540 1544
        regionScope: nil,
1541 1545
        applications: nil,
1546 +
        completedApplications: nil,
1542 1547
        scope: pkgScope,
1543 1548
        pkgScope: pkgScope,
1544 1549
        loopStack: undefined,
1545 1550
        loopDepth: 0,
1546 1551
        currentFn: nil,
lib/std/lang/resolver/tests/regions.rad +23 -0
640 640
        try testing::expect(first.layout == second.layout);
641 641
        try testing::expect(first.layout.size == 4);
642 642
    }
643 643
}
644 644
645 +
646 +
/// Applications introduced in successive function bodies are fully resolved.
647 +
@test unsafe fn testNominalCompletionAcrossBodies() throws (testing::TestError) {
648 +
    let mut arena = super::testArena();
649 +
    let storage: 'test = &mut arena in {
650 +
        let mut res = super::testResolver(storage);
651 +
        let result = try super::resolveProgramStr(&mut res,
652 +
            "record N: 'r + Copy { value: &'r u32 } fn f 'a (x: &'a u32) { let n = N 'a { value: x }; } fn g 'b (x: &'b u32) { let n = N 'b { value: x }; }"
653 +
        );
654 +
        try super::expectNoErrors(&result);
655 +
        let mut count: u32 = 0;
656 +
        let mut cursor = res.applications;
657 +
        while let applied = cursor {
658 +
            let case resolver::NominalType::Record(body) = *applied.view else throw testing::TestError::Failed;
659 +
            assert body.application == applied;
660 +
            assert body.fields.len == 1;
661 +
            set count += 1;
662 +
            set cursor = applied.next;
663 +
        }
664 +
        assert count == 2;
665 +
    }
666 +
}
667 +
645 668
/// Recursive fields refer to their own exact applied descriptor.
646 669
@test unsafe fn testRecursiveNominalApplications() throws (testing::TestError) {
647 670
    let mut testArena20 = super::testArena();
648 671
    let testStorage20: 'test20 = &mut testArena20 in {
649 672
        let mut res = super::testResolver(testStorage20);