Skip to content

Commit f35a3c3

Browse files
committed
try tracking record field type checking
1 parent 0bf1af9 commit f35a3c3

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

compiler/ml/error_message_utils.ml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ let type_expr ppf typ =
7171
7272
type type_clash_statement = FunctionCall
7373
type type_clash_context =
74-
| SetRecordField
74+
| SetRecordField of string (* field name *)
75+
| RecordField of string (* field name *)
7576
| ArrayValue
7677
| MaybeUnwrapOption
7778
| IfCondition
@@ -99,7 +100,8 @@ let context_to_string = function
99100
| Some (Statement _) -> "Statement"
100101
| Some (MathOperator _) -> "MathOperator"
101102
| Some ArrayValue -> "ArrayValue"
102-
| Some SetRecordField -> "SetRecordField"
103+
| Some (SetRecordField _) -> "SetRecordField"
104+
| Some (RecordField _) -> "RecordField"
103105
| Some MaybeUnwrapOption -> "MaybeUnwrapOption"
104106
| Some SwitchReturn -> "SwitchReturn"
105107
| Some TryReturn -> "TryReturn"
@@ -117,7 +119,7 @@ let error_type_text ppf type_clash_context =
117119
| Some (Statement FunctionCall) -> "This function call returns:"
118120
| Some (MathOperator {is_constant = Some _}) -> "This value has type:"
119121
| Some ArrayValue -> "This array item has type:"
120-
| Some SetRecordField ->
122+
| Some (SetRecordField _) ->
121123
"You're assigning something to this field that has type:"
122124
| _ -> "This has type:"
123125
in
@@ -142,7 +144,10 @@ let error_expected_type_text ppf type_clash_context =
142144
fprintf ppf "But this @{<info>if@} statement is expected to return:"
143145
| Some ArrayValue ->
144146
fprintf ppf "But this array is expected to have items of type:"
145-
| Some SetRecordField -> fprintf ppf "But this record field is of type:"
147+
| Some (SetRecordField _) -> fprintf ppf "But this record field is of type:"
148+
| Some (RecordField field_name) ->
149+
fprintf ppf "But this record field @{<info>%s@} is expected to have type:"
150+
field_name
146151
| Some (Statement FunctionCall) -> fprintf ppf "But it's expected to return:"
147152
| Some (MathOperator {operator}) ->
148153
fprintf ppf

compiler/ml/typecore.ml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,7 +2575,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
25752575
(type_record_elem_list loc true env
25762576
(fun e k ->
25772577
k
2578-
(type_label_exp ~context:None true env loc ty_record
2578+
(type_label_exp ~call_context:`Regular true env loc ty_record
25792579
(process_optional_label e)))
25802580
opath lid_sexp_list)
25812581
(fun x -> x)
@@ -2685,7 +2685,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
26852685
(type_record_elem_list loc closed env
26862686
(fun e k ->
26872687
k
2688-
(type_label_exp ~context:None true env loc ty_record
2688+
(type_label_exp ~call_context:`Regular true env loc ty_record
26892689
(process_optional_label e)))
26902690
opath lid_sexp_list)
26912691
(fun x -> x)
@@ -2764,7 +2764,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
27642764
let record, label, opath = type_label_access env srecord lid in
27652765
let ty_record = if opath = None then newvar () else record.exp_type in
27662766
let label_loc, label, newval, _ =
2767-
type_label_exp ~context:(Some SetRecordField) false env loc ty_record
2767+
type_label_exp ~call_context:`SetRecordField false env loc ty_record
27682768
(lid, label, snewval, false)
27692769
in
27702770
unify_exp ~context:None env record ty_record;
@@ -3296,7 +3296,8 @@ and type_label_access env srecord lid =
32963296
(* Typing format strings for printing or reading.
32973297
These formats are used by functions in modules Printf, Format, and Scanf.
32983298
(Handling of * modifiers contributed by Thorsten Ohl.) *)
3299-
and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
3299+
and type_label_exp ~(call_context : [`SetRecordField | `Regular]) create env loc
3300+
ty_expected (lid, label, sarg, opt) =
33003301
(* Here also ty_expected may be at generic_level *)
33013302
begin_def ();
33023303
let separate = Env.has_local_constraints env in
@@ -3323,7 +3324,15 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33233324
else raise (Error (lid.loc, env, Private_label (lid.txt, ty_expected)));
33243325
let arg =
33253326
let snap = if vars = [] then None else Some (Btype.snapshot ()) in
3326-
let arg = type_argument ~context env sarg ty_arg (instance env ty_arg) in
3327+
let field_name = Longident.last lid.txt in
3328+
let field_context =
3329+
match call_context with
3330+
| `SetRecordField -> Some (Error_message_utils.SetRecordField field_name)
3331+
| `Regular -> Some (Error_message_utils.RecordField field_name)
3332+
in
3333+
let arg =
3334+
type_argument ~context:field_context env sarg ty_arg (instance env ty_arg)
3335+
in
33273336
end_def ();
33283337
try
33293338
check_univars env (vars <> []) "field value" arg label.lbl_arg vars;
@@ -3333,10 +3342,10 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33333342
(* Try to retype without propagating ty_arg, cf PR#4862 *)
33343343
may Btype.backtrack snap;
33353344
begin_def ();
3336-
let arg = type_exp ~context env sarg in
3345+
let arg = type_exp ~context:field_context env sarg in
33373346
end_def ();
33383347
generalize_expansive env arg.exp_type;
3339-
unify_exp ~context env arg ty_arg;
3348+
unify_exp ~context:field_context env arg ty_arg;
33403349
check_univars env false "field value" arg label.lbl_arg vars;
33413350
arg
33423351
with

tests/build_tests/super_errors/expected/inline_types_record_type_params.res.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
15 ┆ otherExtra: Some({test: true, anotherInlined: {record: true}}),
1010

1111
This has type: int
12-
But it's expected to have type: string
12+
But this record field age is expected to have type: string
1313

1414
You can convert int to string with Int.toString.

0 commit comments

Comments
 (0)