compiler: Skip completed nominal application suffixes
1de5c499b6e6007fa23216913cf31178ea0fa5df0bebbbe316980061495f664c
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); |