Skip to content

Commit 6772661

Browse files
committed
Make it a compile error to have inline record fields whose fields conflict with the variant tag
1 parent 05c10e3 commit 6772661

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

compiler/ml/ast_untagged_variants.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type error =
5757
| Duplicated_bs_as
5858
| InvalidVariantTagAnnotation
5959
| InvalidUntaggedVariantDefinition of untagged_error
60+
| TagFieldNameConflict of string * string
6061
exception Error of Location.t * error
6162

6263
let report_error ppf =
@@ -90,6 +91,11 @@ let report_error ppf =
9091
| DuplicateLiteral s -> "Duplicate literal " ^ s ^ "."
9192
| ConstructorMoreThanOneArg name ->
9293
"Constructor " ^ name ^ " has more than one argument.")
94+
| TagFieldNameConflict (constructor_name, field_name) ->
95+
fprintf ppf
96+
"Constructor %s: the @tag name \"%s\" conflicts with inline record field \"%s\". \
97+
Use a different @tag name or rename the field."
98+
constructor_name field_name field_name
9399

94100
(* Type of the runtime representation of an untagged block (case with payoad) *)
95101
type block_type =
@@ -462,12 +468,27 @@ let names_from_type_variant ?(is_untagged_def = false) ~env
462468
let blocks = Ext_array.reverse_of_list blocks in
463469
Some {consts; blocks}
464470

471+
let check_tag_field_conflicts (cstrs : Types.constructor_declaration list) =
472+
List.iter (fun (cstr : Types.constructor_declaration) ->
473+
match process_tag_name cstr.cd_attributes with
474+
| Some tag_name -> (
475+
match cstr.cd_args with
476+
| Cstr_record fields ->
477+
List.iter (fun (field : Types.label_declaration) ->
478+
if Ident.name field.ld_id = tag_name then
479+
raise (Error (cstr.cd_loc, TagFieldNameConflict (Ident.name cstr.cd_id, tag_name)))
480+
) fields
481+
| _ -> ())
482+
| None -> ()
483+
) cstrs
484+
465485
type well_formedness_check = {
466486
is_untagged_def: bool;
467487
cstrs: Types.constructor_declaration list;
468488
}
469489

470490
let check_well_formed ~env {is_untagged_def; cstrs} =
491+
check_tag_field_conflicts cstrs;
471492
ignore (names_from_type_variant ~env ~is_untagged_def cstrs)
472493

473494
let has_undefined_literal attrs = process_tag_type attrs = Some Undefined

0 commit comments

Comments
 (0)