Skip to content

Commit 9f79885

Browse files
committed
try tracking record field type checking
1 parent 3dff296 commit 9f79885

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
@@ -2571,7 +2571,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
25712571
(type_label_a_list loc true env
25722572
(fun e k ->
25732573
k
2574-
(type_label_exp ~context:None true env loc ty_record
2574+
(type_label_exp ~call_context:`Regular true env loc ty_record
25752575
(process_optional_label e)))
25762576
opath lid_sexp_list)
25772577
(fun x -> x)
@@ -2681,7 +2681,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
26812681
(type_label_a_list loc closed env
26822682
(fun e k ->
26832683
k
2684-
(type_label_exp ~context:None true env loc ty_record
2684+
(type_label_exp ~call_context:`Regular true env loc ty_record
26852685
(process_optional_label e)))
26862686
opath lid_sexp_list)
26872687
(fun x -> x)
@@ -2760,7 +2760,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
27602760
let record, label, opath = type_label_access env srecord lid in
27612761
let ty_record = if opath = None then newvar () else record.exp_type in
27622762
let label_loc, label, newval, _ =
2763-
type_label_exp ~context:(Some SetRecordField) false env loc ty_record
2763+
type_label_exp ~call_context:`SetRecordField false env loc ty_record
27642764
(lid, label, snewval, false)
27652765
in
27662766
unify_exp ~context:None env record ty_record;
@@ -3292,7 +3292,8 @@ and type_label_access env srecord lid =
32923292
(* Typing format strings for printing or reading.
32933293
These formats are used by functions in modules Printf, Format, and Scanf.
32943294
(Handling of * modifiers contributed by Thorsten Ohl.) *)
3295-
and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
3295+
and type_label_exp ~(call_context : [`SetRecordField | `Regular]) create env loc
3296+
ty_expected (lid, label, sarg, opt) =
32963297
(* Here also ty_expected may be at generic_level *)
32973298
begin_def ();
32983299
let separate = Env.has_local_constraints env in
@@ -3319,7 +3320,15 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33193320
else raise (Error (lid.loc, env, Private_label (lid.txt, ty_expected)));
33203321
let arg =
33213322
let snap = if vars = [] then None else Some (Btype.snapshot ()) in
3322-
let arg = type_argument ~context env sarg ty_arg (instance env ty_arg) in
3323+
let field_name = Longident.last lid.txt in
3324+
let field_context =
3325+
match call_context with
3326+
| `SetRecordField -> Some (Error_message_utils.SetRecordField field_name)
3327+
| `Regular -> Some (Error_message_utils.RecordField field_name)
3328+
in
3329+
let arg =
3330+
type_argument ~context:field_context env sarg ty_arg (instance env ty_arg)
3331+
in
33233332
end_def ();
33243333
try
33253334
check_univars env (vars <> []) "field value" arg label.lbl_arg vars;
@@ -3329,10 +3338,10 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33293338
(* Try to retype without propagating ty_arg, cf PR#4862 *)
33303339
may Btype.backtrack snap;
33313340
begin_def ();
3332-
let arg = type_exp ~context env sarg in
3341+
let arg = type_exp ~context:field_context env sarg in
33333342
end_def ();
33343343
generalize_expansive env arg.exp_type;
3335-
unify_exp ~context env arg ty_arg;
3344+
unify_exp ~context:field_context env arg ty_arg;
33363345
check_univars env false "field value" arg label.lbl_arg vars;
33373346
arg
33383347
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)