resolver: resolve nominal call result views

80a2b616ded7c68d39a1ce07f86b6b059c03a32a26ae83307ae050b4b8074f90
Alexis Sellier committed ago 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 +
}