Skip to content

Commit 0bb7d09

Browse files
committed
improve error message when an object is passed where a record is expected
1 parent 5f5917e commit 0bb7d09

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

compiler/ml/error_message_utils.ml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ let error_expected_type_text ppf type_clash_context =
5757
fprintf ppf "But this function is expecting you to return:"
5858
| _ -> fprintf ppf "But it's expected to have type:"
5959

60-
let print_extra_type_clash_help ppf trace type_clash_context =
60+
let is_record_type ~extract_concrete_typedecl ~env ty =
61+
try
62+
match extract_concrete_typedecl env ty with
63+
| _, _, {Types.type_kind = Type_record _; _} -> true
64+
| _ -> false
65+
with _ -> false
66+
67+
let print_extra_type_clash_help ~extract_concrete_typedecl ~env ppf trace
68+
type_clash_context =
6169
match (type_clash_context, trace) with
6270
| Some (MathOperator {for_float; operator; is_constant}), _ -> (
6371
let operator_for_other_type =
@@ -176,6 +184,15 @@ let print_extra_type_clash_help ppf trace type_clash_context =
176184
\ - If you don't care about the result of this expression, you can \
177185
assign it to @{<info>_@} via @{<info>let _ = ...@} or pipe it to \
178186
@{<info>ignore@} via @{<info>expression->ignore@}\n\n"
187+
| _, [({desc = Tobject _}, _); (({Types.desc = Tconstr _} as t1), _)]
188+
when is_record_type ~extract_concrete_typedecl ~env t1 ->
189+
fprintf ppf
190+
"\n\n\
191+
\ You're passing a @{<error>ReScript object@} where a @{<info>record@} \
192+
is expected. \n\n\
193+
\ - Did you mean to pass a record instead of an object? Objects are \
194+
written with quoted keys, and records with unquoted keys. Remove the \
195+
quotes from the object keys to pass it as a record instead of object. \n\n"
179196
| _ -> ()
180197

181198
let type_clash_context_from_function sexp sfunct =

compiler/ml/typecore.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,8 @@ let print_expr_type_clash ?type_clash_context env trace ppf =
814814
| ppf -> error_type_text ppf type_clash_context)
815815
(function
816816
| ppf -> error_expected_type_text ppf type_clash_context);
817-
print_extra_type_clash_help ppf trace type_clash_context;
817+
print_extra_type_clash_help ~extract_concrete_typedecl ~env ppf trace
818+
type_clash_context;
818819
show_extra_help ppf env trace
819820

820821
let report_arity_mismatch ~arity_a ~arity_b ppf =
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
We've found a bug for you!
3+
/.../fixtures/object_passed_when_record_expected.res:4:14-26
4+
5+
2 │ type xx = array<x>
6+
3 │
7+
4 │ let x: xx = [{"one": true}]
8+
5 │
9+
10+
This has type: {"one": bool}
11+
But it's expected to have type: x
12+
13+
You're passing a ReScript object where a record is expected.
14+
15+
- 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.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type x = {one: bool}
2+
type xx = array<x>
3+
4+
let x: xx = [{"one": true}]

0 commit comments

Comments
 (0)