Show the right fct name in type error messages

This commit is contained in:
jecaro 2023-11-16 16:44:55 +01:00
parent 7b1f2d2ac1
commit c858031f74
No known key found for this signature in database
GPG Key ID: 3AEB4D2AFA2ACD45
6 changed files with 125 additions and 13 deletions

View File

@ -502,6 +502,7 @@ pub fn constrain_expr(
let reason = Reason::FnArg {
name: opt_symbol,
arg_index: HumanIndex::zero_based(index),
called_via: *called_via,
};
let expected_arg =
constraints.push_expected_type(ForReason(reason, arg_type_index, region));

View File

@ -102,6 +102,15 @@ pub enum UnaryOp {
Not,
}
impl std::fmt::Display for UnaryOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UnaryOp::Negate => write!(f, "-"),
UnaryOp::Not => write!(f, "!"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BinOp {
// highest precedence

View File

@ -3370,6 +3370,7 @@ pub enum Reason {
FnArg {
name: Option<Symbol>,
arg_index: HumanIndex,
called_via: CalledVia,
},
TypedArg {
name: Option<Symbol>,

View File

@ -658,17 +658,17 @@ fn too_few_args() {
#[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes!
#[test]
fn type_problem() {
fn type_problem_function() {
expect_failure(
"1 + \"\"",
"Num.add 1 \"not a num\"",
indoc!(
r#"
TYPE MISMATCH
This 2nd argument to add has an unexpected type:
4 1 + ""
^^
4 Num.add 1 "not a num"
^^^^^^^^^^^
The argument is a string of type:
@ -682,6 +682,84 @@ fn type_problem() {
);
}
#[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes!
#[test]
fn type_problem_binary_operator() {
expect_failure(
"1 + \"\"",
indoc!(
r#"
TYPE MISMATCH
This 2nd argument to + has an unexpected type:
4 1 + ""
^^
The argument is a string of type:
Str
But + needs its 2nd argument to be:
Num *
"#
),
);
}
#[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes!
#[test]
fn type_problem_unary_operator() {
expect_failure(
"!\"not a bool\"",
indoc!(
r#"
TYPE MISMATCH
This 1st argument to ! has an unexpected type:
4 !"not a bool"
^^^^^^^^^^^^
The argument is a string of type:
Str
But ! needs its 1st argument to be:
Bool
"#
),
);
}
#[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes!
#[test]
fn type_problem_string_interpolation() {
expect_failure(
"\"This is not a string -> \\(1)\"",
indoc!(
r#"
TYPE MISMATCH
This argument to this string interpolation has an unexpected type:
4 "This is not a string -> \(1)"
^
The argument is a number of type:
Num *
But this string interpolation needs its argument to be:
Str
"#
),
);
}
#[test]
fn issue_2149_i8_ok() {
expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]");

View File

@ -1273,12 +1273,24 @@ fn to_expr_report<'b>(
}
}
},
Reason::FnArg { name, arg_index } => {
Reason::FnArg {
name,
arg_index,
called_via,
} => {
let ith = arg_index.ordinal();
let this_function = match name {
None => alloc.text("this function"),
Some(symbol) => alloc.symbol_unqualified(symbol),
let this_function = match (called_via, name) {
(CalledVia::Space, Some(symbole)) => alloc.symbol_unqualified(symbole),
(CalledVia::BinOp(op), _) => alloc.binop(op),
(CalledVia::UnaryOp(op), _) => alloc.unop(op),
(CalledVia::StringInterpolation, _) => alloc.text("this string interpolation"),
_ => alloc.text("this function"),
};
let argument = match called_via {
CalledVia::StringInterpolation => "argument".to_string(),
_ => format!("{ith} argument"),
};
report_mismatch(
@ -1292,7 +1304,7 @@ fn to_expr_report<'b>(
region,
Some(expr_region),
alloc.concat([
alloc.string(format!("This {ith} argument to ")),
alloc.string(format!("This {argument} to ")),
this_function.clone(),
alloc.text(" has an unexpected type:"),
]),
@ -1300,7 +1312,7 @@ fn to_expr_report<'b>(
alloc.concat([
alloc.text("But "),
this_function,
alloc.string(format!(" needs its {ith} argument to be:")),
alloc.string(format!(" needs its {argument} to be:")),
]),
None,
)

View File

@ -490,6 +490,13 @@ impl<'a> RocDocAllocator<'a> {
self.text(content.to_string()).annotate(Annotation::BinOp)
}
pub fn unop(
&'a self,
content: roc_module::called_via::UnaryOp,
) -> DocBuilder<'a, Self, Annotation> {
self.text(content.to_string()).annotate(Annotation::UnaryOp)
}
/// Turns off backticks/colors in a block
pub fn type_block(
&'a self,
@ -843,6 +850,7 @@ pub enum Annotation {
Structure,
Symbol,
BinOp,
UnaryOp,
Error,
GutterBar,
LineNumber,
@ -1027,6 +1035,9 @@ where
BinOp => {
self.write_str(self.palette.alias)?;
}
UnaryOp => {
self.write_str(self.palette.alias)?;
}
Symbol => {
self.write_str(self.palette.variable)?;
}
@ -1075,9 +1086,9 @@ where
match self.style_stack.pop() {
None => {}
Some(annotation) => match annotation {
Emphasized | Url | TypeVariable | Alias | Symbol | BinOp | Error | GutterBar
| Ellipsis | Typo | TypoSuggestion | ParserSuggestion | Structure | CodeBlock
| PlainText | LineNumber | Tip | Module | Header | Keyword => {
Emphasized | Url | TypeVariable | Alias | Symbol | BinOp | UnaryOp | Error
| GutterBar | Ellipsis | Typo | TypoSuggestion | ParserSuggestion | Structure
| CodeBlock | PlainText | LineNumber | Tip | Module | Header | Keyword => {
self.write_str(self.palette.reset)?;
}