ReviewOS

also looking at this

home-lang/home

fix(types): give catch clauses the enclosing scope as their parent

#933
Open mkantautas wants to merge fix/types-catch-scope-parent into main
2 files +31 -7

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/types/src/type_system.zigmodified+11-7
Changes to packages/types/src/type_system.zig
@@ -2254,16 +2254,20 @@ pub const TypeChecker = struct {
22542254 for (try_stmt.catch_clauses) |catch_clause| {
22552255 // Create new scope for error variable if present
22562256 if (catch_clause.error_name) |error_name| {
2257 const saved_env = try self.allocator.create(TypeEnvironment);
2258 saved_env.* = self.env;
2259
22572260 var catch_env = TypeEnvironment.init(self.allocator);
2258 catch_env.parent = &self.env;
2259 defer catch_env.deinit();
2261 catch_env.parent = saved_env;
2262 self.env = catch_env;
2263 defer {
2264 self.env.deinit();
2265 self.env = saved_env.*;
2266 self.allocator.destroy(saved_env);
2267 }
22602268
22612269 // Define error variable (type is string for now)
2262 try catch_env.define(error_name, Type.String);
2263
2264 const saved_env = self.env;
2265 self.env = catch_env;
2266 defer self.env = saved_env;
2270 try self.env.define(error_name, Type.String);
22672271
22682272 for (catch_clause.body.statements) |catch_body_stmt| {
22692273 self.checkStatement(catch_body_stmt) catch |err| {
packages/types/tests/control_flow_checker_test.zigmodified+20-0
Changes to packages/types/tests/control_flow_checker_test.zig
@@ -886,3 +886,23 @@ test "checker rejects missing static methods" {
886886 \\}
887887 ));
888888}
889
890test "checker resolves enclosing variables inside a catch clause" {
891 try std.testing.expect(try checkSource(
892 \\fn run() {
893 \\ let x = 1
894 \\ try {
895 \\ } catch (e) {
896 \\ let y = x
897 \\ }
898 \\}
899 ));
900 try std.testing.expect(try checkSourceErrorContains(
901 \\fn run() {
902 \\ try {
903 \\ } catch (e) {
904 \\ let y = missing
905 \\ }
906 \\}
907 , "Undefined variable"));
908}