Skip to content
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

Improve error message when an object is passed where a record is expected #7101

Merged
merged 2 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
- Improve error messages around JSX components. https://github.com/rescript-lang/rescript-compiler/pull/7038
- Improve output of record copying. https://github.com/rescript-lang/rescript-compiler/pull/7043
- Provide additional context in error message when `unit` is expected. https://github.com/rescript-lang/rescript-compiler/pull/7045
- Improve error message when passing an object where a record is expected. https://github.com/rescript-lang/rescript-compiler/pull/7101

#### :house: Internal

Expand Down
19 changes: 18 additions & 1 deletion compiler/ml/error_message_utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ let error_expected_type_text ppf type_clash_context =
fprintf ppf "But this function is expecting you to return:"
| _ -> fprintf ppf "But it's expected to have type:"

let print_extra_type_clash_help ppf trace type_clash_context =
let is_record_type ~extract_concrete_typedecl ~env ty =
try
match extract_concrete_typedecl env ty with
| _, _, {Types.type_kind = Type_record _; _} -> true
| _ -> false
with _ -> false

let print_extra_type_clash_help ~extract_concrete_typedecl ~env ppf trace
type_clash_context =
match (type_clash_context, trace) with
| Some (MathOperator {for_float; operator; is_constant}), _ -> (
let operator_for_other_type =
Expand Down Expand Up @@ -176,6 +184,15 @@ let print_extra_type_clash_help ppf trace type_clash_context =
\ - If you don't care about the result of this expression, you can \
assign it to @{<info>_@} via @{<info>let _ = ...@} or pipe it to \
@{<info>ignore@} via @{<info>expression->ignore@}\n\n"
| _, [({desc = Tobject _}, _); (({Types.desc = Tconstr _} as t1), _)]
when is_record_type ~extract_concrete_typedecl ~env t1 ->
fprintf ppf
"\n\n\
\ You're passing a @{<error>ReScript object@} where a @{<info>record@} \
is expected. \n\n\
\ - Did you mean to pass a record instead of an object? Objects are \
written with quoted keys, and records with unquoted keys. Remove the \
quotes from the object keys to pass it as a record instead of object. \n\n"
| _ -> ()

let type_clash_context_from_function sexp sfunct =
Expand Down
3 changes: 2 additions & 1 deletion compiler/ml/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,8 @@ let print_expr_type_clash ?type_clash_context env trace ppf =
| ppf -> error_type_text ppf type_clash_context)
(function
| ppf -> error_expected_type_text ppf type_clash_context);
print_extra_type_clash_help ppf trace type_clash_context;
print_extra_type_clash_help ~extract_concrete_typedecl ~env ppf trace
type_clash_context;
show_extra_help ppf env trace

let report_arity_mismatch ~arity_a ~arity_b ppf =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

We've found a bug for you!
/.../fixtures/object_passed_when_record_expected.res:4:14-26

2 │ type xx = array<x>
3 │
4 │ let x: xx = [{"one": true}]
5 │

This has type: {"one": bool}
But it's expected to have type: x

You're passing a ReScript object where a record is expected.

- Did you mean to pass a record instead of an object? Objects are written with quoted keys, and records with unquoted keys. Remove the quotes from the object keys to pass it as a record instead of object.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type x = {one: bool}
type xx = array<x>

let x: xx = [{"one": true}]