@@ -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 | {
0 commit comments