Skip to content

Commit c0bd807

Browse files
committed
Fix issue with record type coercion and unboxed
1 parent cfe1610 commit c0bd807

File tree

2 files changed

+28
-17
lines changed

2 files changed

+28
-17
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Fix error location to be the type with the spreads when spreading record types with duplicate labels. https://github.com/rescript-lang/rescript-compiler/pull/6157
2020
- Disable warning on `@inline` attibute on uncurried functions. https://github.com/rescript-lang/rescript-compiler/pull/6152
2121
- Support doc comments on arguments of function types. https://github.com/rescript-lang/rescript-compiler/pull/6161
22+
- Fix issue with record type coercion and unboxed. https://github.com/rescript-lang/rescript-compiler/issues/6158
2223

2324
# 11.0.0-alpha.3
2425

jscomp/ml/ctype.ml

+27-17
Original file line numberDiff line numberDiff line change
@@ -3954,26 +3954,36 @@ let rec subtype_rec env trace t1 t2 cstrs =
39543954
| (Tconstr(_, [], _), Tconstr(_, [], _)) -> (* type coercion for records *)
39553955
(match extract_concrete_typedecl env t1, extract_concrete_typedecl env t2 with
39563956
| (_, _, {type_kind=Type_record (fields1, repr1)}), (_, _, {type_kind=Type_record (fields2, repr2)}) ->
3957-
let field_is_optional id repr = match repr with
3958-
| Record_optional_labels lbls -> List.mem (Ident.name id) lbls
3957+
let same_repr = match repr1, repr2 with
3958+
| (Record_regular | Record_optional_labels _), (Record_regular | Record_optional_labels _) ->
3959+
true (* handled in the fields checks *)
3960+
| Record_unboxed b1, Record_unboxed b2 -> b1 = b2
3961+
| Record_inlined _, Record_inlined _ -> repr1 = repr2
3962+
| Record_extension, Record_extension -> true
39593963
| _ -> false in
3960-
let violation = ref false in
3961-
let label_decl_sub (acc1, acc2) ld2 =
3962-
match fields1 |> List.find_opt (fun ld1 -> Ident.name ld1.ld_id = Ident.name ld2.ld_id) with
3963-
| Some ld1 ->
3964-
if field_is_optional ld1.ld_id repr1 && not (field_is_optional ld2.ld_id repr2) then
3965-
(* optional field can't be cast to non-optional one *)
3964+
if same_repr then
3965+
let field_is_optional id repr = match repr with
3966+
| Record_optional_labels lbls -> List.mem (Ident.name id) lbls
3967+
| _ -> false in
3968+
let violation = ref false in
3969+
let label_decl_sub (acc1, acc2) ld2 =
3970+
match fields1 |> List.find_opt (fun ld1 -> Ident.name ld1.ld_id = Ident.name ld2.ld_id) with
3971+
| Some ld1 ->
3972+
if field_is_optional ld1.ld_id repr1 && not (field_is_optional ld2.ld_id repr2) then
3973+
(* optional field can't be cast to non-optional one *)
3974+
violation := true;
3975+
ld1.ld_type :: acc1, ld2.ld_type :: acc2
3976+
| None ->
3977+
(* field must be present *)
39663978
violation := true;
3967-
ld1.ld_type :: acc1, ld2.ld_type :: acc2
3968-
| None ->
3969-
(* field must be present *)
3970-
violation := true;
3971-
(acc1, acc2) in
3972-
let tl1, tl2 = List.fold_left label_decl_sub ([], []) fields2 in
3973-
if !violation
3974-
then (trace, t1, t2, !univar_pairs)::cstrs
3979+
(acc1, acc2) in
3980+
let tl1, tl2 = List.fold_left label_decl_sub ([], []) fields2 in
3981+
if !violation
3982+
then (trace, t1, t2, !univar_pairs)::cstrs
3983+
else
3984+
subtype_list env trace tl1 tl2 cstrs
39753985
else
3976-
subtype_list env trace tl1 tl2 cstrs
3986+
(trace, t1, t2, !univar_pairs)::cstrs
39773987
| _ -> (trace, t1, t2, !univar_pairs)::cstrs
39783988
| exception Not_found -> (trace, t1, t2, !univar_pairs)::cstrs
39793989
)

0 commit comments

Comments
 (0)