Skip to content

Commit 60267ff

Browse files
committed
improve error message of non optional rest field already matched
1 parent 259263c commit 60267ff

2 files changed

Lines changed: 32 additions & 19 deletions

File tree

compiler/ml/typecore.ml

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ type error =
9898
| Record_rest_invalid_type
9999
| Record_rest_requires_type_annotation of string
100100
| Record_rest_not_record of Longident.t
101-
| Record_rest_field_not_optional of string * Longident.t
101+
| Record_rest_field_not_optional of string list * Longident.t
102102
| Record_rest_field_missing of string list * Longident.t
103103
| Record_rest_extra_field of string * Longident.t
104104

@@ -1609,19 +1609,20 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp
16091609
rest_labels
16101610
in
16111611
(* Validate: fields in both explicit and rest must be optional in the explicit pattern *)
1612-
List.iter
1613-
(fun rest_field ->
1614-
if
1612+
let not_optional =
1613+
List.filter
1614+
(fun rest_field ->
16151615
List.mem rest_field explicit_fields
1616-
&& not (List.mem rest_field explicit_optional_fields)
1617-
then
1618-
raise
1619-
(Error
1620-
( rest_pat.ppat_loc,
1621-
!env,
1622-
Record_rest_field_not_optional
1623-
(rest_field, rest_type_lid.txt) )))
1624-
rest_field_names;
1616+
&& not (List.mem rest_field explicit_optional_fields))
1617+
rest_field_names
1618+
in
1619+
if not_optional <> [] then
1620+
raise
1621+
(Error
1622+
( rest_pat.ppat_loc,
1623+
!env,
1624+
Record_rest_field_not_optional
1625+
(not_optional, rest_type_lid.txt) ));
16251626
(* Validate: all source fields must be in explicit or rest *)
16261627
(match lbl_pat_list with
16271628
| (_, label1, _, _) :: _ ->
@@ -4961,11 +4962,23 @@ let report_error env loc ppf error =
49614962
"Type %a is not a record type and cannot be used as a record rest \
49624963
pattern."
49634964
longident lid
4964-
| Record_rest_field_not_optional (field, lid) ->
4965-
fprintf ppf
4966-
"Field `%s` appears in both the explicit pattern and the rest type `%a`. \
4967-
It must be marked as optional (`?%s`) in the explicit pattern."
4968-
field longident lid field
4965+
| Record_rest_field_not_optional (fields, lid) -> (
4966+
let field_list =
4967+
fields |> List.map (fun f -> "\n- " ^ f) |> String.concat ""
4968+
in
4969+
match fields with
4970+
| [field] ->
4971+
fprintf ppf
4972+
"The following field appears in both the explicit pattern and the rest \
4973+
type `%a`:%s\n\n\
4974+
Mark it as optional (`?%s`) in the explicit pattern."
4975+
longident lid field_list field
4976+
| _ ->
4977+
fprintf ppf
4978+
"The following fields appear in both the explicit pattern and the rest \
4979+
type `%a`:%s\n\n\
4980+
Mark them as optional (e.g. `?fieldName`) in the explicit pattern."
4981+
longident lid field_list)
49694982
| Record_rest_field_missing (fields, lid) -> (
49704983
let field_list =
49714984
fields |> List.map (fun f -> "\n- " ^ f) |> String.concat ""

compiler/ml/typecore.mli

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

0 commit comments

Comments
 (0)