More error message improvements

This commit is contained in:
Richard Feldman 2025-08-15 18:16:24 -04:00
parent 9a3bb0face
commit cc597648a0
No known key found for this signature in database
17 changed files with 75 additions and 25 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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:

View file

@ -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: