@@ -27,6 +27,13 @@ module Paths = Odoc_model.Paths
27
27
28
28
module Compat = struct
29
29
#if OCAML_VERSION > = (4 , 14 , 0 )
30
+ (* * this is the type on which physical equality is meaningful *)
31
+ type repr_type_node = Types .transient_expr
32
+
33
+ (* * repr has morally type [type_expr -> repr_type_node] in all OCaml
34
+ versions *)
35
+ let repr x = Transient_expr. repr x
36
+
30
37
let get_desc = Types. get_desc
31
38
let get_row_name = Types. row_name
32
39
let row_field_repr = Types. row_field_repr
@@ -35,30 +42,40 @@ module Compat = struct
35
42
let row_closed = Types. row_closed
36
43
let row_fields = Types. row_fields
37
44
let field_public = Types. Fpublic
38
- let repr x = x
39
45
let self_type = Btype. self_type
40
46
let csig_self x = x.Types. csig_self
41
47
let row_repr x = x
42
48
let concr_mem = Types.Meths. mem
43
49
let csig_concr x = x.Types. csig_meths
50
+ let eq_type = Types. eq_type
51
+ let invisible_wrap ty = newty2 ~level: Btype. generic_level (Ttuple [ty])
44
52
#else
45
- let get_desc x = x.Types. desc
53
+ type repr_type_node = Types .type_expr
54
+ let repr = Btype. repr
55
+ let get_desc x = (repr x).Types. desc
46
56
let get_row_name x = x.Types. row_name
47
57
let row_field_repr = Btype. row_field_repr
48
58
let field_kind_repr = Btype. field_kind_repr
49
59
let static_row_repr x = Btype. static_row (Btype. row_repr x)
50
60
let row_closed x = x.Types. row_closed
51
61
let row_fields x = x.Types. row_fields
52
62
let field_public = Types. Fpresent
53
- let repr = Btype. repr
54
63
let self_type = Ctype. self_type
55
64
let csig_self x = Btype. repr x.Types. csig_self
56
65
let row_repr = Btype. row_repr
57
66
let concr_mem = Types.Concr. mem
58
67
let csig_concr x = x.Types. csig_concr
68
+ let eq_type x y = x == y || repr x == repr y
69
+
70
+ (* * Create a new node pointing to [ty] that is printed in the same way as
71
+ [ty]*)
72
+ let invisible_wrap ty =
73
+ Btype. (newty2 generic_level (Ttuple [ty]))
59
74
#endif
60
75
end
61
76
77
+ let proxy ty = Compat. (repr (Btype. proxy ty))
78
+
62
79
let opt_map f = function
63
80
| None -> None
64
81
| Some x -> Some (f x)
@@ -87,7 +104,10 @@ let read_label lbl =
87
104
88
105
(* Handle type variable names *)
89
106
90
- let used_names = ref []
107
+ (* * To identify equal type node for type variables, we need a map from the
108
+ representative type node to names. Otherwise, equivalent variables would end
109
+ up with distinct names *)
110
+ let used_names : (Compat.repr_type_node * string) list ref = ref []
91
111
let name_counter = ref 0
92
112
let reserved_names = ref []
93
113
@@ -119,25 +139,27 @@ let fresh_name base =
119
139
done ;
120
140
! current_name
121
141
122
- let name_of_type (ty : Types.type_expr ) =
142
+ let name_of_type_repr (ty : Compat.repr_type_node ) =
123
143
try
124
144
List. assq ty ! used_names
125
145
with Not_found ->
126
146
let base =
127
- match Compat. get_desc ty with
147
+ match ty.desc with
128
148
| Tvar (Some name ) | Tunivar (Some name ) -> name
129
149
| _ -> next_name ()
130
150
in
131
151
let name = fresh_name base in
132
152
if name <> " _" then used_names := (ty, name) :: ! used_names;
133
153
name
134
154
155
+ let name_of_type ty = name_of_type_repr (Compat. repr ty)
156
+
135
157
let remove_names tyl =
136
158
used_names := List. filter (fun (ty ,_ ) -> not (List. memq ty tyl)) ! used_names
137
159
138
160
(* Handle recursive types and shared row variables *)
139
161
140
- let aliased = ref []
162
+ let aliased: Compat. repr_type_node list ref = ref []
141
163
let used_aliases = ref []
142
164
143
165
let reset_aliased () = aliased := [] ; used_aliases := []
@@ -149,20 +171,21 @@ let aliasable (ty : Types.type_expr) =
149
171
| Tvar _ | Tunivar _ | Tpoly _ -> false
150
172
| _ -> true
151
173
152
- let add_alias ty =
153
- let px = Btype. proxy ty in
174
+ let add_alias_proxy px =
154
175
if not (List. memq px ! aliased) then begin
155
176
aliased := px :: ! aliased;
156
- match Compat. get_desc px with
177
+ match px.desc with
157
178
| Tvar name | Tunivar name -> reserve_name name
158
179
| _ -> ()
159
180
end
160
181
161
- let used_alias (px : Types.type_expr ) = List. memq px ! used_aliases
182
+ let add_alias ty = add_alias_proxy (proxy ty)
183
+
184
+ let used_alias (px : Compat.repr_type_node ) = List. memq px ! used_aliases
162
185
163
- let use_alias (px : Types.type_expr ) = used_aliases := px :: ! used_aliases
186
+ let use_alias (px : Compat.repr_type_node ) = used_aliases := px :: ! used_aliases
164
187
165
- let visited_rows = ref []
188
+ let visited_rows: Compat. repr_type_node list ref = ref []
166
189
167
190
let reset_visited_rows () = visited_rows := []
168
191
@@ -191,9 +214,8 @@ let namable_row row =
191
214
192
215
let mark_type ty =
193
216
let rec loop visited ty =
194
- let ty = Compat. repr ty in
195
- let px = Btype. proxy ty in
196
- if List. memq px visited && aliasable ty then add_alias px else
217
+ let px = proxy ty in
218
+ if List. memq px visited && aliasable ty then add_alias_proxy px else
197
219
let visited = px :: visited in
198
220
match Compat. get_desc ty with
199
221
| Tvar name -> reserve_name name
@@ -204,7 +226,7 @@ let mark_type ty =
204
226
| Tconstr (_ , tyl , _ ) ->
205
227
List. iter (loop visited) tyl
206
228
| Tvariant row ->
207
- if is_row_visited px then add_alias px else
229
+ if is_row_visited px then add_alias_proxy px else
208
230
begin
209
231
if not (Compat. static_row_repr row) then visit_row px;
210
232
match Compat. get_row_name row with
@@ -214,7 +236,7 @@ let mark_type ty =
214
236
Btype. iter_row (loop visited) row
215
237
end
216
238
| Tobject (fi , nm ) ->
217
- if is_row_visited px then add_alias px else
239
+ if is_row_visited px then add_alias_proxy px else
218
240
begin
219
241
visit_object ty px;
220
242
match ! nm with
@@ -268,31 +290,34 @@ let mark_value_description vd =
268
290
mark_type vd.val_type
269
291
270
292
let mark_type_parameter param =
271
- add_alias param;
293
+ let px = proxy param in
294
+ add_alias_proxy px;
272
295
mark_type param;
273
- if aliasable param then use_alias ( Btype. proxy param)
296
+ if aliasable param then use_alias px
274
297
275
298
#if OCAML_VERSION < (4 ,13 ,0 )
276
- let tsubst x = Tsubst x
277
299
let tvar_none ty = ty.desc < - Tvar None
278
300
#elif OCAML_VERSION < (4 ,14 ,0 )
279
- let tsubst x = Tsubst (x,None )
280
301
let tvar_none ty = Types.Private_type_expr. set_desc ty (Tvar None )
281
302
#else
282
- let tsubst x = Tsubst (x,None )
283
303
let tvar_none ty = Types.Transient_expr. (set_desc (coerce ty) (Tvar None ))
284
304
#endif
285
305
286
- let prepare_type_parameters params manifest =
306
+ let wrap_constrained_params tyl =
287
307
let params =
288
308
List. fold_left
289
- (fun params param ->
290
- let param = Compat. repr param in
291
- if List. memq param params then Btype. newgenty (tsubst param) :: params
292
- else param :: params)
293
- [] params
294
- in
295
- let params = List. rev params in
309
+ (fun tyl ty ->
310
+ if List. exists (Compat. eq_type ty) tyl
311
+ then Compat. invisible_wrap ty :: tyl
312
+ else ty :: tyl)
313
+ (* Two parameters might be identical due to a constraint but we need to
314
+ print them differently in order to make the output syntactically valid.
315
+ We use [Ttuple [ty]] because it is printed as [ty]. *)
316
+ [] tyl
317
+ in List. rev params
318
+
319
+ let prepare_type_parameters params manifest =
320
+ let params = wrap_constrained_params params in
296
321
begin match manifest with
297
322
| Some ty ->
298
323
let vars = Ctype. free_variables ty in
@@ -366,22 +391,22 @@ let mark_exception ext =
366
391
let rec mark_class_type params = function
367
392
| Cty_constr (_ , tyl , cty ) ->
368
393
let sty = Compat. self_type cty in
369
- if is_row_visited (Btype. proxy sty)
394
+ if is_row_visited (proxy sty)
370
395
|| List. exists aliasable params
371
396
|| List. exists (Ctype. deep_occur sty) tyl
372
397
then mark_class_type params cty
373
398
else List. iter mark_type tyl
374
399
| Cty_signature sign ->
375
400
let sty = Compat. csig_self sign in
376
- let px = Btype. proxy sty in
377
- if is_row_visited px then add_alias sty
401
+ let px = proxy sty in
402
+ if is_row_visited px then add_alias_proxy px
378
403
else visit_row px;
379
404
let (fields, _) =
380
405
Ctype. flatten_fields (Ctype. object_fields sign.csig_self)
381
406
in
382
407
List. iter (fun (_ , _ , ty ) -> mark_type ty) fields;
383
408
Vars. iter (fun _ (_ , _ , ty ) -> mark_type ty) sign.csig_vars;
384
- if is_aliased sty && aliasable sty then use_alias px
409
+ if is_aliased px && aliasable sty then use_alias px
385
410
| Cty_arrow (_ , ty , cty ) ->
386
411
mark_type ty;
387
412
mark_class_type params cty
@@ -398,8 +423,7 @@ let mark_class_declaration cld =
398
423
399
424
let rec read_type_expr env typ =
400
425
let open TypeExpr in
401
- let typ = Compat. repr typ in
402
- let px = Btype. proxy typ in
426
+ let px = proxy typ in
403
427
if used_alias px then Var (name_of_type typ)
404
428
else begin
405
429
let alias =
@@ -418,7 +442,7 @@ let rec read_type_expr env typ =
418
442
| Tarrow (lbl , arg , res , _ ) ->
419
443
let arg =
420
444
if Btype. is_optional lbl then
421
- match Compat. get_desc ( Compat. repr arg) with
445
+ match Compat. get_desc arg with
422
446
| Tconstr (_option , [arg ], _ ) -> read_type_expr env arg
423
447
| _ -> assert false
424
448
else read_type_expr env arg
@@ -439,7 +463,7 @@ let rec read_type_expr env typ =
439
463
| Tpoly (typ , [] ) -> read_type_expr env typ
440
464
| Tpoly (typ , tyl ) ->
441
465
let tyl = List. map Compat. repr tyl in
442
- let vars = List. map name_of_type tyl in
466
+ let vars = List. map name_of_type_repr tyl in
443
467
let typ = read_type_expr env typ in
444
468
remove_names tyl;
445
469
Poly (vars, typ)
@@ -540,8 +564,7 @@ and read_row env _px row =
540
564
and read_object env fi nm =
541
565
let open TypeExpr in
542
566
let open TypeExpr.Object in
543
- let fi = Compat. repr fi in
544
- let px = Btype. proxy fi in
567
+ let px = proxy fi in
545
568
if used_alias px then Var (name_of_type fi)
546
569
else begin
547
570
use_alias px;
@@ -816,14 +839,14 @@ let read_instance_variable env parent (name, mutable_, virtual_, typ) =
816
839
ClassSignature. InstanceVariable {id; doc; mutable_; virtual_; type_}
817
840
818
841
let read_self_type sty =
819
- let sty = Compat. repr sty in
820
- if not (is_aliased sty ) then None
821
- else Some (TypeExpr. Var (name_of_type ( Btype. proxy sty) ))
842
+ let px = proxy sty in
843
+ if not (is_aliased px ) then None
844
+ else Some (TypeExpr. Var (name_of_type_repr px ))
822
845
823
846
let rec read_class_signature env parent params =
824
847
let open ClassType in function
825
848
| Cty_constr (p , _ , cty ) ->
826
- if is_row_visited (Btype. proxy (Compat. self_type cty))
849
+ if is_row_visited (proxy (Compat. self_type cty))
827
850
|| List. exists aliasable params
828
851
then read_class_signature env parent params cty
829
852
else begin
@@ -902,7 +925,7 @@ let rec read_class_type env parent params =
902
925
| Cty_arrow (lbl , arg , cty ) ->
903
926
let arg =
904
927
if Btype. is_optional lbl then
905
- match Compat. get_desc ( Compat. repr arg) with
928
+ match Compat. get_desc arg with
906
929
| Tconstr (path, [arg], _)
907
930
when OCamlPath. same path Predef. path_option ->
908
931
read_type_expr env arg
0 commit comments