Improve ability generalization error message

This commit is contained in:
Ayaz Hafiz 2022-04-19 13:36:42 -04:00
parent 9d71a3d1ac
commit cbfd76380a
No known key found for this signature in database
GPG Key ID: 0E2A37416A25EF58
2 changed files with 46 additions and 9 deletions

View File

@ -1767,7 +1767,7 @@ pub enum Problem {
FieldsMissing(Vec<Lowercase>),
TagTypo(TagName, Vec<TagName>),
TagsMissing(Vec<TagName>),
BadRigidVar(Lowercase, ErrorType),
BadRigidVar(Lowercase, ErrorType, Option<Symbol>),
OptionalRequiredMismatch(Lowercase),
OpaqueComparedToNonOpaque,
}
@ -1872,7 +1872,7 @@ fn diff_is_wildcard_comparison<'b>(
) -> bool {
let Comparison { problems, .. } = to_comparison(alloc, actual, expected);
match problems.last() {
Some(Problem::BadRigidVar(v1, ErrorType::RigidVar(v2))) => {
Some(Problem::BadRigidVar(v1, ErrorType::RigidVar(v2), None)) => {
v1.as_str() == WILDCARD && v2.as_str() == WILDCARD
}
_ => false,
@ -2143,6 +2143,32 @@ fn to_diff<'b>(
same(alloc, parens, type1)
}
(RigidVar(x), other) | (other, RigidVar(x)) => {
let (left, left_able) = to_doc(alloc, Parens::InFn, type1);
let (right, right_able) = to_doc(alloc, Parens::InFn, type2);
Diff {
left,
right,
status: Status::Different(vec![Problem::BadRigidVar(x, other, None)]),
left_able,
right_able,
}
}
(RigidAbleVar(x, ab), other) | (other, RigidAbleVar(x, ab)) => {
let (left, left_able) = to_doc(alloc, Parens::InFn, type1);
let (right, right_able) = to_doc(alloc, Parens::InFn, type2);
Diff {
left,
right,
status: Status::Different(vec![Problem::BadRigidVar(x, other, Some(ab))]),
left_able,
right_able,
}
}
(Function(args1, _, ret1), Function(args2, _, ret2)) => {
if args1.len() == args2.len() {
let mut status = Status::Similar;
@ -2325,7 +2351,6 @@ fn to_diff<'b>(
};
let problems = match pair {
(RigidVar(x), other) | (other, RigidVar(x)) => vec![Problem::BadRigidVar(x, other)],
(a, b) if (is_int(&a) && is_float(&b)) || (is_float(&a) && is_int(&b)) => {
vec![Problem::IntFloat]
}
@ -2751,6 +2776,7 @@ fn ext_to_status(ext1: &TypeExt, ext2: &TypeExt) -> Status {
Status::Different(vec![Problem::BadRigidVar(
x.clone(),
ErrorType::RigidVar(y.clone()),
None,
)])
}
}
@ -3128,15 +3154,25 @@ fn type_problem_to_pretty<'b>(
alloc.tip().append(line)
}
(BadRigidVar(x, tipe), expectation) => {
(BadRigidVar(x, tipe, opt_ability), expectation) => {
use ErrorType::*;
let bad_rigid_var = |name: Lowercase, a_thing| {
let kind_of_value = match opt_ability {
Some(ability) => alloc.concat(vec![
alloc.reflow("any value implementing the "),
alloc.symbol_unqualified(ability),
alloc.reflow(" ability"),
]),
None => alloc.reflow("any type of value"),
};
alloc
.tip()
.append(alloc.reflow("The type annotation uses the type variable "))
.append(alloc.type_variable(name))
.append(alloc.reflow(" to say that this definition can produce any type of value. But in the body I see that it will only produce "))
.append(alloc.reflow(" to say that this definition can produce ")
.append(kind_of_value)
.append(alloc.reflow(". But in the body I see that it will only produce ")))
.append(a_thing)
.append(alloc.reflow(" of a single specific type. Maybe change the type annotation to be more specific? Maybe change the code to be more general?"))
};

View File

@ -9864,10 +9864,11 @@ I need all branches in an `if` to have the same type!
a | a has Hash
Tip: Type comparisons between an opaque type are only ever equal if
both types are the same opaque type. Did you mean to create an opaque
type by wrapping it? If I have an opaque type Age := U32 I can create
an instance of this opaque type by doing @Age 23.
Tip: The type annotation uses the type variable `a` to say that this
definition can produce any value implementing the `Hash` ability. But in
the body I see that it will only produce a `Id` value of a single
specific type. Maybe change the type annotation to be more specific?
Maybe change the code to be more general?
"#
),
)