1 (***********************************************************************)
5 (* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*)
7 (* Copyright 1996 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* $Id: printtyp.ml 8922 2008-07-19 02:13:09Z garrigue $ *)
15 (* Printing functions *)
27 (* Print a long identifier *)
29 let rec longident ppf = function
30 | Lident s -> fprintf ppf "%s" s
31 | Ldot(p, s) -> fprintf ppf "%a.%s" longident p s
32 | Lapply(p1, p2) -> fprintf ppf "%a(%a)" longident p1 longident p2
34 (* Print an identifier *)
36 let ident ppf id = fprintf ppf "%s" (Ident.name id)
40 let ident_pervasive = Ident.create_persistent "Pervasives"
42 let rec tree_of_path = function
44 Oide_ident (Ident.name id)
45 | Pdot(Pident id, s, pos) when Ident.same id ident_pervasive ->
48 Oide_dot (tree_of_path p, s)
50 Oide_apply (tree_of_path p1, tree_of_path p2)
52 let rec path ppf = function
55 | Pdot(Pident id, s, pos) when Ident.same id ident_pervasive ->
58 fprintf ppf "%a.%s" path p s
60 fprintf ppf "%a(%a)" path p1 path p2
62 (* Print a recursive annotation *)
64 let tree_of_rec = function
65 | Trec_not -> Orec_not
66 | Trec_first -> Orec_first
67 | Trec_next -> Orec_next
69 (* Print a raw type expression, with sharing *)
71 let raw_list pr ppf = function
72 [] -> fprintf ppf "[]"
74 fprintf ppf "@[<1>[%a%t]@]" pr a
75 (fun ppf -> List.iter (fun x -> fprintf ppf ";@,%a" pr x) l)
77 let rec safe_kind_repr v = function
78 Fvar {contents=Some k} ->
79 if List.memq k v then "Fvar loop" else
80 safe_kind_repr (k::v) k
81 | Fvar _ -> "Fvar None"
82 | Fpresent -> "Fpresent"
83 | Fabsent -> "Fabsent"
85 let rec safe_commu_repr v = function
87 | Cunknown -> "Cunknown"
89 if List.memq r v then "Clink loop" else
90 safe_commu_repr (r::v) !r
92 let rec safe_repr v = function
93 {desc = Tlink t} when not (List.memq t v) ->
97 let rec list_of_memo = function
99 | Mcons (priv, p, t1, t2, rem) -> p :: list_of_memo rem
100 | Mlink rem -> list_of_memo !rem
103 let rec raw_type ppf ty =
104 let ty = safe_repr [] ty in
105 if List.memq ty !visited then fprintf ppf "{id=%d}" ty.id else begin
106 visited := ty :: !visited;
107 fprintf ppf "@[<1>{id=%d;level=%d;desc=@,%a}@]" ty.id ty.level
108 raw_type_desc ty.desc
110 and raw_type_list tl = raw_list raw_type tl
111 and raw_type_desc ppf = function
112 Tvar -> fprintf ppf "Tvar"
113 | Tarrow(l,t1,t2,c) ->
114 fprintf ppf "@[<hov1>Tarrow(%s,@,%a,@,%a,@,%s)@]"
115 l raw_type t1 raw_type t2
116 (safe_commu_repr [] c)
118 fprintf ppf "@[<1>Ttuple@,%a@]" raw_type_list tl
119 | Tconstr (p, tl, abbrev) ->
120 fprintf ppf "@[<hov1>Tconstr(@,%a,@,%a,@,%a)@]" path p
122 (raw_list path) (list_of_memo !abbrev)
124 fprintf ppf "@[<hov1>Tobject(@,%a,@,@[<1>ref%t@])@]" raw_type t
126 match !nm with None -> fprintf ppf " None"
128 fprintf ppf "(Some(@,%a,@,%a))" path p raw_type_list tl)
129 | Tfield (f, k, t1, t2) ->
130 fprintf ppf "@[<hov1>Tfield(@,%s,@,%s,@,%a,@;<0 -1>%a)@]" f
131 (safe_kind_repr [] k)
132 raw_type t1 raw_type t2
133 | Tnil -> fprintf ppf "Tnil"
134 | Tlink t -> fprintf ppf "@[<1>Tlink@,%a@]" raw_type t
135 | Tsubst t -> fprintf ppf "@[<1>Tsubst@,%a@]" raw_type t
136 | Tunivar -> fprintf ppf "Tunivar"
138 fprintf ppf "@[<hov1>Tpoly(@,%a,@,%a)@]"
143 "@[<hov1>{@[%s@,%a;@]@ @[%s@,%a;@]@ %s%b;@ %s%b;@ @[<1>%s%t@]}@]"
145 (raw_list (fun ppf (l, f) ->
146 fprintf ppf "@[%s,@ %a@]" l raw_field f))
148 "row_more=" raw_type row.row_more
149 "row_closed=" row.row_closed
150 "row_fixed=" row.row_fixed
153 match row.row_name with None -> fprintf ppf "None"
155 fprintf ppf "Some(@,%a,@,%a)" path p raw_type_list tl)
157 and raw_field ppf = function
158 Rpresent None -> fprintf ppf "Rpresent None"
159 | Rpresent (Some t) -> fprintf ppf "@[<1>Rpresent(Some@,%a)@]" raw_type t
160 | Reither (c,tl,m,e) ->
161 fprintf ppf "@[<hov1>Reither(%b,@,%a,@,%b,@,@[<1>ref%t@])@]" c
164 match !e with None -> fprintf ppf " None"
165 | Some f -> fprintf ppf "@,@[<1>(%a)@]" raw_field f)
166 | Rabsent -> fprintf ppf "Rabsent"
168 let raw_type_expr ppf t =
173 (* Print a type expression *)
175 let names = ref ([] : (type_expr * string) list)
176 let name_counter = ref 0
178 let reset_names () = names := []; name_counter := 0
182 if !name_counter < 26
183 then String.make 1 (Char.chr(97 + !name_counter))
184 else String.make 1 (Char.chr(97 + !name_counter mod 26)) ^
185 string_of_int(!name_counter / 26) in
190 try List.assq t !names with Not_found ->
191 let name = new_name () in
192 names := (t, name) :: !names;
195 let check_name_of_type t = ignore(name_of_type t)
197 let non_gen_mark sch ty =
198 if sch && ty.desc = Tvar && ty.level <> generic_level then "_" else ""
200 let print_name_of_type sch ppf t =
201 fprintf ppf "'%s%s" (non_gen_mark sch t) (name_of_type t)
203 let visited_objects = ref ([] : type_expr list)
204 let aliased = ref ([] : type_expr list)
205 let delayed = ref ([] : type_expr list)
208 if not (List.memq t !delayed) then delayed := t :: !delayed
210 let is_aliased ty = List.memq (proxy ty) !aliased
213 if not (is_aliased px) then aliased := px :: !aliased
215 match ty.desc with Tvar | Tunivar | Tpoly _ -> false | _ -> true
217 let namable_row row =
218 row.row_name <> None &&
221 match row_field_repr f with
222 | Reither(c, l, _, _) ->
223 row.row_closed && if c then l = [] else List.length l = 1
227 let rec mark_loops_rec visited ty =
230 if List.memq px visited && aliasable ty then add_alias px else
231 let visited = px :: visited in
234 | Tarrow(_, ty1, ty2, _) ->
235 mark_loops_rec visited ty1; mark_loops_rec visited ty2
236 | Ttuple tyl -> List.iter (mark_loops_rec visited) tyl
237 | Tconstr(_, tyl, _) ->
238 List.iter (mark_loops_rec visited) tyl
240 if List.memq px !visited_objects then add_alias px else
242 let row = row_repr row in
243 if not (static_row row) then
244 visited_objects := px :: !visited_objects;
245 match row.row_name with
246 | Some(p, tyl) when namable_row row ->
247 List.iter (mark_loops_rec visited) tyl
249 iter_row (mark_loops_rec visited) row
251 | Tobject (fi, nm) ->
252 if List.memq px !visited_objects then add_alias px else
254 if opened_object ty then
255 visited_objects := px :: !visited_objects;
258 let fields, _ = flatten_fields fi in
260 (fun (_, kind, ty) ->
261 if field_kind_repr kind = Fpresent then
262 mark_loops_rec visited ty)
265 List.iter (mark_loops_rec visited) (List.tl l)
268 | Tfield(_, kind, ty1, ty2) when field_kind_repr kind = Fpresent ->
269 mark_loops_rec visited ty1; mark_loops_rec visited ty2
270 | Tfield(_, _, _, ty2) ->
271 mark_loops_rec visited ty2
273 | Tsubst ty -> mark_loops_rec visited ty
274 | Tlink _ -> fatal_error "Printtyp.mark_loops_rec (2)"
276 List.iter (fun t -> add_alias t) tyl;
277 mark_loops_rec visited ty
281 normalize_type Env.empty ty;
282 mark_loops_rec [] ty;;
284 let reset_loop_marks () =
285 visited_objects := []; aliased := []; delayed := []
288 reset_names (); reset_loop_marks ()
290 let reset_and_mark_loops ty =
291 reset (); mark_loops ty
293 let reset_and_mark_loops_list tyl =
294 reset (); List.iter mark_loops tyl
296 (* Disabled in classic mode when printing an unification error *)
297 let print_labels = ref true
298 let print_label ppf l =
299 if !print_labels && l <> "" || is_optional l then fprintf ppf "%s:" l
301 let rec tree_of_typexp sch ty =
304 if List.mem_assq px !names && not (List.memq px !delayed) then
305 let mark = is_non_gen sch ty in
306 Otyp_var (mark, name_of_type px) else
311 Otyp_var (is_non_gen sch ty, name_of_type ty)
312 | Tarrow(l, ty1, ty2, _) ->
313 let pr_arrow l ty1 ty2 =
315 if !print_labels && l <> "" || is_optional l then l else ""
318 if is_optional l then
319 match (repr ty1).desc with
320 | Tconstr(path, [ty], _)
321 when Path.same path Predef.path_option ->
322 tree_of_typexp sch ty
323 | _ -> Otyp_stuff "<hidden>"
324 else tree_of_typexp sch ty1 in
325 Otyp_arrow (lab, t1, tree_of_typexp sch ty2) in
328 Otyp_tuple (tree_of_typlist sch tyl)
329 | Tconstr(p, tyl, abbrev) ->
330 Otyp_constr (tree_of_path p, tree_of_typlist sch tyl)
332 let row = row_repr row in
334 if row.row_closed then
335 List.filter (fun (_, f) -> row_field_repr f <> Rabsent)
337 else row.row_fields in
341 match row_field_repr f with
345 let all_present = List.length present = List.length fields in
346 begin match row.row_name with
347 | Some(p, tyl) when namable_row row ->
348 let id = tree_of_path p in
349 let args = tree_of_typlist sch tyl in
350 if row.row_closed && all_present then
351 Otyp_constr (id, args)
353 let non_gen = is_non_gen sch px in
355 if all_present then None else Some (List.map fst present) in
356 Otyp_variant (non_gen, Ovar_name(tree_of_path p, args),
357 row.row_closed, tags)
360 not (row.row_closed && all_present) && is_non_gen sch px in
361 let fields = List.map (tree_of_row_field sch) fields in
363 if all_present then None else Some (List.map fst present) in
364 Otyp_variant (non_gen, Ovar_fields fields, row.row_closed, tags)
366 | Tobject (fi, nm) ->
367 tree_of_typobject sch fi nm
369 tree_of_typexp sch ty
370 | Tlink _ | Tnil | Tfield _ ->
371 fatal_error "Printtyp.tree_of_typexp"
373 tree_of_typexp sch ty
375 let tyl = List.map repr tyl in
376 (* let tyl = List.filter is_aliased tyl in *)
377 if tyl = [] then tree_of_typexp sch ty else begin
378 let old_delayed = !delayed in
379 List.iter add_delayed tyl;
380 let tl = List.map name_of_type tyl in
381 let tr = Otyp_poly (tl, tree_of_typexp sch ty) in
382 delayed := old_delayed; tr
385 Otyp_var (false, name_of_type ty)
387 if List.memq px !delayed then delayed := List.filter ((!=) px) !delayed;
388 if is_aliased px && aliasable ty then begin
389 check_name_of_type px;
390 Otyp_alias (pr_typ (), name_of_type px) end
393 and tree_of_row_field sch (l, f) =
394 match row_field_repr f with
395 | Rpresent None | Reither(true, [], _, _) -> (l, false, [])
396 | Rpresent(Some ty) -> (l, false, [tree_of_typexp sch ty])
397 | Reither(c, tyl, _, _) ->
398 if c (* contradiction: un constructeur constant qui a un argument *)
399 then (l, true, tree_of_typlist sch tyl)
400 else (l, false, tree_of_typlist sch tyl)
401 | Rabsent -> (l, false, [] (* une erreur, en fait *))
403 and tree_of_typlist sch tyl =
404 List.map (tree_of_typexp sch) tyl
406 and tree_of_typobject sch fi nm =
410 let (fields, rest) = flatten_fields fi in
414 match field_kind_repr k with
415 | Fpresent -> (n, t) :: l
419 Sort.list (fun (n, _) (n', _) -> n <= n') present_fields in
420 tree_of_typfields sch rest sorted_fields in
421 let (fields, rest) = pr_fields fi in
422 Otyp_object (fields, rest)
423 | Some (p, ty :: tyl) ->
424 let non_gen = is_non_gen sch (repr ty) in
425 let args = tree_of_typlist sch tyl in
426 Otyp_class (non_gen, tree_of_path p, args)
428 fatal_error "Printtyp.tree_of_typobject"
431 and is_non_gen sch ty =
432 sch && ty.desc = Tvar && ty.level <> generic_level
434 and tree_of_typfields sch rest = function
438 | Tvar | Tunivar -> Some (is_non_gen sch rest)
439 | Tconstr _ -> Some false
441 | _ -> fatal_error "typfields (1)"
445 let field = (s, tree_of_typexp sch t) in
446 let (fields, rest) = tree_of_typfields sch rest l in
447 (field :: fields, rest)
449 let typexp sch prio ppf ty =
450 !Oprint.out_type ppf (tree_of_typexp sch ty)
452 let type_expr ppf ty = typexp false 0 ppf ty
454 and type_sch ppf ty = typexp true 0 ppf ty
456 and type_scheme ppf ty = reset_and_mark_loops ty; typexp true 0 ppf ty
459 let type_scheme_max ?(b_reset_names=true) ppf ty =
460 if b_reset_names then reset_names () ;
464 let tree_of_type_scheme ty = reset_and_mark_loops ty; tree_of_typexp true ty
466 (* Print one type declaration *)
468 let tree_of_constraints params =
471 let ty' = unalias ty in
472 if proxy ty != proxy ty' then
473 let tr = tree_of_typexp true ty in
474 (tr, tree_of_typexp true ty') :: list
478 let filter_params tyl =
483 if List.memq ty tyl then Btype.newgenty (Tsubst ty) :: tyl
488 let string_of_mutable = function
490 | Mutable -> "mutable "
492 let rec tree_of_type_decl id decl =
496 let params = filter_params decl.type_params in
498 List.iter add_alias params;
499 List.iter mark_loops params;
500 List.iter check_name_of_type (List.map proxy params);
502 match decl.type_manifest with
506 (* Special hack to hide variant name *)
507 match repr ty with {desc=Tvariant row} ->
508 let row = row_repr row in
509 begin match row.row_name with
510 Some (Pident id', _) when Ident.same id id' ->
511 newgenty (Tvariant {row with row_name = None})
519 begin match decl.type_kind with
520 | Type_abstract -> ()
521 | Type_variant [] -> ()
522 | Type_variant cstrs ->
523 List.iter (fun (_, args) -> List.iter mark_loops args) cstrs
524 | Type_record(l, rep) ->
525 List.iter (fun (_, _, ty) -> mark_loops ty) l
530 | Otyp_var (_, id) -> id
533 let type_defined decl =
535 match decl.type_kind with
537 begin match decl.type_manifest with
539 | Some ty -> has_constr_row ty
541 | Type_variant _ | Type_record(_,_) ->
542 decl.type_private = Private
546 (fun ty (co,cn,ct) ->
547 if abstr || (repr ty).desc <> Tvar then (co,cn) else (true,true))
548 decl.type_params decl.type_variance
551 List.map2 (fun ty cocn -> type_param (tree_of_typexp false ty), cocn)
554 let tree_of_manifest ty1 =
555 match ty_manifest with
557 | Some ty -> Otyp_manifest (tree_of_typexp false ty, ty1)
559 let (name, args) = type_defined decl in
560 let constraints = tree_of_constraints params in
562 match decl.type_kind with
564 begin match ty_manifest with
565 | None -> (Otyp_abstract, Public)
567 tree_of_typexp false ty, decl.type_private
569 | Type_variant cstrs ->
570 tree_of_manifest (Otyp_sum (List.map tree_of_constructor cstrs)),
572 | Type_record(lbls, rep) ->
573 tree_of_manifest (Otyp_record (List.map tree_of_label lbls)),
576 (name, args, ty, priv, constraints)
578 and tree_of_constructor (name, args) =
579 (name, tree_of_typlist false args)
581 and tree_of_label (name, mut, arg) =
582 (name, mut = Mutable, tree_of_typexp false arg)
584 let tree_of_type_declaration id decl rs =
585 Osig_type (tree_of_type_decl id decl, tree_of_rec rs)
587 let type_declaration id ppf decl =
588 !Oprint.out_sig_item ppf (tree_of_type_declaration id decl Trec_first)
590 (* Print an exception declaration *)
592 let tree_of_exception_declaration id decl =
593 reset_and_mark_loops_list decl;
594 let tyl = tree_of_typlist false decl in
595 Osig_exception (Ident.name id, tyl)
597 let exception_declaration id ppf decl =
598 !Oprint.out_sig_item ppf (tree_of_exception_declaration id decl)
600 (* Print a value declaration *)
602 let tree_of_value_description id decl =
603 let id = Ident.name id in
604 let ty = tree_of_type_scheme decl.val_type in
606 match decl.val_kind with
607 | Val_prim p -> Primitive.description_list p
610 Osig_value (id, ty, prims)
612 let value_description id ppf decl =
613 !Oprint.out_sig_item ppf (tree_of_value_description id decl)
615 (* Print a class type *)
617 let class_var sch ppf l (m, t) =
619 "@ @[<2>val %s%s :@ %a@]" (string_of_mutable m) l (typexp sch 0) t
621 let method_type (_, kind, ty) =
622 match field_kind_repr kind, repr ty with
623 Fpresent, {desc=Tpoly(ty, _)} -> ty
626 let tree_of_metho sch concrete csil (lab, kind, ty) =
627 if lab <> dummy_method then begin
628 let kind = field_kind_repr kind in
629 let priv = kind <> Fpresent in
630 let virt = not (Concr.mem lab concrete) in
631 let ty = method_type (lab, kind, ty) in
632 Ocsg_method (lab, priv, virt, tree_of_typexp sch ty) :: csil
636 let rec prepare_class_type params = function
637 | Tcty_constr (p, tyl, cty) ->
638 let sty = Ctype.self_type cty in
639 if List.memq (proxy sty) !visited_objects
640 || List.exists (fun ty -> (repr ty).desc <> Tvar) params
641 || List.exists (deep_occur sty) tyl
642 then prepare_class_type params cty
643 else List.iter mark_loops tyl
644 | Tcty_signature sign ->
645 let sty = repr sign.cty_self in
646 (* Self may have a name *)
647 let px = proxy sty in
648 if List.memq px !visited_objects then add_alias sty
649 else visited_objects := px :: !visited_objects;
651 Ctype.flatten_fields (Ctype.object_fields sign.cty_self)
653 List.iter (fun met -> mark_loops (method_type met)) fields;
654 Vars.iter (fun _ (_, _, ty) -> mark_loops ty) sign.cty_vars
655 | Tcty_fun (_, ty, cty) ->
657 prepare_class_type params cty
659 let rec tree_of_class_type sch params =
661 | Tcty_constr (p', tyl, cty) ->
662 let sty = Ctype.self_type cty in
663 if List.memq (proxy sty) !visited_objects
664 || List.exists (fun ty -> (repr ty).desc <> Tvar) params
666 tree_of_class_type sch params cty
668 Octy_constr (tree_of_path p', tree_of_typlist true tyl)
669 | Tcty_signature sign ->
670 let sty = repr sign.cty_self in
672 if is_aliased sty then
673 Some (Otyp_var (false, name_of_type (proxy sty)))
677 Ctype.flatten_fields (Ctype.object_fields sign.cty_self)
682 (fun csil (ty1, ty2) -> Ocsg_constraint (ty1, ty2) :: csil)
683 csil (tree_of_constraints params)
686 Vars.fold (fun l (m, v, t) all -> (l, m, v, t) :: all) sign.cty_vars []
688 (* Consequence of PR#3607: order of Map.fold has changed! *)
689 let all_vars = List.rev all_vars in
692 (fun csil (l, m, v, t) ->
693 Ocsg_value (l, m = Mutable, v = Virtual, tree_of_typexp sch t)
698 List.fold_left (tree_of_metho sch sign.cty_concr) csil fields
700 Octy_signature (self_ty, List.rev csil)
701 | Tcty_fun (l, ty, cty) ->
702 let lab = if !print_labels && l <> "" || is_optional l then l else "" in
704 if is_optional l then
705 match (repr ty).desc with
706 | Tconstr(path, [ty], _) when Path.same path Predef.path_option -> ty
707 | _ -> newconstr (Path.Pident(Ident.create "<hidden>")) []
709 let tr = tree_of_typexp sch ty in
710 Octy_fun (lab, tr, tree_of_class_type sch params cty)
712 let class_type ppf cty =
714 prepare_class_type [] cty;
715 !Oprint.out_class_type ppf (tree_of_class_type false [] cty)
717 let tree_of_class_param param variance =
718 (match tree_of_typexp true param with
721 if (repr param).desc = Tvar then (true, true) else variance
723 let tree_of_class_params params =
724 let tyl = tree_of_typlist true params in
725 List.map (function Otyp_var (_, s) -> s | _ -> "?") tyl
727 let tree_of_class_declaration id cl rs =
728 let params = filter_params cl.cty_params in
731 List.iter add_alias params;
732 prepare_class_type params cl.cty_type;
733 let sty = self_type cl.cty_type in
734 List.iter mark_loops params;
736 List.iter check_name_of_type (List.map proxy params);
737 if is_aliased sty then check_name_of_type (proxy sty);
739 let vir_flag = cl.cty_new = None in
741 (vir_flag, Ident.name id,
742 List.map2 tree_of_class_param params cl.cty_variance,
743 tree_of_class_type true params cl.cty_type,
746 let class_declaration id ppf cl =
747 !Oprint.out_sig_item ppf (tree_of_class_declaration id cl Trec_first)
749 let tree_of_cltype_declaration id cl rs =
750 let params = List.map repr cl.clty_params in
753 List.iter add_alias params;
754 prepare_class_type params cl.clty_type;
755 let sty = self_type cl.clty_type in
756 List.iter mark_loops params;
758 List.iter check_name_of_type (List.map proxy params);
759 if is_aliased sty then check_name_of_type (proxy sty);
761 let sign = Ctype.signature_of_class_type cl.clty_type in
765 Ctype.flatten_fields (Ctype.object_fields sign.cty_self) in
768 not (lab = dummy_method || Concr.mem lab sign.cty_concr))
770 || Vars.fold (fun _ (_,vr,_) b -> vr = Virtual || b) sign.cty_vars false
774 (virt, Ident.name id,
775 List.map2 tree_of_class_param params cl.clty_variance,
776 tree_of_class_type true params cl.clty_type,
779 let cltype_declaration id ppf cl =
780 !Oprint.out_sig_item ppf (tree_of_cltype_declaration id cl Trec_first)
782 (* Print a module type *)
784 let rec tree_of_modtype = function
786 Omty_ident (tree_of_path p)
787 | Tmty_signature sg ->
788 Omty_signature (tree_of_signature sg)
789 | Tmty_functor(param, ty_arg, ty_res) ->
791 (Ident.name param, tree_of_modtype ty_arg, tree_of_modtype ty_res)
793 and tree_of_signature = function
795 | Tsig_value(id, decl) :: rem ->
796 tree_of_value_description id decl :: tree_of_signature rem
797 | Tsig_type(id, _, _) :: rem when is_row_name (Ident.name id) ->
798 tree_of_signature rem
799 | Tsig_type(id, decl, rs) :: rem ->
800 Osig_type(tree_of_type_decl id decl, tree_of_rec rs) ::
801 tree_of_signature rem
802 | Tsig_exception(id, decl) :: rem ->
803 tree_of_exception_declaration id decl :: tree_of_signature rem
804 | Tsig_module(id, mty, rs) :: rem ->
805 Osig_module (Ident.name id, tree_of_modtype mty, tree_of_rec rs) ::
806 tree_of_signature rem
807 | Tsig_modtype(id, decl) :: rem ->
808 tree_of_modtype_declaration id decl :: tree_of_signature rem
809 | Tsig_class(id, decl, rs) :: ctydecl :: tydecl1 :: tydecl2 :: rem ->
810 tree_of_class_declaration id decl rs :: tree_of_signature rem
811 | Tsig_cltype(id, decl, rs) :: tydecl1 :: tydecl2 :: rem ->
812 tree_of_cltype_declaration id decl rs :: tree_of_signature rem
816 and tree_of_modtype_declaration id decl =
819 | Tmodtype_abstract -> Omty_abstract
820 | Tmodtype_manifest mty -> tree_of_modtype mty
822 Osig_modtype (Ident.name id, mty)
824 let tree_of_module id mty rs =
825 Osig_module (Ident.name id, tree_of_modtype mty, tree_of_rec rs)
827 let modtype ppf mty = !Oprint.out_module_type ppf (tree_of_modtype mty)
828 let modtype_declaration id ppf decl =
829 !Oprint.out_sig_item ppf (tree_of_modtype_declaration id decl)
831 (* Print a signature body (used by -i when compiling a .ml) *)
833 let print_signature ppf tree =
834 fprintf ppf "@[<v>%a@]" !Oprint.out_signature tree
836 let signature ppf sg =
837 fprintf ppf "%a" print_signature (tree_of_signature sg)
839 (* Print an unification error *)
841 let type_expansion t ppf t' =
842 if t == t' then type_expr ppf t else
843 let t' = if proxy t == proxy t' then unalias t' else t' in
844 fprintf ppf "@[<2>%a@ =@ %a@]" type_expr t type_expr t'
846 let rec trace fst txt ppf = function
847 | (t1, t1') :: (t2, t2') :: rem ->
848 if not fst then fprintf ppf "@,";
849 fprintf ppf "@[Type@;<1 2>%a@ %s@;<1 2>%a@] %a"
850 (type_expansion t1) t1' txt (type_expansion t2) t2'
851 (trace false txt) rem
854 let rec filter_trace = function
855 | (t1, t1') :: (t2, t2') :: rem ->
856 let rem' = filter_trace rem in
857 if t1 == t1' && t2 == t2'
859 else (t1, t1') :: (t2, t2') :: rem'
862 (* Hide variant name and var, to force printing the expanded type *)
863 let hide_variant_name t =
865 | {desc = Tvariant row} as t when (row_repr row).row_name <> None ->
867 (Tvariant {(row_repr row) with row_name = None;
868 row_more = newty2 (row_more row).level Tvar})
871 let prepare_expansion (t, t') =
872 let t' = hide_variant_name t' in
873 mark_loops t; if t != t' then mark_loops t';
876 let may_prepare_expansion compact (t, t') =
877 match (repr t').desc with
878 Tvariant _ | Tobject _ when compact ->
880 | _ -> prepare_expansion (t, t')
882 let print_tags ppf fields =
883 match fields with [] -> ()
884 | (t, _) :: fields ->
886 List.iter (fun (t, _) -> fprintf ppf ",@ `%s" t) fields
888 let has_explanation unif t3 t4 =
889 match t3.desc, t4.desc with
890 Tfield _, _ | _, Tfield _
891 | Tunivar, Tvar | Tvar, Tunivar
892 | Tvariant _, Tvariant _ -> true
893 | Tconstr (p, _, _), Tvar | Tvar, Tconstr (p, _, _) ->
894 unif && min t3.level t4.level < Path.binding_time p
897 let rec mismatch unif = function
898 (_, t) :: (_, t') :: rem ->
899 begin match mismatch unif rem with
902 if has_explanation unif t t' then Some(t,t') else None
907 let explanation unif t3 t4 ppf =
908 match t3.desc, t4.desc with
909 | Tfield _, Tvar | Tvar, Tfield _ ->
910 fprintf ppf "@,Self type cannot escape its class"
911 | Tconstr (p, _, _), Tvar
912 when unif && t4.level < Path.binding_time p ->
914 "@,@[The type constructor@;<1 2>%a@ would escape its scope@]"
916 | Tvar, Tconstr (p, _, _)
917 when unif && t3.level < Path.binding_time p ->
919 "@,@[The type constructor@;<1 2>%a@ would escape its scope@]"
921 | Tvar, Tunivar | Tunivar, Tvar ->
922 fprintf ppf "@,The universal variable %a would escape its scope"
923 type_expr (if t3.desc = Tunivar then t3 else t4)
924 | Tfield (lab, _, _, _), _
925 | _, Tfield (lab, _, _, _) when lab = dummy_method ->
927 "@,Self type cannot be unified with a closed object type"
928 | Tfield (l, _, _, _), Tfield (l', _, _, _) when l = l' ->
929 fprintf ppf "@,Types for method %s are incompatible" l
930 | _, Tfield (l, _, _, _) ->
932 "@,@[The first object type has no method %s@]" l
933 | Tfield (l, _, _, _), _ ->
935 "@,@[The second object type has no method %s@]" l
936 | Tvariant row1, Tvariant row2 ->
937 let row1 = row_repr row1 and row2 = row_repr row2 in
939 row1.row_fields, row1.row_closed, row2.row_fields, row2.row_closed with
940 | [], true, [], true ->
941 fprintf ppf "@,These two variant types have no intersection"
942 | [], true, fields, _ ->
944 "@,@[The first variant type does not allow tag(s)@ @[<hov>%a@]@]"
946 | fields, _, [], true ->
948 "@,@[The second variant type does not allow tag(s)@ @[<hov>%a@]@]"
950 | [l1,_], true, [l2,_], true when l1 = l2 ->
951 fprintf ppf "@,Types for tag `%s are incompatible" l1
956 let explanation unif mis ppf =
959 | Some (t3, t4) -> explanation unif t3 t4 ppf
961 let unification_error unif tr txt1 ppf txt2 =
963 let tr = List.map (fun (t, t') -> (t, hide_variant_name t')) tr in
964 let mis = mismatch unif tr in
966 | [] | _ :: [] -> assert false
969 let tr = filter_trace tr in
970 let t1, t1' = may_prepare_expansion (tr = []) t1
971 and t2, t2' = may_prepare_expansion (tr = []) t2 in
972 print_labels := not !Clflags.classic;
973 let tr = List.map prepare_expansion tr in
980 txt1 (type_expansion t1) t1'
981 txt2 (type_expansion t2) t2'
982 (trace false "is not compatible with type") tr
983 (explanation unif mis);
986 print_labels := true;
989 let report_unification_error ppf tr txt1 txt2 =
990 unification_error true tr txt1 ppf txt2;;
992 let trace fst txt ppf tr =
993 print_labels := not !Clflags.classic;
996 if fst then trace fst txt ppf (t1 :: t2 :: filter_trace tr')
997 else trace fst txt ppf (filter_trace tr);
1001 print_labels := true;
1004 let report_subtyping_error ppf tr1 txt1 tr2 =
1006 let tr1 = List.map prepare_expansion tr1
1007 and tr2 = List.map prepare_expansion tr2 in
1008 trace true txt1 ppf tr1;
1009 if tr2 = [] then () else
1010 let mis = mismatch true tr2 in
1011 trace false "is not compatible with type" ppf tr2;
1012 explanation true mis ppf