@@ -3951,7 +3951,33 @@ let rec subtype_rec env trace t1 t2 cstrs =
3951
3951
end
3952
3952
| (Tconstr(p1 , _ , _ ), _ ) when generic_private_abbrev env p1 ->
3953
3953
subtype_rec env trace (expand_abbrev_opt env t1) t2 cstrs
3954
- (* | (_, Tconstr(p2, _, _)) when generic_private_abbrev false env p2 ->
3954
+ | (Tconstr(_ , [] , _ ), Tconstr(_ , [] , _ )) -> (* type coercion for records *)
3955
+ (match extract_concrete_typedecl env t1, extract_concrete_typedecl env t2 with
3956
+ | (_ , _ , {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
3959
+ | _ -> 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 *)
3966
+ 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
3975
+ else
3976
+ subtype_list env trace tl1 tl2 cstrs
3977
+ | _ -> (trace, t1, t2, ! univar_pairs)::cstrs
3978
+ | exception Not_found -> (trace, t1, t2, ! univar_pairs)::cstrs
3979
+ )
3980
+ (* | (_, Tconstr(p2, _, _)) when generic_private_abbrev false env p2 ->
3955
3981
subtype_rec env trace t1 (expand_abbrev_opt env t2) cstrs *)
3956
3982
| (Tobject (f1, _), Tobject (f2, _))
3957
3983
when is_Tvar (object_row f1) && is_Tvar (object_row f2) ->
0 commit comments