compiler: Require successful resolution before ownership checks

05c6985b33825e622ff7c9d0f381ce048958fbbec0118f9fbebb8d5f51672dd0
Alexis Sellier committed ago 1 parent e8927bdf
lib/std/lang/resolver.rad +4 -1
4657 4657
    let retTy = *fnType.returnType;
4658 4658
    let bodyTy = try checkAssignable(self, body, Type::Void);
4659 4659
    if retTy <> Type::Void and bodyTy <> Type::Never {
4660 4660
        return true;
4661 4661
    }
4662 -
    try checkLinearFn(self, receiverName, params, body);
4662 +
    // Ownership checks require complete type and call metadata.
4663 +
    if self.errors.len == 0 {
4664 +
        try checkLinearFn(self, receiverName, params, body);
4665 +
    }
4663 4666
    return false;
4664 4667
}
4665 4668
4666 4669
/// Analyze a function parameter and bind its identifier.
4667 4670
unsafe fn resolveFnParam 'arena (self: &mut Resolver 'arena, node: *ast::Node, param: ast::FnParam) -> Type
lib/std/lang/resolver/tests.rad +29 -0
2106 2106
            actual: 1,
2107 2107
        }));
2108 2108
    }
2109 2109
}
2110 2110
2111 +
/// Invalid calls in function bodies retain their resolution diagnostics.
2112 +
@test unsafe fn testInvalidBodyCalls() throws (testing::TestError) {
2113 +
    for program in &[
2114 +
        "fn f(x: u32) {} fn g() { f(1, 2); }",
2115 +
        "fn f(x: u32) {} fn g() { if true { f(1, 2); } }",
2116 +
        "fn f(x: u32) {} unsafe fn g() { f(1, 2); }",
2117 +
    ] {
2118 +
        let mut arena = testArena();
2119 +
        let storage: 'test = &mut arena in {
2120 +
            let mut res = testResolver(storage);
2121 +
            let result = try resolveProgramStr(&mut res, program);
2122 +
            try expectErrorKind(&result, super::ErrorKind::FnArgCountMismatch(super::CountMismatch {
2123 +
                expected: 1, actual: 2,
2124 +
            }));
2125 +
        }
2126 +
    }
2127 +
}
2128 +
2129 +
/// Unsafe calls with excess arguments report the unsafe-call diagnostic.
2130 +
@test unsafe fn testInvalidUnsafeBodyCall() throws (testing::TestError) {
2131 +
    let mut arena = testArena();
2132 +
    let storage: 'test = &mut arena in {
2133 +
        let mut res = testResolver(storage);
2134 +
        let result = try resolveProgramStr(&mut res,
2135 +
            "unsafe fn f(x: u32) {} fn g() { f(1, 2); }");
2136 +
        try expectErrorKind(&result, super::ErrorKind::UnsafeCall);
2137 +
    }
2138 +
}
2139 +
2111 2140
@test unsafe fn testResolveFnCallArgumentTypeMismatch() throws (testing::TestError) {
2112 2141
    let mut testArena120 = testArena();
2113 2142
    let testStorage120: 'test120 = &mut testArena120 in {
2114 2143
        let mut a = testResolver(testStorage120);
2115 2144
        let program = "fn f(x: i8) {} f(true);";