mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 21:01:10 +00:00
Improve type mismatch messages
This commit is contained in:
parent
14bb674068
commit
d26909c317
7 changed files with 50 additions and 27 deletions
|
@ -1,7 +1,7 @@
|
|||
use erg_common::enum_unwrap;
|
||||
|
||||
use crate::ty::typaram::TyParam;
|
||||
use crate::ty::Type;
|
||||
use crate::ty::{HasType, Type};
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
|
@ -11,8 +11,9 @@ enum Sequence {
|
|||
Backward,
|
||||
}
|
||||
|
||||
// TODO: these should not be in Context
|
||||
impl Context {
|
||||
fn readable_type(&self, typ: &Type) -> Type {
|
||||
fn readable_type(typ: &Type) -> Type {
|
||||
match typ {
|
||||
Type::FreeVar(fv) if fv.constraint_is_sandwiched() => {
|
||||
let (sub, sup) = fv.get_subsup().unwrap();
|
||||
|
@ -25,7 +26,20 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option<String> {
|
||||
/// TODO: custom types
|
||||
fn get_verb_and_preposition(trait_: &Type) -> Option<(&str, &str, Sequence)> {
|
||||
match &trait_.qual_name()[..] {
|
||||
"Add" => Some(("add", "and", Sequence::Forward)),
|
||||
"Sub" => Some(("subtract", "from", Sequence::Backward)),
|
||||
"Mul" => Some(("multiply", "and", Sequence::Forward)),
|
||||
"Div" => Some(("divide", "by", Sequence::Forward)),
|
||||
"Eq" => Some(("compare", "and", Sequence::Forward)),
|
||||
"Ord" => Some(("compare", "and", Sequence::Forward)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type_mismatch_hint(expected: &Type, found: &Type) -> Option<String> {
|
||||
let expected = if let Type::FreeVar(fv) = expected {
|
||||
if fv.is_linked() {
|
||||
fv.crack().clone()
|
||||
|
@ -38,27 +52,26 @@ impl Context {
|
|||
};
|
||||
match (&expected.qual_name()[..], &found.qual_name()[..]) {
|
||||
("Eq", "Float") => Some(String::from("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")),
|
||||
_ => None,
|
||||
_ => {
|
||||
let (verb, preposition, _sequence) = Self::get_verb_and_preposition(&expected)?;
|
||||
found.union_types()
|
||||
.map(|(t1, t2)| format!("cannot {verb} {t1} {preposition} {t2}"))
|
||||
.or_else(|| {
|
||||
let ts = expected.inner_ts();
|
||||
Some(format!("cannot {verb} {found} {preposition} {}", ts[0]))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<String> {
|
||||
pub(crate) fn get_no_candidate_hint(proj: &Type) -> Option<String> {
|
||||
match proj {
|
||||
Type::Proj { lhs, rhs: _ } => {
|
||||
if let Type::FreeVar(fv) = lhs.as_ref() {
|
||||
let (sub, sup) = fv.get_subsup()?;
|
||||
// TODO: automating
|
||||
let (verb, preposition, sequence) = match &sup.qual_name()[..] {
|
||||
"Add" => Some(("add", "and", Sequence::Forward)),
|
||||
"Sub" => Some(("subtract", "from", Sequence::Backward)),
|
||||
"Mul" => Some(("multiply", "and", Sequence::Forward)),
|
||||
"Div" => Some(("divide", "by", Sequence::Forward)),
|
||||
"Eq" => Some(("compare", "and", Sequence::Forward)),
|
||||
"Ord" => Some(("compare", "and", Sequence::Forward)),
|
||||
_ => None,
|
||||
}?;
|
||||
let (verb, preposition, sequence) = Self::get_verb_and_preposition(&sup)?;
|
||||
let sup = enum_unwrap!(sup.typarams().remove(0), TyParam::Type);
|
||||
let sup = self.readable_type(&sup);
|
||||
let sup = Self::readable_type(&sup);
|
||||
let (l, r) = if sequence == Sequence::Forward {
|
||||
(sub, sup)
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue