Skip to content

Commit 259263c

Browse files
committed
improve error message of superfluous fields in rest
1 parent ad170f6 commit 259263c

2 files changed

Lines changed: 35 additions & 19 deletions

File tree

compiler/ml/typecore.ml

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ type error =
9999
| Record_rest_requires_type_annotation of string
100100
| Record_rest_not_record of Longident.t
101101
| Record_rest_field_not_optional of string * Longident.t
102-
| Record_rest_field_missing of string * Longident.t
102+
| Record_rest_field_missing of string list * Longident.t
103103
| Record_rest_extra_field of string * Longident.t
104104

105105
exception Error of Location.t * Env.t * error
@@ -1626,19 +1626,22 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp
16261626
(match lbl_pat_list with
16271627
| (_, label1, _, _) :: _ ->
16281628
let all_source = label1.lbl_all in
1629-
Array.iter
1630-
(fun source_label ->
1631-
let name = source_label.lbl_name in
1632-
if
1633-
(not (List.mem name explicit_fields))
1634-
&& not (List.mem name rest_field_names)
1635-
then
1636-
raise
1637-
(Error
1638-
( rest_pat.ppat_loc,
1639-
!env,
1640-
Record_rest_field_missing (name, rest_type_lid.txt) )))
1641-
all_source
1629+
let missing =
1630+
Array.to_list all_source
1631+
|> List.filter_map (fun source_label ->
1632+
let name = source_label.lbl_name in
1633+
if
1634+
(not (List.mem name explicit_fields))
1635+
&& not (List.mem name rest_field_names)
1636+
then Some name
1637+
else None)
1638+
in
1639+
if missing <> [] then
1640+
raise
1641+
(Error
1642+
( rest_pat.ppat_loc,
1643+
!env,
1644+
Record_rest_field_missing (missing, rest_type_lid.txt) ))
16421645
| [] -> ());
16431646
(* Validate: rest type fields must all exist in source *)
16441647
(match lbl_pat_list with
@@ -4963,10 +4966,23 @@ let report_error env loc ppf error =
49634966
"Field `%s` appears in both the explicit pattern and the rest type `%a`. \
49644967
It must be marked as optional (`?%s`) in the explicit pattern."
49654968
field longident lid field
4966-
| Record_rest_field_missing (field, lid) ->
4967-
fprintf ppf
4968-
"Field `%s` is not covered by the explicit pattern or the rest type `%a`."
4969-
field longident lid
4969+
| Record_rest_field_missing (fields, lid) -> (
4970+
let field_list =
4971+
fields |> List.map (fun f -> "\n- " ^ f) |> String.concat ""
4972+
in
4973+
match fields with
4974+
| [_] ->
4975+
fprintf ppf
4976+
"The following field is not part of the rest type `%a`:%s\n\n\
4977+
List this field in the record pattern before the spread so it's not \
4978+
present in the rest record."
4979+
longident lid field_list
4980+
| _ ->
4981+
fprintf ppf
4982+
"The following fields are not part of the rest type `%a`:%s\n\n\
4983+
List these fields in the record pattern before the spread so they're \
4984+
not present in the rest record."
4985+
longident lid field_list)
49704986
| Record_rest_extra_field (field, lid) ->
49714987
fprintf ppf
49724988
"Field `%s` in the rest type `%a` does not exist in the source record \

compiler/ml/typecore.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ type error =
132132
| Record_rest_requires_type_annotation of string
133133
| Record_rest_not_record of Longident.t
134134
| Record_rest_field_not_optional of string * Longident.t
135-
| Record_rest_field_missing of string * Longident.t
135+
| Record_rest_field_missing of string list * Longident.t
136136
| Record_rest_extra_field of string * Longident.t
137137

138138
exception Error of Location.t * Env.t * error

0 commit comments

Comments
 (0)