mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Hide params from annotation type mismatches
This commit is contained in:
parent
a4f4d00ff0
commit
d033057a58
5 changed files with 117 additions and 11 deletions
|
@ -846,6 +846,57 @@ mod cli_run {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(windows, ignore)]
|
||||||
|
fn module_params_bad_ann() {
|
||||||
|
check_compile_error_with(
|
||||||
|
CMD_DEV,
|
||||||
|
&cli_testing_dir("/module_params/bad_ann.roc"),
|
||||||
|
&[],
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
── TYPE MISMATCH in tests/module_params/BadAnn.roc ─────────────────────────────
|
||||||
|
|
||||||
|
Something is off with the body of the fnAnnotatedAsValue definition:
|
||||||
|
|
||||||
|
3│ fnAnnotatedAsValue : Str
|
||||||
|
4│> fnAnnotatedAsValue = /postId, commentId ->
|
||||||
|
5│> "/posts/$(postId)/comments/$(Num.toStr commentId)"
|
||||||
|
|
||||||
|
The body is an anonymous function of type:
|
||||||
|
|
||||||
|
Str, Num * -> Str
|
||||||
|
|
||||||
|
But the type annotation on fnAnnotatedAsValue says it should be:
|
||||||
|
|
||||||
|
Str
|
||||||
|
|
||||||
|
|
||||||
|
── TYPE MISMATCH in tests/module_params/BadAnn.roc ─────────────────────────────
|
||||||
|
|
||||||
|
Something is off with the body of the missingArg definition:
|
||||||
|
|
||||||
|
7│ missingArg : Str -> Str
|
||||||
|
8│> missingArg = /postId, _ ->
|
||||||
|
9│> "/posts/$(postId)/comments"
|
||||||
|
|
||||||
|
The body is an anonymous function of type:
|
||||||
|
|
||||||
|
(Str, ? -> Str)
|
||||||
|
|
||||||
|
But the type annotation on missingArg says it should be:
|
||||||
|
|
||||||
|
(Str -> Str)
|
||||||
|
|
||||||
|
Tip: It looks like it takes too many arguments. I'm seeing 1 extra.
|
||||||
|
|
||||||
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
2 errors and 1 warning found in <ignored for test> ms."#
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(windows, ignore)]
|
#[cfg_attr(windows, ignore)]
|
||||||
fn transitive_expects() {
|
fn transitive_expects() {
|
||||||
|
|
9
crates/cli/tests/module_params/BadAnn.roc
Normal file
9
crates/cli/tests/module_params/BadAnn.roc
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module { appId } -> [fnAnnotatedAsValue, missingArg]
|
||||||
|
|
||||||
|
fnAnnotatedAsValue : Str
|
||||||
|
fnAnnotatedAsValue = \postId, commentId ->
|
||||||
|
"/posts/$(postId)/comments/$(Num.toStr commentId)"
|
||||||
|
|
||||||
|
missingArg : Str -> Str
|
||||||
|
missingArg = \postId, _ ->
|
||||||
|
"/posts/$(postId)/comments"
|
8
crates/cli/tests/module_params/bad_ann.roc
Normal file
8
crates/cli/tests/module_params/bad_ann.roc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
app [main] {
|
||||||
|
pf: platform "../fixtures/multi-dep-str/platform/main.roc",
|
||||||
|
}
|
||||||
|
|
||||||
|
import BadAnn { appId: "one" }
|
||||||
|
|
||||||
|
main =
|
||||||
|
""
|
|
@ -1,4 +1,4 @@
|
||||||
use roc_can::expected::Expected;
|
use roc_can::{expected::Expected, pattern::Pattern};
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{ModuleId, Symbol};
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
use roc_solve_problem::TypeError;
|
use roc_solve_problem::TypeError;
|
||||||
|
@ -32,9 +32,47 @@ pub fn remove_module_param_arguments(
|
||||||
for error in errors {
|
for error in errors {
|
||||||
match error {
|
match error {
|
||||||
TypeError::BadExpr(_, _, found, Expected::ForReason(reason, expected, _)) => {
|
TypeError::BadExpr(_, _, found, Expected::ForReason(reason, expected, _)) => {
|
||||||
remove_with_bad_expr_reason(&env, found, reason, expected);
|
remove_for_reason(&env, found, reason, expected);
|
||||||
}
|
}
|
||||||
TypeError::BadExpr(_, _, _, _) => todo!("{:?}", error),
|
|
||||||
|
TypeError::BadExpr(
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
found,
|
||||||
|
Expected::FromAnnotation(
|
||||||
|
Loc {
|
||||||
|
value: Pattern::Identifier(name),
|
||||||
|
region: _,
|
||||||
|
},
|
||||||
|
arity,
|
||||||
|
_,
|
||||||
|
expected,
|
||||||
|
),
|
||||||
|
) if env.is_extended(name) => {
|
||||||
|
if *arity > 1 {
|
||||||
|
*arity -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_last_argument(found);
|
||||||
|
drop_last_argument(expected);
|
||||||
|
|
||||||
|
if let (
|
||||||
|
ErrorType::Function(found_args, _, _),
|
||||||
|
ErrorType::Function(expected_args, _, _),
|
||||||
|
) = (found, expected)
|
||||||
|
{
|
||||||
|
if found_args.len() > expected_args.len() {
|
||||||
|
// If the found arity doesn't match the annotation's, the params
|
||||||
|
// record would appear in the error, so we replace it with `?`.
|
||||||
|
if let Some(last) = found_args.last_mut() {
|
||||||
|
*last = ErrorType::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeError::BadExpr(_, _, _, Expected::FromAnnotation(_, _, _, _))
|
||||||
|
| TypeError::BadExpr(_, _, _, Expected::NoExpectation(_)) => {}
|
||||||
|
|
||||||
// Irrelevant
|
// Irrelevant
|
||||||
TypeError::BadPattern(_, _, _, _)
|
TypeError::BadPattern(_, _, _, _)
|
||||||
|
@ -80,7 +118,7 @@ impl Env {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_with_bad_expr_reason(
|
fn remove_for_reason(
|
||||||
env: &Env,
|
env: &Env,
|
||||||
found_type: &mut ErrorType,
|
found_type: &mut ErrorType,
|
||||||
reason: &mut Reason,
|
reason: &mut Reason,
|
||||||
|
|
|
@ -3594,7 +3594,7 @@ pub enum Mismatch {
|
||||||
|
|
||||||
pub type DoesNotImplementAbility = Vec<(ErrorType, Symbol)>;
|
pub type DoesNotImplementAbility = Vec<(ErrorType, Symbol)>;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Hash)]
|
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
|
||||||
pub enum ErrorType {
|
pub enum ErrorType {
|
||||||
Infinite,
|
Infinite,
|
||||||
Type(Symbol, Vec<ErrorType>),
|
Type(Symbol, Vec<ErrorType>),
|
||||||
|
@ -3619,12 +3619,12 @@ pub enum ErrorType {
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for ErrorType {
|
// impl std::fmt::Debug for ErrorType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// TODO remove clone
|
// // TODO remove clone
|
||||||
write!(f, "{:?}", write_debug_error_type(self.clone()))
|
// write!(f, "{:?}", write_debug_error_type(self.clone()))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl ErrorType {
|
impl ErrorType {
|
||||||
pub fn unwrap_structural_alias(self) -> ErrorType {
|
pub fn unwrap_structural_alias(self) -> ErrorType {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue