-
Notifications
You must be signed in to change notification settings - Fork 470
More error messages #7522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More error messages #7522
Conversation
rescript
@rescript/darwin-arm64
@rescript/darwin-x64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/win32-x64
commit: |
9f79885
to
b88d643
Compare
match p with | ||
| Path.Pdot (Path.Pident {Ident.name = jsx_module_name}, "fragmentProps", _) | ||
when Some jsx_module_name = !configured_jsx_module -> | ||
Some {props_record_path = p; fields = []; jsx_type = `Fragment} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic isn't perfect, and at some point we probably need to figure out a better approach for matching on "what is a JSX component" in order to give better error messages. But for now with the state we're in, this is an improvement.
when Some jsx_module_name = !configured_jsx_module -> | ||
Some {props_record_path = p; fields = []; jsx_type = `Fragment} | ||
| _ -> ( | ||
(* TODO: handle lowercase components using JSXDOM.domProps *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving this for a follow up.
@cknitt @tsnobip could you look over the messages/wording please? 🙏 @cristianoc could you have a general look at the code? I tried to make passing the context more explicit to make it simpler to follow the logic, and to add new cases as needed. |
The code looks good. Augmenting the error info with more details seems pretty robust. |
@@ -2637,7 +2651,7 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp | |||
} | |||
| Pexp_record (lid_sexp_list, Some sexp) -> | |||
assert (lid_sexp_list <> []); | |||
let exp = type_exp ~recarg env sexp in | |||
let exp = type_exp ~context:None ~recarg env sexp in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zth this is where I believe one can pass context to special case error messages for e.g. optional fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
Here are some suggestions for the messages.
tests/build_tests/super_errors/expected/jsx_custom_component_children.res.expected
Outdated
Show resolved
Hide resolved
tests/build_tests/super_errors/expected/jsx_type_mismatch_float.res.expected
Outdated
Show resolved
Hide resolved
tests/build_tests/super_errors/expected/optional_fn_argument_pass_option.res.expected
Outdated
Show resolved
Hide resolved
But this optional function argument is expecting: [1;33mint[0m | ||
|
||
You're passing an optional value into an optional function argument. | ||
Optional function arguments expect you to pass the concrete value, not an option, when passed directly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this wording is easy to understand. Maybe we can omit the "when passed directly"?
tests/build_tests/super_errors/expected/optional_record_field_pass_option.res.expected
Outdated
Show resolved
Hide resolved
2bcdff7
to
86f63f3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kudos @zth, great QoL improvements! Just a few comments, mostly nitpicking, so you can entirely decide to ignore them ^^
@@ -9,6 +9,6 @@ | |||
15 [2m┆[0m otherExtra: Some({test: true, anotherInlined: {record: true}}), | |||
|
|||
This has type: [1;31mint[0m | |||
But it's expected to have type: [1;33mstring[0m | |||
But the record field [1;33mage[0m is expected to have type: [1;33mstring[0m |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hell yeah, there were way too many "this" and "it"s
tests/build_tests/super_errors/expected/jsx_type_mismatch_float.res.expected
Outdated
Show resolved
Hide resolved
25 [2m│[0m | ||
|
||
This has type: [1;31mfloat[0m | ||
But children passed to this component are expected to have type: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why @cknitt corrected "is" to "are", but I still find it a bit confusing to use the plural for something that can be singular so we could maybe use a more neutral verb
But children passed to this component are expected to have type: | |
But children passed to this component must be of have type: |
or we could even keep the default wording:
But children passed to this component are expected to have type: | |
But the component prop children is expected to have type: |
But definitely nitpicking here!
But children of JSX fragments are expected to have type: | ||
[1;33mReact.element[0m [2m(defined as[0m [1;33mJsx.element[0m[2m)[0m |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's less true here since fragments only accept React.element
children that can indeed be plural.
But this optional function argument [1;33m~x[0m is expecting: [1;33mint[0m | ||
|
||
You're passing an optional value into an optional function argument. | ||
Optional function arguments expect you to pass the concrete value, not an option. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking again, but I'm not a big fan of concrete here, especially since sometimes, the concrete value that is expected can actually be an option, maybe use "unwrapped" instead? I won't start a war over this, it's really ok as is too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No that's great! I'm really not sure how to word this to make it clear, so all suggestions are great.
This has type: [1;31mstring[0m | ||
But this try/catch is expected to return: [1;33mint[0m | ||
|
||
The [1;33mtry[0m body and the [1;33mcatch[0m block must return the same type. | ||
To fix this, change your try/catch blocks to return the expected type. | ||
|
||
You can convert [1;33mstring[0m to [1;33mint[0m with [1;33mInt.fromString[0m. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a great improvement!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
But this optional function argument [1;33m~x[0m is expecting: [1;33mint[0m | ||
|
||
You're passing an optional value into an optional function argument. | ||
Optional function arguments expect you to pass a non-optional value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said, an optional parameter can expect an optional type in some cases, but I can't find a better wording and in 99% of the cases it's indeed a non optional value, so let's keep this for now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add a condition to check that the field isn't expecting an option per se.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it'd be better if we could just adjust the wording to be generic enough to cover both cases. I'll try and think of something. Maybe @cknitt or @cristianoc has ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the argument had option type we wouldn't have this error (except if we're passing nested when a single is expected).
Attempt: values passed to optional arguments don't need to be wrapped into an option.
You might need to adjust the type of the value supplied: avoid wrapping the value into an option, or unwrap the option from the value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great wording @cristianoc , thanks!
32ccee2
to
f2d3278
Compare
A bunch of more error message improvements.