compiler: Require successful resolution before ownership checks
05c6985b33825e622ff7c9d0f381ce048958fbbec0118f9fbebb8d5f51672dd0
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);"; |