Skip to content

Commit b88d643

Browse files
committed
try tracking record field type checking
1 parent a80d31a commit b88d643

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
@@ -2572,7 +2572,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
25722572
(type_label_a_list loc true env
25732573
(fun e k ->
25742574
k
2575-
(type_label_exp ~context:None true env loc ty_record
2575+
(type_label_exp ~call_context:`Regular true env loc ty_record
25762576
(process_optional_label e)))
25772577
opath lid_sexp_list)
25782578
(fun x -> x)
@@ -2682,7 +2682,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
26822682
(type_label_a_list loc closed env
26832683
(fun e k ->
26842684
k
2685-
(type_label_exp ~context:None true env loc ty_record
2685+
(type_label_exp ~call_context:`Regular true env loc ty_record
26862686
(process_optional_label e)))
26872687
opath lid_sexp_list)
26882688
(fun x -> x)
@@ -2761,7 +2761,7 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
27612761
let record, label, opath = type_label_access env srecord lid in
27622762
let ty_record = if opath = None then newvar () else record.exp_type in
27632763
let label_loc, label, newval, _ =
2764-
type_label_exp ~context:(Some SetRecordField) false env loc ty_record
2764+
type_label_exp ~call_context:`SetRecordField false env loc ty_record
27652765
(lid, label, snewval, false)
27662766
in
27672767
unify_exp ~context:None env record ty_record;
@@ -3293,7 +3293,8 @@ and type_label_access env srecord lid =
32933293
(* Typing format strings for printing or reading.
32943294
These formats are used by functions in modules Printf, Format, and Scanf.
32953295
(Handling of * modifiers contributed by Thorsten Ohl.) *)
3296-
and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
3296+
and type_label_exp ~(call_context : [`SetRecordField | `Regular]) create env loc
3297+
ty_expected (lid, label, sarg, opt) =
32973298
(* Here also ty_expected may be at generic_level *)
32983299
begin_def ();
32993300
let separate = Env.has_local_constraints env in
@@ -3320,7 +3321,15 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33203321
else raise (Error (lid.loc, env, Private_label (lid.txt, ty_expected)));
33213322
let arg =
33223323
let snap = if vars = [] then None else Some (Btype.snapshot ()) in
3323-
let arg = type_argument ~context env sarg ty_arg (instance env ty_arg) in
3324+
let field_name = Longident.last lid.txt in
3325+
let field_context =
3326+
match call_context with
3327+
| `SetRecordField -> Some (Error_message_utils.SetRecordField field_name)
3328+
| `Regular -> Some (Error_message_utils.RecordField field_name)
3329+
in
3330+
let arg =
3331+
type_argument ~context:field_context env sarg ty_arg (instance env ty_arg)
3332+
in
33243333
end_def ();
33253334
try
33263335
check_univars env (vars <> []) "field value" arg label.lbl_arg vars;
@@ -3330,10 +3339,10 @@ and type_label_exp ~context create env loc ty_expected (lid, label, sarg, opt) =
33303339
(* Try to retype without propagating ty_arg, cf PR#4862 *)
33313340
may Btype.backtrack snap;
33323341
begin_def ();
3333-
let arg = type_exp ~context env sarg in
3342+
let arg = type_exp ~context:field_context env sarg in
33343343
end_def ();
33353344
generalize_expansive env arg.exp_type;
3336-
unify_exp ~context env arg ty_arg;
3345+
unify_exp ~context:field_context env arg ty_arg;
33373346
check_univars env false "field value" arg label.lbl_arg vars;
33383347
arg
33393348
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)