Skip to content

Commit 31786b7

Browse files
committed
If a inline def body errors, preserve the anno type
1 parent 7c5c39a commit 31786b7

16 files changed

+101
-67
lines changed

src/check/Check.zig

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,11 @@ fn checkDef(self: *Self, def_idx: CIR.Def.Idx, env: *Env) std.mem.Allocator.Erro
836836
// Check any accumulated static dispatch constraints
837837
try self.checkDeferredStaticDispatchConstraints(env);
838838

839+
// TODO: This currently only works if the root type is an error, but we
840+
// should later expand this to use the annotation if there's _any_ error.
841+
//
842+
// For example, if the expr resolves to `Error -> Error` does not
843+
// trigger this codepath
839844
if (mb_instantiated_anno_var != null and
840845
self.types.resolveVar(expr_var).desc.content == .err)
841846
{
@@ -3171,27 +3176,38 @@ fn checkBlockStatements(self: *Self, statements: []const CIR.Statement.Idx, env:
31713176

31723177
switch (stmt) {
31733178
.s_decl => |decl_stmt| {
3179+
const decl_expr_var: Var = ModuleEnv.varFrom(decl_stmt.expr);
3180+
const decl_pattern_var: Var = ModuleEnv.varFrom(decl_stmt.pattern);
3181+
31743182
// Check the pattern
31753183
try self.checkPattern(decl_stmt.pattern, env, .no_expectation);
3176-
const decl_pattern_var: Var = ModuleEnv.varFrom(decl_stmt.pattern);
3184+
3185+
// Create placeholder for the annotation, if it exists
3186+
var mb_instantiated_anno_var: ?Var = null;
31773187

31783188
// Evaluate the rhs of the expression
3179-
const decl_expr_var: Var = ModuleEnv.varFrom(decl_stmt.expr);
31803189
{
3190+
// Enter a new rank
3191+
try env.var_pool.pushRank();
3192+
defer env.var_pool.popRank();
3193+
31813194
// Check the annotation, if it exists
31823195
const expectation = blk: {
31833196
if (decl_stmt.anno) |annotation_idx| {
31843197
// Generate the annotation type var in-place
31853198
try self.generateAnnotationType(annotation_idx, env);
31863199
const annotation_var = ModuleEnv.varFrom(annotation_idx);
31873200

3188-
// TODO: If we instantiate here, then var lookups break. But if we don't
3189-
// then the type anno gets corrupted if we have an error in the body
3190-
// const instantiated_anno_var = try self.instantiateVarPreserveRigids(
3191-
// annotation_var,
3192-
// rank,
3193-
// .use_last_var,
3194-
// );
3201+
// Here we copy the annotation before we unify against it
3202+
//
3203+
// This is so if there's an error in the expr/ptrn, we can preserve
3204+
// the annotation so other places that reference it still get the
3205+
// type of the annotation.
3206+
mb_instantiated_anno_var = try self.instantiateVarPreserveRigids(
3207+
annotation_var,
3208+
env,
3209+
.use_last_var,
3210+
);
31953211

31963212
// Return the expectation
31973213
break :blk Expected{
@@ -3202,10 +3218,6 @@ fn checkBlockStatements(self: *Self, statements: []const CIR.Statement.Idx, env:
32023218
}
32033219
};
32043220

3205-
// Enter a new rank
3206-
try env.var_pool.pushRank();
3207-
defer env.var_pool.popRank();
3208-
32093221
does_fx = try self.checkExpr(decl_stmt.expr, env, expectation) or does_fx;
32103222

32113223
// Now that we are existing the scope, we must generalize then pop this rank
@@ -3215,10 +3227,19 @@ fn checkBlockStatements(self: *Self, statements: []const CIR.Statement.Idx, env:
32153227
try self.checkDeferredStaticDispatchConstraints(env);
32163228
}
32173229

3218-
_ = try self.unify(decl_pattern_var, decl_expr_var, env);
3230+
if (mb_instantiated_anno_var != null and
3231+
self.types.resolveVar(decl_expr_var).desc.content == .err)
3232+
{
3233+
// If there was an annotation AND the expr errored, then
3234+
// unify the ptrn against the annotation
3235+
const instantiated_anno_var = mb_instantiated_anno_var.?;
3236+
_ = try self.unify(decl_pattern_var, instantiated_anno_var, env);
3237+
} else {
3238+
// Otherwise, unify the ptrn and expr
3239+
_ = try self.unify(decl_pattern_var, decl_expr_var, env);
3240+
}
32193241

32203242
// Unify the pattern with the expression
3221-
32223243
_ = try self.unify(stmt_var, decl_pattern_var, env);
32233244
},
32243245
.s_var => |var_stmt| {

src/check/test/type_checking_integration.zig

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,28 +1787,28 @@ test "check type - body w/ anno does not leak to references - top level" {
17871787
try test_env.assertDefTypeOptions("y", "Bool", .{ .allow_type_errors = true });
17881788
}
17891789

1790-
// test "check type - body w/ anno does not leak to references - inline" {
1791-
// // First verify Bool basics work
1792-
// const source =
1793-
// \\Test := [].{}
1794-
// \\
1795-
// \\test = {
1796-
// \\ x : Num(size)
1797-
// \\ x = False
1798-
// \\
1799-
// \\ y : Num(size)
1800-
// \\ y = x + 10
1801-
// \\
1802-
// \\ y
1803-
// \\}
1804-
// ;
1805-
1806-
// var test_env = try TestEnv.init("Test", source);
1807-
// defer test_env.deinit();
1808-
1809-
// try test_env.assertOneTypeError("TYPE MISMATCH");
1810-
// try test_env.assertDefTypeOptions("test", "Bool", .{ .allow_type_errors = true });
1811-
// }
1790+
test "check type - body w/ anno does not leak to references - inline" {
1791+
// First verify Bool basics work
1792+
const source =
1793+
\\Test := [].{}
1794+
\\
1795+
\\test = {
1796+
\\ x : Num(size)
1797+
\\ x = False
1798+
\\
1799+
\\ y : Num(size)
1800+
\\ y = x + 10
1801+
\\
1802+
\\ y
1803+
\\}
1804+
;
1805+
1806+
var test_env = try TestEnv.init("Test", source);
1807+
defer test_env.deinit();
1808+
1809+
try test_env.assertOneTypeError("TYPE MISMATCH");
1810+
try test_env.assertDefTypeOptions("test", "Num(size)", .{ .allow_type_errors = true });
1811+
}
18121812

18131813
// Associated items referencing each other
18141814

test/snapshots/annotations.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ NO CHANGE
316316
(patt (type "Pair(Str)"))
317317
(patt (type "a, a -> Pair(a)"))
318318
(patt (type "Pair(Num(Int(Unsigned8)))"))
319-
(patt (type "Error"))
320-
(patt (type "Error"))
319+
(patt (type "Pair(Num(Int(Unsigned8)))"))
320+
(patt (type "Pair(Num(Int(Unsigned64)))"))
321321
(patt (type "a, b -> Error")))
322322
(type_decls
323323
(nominal (type "Pair(a)")

test/snapshots/fuzz_crash/fuzz_crash_025.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ j = -17011687303715884105728
313313
(patt (type "Num(Int(Unsigned8))"))
314314
(patt (type "Num(Int(Unsigned16))"))
315315
(patt (type "Num(Int(Unsigned32))"))
316-
(patt (type "Error"))
316+
(patt (type "Num(Int(Unsigned128))"))
317317
(patt (type "Num(Int(Signed16))"))
318318
(patt (type "Num(Int(Signed32))"))
319319
(patt (type "Num(Int(Signed64))"))

test/snapshots/issue/simple_underscore_error.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ NO CHANGE
8181
~~~clojure
8282
(inferred-types
8383
(defs
84-
(patt (type "Error")))
84+
(patt (type "BadType")))
8585
(type_decls
8686
(nominal (type "BadType")
8787
(ty-header (name "BadType"))))

test/snapshots/issue/test_error_propagation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ NO CHANGE
9393
~~~clojure
9494
(inferred-types
9595
(defs
96-
(patt (type "Error")))
96+
(patt (type "GoodAlias")))
9797
(type_decls
9898
(nominal (type "BadBase")
9999
(ty-header (name "BadBase")))

test/snapshots/issue/underscore_error_propagation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ NO CHANGE
145145
~~~clojure
146146
(inferred-types
147147
(defs
148-
(patt (type "Error"))
149-
(patt (type "Error")))
148+
(patt (type "BadDerived"))
149+
(patt (type "GoodDerived")))
150150
(type_decls
151151
(nominal (type "BadBase")
152152
(ty-header (name "BadBase")))

test/snapshots/issue/underscore_error_type.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,11 @@ quux = ("hello", 42)
387387
~~~clojure
388388
(inferred-types
389389
(defs
390-
(patt (type "Error"))
391-
(patt (type "Error"))
392-
(patt (type "Error"))
393-
(patt (type "Error"))
394-
(patt (type "Error")))
390+
(patt (type "BadType"))
391+
(patt (type "BadList"))
392+
(patt (type "BadRecord"))
393+
(patt (type "BadFunction"))
394+
(patt (type "BadTuple")))
395395
(type_decls
396396
(nominal (type "BadType")
397397
(ty-header (name "BadType")))

test/snapshots/issue/usage_test.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ NO CHANGE
103103
~~~clojure
104104
(inferred-types
105105
(defs
106-
(patt (type "Error")))
106+
(patt (type "UsedType")))
107107
(type_decls
108108
(nominal (type "UnusedType")
109109
(ty-header (name "UnusedType")))

test/snapshots/nominal/nominal_tag_simple.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ NO CHANGE
9494
(inferred-types
9595
(defs
9696
(patt (type "Color"))
97-
(patt (type "Error")))
97+
(patt (type "Color")))
9898
(type_decls
9999
(nominal (type "Color")
100100
(ty-header (name "Color"))))

0 commit comments

Comments
 (0)