diff --git a/src/check/Check.zig b/src/check/Check.zig index 707ae48628..723bc3d52d 100644 --- a/src/check/Check.zig +++ b/src/check/Check.zig @@ -155,6 +155,23 @@ pub fn unify(self: *Self, a: Var, b: Var) std.mem.Allocator.Error!unifier.Result ); } +pub fn unifyWithAnnotation(self: *Self, a: Var, b: Var) std.mem.Allocator.Error!unifier.Result { + const trace = tracy.trace(@src()); + defer trace.end(); + + return try unifier.unifyWithContext( + self.cir, + self.types, + &self.problems, + &self.snapshots, + &self.unify_scratch, + &self.occurs_scratch, + a, + b, + true, // from_annotation = true + ); +} + // instantiate // const InstantiateRegionBehavior = union(enum) { @@ -406,7 +423,7 @@ fn checkDef(self: *Self, def_idx: CIR.Def.Idx) std.mem.Allocator.Error!void { _ = try self.checkExpr(def.expr); // Unify the expression with its annotation - _ = try self.unify(expr_var, anno_var); + _ = try self.unifyWithAnnotation(expr_var, anno_var); } } else { // Check the expr @@ -1469,7 +1486,7 @@ fn checkLambdaWithAnno( // Unify against the annotation const pattern_var = ModuleEnv.varFrom(pattern_idx); - _ = try self.unify(pattern_var, expected_arg); + _ = try self.unifyWithAnnotation(pattern_var, expected_arg); } } } @@ -1493,12 +1510,12 @@ fn checkLambdaWithAnno( // STEP 4: Validate the function body against the annotation return type if (mb_expected_func) |func| { - _ = try self.unify(return_var, func.ret); + _ = try self.unifyWithAnnotation(return_var, func.ret); } // STEP 5: Validate the entire function against the annotation if (mb_expected_var) |expected_var| { - _ = try self.unify(fn_var, expected_var); + _ = try self.unifyWithAnnotation(fn_var, expected_var); } return is_effectful; diff --git a/src/check/problem.zig b/src/check/problem.zig index c3fdcf15fc..2d8b96574b 100644 --- a/src/check/problem.zig +++ b/src/check/problem.zig @@ -84,6 +84,8 @@ pub const TypePair = struct { expected_snapshot: SnapshotContentIdx, actual_var: Var, actual_snapshot: SnapshotContentIdx, + /// True if the expected type comes from a type annotation + from_annotation: bool = false, }; /// More specific details about a particular type mismatch. @@ -335,7 +337,11 @@ pub const ReportBuilder = struct { ); try report.document.addLineBreak(); - try report.document.addText("The type annotation says it should have the type:"); + if (types.from_annotation) { + try report.document.addText("The type annotation says it should have the type:"); + } else { + try report.document.addText("It is of type:"); + } try report.document.addLineBreak(); try report.document.addText(" "); try report.document.addAnnotated(owned_actual, .type_variable); diff --git a/src/check/unify.zig b/src/check/unify.zig index 6c661a2e4f..1920732fa8 100644 --- a/src/check/unify.zig +++ b/src/check/unify.zig @@ -114,13 +114,8 @@ pub const Result = union(enum) { } }; -/// Unify two type variables -/// -/// This function -/// * Resolves type variables & compresses paths -/// * Compares variable contents for equality -/// * Merges unified variables so 1 is "root" and the other is "redirect" -pub fn unify( +/// Unify two type variables with context about whether this is from an annotation +pub fn unifyWithContext( module_env: *ModuleEnv, types: *types_mod.Store, problems: *problem_mod.Store, @@ -129,6 +124,7 @@ pub fn unify( occurs_scratch: *occurs.Scratch, a: Var, b: Var, + from_annotation: bool, ) std.mem.Allocator.Error!Result { const trace = tracy.trace(@src()); defer trace.end(); @@ -153,6 +149,7 @@ pub fn unify( .expected_snapshot = expected_snapshot, .actual_var = b, .actual_snapshot = actual_snapshot, + .from_annotation = from_annotation, }, .detail = null, } }; @@ -287,6 +284,36 @@ pub fn unify( return .ok; } +/// Unify two type variables +/// +/// This function +/// * Resolves type variables & compresses paths +/// * Compares variable contents for equality +/// * Merges unified variables so 1 is "root" and the other is "redirect" +pub fn unify( + module_env: *ModuleEnv, + types: *types_mod.Store, + problems: *problem_mod.Store, + snapshots: *snapshot_mod.Store, + unify_scratch: *Scratch, + occurs_scratch: *occurs.Scratch, + a: Var, + b: Var, +) std.mem.Allocator.Error!Result { + // Default to not from annotation for backward compatibility + return unifyWithContext( + module_env, + types, + problems, + snapshots, + unify_scratch, + occurs_scratch, + a, + b, + false, // from_annotation = false by default + ); +} + /// A temporary unification context used to unify two type variables within a `Store`. /// /// `Unifier` is created per unification call and: diff --git a/test/snapshots/expr/not_tag.md b/test/snapshots/expr/not_tag.md index 1ba693476b..c469b3083c 100644 --- a/test/snapshots/expr/not_tag.md +++ b/test/snapshots/expr/not_tag.md @@ -18,7 +18,7 @@ This expression is used in an unexpected way: ``` ^^^^^^^ -The type annotation says it should have the type: +It is of type: _Bool_ But you are trying to use it as: diff --git a/test/snapshots/fuzz_crash/fuzz_crash_019.md b/test/snapshots/fuzz_crash/fuzz_crash_019.md index c7a934e117..ffaccae1f8 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_019.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_019.md @@ -875,7 +875,7 @@ This expression is used in an unexpected way: )crash ke"Unr!" #) ``` -The type annotation says it should have the type: +It is of type: __arg -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/fuzz_crash/fuzz_crash_023.md b/test/snapshots/fuzz_crash/fuzz_crash_023.md index 2c52dde4de..39f9d287d4 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_023.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_023.md @@ -961,7 +961,7 @@ This expression is used in an unexpected way: ) ``` -The type annotation says it should have the type: +It is of type: __arg -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/fuzz_crash/fuzz_crash_027.md b/test/snapshots/fuzz_crash/fuzz_crash_027.md index 8008f5bec3..4731de5f3c 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_027.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_027.md @@ -912,7 +912,7 @@ This expression is used in an unexpected way: ) ``` -The type annotation says it should have the type: +It is of type: __arg -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/fuzz_crash/fuzz_crash_028.md b/test/snapshots/fuzz_crash/fuzz_crash_028.md index 56dbd1e6ad..6cc12b9a5d 100644 Binary files a/test/snapshots/fuzz_crash/fuzz_crash_028.md and b/test/snapshots/fuzz_crash/fuzz_crash_028.md differ diff --git a/test/snapshots/lambda_annotation_mismatch_error.md b/test/snapshots/lambda_annotation_mismatch_error.md index 7a85e743cc..65de349cbb 100644 --- a/test/snapshots/lambda_annotation_mismatch_error.md +++ b/test/snapshots/lambda_annotation_mismatch_error.md @@ -26,7 +26,7 @@ string_function = |x| x + 42 ``` ^ -The type annotation says it should have the type: +It is of type: _Str_ But you are trying to use it as: diff --git a/test/snapshots/lambda_currying_constraint.md b/test/snapshots/lambda_currying_constraint.md index e44e90c9a5..a3e473d66a 100644 --- a/test/snapshots/lambda_currying_constraint.md +++ b/test/snapshots/lambda_currying_constraint.md @@ -86,7 +86,7 @@ makeAdder = |x| |y| x + y ``` ^ -The type annotation says it should have the type: +It is of type: _a_ But you are trying to use it as: diff --git a/test/snapshots/simple_lambda_constraint_success.md b/test/snapshots/simple_lambda_constraint_success.md index d78c2df489..b9a174655e 100644 --- a/test/snapshots/simple_lambda_constraint_success.md +++ b/test/snapshots/simple_lambda_constraint_success.md @@ -26,7 +26,7 @@ addTwoF64 = |x| x + 2.0 ``` ^ -The type annotation says it should have the type: +It is of type: _F64_ But you are trying to use it as: diff --git a/test/snapshots/syntax_grab_bag.md b/test/snapshots/syntax_grab_bag.md index 0fe29dd387..1b484edae9 100644 --- a/test/snapshots/syntax_grab_bag.md +++ b/test/snapshots/syntax_grab_bag.md @@ -897,7 +897,7 @@ This expression is used in an unexpected way: ) ``` -The type annotation says it should have the type: +It is of type: __arg -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/test_exact_pattern_crash.md b/test/snapshots/test_exact_pattern_crash.md index 1d11535c58..9b7512940c 100644 --- a/test/snapshots/test_exact_pattern_crash.md +++ b/test/snapshots/test_exact_pattern_crash.md @@ -56,7 +56,7 @@ This expression is used in an unexpected way: ``` ^^^^^^^^ -The type annotation says it should have the type: +It is of type: _Num(_size), Num(_size2), Num(_size3) -> Num(_size4), Num(_size5) -> Num(_size6) -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/test_instantiation_arity_mismatch.md b/test/snapshots/test_instantiation_arity_mismatch.md index 5388756b90..a95ceb54e8 100644 --- a/test/snapshots/test_instantiation_arity_mismatch.md +++ b/test/snapshots/test_instantiation_arity_mismatch.md @@ -23,7 +23,7 @@ This expression is used in an unexpected way: ``` ^^^^^^^^^^^^^^ -The type annotation says it should have the type: +It is of type: _Num(_size), Num(_size2) -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/test_tuple_instantiation_crash.md b/test/snapshots/test_tuple_instantiation_crash.md index bad0583ede..ec5f35c60a 100644 --- a/test/snapshots/test_tuple_instantiation_crash.md +++ b/test/snapshots/test_tuple_instantiation_crash.md @@ -26,7 +26,7 @@ main = swap(1, 2) ``` ^^^^ -The type annotation says it should have the type: +It is of type: _Num(_size), Num(_size2) -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/type_alias_parameterized.md b/test/snapshots/type_alias_parameterized.md index a1423eb5a1..10c340fd35 100644 --- a/test/snapshots/type_alias_parameterized.md +++ b/test/snapshots/type_alias_parameterized.md @@ -25,7 +25,7 @@ main! = |_| swapPair(1, 2) ``` ^^^^^^^^ -The type annotation says it should have the type: +It is of type: _Num(_size), Num(_size2) -> _ret_ But you are trying to use it as: diff --git a/test/snapshots/type_app_with_vars.md b/test/snapshots/type_app_with_vars.md index 32c32c05d5..a6655f4c49 100644 --- a/test/snapshots/type_app_with_vars.md +++ b/test/snapshots/type_app_with_vars.md @@ -23,7 +23,7 @@ main! = |_| mapList([1,2,3,4,5]) ``` ^^^^^^^ -The type annotation says it should have the type: +It is of type: _List(Num(_size)) -> _ret_ But you are trying to use it as: