compiler: Require successful resolution before ownership checks
570e9a44bed511e7ab7c20afc9373503aa096e2935c882b5537bd9fe6a9db572
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 | + | } |