@@ -95,7 +95,12 @@ let add_type ~check id decl env =
95
95
Builtin_attributes. warning_scope ~ppwarning: false decl.type_attributes
96
96
(fun () -> Env. add_type ~check id decl env)
97
97
98
- let enter_type rec_flag env sdecl (id , uid ) =
98
+ (* Add a dummy type declaration to the environment, with the given arity.
99
+ The [type_kind] is [Type_abstract], but there is a generic [type_manifest]
100
+ for abbreviations, to allow polymorphic expansion, except if
101
+ [abstract_abbrevs] is [true].
102
+ This function is only used in [transl_type_decl]. *)
103
+ let enter_type ~abstract_abbrevs rec_flag env sdecl (id , uid ) =
99
104
let needed =
100
105
match rec_flag with
101
106
| Asttypes. Nonrecursive ->
@@ -111,15 +116,17 @@ let enter_type rec_flag env sdecl (id, uid) =
111
116
in
112
117
let arity = List. length sdecl.ptype_params in
113
118
if not needed then env else
119
+ let type_manifest = match sdecl.ptype_manifest, abstract_abbrevs with
120
+ | None , _ | Some _ , true -> None
121
+ | Some _ , false -> Some (Ctype. newvar () )
122
+ in
114
123
let decl =
115
124
{ type_params =
116
125
List. map (fun _ -> Btype. newgenvar () ) sdecl.ptype_params;
117
126
type_arity = arity;
118
127
type_kind = Type_abstract ;
119
128
type_private = sdecl.ptype_private;
120
- type_manifest =
121
- begin match sdecl.ptype_manifest with None -> None
122
- | Some _ -> Some (Ctype. newvar () ) end ;
129
+ type_manifest;
123
130
type_variance = Variance. unknown_signature ~injective: false ~arity ;
124
131
type_separability = Types.Separability. default_signature ~arity ;
125
132
type_is_newtype = false ;
@@ -782,7 +789,7 @@ let check_abbrev env sdecl (id, decl) =
782
789
- if -rectypes is not used, we only allow cycles in the type graph
783
790
if they go through an object or polymorphic variant type *)
784
791
785
- let check_well_founded env loc path to_check visited ty0 =
792
+ let check_well_founded ~ abs_env env loc path to_check visited ty0 =
786
793
let rec check parents trace ty =
787
794
if TypeSet. mem ty parents then begin
788
795
(* Format.eprintf "@[%a@]@." Printtyp.raw_type_expr ty;*)
@@ -798,8 +805,8 @@ let check_well_founded env loc path to_check visited ty0 =
798
805
| trace -> List. rev trace, false
799
806
in
800
807
if rec_abbrev
801
- then Recursive_abbrev (Path. name path, env , reaching_path)
802
- else Cycle_in_def (Path. name path, env , reaching_path)
808
+ then Recursive_abbrev (Path. name path, abs_env , reaching_path)
809
+ else Cycle_in_def (Path. name path, abs_env , reaching_path)
803
810
in raise (Error (loc, err))
804
811
end ;
805
812
let (fini, parents) =
@@ -844,11 +851,11 @@ let check_well_founded env loc path to_check visited ty0 =
844
851
(* Will be detected by check_regularity *)
845
852
Btype. backtrack snap
846
853
847
- let check_well_founded_manifest env loc path decl =
854
+ let check_well_founded_manifest ~ abs_env env loc path decl =
848
855
if decl.type_manifest = None then () else
849
856
let args = List. map (fun _ -> Ctype. newvar() ) decl.type_params in
850
857
let visited = ref TypeMap. empty in
851
- check_well_founded env loc path (Path. same path) visited
858
+ check_well_founded ~abs_env env loc path (Path. same path) visited
852
859
(Ctype. newconstr path args)
853
860
854
861
(* Given a new type declaration [type t = ...] (potentially mutually-recursive),
@@ -866,7 +873,7 @@ let check_well_founded_manifest env loc path decl =
866
873
(we don't have an example at hand where it is necessary), but we
867
874
are doing it anyway out of caution.
868
875
*)
869
- let check_well_founded_decl env loc path decl to_check =
876
+ let check_well_founded_decl ~ abs_env env loc path decl to_check =
870
877
let open Btype in
871
878
(* We iterate on all subexpressions of the declaration to check
872
879
"in depth" that no ill-founded type exists. *)
@@ -885,7 +892,7 @@ let check_well_founded_decl env loc path decl to_check =
885
892
{type_iterators with it_type_expr =
886
893
(fun self ty ->
887
894
if TypeSet. mem ty ! checked then () else begin
888
- check_well_founded env loc path to_check visited ty;
895
+ check_well_founded ~abs_env env loc path to_check visited ty;
889
896
checked := TypeSet. add ty ! checked;
890
897
self.it_do_type_expr self ty
891
898
end )} in
@@ -1073,7 +1080,8 @@ let transl_type_decl env rec_flag sdecl_list =
1073
1080
Ctype. with_local_level_iter ~post: generalize_decl begin fun () ->
1074
1081
(* Enter types. *)
1075
1082
let temp_env =
1076
- List. fold_left2 (enter_type rec_flag) env sdecl_list ids_list in
1083
+ List. fold_left2 (enter_type ~abstract_abbrevs: false rec_flag)
1084
+ env sdecl_list ids_list in
1077
1085
(* Translate each declaration. *)
1078
1086
let current_slot = ref None in
1079
1087
let warn_unused =
@@ -1130,14 +1138,23 @@ let transl_type_decl env rec_flag sdecl_list =
1130
1138
List. map2 (fun (id , _ ) sdecl -> (id, sdecl.ptype_loc))
1131
1139
ids_list sdecl_list
1132
1140
in
1141
+ (* Error messages cannot use the new environment, as this might result in
1142
+ non-termination. Instead we use a completely abstract version of the
1143
+ temporary environment, giving a reason for why abbreviations cannot be
1144
+ expanded (#12645, #12649) *)
1145
+ let abs_env =
1146
+ List. fold_left2
1147
+ (enter_type ~abstract_abbrevs: true rec_flag)
1148
+ env sdecl_list ids_list in
1133
1149
List. iter (fun (id , decl ) ->
1134
- check_well_founded_manifest new_env (List. assoc id id_loc_list)
1150
+ check_well_founded_manifest ~abs_env new_env (List. assoc id id_loc_list)
1135
1151
(Path. Pident id) decl)
1136
1152
decls;
1137
1153
let to_check =
1138
1154
function Path. Pident id -> List. mem_assoc id id_loc_list | _ -> false in
1139
1155
List. iter (fun (id , decl ) ->
1140
- check_well_founded_decl new_env (List. assoc id id_loc_list) (Path. Pident id)
1156
+ check_well_founded_decl ~abs_env new_env (List. assoc id id_loc_list)
1157
+ (Path. Pident id)
1141
1158
decl to_check)
1142
1159
decls;
1143
1160
List. iter
@@ -1818,7 +1835,7 @@ let check_recmod_typedecl env loc recmod_ids path decl =
1818
1835
(* recmod_ids is the list of recursively-defined module idents.
1819
1836
(path, decl) is the type declaration to be checked. *)
1820
1837
let to_check path = Path. exists_free recmod_ids path in
1821
- check_well_founded_decl env loc path decl to_check;
1838
+ check_well_founded_decl ~abs_env: env env loc path decl to_check;
1822
1839
check_regularity ~orig_env: env env loc path decl to_check;
1823
1840
(* additionally check coherece, as one might build an incoherent signature,
1824
1841
and use it to build an incoherent module, cf. #7851 *)
0 commit comments