@@ -3951,56 +3951,59 @@ 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(_ , [] , _ ), Tconstr(path , [] , _ )) -> (* type coercion for variants and records *)
3955
- (match extract_concrete_typedecl env t1 with
3956
- | (_ , _ , {type_kind =Type_variant constructors } ) ->
3957
- if Variant_coercion. can_coerce_variant constructors ~path then
3958
- cstrs
3954
+ | (Tconstr (_, [] , _), Tconstr (path, [] , _)) when Variant_coercion. can_coerce_path path &&
3955
+ extract_concrete_typedecl env t1 |> Variant_coercion. is_variant_typedecl |> Option. is_some
3956
+ ->
3957
+ (* type coercion for variants *)
3958
+ (match Variant_coercion. is_variant_typedecl (extract_concrete_typedecl env t1) with
3959
+ | Some constructors ->
3960
+ if constructors |> Variant_coercion. can_coerce_variant ~path then
3961
+ cstrs
3959
3962
else
3960
3963
(trace, t1, t2, ! univar_pairs)::cstrs
3961
- | (_ , _ , {type_kind =Type_record (fields1 , repr1 )} ) -> (
3962
- match extract_concrete_typedecl env t2 with
3963
- | (_ , _ , {type_kind =Type_record (fields2 , repr2 )} ) ->
3964
- let same_repr = match repr1, repr2 with
3965
- | (Record_regular | Record_optional_labels _ ), (Record_regular | Record_optional_labels _ ) ->
3966
- true (* handled in the fields checks *)
3967
- | Record_unboxed b1 , Record_unboxed b2 -> b1 = b2
3968
- | Record_inlined _ , Record_inlined _ -> repr1 = repr2
3969
- | Record_extension , Record_extension -> true
3964
+ | None -> (trace, t1, t2, ! univar_pairs)::cstrs)
3965
+ | (Tconstr(_ , [] , _ ), Tconstr(_ , [] , _ )) -> (* type coercion for records *)
3966
+ (match extract_concrete_typedecl env t1, extract_concrete_typedecl env t2 with
3967
+ | (_ , _ , {type_kind =Type_record (fields1 , repr1 )} ), (_ , _ , {type_kind =Type_record (fields2 , repr2 )} ) ->
3968
+ let same_repr = match repr1, repr2 with
3969
+ | (Record_regular | Record_optional_labels _ ), (Record_regular | Record_optional_labels _ ) ->
3970
+ true (* handled in the fields checks *)
3971
+ | Record_unboxed b1 , Record_unboxed b2 -> b1 = b2
3972
+ | Record_inlined _ , Record_inlined _ -> repr1 = repr2
3973
+ | Record_extension , Record_extension -> true
3974
+ | _ -> false in
3975
+ if same_repr then
3976
+ let field_is_optional id repr = match repr with
3977
+ | Record_optional_labels lbls -> List. mem (Ident. name id) lbls
3970
3978
| _ -> false in
3971
- if same_repr then
3972
- let field_is_optional id repr = match repr with
3973
- | Record_optional_labels lbls -> List. mem (Ident. name id) lbls
3974
- | _ -> false in
3975
- let violation = ref false in
3976
- let label_decl_sub (acc1 , acc2 ) ld2 =
3977
- match Ext_list. find_first fields1 (fun ld1 -> ld1.ld_id.name = ld2.ld_id.name) with
3978
- | Some ld1 ->
3979
- if field_is_optional ld1.ld_id repr1 <> (field_is_optional ld2.ld_id repr2) then
3980
- (* optional field can't be modified *)
3981
- violation := true ;
3982
- let get_as (({txt} , payload ) : Parsetree. attribute ) =
3983
- if txt = " as" then Ast_payload. is_single_string payload
3984
- else None in
3985
- let get_as_name ld = match Ext_list. filter_map ld.ld_attributes get_as with
3986
- | [] -> ld.ld_id.name
3987
- | (s ,_ )::_ -> s in
3988
- if get_as_name ld1 <> get_as_name ld2 then violation := true ;
3989
- ld1.ld_type :: acc1, ld2.ld_type :: acc2
3990
- | None ->
3991
- (* field must be present *)
3979
+ let violation = ref false in
3980
+ let label_decl_sub (acc1 , acc2 ) ld2 =
3981
+ match Ext_list. find_first fields1 (fun ld1 -> ld1.ld_id.name = ld2.ld_id.name) with
3982
+ | Some ld1 ->
3983
+ if field_is_optional ld1.ld_id repr1 <> (field_is_optional ld2.ld_id repr2) then
3984
+ (* optional field can't be modified *)
3992
3985
violation := true ;
3993
- (acc1, acc2) in
3994
- let tl1, tl2 = List. fold_left label_decl_sub ([] , [] ) fields2 in
3995
- if ! violation
3996
- then (trace, t1, t2, ! univar_pairs)::cstrs
3997
- else
3998
- subtype_list env trace tl1 tl2 cstrs
3986
+ let get_as (({txt} , payload ) : Parsetree. attribute ) =
3987
+ if txt = " as" then Ast_payload. is_single_string payload
3988
+ else None in
3989
+ let get_as_name ld = match Ext_list. filter_map ld.ld_attributes get_as with
3990
+ | [] -> ld.ld_id.name
3991
+ | (s ,_ )::_ -> s in
3992
+ if get_as_name ld1 <> get_as_name ld2 then violation := true ;
3993
+ ld1.ld_type :: acc1, ld2.ld_type :: acc2
3994
+ | None ->
3995
+ (* field must be present *)
3996
+ violation := true ;
3997
+ (acc1, acc2) in
3998
+ let tl1, tl2 = List. fold_left label_decl_sub ([] , [] ) fields2 in
3999
+ if ! violation
4000
+ then (trace, t1, t2, ! univar_pairs)::cstrs
3999
4001
else
4000
- ( trace, t1, t2, ! univar_pairs):: cstrs
4001
- | _ -> (trace, t1, t2, ! univar_pairs)::cstrs
4002
- | exception Not_found -> (trace, t1, t2, ! univar_pairs)::cstrs)
4002
+ subtype_list env trace tl1 tl2 cstrs
4003
+ else
4004
+ (trace, t1, t2, ! univar_pairs)::cstrs
4003
4005
| _ -> (trace, t1, t2, ! univar_pairs)::cstrs
4006
+ | exception Not_found -> (trace, t1, t2, ! univar_pairs)::cstrs
4004
4007
)
4005
4008
(* | (_, Tconstr(p2, _, _)) when generic_private_abbrev false env p2 ->
4006
4009
subtype_rec env trace t1 (expand_abbrev_opt env t2) cstrs *)
0 commit comments