compiler: Require successful resolution before ownership checks

570e9a44bed511e7ab7c20afc9373503aa096e2935c882b5537bd9fe6a9db572
Alexis Sellier committed ago 1 parent 9ed57feb
lib/std/lang/resolver.rad +4 -1
3585 3585
    let retTy = *fnType.returnType;
3586 3586
    let bodyTy = try checkAssignable(self, body, Type::Void);
3587 3587
    if retTy <> Type::Void and bodyTy <> Type::Never {
3588 3588
        return true;
3589 3589
    }
3590 -
    try checkLinearFn(self, receiverName, params, body);
3590 +
    // Ownership checks require complete type and call metadata.
3591 +
    if self.errors.len == 0 {
3592 +
        try checkLinearFn(self, receiverName, params, body);
3593 +
    }
3591 3594
    return false;
3592 3595
}
3593 3596
3594 3597
/// Analyze a function parameter and bind its identifier.
3595 3598
unsafe fn resolveFnParam(self: &mut Resolver, node: *ast::Node, param: ast::FnParam) -> Type
lib/std/lang/resolver/tests.rad +24 -0
6341 6341
@test unsafe fn testLocalReferenceDeclarationContext() throws (testing::TestError) {
6342 6342
    let mut a = testResolver();
6343 6343
    let result = try resolveProgramStr(&mut a, "let n: u32 = 1; let p: &u32 = &n;");
6344 6344
    try expectErrorKind(&result, super::ErrorKind::InvalidRefPosition);
6345 6345
}
6346 +
6347 +
/// Invalid calls in function bodies retain their resolution diagnostics.
6348 +
@test unsafe fn testInvalidBodyCalls() throws (testing::TestError) {
6349 +
    for program in &[
6350 +
        "fn f(x: u32) {} fn g() { f(1, 2); }",
6351 +
        "fn f(x: u32) {} fn g() { if true { f(1, 2); } }",
6352 +
        "fn f(x: u32) {} unsafe fn g() { f(1, 2); }",
6353 +
        "fn f(x: u32) -> u32 { return x; } fn g() { f(f(1, 2)); }",
6354 +
    ] {
6355 +
        let mut res = testResolver();
6356 +
        let result = try resolveProgramStr(&mut res, program);
6357 +
        try expectErrorKind(&result, super::ErrorKind::FnArgCountMismatch(super::CountMismatch {
6358 +
            expected: 1, actual: 2,
6359 +
        }));
6360 +
    }
6361 +
}
6362 +
6363 +
/// Unsafe calls with excess arguments report the unsafe-call diagnostic.
6364 +
@test unsafe fn testInvalidUnsafeBodyCall() throws (testing::TestError) {
6365 +
    let mut res = testResolver();
6366 +
    let result = try resolveProgramStr(&mut res,
6367 +
        "unsafe fn f(x: u32) {} fn g() { f(1, 2); }");
6368 +
    try expectErrorKind(&result, super::ErrorKind::UnsafeCall);
6369 +
}