resolver: resolve nominal call result views
80a2b616ded7c68d39a1ce07f86b6b059c03a32a26ae83307ae050b4b8074f90
1 parent
aa5d2a53
lib/std/lang/resolver.rad
+3 -0
| 7662 | 7662 | if not objMutable or not try canMutateThrough(self, access.parent) { |
|
| 7663 | 7663 | throw emitError(self, access.parent, ErrorKind::ImmutableBinding); |
|
| 7664 | 7664 | } |
|
| 7665 | 7665 | } |
|
| 7666 | 7666 | let applied = try instantiateCall(self, node, call, method.fnType); |
|
| 7667 | + | try resolveInlineTypeViews(self, *applied.returnType, node); |
|
| 7667 | 7668 | try checkCallArgs(self, node, call, applied, ctx); |
|
| 7668 | 7669 | setTraitMethodCall(self, node, traitInfo, method.index); |
|
| 7669 | 7670 | ||
| 7670 | 7671 | return setNodeType(self, node, *applied.returnType); |
|
| 7671 | 7672 | } |
| 7684 | 7685 | } |
|
| 7685 | 7686 | // Check arguments (excluding receiver). |
|
| 7686 | 7687 | let applied = try instantiateMethodCall( |
|
| 7687 | 7688 | self, node, call, access.parent, subjectTy, method |
|
| 7688 | 7689 | ); |
|
| 7690 | + | try resolveInlineTypeViews(self, *applied.returnType, node); |
|
| 7689 | 7691 | try checkCallArgs(self, node, call, applied, ctx); |
|
| 7690 | 7692 | set self.nodeData.entries[node.id].extra = NodeExtra::MethodCall { method }; |
|
| 7691 | 7693 | ||
| 7692 | 7694 | return setNodeType(self, node, *applied.returnType); |
|
| 7693 | 7695 | } |
| 7698 | 7700 | expected: Type::Unknown, |
|
| 7699 | 7701 | actual: calleeTy, |
|
| 7700 | 7702 | })); |
|
| 7701 | 7703 | }; |
|
| 7702 | 7704 | let applied = try instantiateCall(self, node, call, info); |
|
| 7705 | + | try resolveInlineTypeViews(self, *applied.returnType, node); |
|
| 7703 | 7706 | try checkCallArgs(self, node, call, applied, ctx); |
|
| 7704 | 7707 | // Associate function type to callee. |
|
| 7705 | 7708 | setNodeType(self, call.callee, Type::Fn(applied)); |
|
| 7706 | 7709 | ||
| 7707 | 7710 | // Associate return type to call. |
lib/std/lang/resolver/tests/regions.rad
+18 -0
| 4 | 4 | use std::testing; |
|
| 5 | 5 | use std::lang::types; |
|
| 6 | 6 | use std::lang::resolver; |
|
| 7 | 7 | use std::lang::ast; |
|
| 8 | 8 | ||
| 9 | + | /// Call results resolve regional nominal views before type consumers inspect them. |
|
| 10 | + | @test unsafe fn testCallResultNominalViews() throws (testing::TestError) { |
|
| 11 | + | let programs = [ |
|
| 12 | + | "union R: 'r + Copy { V(&'r u32), E } record M {} fn (m: *M) get 'r(p: &'r u32) -> R 'r { return R::V(p); } fn f 'r(m: *M, p: &'r u32) { let x = m.get 'r(p); match x { case R::V(v) => {}, case R::E => {} } }", |
|
| 13 | + | "union R: 'r + Copy { V(&'r u32), E } trait T { fn (*T) get 'r(p: &'r u32) -> R 'r; } fn f 'r(t: *opaque T, p: &'r u32) { let x = t.get 'r(p); match x { case R::V(v) => {}, case R::E => {} } }", |
|
| 14 | + | "union R: 'r + Copy { V(&'r u32), E } fn get 'r(p: &'r u32) -> ?R 'r { return R::V(p); } fn f 'r(p: &'r u32) { let x = get 'r(p); if let v = x { match v { case R::V(y) => {}, case R::E => {} } } }", |
|
| 15 | + | "union R: 'r + Copy { V(&'r u32), E } fn get 'r(p: &'r u32) -> [R 'r; 1] { return [R::V(p)]; } fn f 'r(p: &'r u32) { let x = get 'r(p); match x[0] { case R::V(y) => {}, case R::E => {} } }", |
|
| 16 | + | ]; |
|
| 17 | + | for program in programs { |
|
| 18 | + | let mut arena = super::testArena(); |
|
| 19 | + | let storage: 'test = &mut arena in { |
|
| 20 | + | let mut res = super::testResolver(storage); |
|
| 21 | + | let result = try super::resolveProgramStr(&mut res, program); |
|
| 22 | + | try super::expectNoErrors(&result); |
|
| 23 | + | } |
|
| 24 | + | } |
|
| 25 | + | } |
|
| 26 | + | ||
| 9 | 27 | /// Optional aggregate payloads start at their required alignment after the tag. |
|
| 10 | 28 | @test fn testOptionalPayloadOffsets() throws (testing::TestError) { |
|
| 11 | 29 | for alignment in [1 as u32, 2, 4, 8, 16] { |
|
| 12 | 30 | let layout = resolver::Layout { size: 32, alignment }; |
|
| 13 | 31 | assert resolver::getOptionalValOffset(layout) == alignment; |
test/tests/regions.call.result.application.rad
added
+61 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! session-support |
|
| 3 | + | ||
| 4 | + | /// Session-backed affine state. |
|
| 5 | + | record State: 'symbols + 'view where 'symbols: 'view { |
|
| 6 | + | /// Persistent storage session. |
|
| 7 | + | storage: &'view Session 'symbols, |
|
| 8 | + | /// Mutable persistent values. |
|
| 9 | + | values: &'symbols mut [u32], |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | /// Result with affine state and separate function storage. |
|
| 13 | + | union Outcome: 'symbols + 'view + 'arena + 'resolverView + 'function |
|
| 14 | + | where 'symbols: 'view, 'arena: 'resolverView, 'symbols: 'function |
|
| 15 | + | { |
|
| 16 | + | /// A ready value. |
|
| 17 | + | Ready { |
|
| 18 | + | /// Returned state. |
|
| 19 | + | state: State 'symbols 'view, |
|
| 20 | + | /// Function-owned values. |
|
| 21 | + | function: &'function mut [u32], |
|
| 22 | + | }, |
|
| 23 | + | /// A skipped value. |
|
| 24 | + | Skipped(State 'symbols 'view), |
|
| 25 | + | /// A failed value. |
|
| 26 | + | Failed { |
|
| 27 | + | /// Returned state. |
|
| 28 | + | state: State 'symbols 'view, |
|
| 29 | + | /// Error number. |
|
| 30 | + | error: u32, |
|
| 31 | + | }, |
|
| 32 | + | } |
|
| 33 | + | ||
| 34 | + | /// Return a ready outcome. |
|
| 35 | + | fn ready 'symbols 'view 'arena 'resolverView 'function ( |
|
| 36 | + | state: State 'symbols 'view, |
|
| 37 | + | function: &'function mut [u32] |
|
| 38 | + | ) -> Outcome 'symbols 'view 'arena 'resolverView 'function |
|
| 39 | + | where 'symbols: 'view, 'arena: 'resolverView, 'symbols: 'function |
|
| 40 | + | { |
|
| 41 | + | return Outcome::Ready { state, function }; |
|
| 42 | + | } |
|
| 43 | + | ||
| 44 | + | /// Consume each outcome variant. |
|
| 45 | + | fn consume 'symbols 'view 'arena 'resolverView 'function ( |
|
| 46 | + | state: State 'symbols 'view, |
|
| 47 | + | function: &'function mut [u32] |
|
| 48 | + | ) -> u32 where 'symbols: 'view, 'arena: 'resolverView, 'symbols: 'function { |
|
| 49 | + | let outcome = ready 'symbols 'view 'arena 'resolverView 'function( |
|
| 50 | + | state, function); |
|
| 51 | + | match outcome { |
|
| 52 | + | case Outcome::Ready { state, .. } => return state.values[0], |
|
| 53 | + | case Outcome::Skipped(state) => return state.values[0], |
|
| 54 | + | case Outcome::Failed { error, .. } => return error, |
|
| 55 | + | } |
|
| 56 | + | } |
|
| 57 | + | ||
| 58 | + | /// Compile the generic inference path. |
|
| 59 | + | @default fn main() -> i32 { |
|
| 60 | + | return 0; |
|
| 61 | + | } |