nac3core: show outer type info in type error messages
Reviewed-on: #274 Co-authored-by: ychenfo <yc@m-labs.hk> Co-committed-by: ychenfo <yc@m-labs.hk>
This commit is contained in:
parent
837aaa95f1
commit
48cb485b89
@ -657,12 +657,16 @@ impl Unifier {
|
|||||||
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
}
|
}
|
||||||
for (x, y) in ty1.iter().zip(ty2.iter()) {
|
for (x, y) in ty1.iter().zip(ty2.iter()) {
|
||||||
self.unify_impl(*x, *y, false)?;
|
if self.unify_impl(*x, *y, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
(TList { ty: ty1 }, TList { ty: ty2 }) => {
|
(TList { ty: ty1 }, TList { ty: ty2 }) => {
|
||||||
self.unify_impl(*ty1, *ty2, false)?;
|
if self.unify_impl(*ty1, *ty2, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
}
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
(TVar { fields: Some(map), range, .. }, TObj { fields, .. }) => {
|
(TVar { fields: Some(map), range, .. }, TObj { fields, .. }) => {
|
||||||
@ -743,12 +747,16 @@ impl Unifier {
|
|||||||
self.incompatible_types(a, b)?;
|
self.incompatible_types(a, b)?;
|
||||||
}
|
}
|
||||||
for (x, y) in zip(params1.values(), params2.values()) {
|
for (x, y) in zip(params1.values(), params2.values()) {
|
||||||
self.unify_impl(*x, *y, false)?;
|
if self.unify_impl(*x, *y, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
(TVirtual { ty: ty1 }, TVirtual { ty: ty2 }) => {
|
(TVirtual { ty: ty1 }, TVirtual { ty: ty2 }) => {
|
||||||
self.unify_impl(*ty1, *ty2, false)?;
|
if self.unify_impl(*ty1, *ty2, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
};
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
(TCall(calls1), TCall(calls2)) => {
|
(TCall(calls1), TCall(calls2)) => {
|
||||||
@ -784,9 +792,13 @@ impl Unifier {
|
|||||||
if x.name != y.name || x.default_value != y.default_value {
|
if x.name != y.name || x.default_value != y.default_value {
|
||||||
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
}
|
}
|
||||||
self.unify_impl(x.ty, y.ty, false)?;
|
if self.unify_impl(x.ty, y.ty, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self.unify_impl(sign1.ret, sign2.ret, false)?;
|
if self.unify_impl(sign1.ret, sign2.ret, false).is_err() {
|
||||||
|
return Err(TypeError::new(TypeErrorKind::IncompatibleTypes(a, b), None));
|
||||||
|
};
|
||||||
self.set_a_to_b(a, b);
|
self.set_a_to_b(a, b);
|
||||||
}
|
}
|
||||||
(TVar { fields: Some(fields), .. }, _) => {
|
(TVar { fields: Some(fields), .. }, _) => {
|
||||||
|
@ -286,7 +286,7 @@ fn test_unify(
|
|||||||
("v1", "tuple[int]"),
|
("v1", "tuple[int]"),
|
||||||
("v2", "tuple[float]"),
|
("v2", "tuple[float]"),
|
||||||
],
|
],
|
||||||
(("v1", "v2"), "Incompatible types: 0 and 1")
|
(("v1", "v2"), "Incompatible types: tuple[0] and tuple[1]")
|
||||||
; "tuple parameter mismatch"
|
; "tuple parameter mismatch"
|
||||||
)]
|
)]
|
||||||
#[test_case(2,
|
#[test_case(2,
|
||||||
@ -478,7 +478,8 @@ fn test_typevar_range() {
|
|||||||
let int_list = env.unifier.add_ty(TypeEnum::TList { ty: int });
|
let int_list = env.unifier.add_ty(TypeEnum::TList { ty: int });
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
env.unify(a_list, int_list),
|
env.unify(a_list, int_list),
|
||||||
Err("Expected any one of these types: 1, but got 0".into())
|
Err("Incompatible types: list[typevar22] and list[0]\
|
||||||
|
\n\nNotes:\n typevar22 ∈ {1}".into())
|
||||||
);
|
);
|
||||||
|
|
||||||
let a = env.unifier.get_fresh_var_with_range(&[int, float], None, None).0;
|
let a = env.unifier.get_fresh_var_with_range(&[int, float], None, None).0;
|
||||||
@ -506,7 +507,7 @@ fn test_rigid_var() {
|
|||||||
|
|
||||||
assert_eq!(env.unify(a, b), Err("Incompatible types: typevar3 and typevar2".to_string()));
|
assert_eq!(env.unify(a, b), Err("Incompatible types: typevar3 and typevar2".to_string()));
|
||||||
env.unifier.unify(list_a, list_x).unwrap();
|
env.unifier.unify(list_a, list_x).unwrap();
|
||||||
assert_eq!(env.unify(list_x, list_int), Err("Incompatible types: 0 and typevar2".to_string()));
|
assert_eq!(env.unify(list_x, list_int), Err("Incompatible types: list[typevar2] and list[0]".to_string()));
|
||||||
|
|
||||||
env.unifier.replace_rigid_var(a, int);
|
env.unifier.replace_rigid_var(a, int);
|
||||||
env.unifier.unify(list_x, list_int).unwrap();
|
env.unifier.unify(list_x, list_int).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user