diff options
author | Jacques Garrigue <garrigue at math.nagoya-u.ac.jp> | 2005-03-23 03:08:37 +0000 |
---|---|---|
committer | Jacques Garrigue <garrigue at math.nagoya-u.ac.jp> | 2005-03-23 03:08:37 +0000 |
commit | ef396b4e5a34ceb49efbbe39058746a68f5ab503 (patch) | |
tree | b614042ada9bbe9f4535eb7c897df7b57b182c63 | |
parent | 607872f95cfc5c76e3c9b48058755911b5f3b091 (diff) |
merge fixedtypes branch
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@6821 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r-- | camlp4/top/rprint.ml | 23 | ||||
-rw-r--r-- | ocamldoc/odoc_sig.ml | 2 | ||||
-rw-r--r-- | otherlibs/labltk/browser/searchpos.ml | 2 | ||||
-rw-r--r-- | otherlibs/labltk/browser/viewer.ml | 2 | ||||
-rw-r--r-- | otherlibs/labltk/support/Makefile.common | 2 | ||||
-rw-r--r-- | parsing/parser.mly | 10 | ||||
-rw-r--r-- | parsing/parsetree.mli | 1 | ||||
-rw-r--r-- | parsing/printast.ml | 2 | ||||
-rw-r--r-- | stdlib/sys.ml | 2 | ||||
-rw-r--r-- | tools/depend.ml | 2 | ||||
-rw-r--r-- | toplevel/toploop.ml | 4 | ||||
-rw-r--r-- | typing/btype.ml | 22 | ||||
-rw-r--r-- | typing/btype.mli | 4 | ||||
-rw-r--r-- | typing/ctype.ml | 49 | ||||
-rw-r--r-- | typing/includecore.ml | 62 | ||||
-rw-r--r-- | typing/includemod.ml | 13 | ||||
-rw-r--r-- | typing/oprint.ml | 29 | ||||
-rw-r--r-- | typing/outcometree.mli | 6 | ||||
-rw-r--r-- | typing/printtyp.ml | 54 | ||||
-rw-r--r-- | typing/subst.ml | 10 | ||||
-rw-r--r-- | typing/typecore.ml | 2 | ||||
-rw-r--r-- | typing/typedecl.ml | 68 | ||||
-rw-r--r-- | typing/typedecl.mli | 13 | ||||
-rw-r--r-- | typing/typemod.ml | 58 |
24 files changed, 337 insertions, 105 deletions
diff --git a/camlp4/top/rprint.ml b/camlp4/top/rprint.ml index 5b1e753f0..1270de354 100644 --- a/camlp4/top/rprint.ml +++ b/camlp4/top/rprint.ml @@ -180,21 +180,16 @@ and print_simple_out_type ppf = print_ident id | Otyp_manifest ty1 ty2 -> fprintf ppf "@[<2>%a ==@ %a@]" print_out_type ty1 print_out_type ty2 - | Otyp_sum constrs priv -> - fprintf ppf "@[<hv>%a[ %a ]@]" print_private priv + | Otyp_sum constrs -> + fprintf ppf "@[<hv>[ %a ]@]" (print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs - | Otyp_record lbls priv -> - fprintf ppf "@[<hv 2>%a{ %a }@]" print_private priv + | Otyp_record lbls -> + fprintf ppf "@[<hv 2>{ %a }@]" (print_list print_out_label (fun ppf -> fprintf ppf ";@ ")) lbls | Otyp_abstract -> fprintf ppf "'abstract" | Otyp_alias _ _ | Otyp_poly _ _ | Otyp_arrow _ _ _ | Otyp_constr _ [_ :: _] as ty -> fprintf ppf "@[<1>(%a)@]" print_out_type ty ] - and print_private ppf = - fun - [ Asttypes.Public -> () - | Asttypes.Private -> fprintf ppf "private " - ] in print_tkind ppf and print_out_constr ppf (name, tyl) = @@ -358,7 +353,7 @@ and print_out_sig_item ppf = fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name Toploop.print_out_type.val ty pr_prims prims ] -and print_out_type_decl kwd ppf (name, args, ty, constraints) = +and print_out_type_decl kwd ppf (name, args, ty, priv, constraints) = let constrain ppf (ty, ty') = fprintf ppf "@ @[<2>constraint %a =@ %a@]" Toploop.print_out_type.val ty Toploop.print_out_type.val ty' @@ -371,8 +366,14 @@ and print_out_type_decl kwd ppf (name, args, ty, constraints) = | _ -> fprintf ppf "%s@ %a" name (print_list type_parameter (fun ppf -> fprintf ppf "@ ")) args ] + and print_private ppf = + fun + [ Asttypes.Public -> () + | Asttypes.Private -> fprintf ppf " private" + ] in - fprintf ppf "@[<2>@[<hv 2>@[%s %t@] =@ %a@]%a@]" kwd type_defined + fprintf ppf "@[<2>@[<hv 2>@[%s %t@] =%a@ %a@]%a@]" kwd type_defined + print_private priv Toploop.print_out_type.val ty print_constraints constraints ; diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml index f3236137c..979579bbf 100644 --- a/ocamldoc/odoc_sig.ml +++ b/ocamldoc/odoc_sig.ml @@ -172,7 +172,7 @@ module Analyser = let name_comment_from_type_kind pos_end pos_limit tk = match tk with - Parsetree.Ptype_abstract -> + Parsetree.Ptype_abstract | Parsetree.Ptype_private -> (0, []) | Parsetree.Ptype_variant (cons_core_type_list_list, _) -> let rec f acc cons_core_type_list_list = diff --git a/otherlibs/labltk/browser/searchpos.ml b/otherlibs/labltk/browser/searchpos.ml index 0a17d04ac..307dfabef 100644 --- a/otherlibs/labltk/browser/searchpos.ml +++ b/otherlibs/labltk/browser/searchpos.ml @@ -166,7 +166,7 @@ let search_pos_type_decl td ~pos ~env = | None -> () end; let rec search_tkind = function - Ptype_abstract -> () + Ptype_abstract | Ptype_private -> () | Ptype_variant (dl, _) -> List.iter dl ~f:(fun (_, tl, _) -> List.iter tl ~f:(search_pos_type ~pos ~env)) diff --git a/otherlibs/labltk/browser/viewer.ml b/otherlibs/labltk/browser/viewer.ml index 6f8c8ca78..17c3ba584 100644 --- a/otherlibs/labltk/browser/viewer.ml +++ b/otherlibs/labltk/browser/viewer.ml @@ -400,7 +400,7 @@ class st_viewer ?(dir=Unix.getcwd()) ?on () = let label = Label.create tl ~anchor:`W ~padx:5 in let view = Frame.create tl in let buttons = Frame.create tl in - let all = Button.create buttons ~text:"Show all" ~padx:20 + let _all = Button.create buttons ~text:"Show all" ~padx:20 and close = Button.create buttons ~text:"Close all" ~command:close_all_views and detach = Button.create buttons ~text:"Detach" and edit = Button.create buttons ~text:"Impl" diff --git a/otherlibs/labltk/support/Makefile.common b/otherlibs/labltk/support/Makefile.common index 483013186..7e8bfadba 100644 --- a/otherlibs/labltk/support/Makefile.common +++ b/otherlibs/labltk/support/Makefile.common @@ -15,7 +15,7 @@ INSTALLDIR=$(LIBDIR)/$(LIBNAME) CAMLRUN=$(TOPDIR)/boot/ocamlrun CAMLC=$(TOPDIR)/ocamlcomp.sh CAMLOPT=$(TOPDIR)/ocamlcompopt.sh -CAMLCOMP=$(CAMLC) -c -warn-error Ay +CAMLCOMP=$(CAMLC) -c -warn-error A CAMLYACC=$(TOPDIR)/boot/ocamlyacc -v CAMLLEX=$(CAMLRUN) $(TOPDIR)/boot/ocamllex CAMLLIBR=$(CAMLC) -a diff --git a/parsing/parser.mly b/parsing/parser.mly index fd7f56f76..b9723e263 100644 --- a/parsing/parser.mly +++ b/parsing/parser.mly @@ -1165,6 +1165,8 @@ type_kind: { (Ptype_variant(List.rev $6, $4), Some $2) } | EQUAL core_type EQUAL private_flag LBRACE label_declarations opt_semi RBRACE { (Ptype_record(List.rev $6, $4), Some $2) } + | EQUAL PRIVATE core_type + { (Ptype_private, Some $3) } ; type_parameters: /*empty*/ { [] } @@ -1209,11 +1211,11 @@ with_constraints: | with_constraints AND with_constraint { $3 :: $1 } ; with_constraint: - TYPE type_parameters label_longident EQUAL core_type constraints + TYPE type_parameters label_longident with_type_binder core_type constraints { let params, variance = List.split $2 in ($3, Pwith_type {ptype_params = params; ptype_cstrs = List.rev $6; - ptype_kind = Ptype_abstract; + ptype_kind = $4; ptype_manifest = Some $5; ptype_variance = variance; ptype_loc = symbol_rloc()}) } @@ -1222,6 +1224,10 @@ with_constraint: | MODULE mod_longident EQUAL mod_ext_longident { ($2, Pwith_module $4) } ; +with_type_binder: + EQUAL { Ptype_abstract } + | EQUAL PRIVATE { Ptype_private } +; /* Polymorphic types */ diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli index f53ad2cbe..33a0e655b 100644 --- a/parsing/parsetree.mli +++ b/parsing/parsetree.mli @@ -133,6 +133,7 @@ and type_kind = | Ptype_variant of (string * core_type list * Location.t) list * private_flag | Ptype_record of (string * mutable_flag * core_type * Location.t) list * private_flag + | Ptype_private and exception_declaration = core_type list diff --git a/parsing/printast.ml b/parsing/printast.ml index db5f79dfa..986cb0f15 100644 --- a/parsing/printast.ml +++ b/parsing/printast.ml @@ -323,6 +323,8 @@ and type_kind i ppf x = | Ptype_record (l, priv) -> line i ppf "Ptype_record %a\n" fmt_private_flag priv; list (i+1) string_x_mutable_flag_x_core_type_x_location ppf l; + | Ptype_private -> + line i ppf "Ptype_private\n" and exception_declaration i ppf x = list i core_type ppf x diff --git a/stdlib/sys.ml b/stdlib/sys.ml index b1dcc9d57..4ddfd7995 100644 --- a/stdlib/sys.ml +++ b/stdlib/sys.ml @@ -78,4 +78,4 @@ let catch_break on = (* OCaml version string, must be in the format described in sys.mli. *) -let ocaml_version = "3.09+dev17 (2005-03-04)";; +let ocaml_version = "3.09+dev18 (2005-03-23)";; diff --git a/tools/depend.ml b/tools/depend.ml index e3b3e64f3..5d0ad6014 100644 --- a/tools/depend.ml +++ b/tools/depend.ml @@ -68,7 +68,7 @@ let add_type_declaration bv td = td.ptype_cstrs; add_opt add_type bv td.ptype_manifest; let rec add_tkind = function - Ptype_abstract -> () + Ptype_abstract | Ptype_private -> () | Ptype_variant (cstrs, _) -> List.iter (fun (c, args, _) -> List.iter (add_type bv) args) cstrs | Ptype_record (lbls, _) -> diff --git a/toplevel/toploop.ml b/toplevel/toploop.ml index a8bb58297..e0a51ddd2 100644 --- a/toplevel/toploop.ml +++ b/toplevel/toploop.ml @@ -148,7 +148,7 @@ let load_lambda ppf lam = (* Print the outcome of an evaluation *) -let pr_item env = function +let rec pr_item env = function | Tsig_value(id, decl) :: rem -> let tree = Printtyp.tree_of_value_description id decl in let valopt = @@ -162,6 +162,8 @@ let pr_item env = function Some v in Some (tree, valopt, rem) + | Tsig_type(id, _, _) :: rem when Btype.is_row_name (Ident.name id) -> + pr_item env rem | Tsig_type(id, decl, rs) :: rem -> let tree = Printtyp.tree_of_type_declaration id decl rs in Some (tree, None, rem) diff --git a/typing/btype.ml b/typing/btype.ml index 2e95c4d95..90e9d83b9 100644 --- a/typing/btype.ml +++ b/typing/btype.ml @@ -140,6 +140,26 @@ let proxy ty = in proxy_obj ty | _ -> ty0 +(**** Utilities for private types ****) + +let has_constr_row t = + match (repr t).desc with + Tobject(t,_) -> + let rec check_row t = + match (repr t).desc with + Tfield(_,_,_,t) -> check_row t + | Tconstr _ -> true + | _ -> false + in check_row t + | Tvariant row -> + (match row_more row with {desc=Tconstr _} -> true | _ -> false) + | _ -> + false + +let is_row_name s = + let l = String.length s in + if l < 4 then false else String.sub s (l-4) 4 = "#row" + (**********************************) (* Utilities for type traversal *) @@ -155,7 +175,7 @@ let rec iter_row f row = row.row_fields; match (repr row.row_more).desc with Tvariant row -> iter_row f row - | Tvar | Tnil | Tunivar | Tsubst _ -> + | Tvar | Tunivar | Tsubst _ | Tconstr _ -> Misc.may (fun (_,l) -> List.iter f l) row.row_name; List.iter f row.row_bound | _ -> assert false diff --git a/typing/btype.mli b/typing/btype.mli index 02a3cc1c1..251bc1ef5 100644 --- a/typing/btype.mli +++ b/typing/btype.mli @@ -59,6 +59,10 @@ val proxy: type_expr -> type_expr (* Return the proxy representative of the type: either itself or a row variable *) +(**** Utilities for private types ****) +val has_constr_row: type_expr -> bool +val is_row_name: string -> bool + (**** Utilities for type traversal ****) val iter_type_expr: (type_expr -> unit) -> type_expr -> unit diff --git a/typing/ctype.ml b/typing/ctype.ml index 35494cc5c..47402a39d 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -225,6 +225,7 @@ let rec opened_object ty = | Tfield(_, _, _, t) -> opened_object t | Tvar -> true | Tunivar -> true + | Tconstr _ -> true | _ -> false (**** Close an object ****) @@ -778,10 +779,15 @@ let rec copy ty = (* If the row variable is not generic, we must keep it *) let keep = more.level <> generic_level in let more' = - match more.desc with Tsubst ty -> ty - | _ -> + match more.desc with + Tsubst ty -> ty + | Tconstr _ -> + if keep then save_desc more more.desc; + copy more + | Tvar | Tunivar -> save_desc more more.desc; if keep then more else newty more.desc + | _ -> assert false in (* Register new type first for recursion *) more.desc <- Tsubst(newgenty(Ttuple[more';t])); @@ -931,7 +937,8 @@ let rec copy_sep fixed free bound visited ty = (* We shall really check the level on the row variable *) let keep = more.desc = Tvar && more.level <> generic_level in let more' = copy_rec more in - let row = copy_row copy_rec fixed row keep more' in + let fixed' = fixed && (repr more').desc = Tvar in + let row = copy_row copy_rec fixed' row keep more' in Tvariant row | Tpoly (t1, tl) -> let tl = List.map repr tl in @@ -2256,8 +2263,13 @@ and eqtype_list rename type_pairs subst env tl1 tl2 = List.iter2 (eqtype rename type_pairs subst env) tl1 tl2 and eqtype_fields rename type_pairs subst env ty1 ty2 = - let (fields1, rest1) = flatten_fields ty1 - and (fields2, rest2) = flatten_fields ty2 in + let (fields2, rest2) = flatten_fields ty2 in + (* Try expansion, needed when called from Includecore.type_manifest *) + try match try_expand_head env rest2 with + {desc=Tobject(ty2,_)} -> eqtype_fields rename type_pairs subst env ty1 ty2 + | _ -> raise Cannot_expand + with Cannot_expand -> + let (fields1, rest1) = flatten_fields ty1 in let (pairs, miss1, miss2) = associate_fields fields1 fields2 in eqtype rename type_pairs subst env rest1 rest2; if (miss1 <> []) || (miss2 <> []) then raise (Unify []); @@ -2278,6 +2290,11 @@ and eqtype_kind k1 k2 = | _ -> raise (Unify []) and eqtype_row rename type_pairs subst env row1 row2 = + (* Try expansion, needed when called from Includecore.type_manifest *) + try match try_expand_head env (row_more row2) with + {desc=Tvariant row2} -> eqtype_row rename type_pairs subst env row1 row2 + | _ -> raise Cannot_expand + with Cannot_expand -> let row1 = row_repr row1 and row2 = row_repr row2 in let r1, r2, pairs = merge_row_fields row1.row_fields row2.row_fields in if row1.row_closed <> row2.row_closed @@ -2646,6 +2663,9 @@ let find_cltype_for_path env p = end | None -> assert false +let has_constr_row' env t = + has_constr_row (expand_abbrev env t) + let rec build_subtype env visited loops posi level t = let t = repr t in match t.desc with @@ -2676,7 +2696,8 @@ let rec build_subtype env visited loops posi level t = let c = collect tlist' in if c > Unchanged then (newty (Ttuple (List.map fst tlist')), c) else (t, Unchanged) - | Tconstr(p, tl, abbrev) when level > 0 && generic_abbrev env p -> + | Tconstr(p, tl, abbrev) + when level > 0 && generic_abbrev env p && not (has_constr_row' env t) -> let t' = repr (expand_abbrev env t) in let level' = pred_expand level in begin try match t'.desc with @@ -2716,7 +2737,8 @@ let rec build_subtype env visited loops posi level t = let visited = t :: visited in begin try let decl = Env.find_type p env in - if level = 0 && generic_abbrev env p then warn := true; + if level = 0 && generic_abbrev env p && not (has_constr_row' env t) + then warn := true; let tl' = List.map2 (fun (co,cn,_) t -> @@ -2762,7 +2784,7 @@ let rec build_subtype env visited loops posi level t = fields in let c = collect fields in - if posi && short && c = Unchanged then (t, Unchanged) else + if short && c = Unchanged then (t, Unchanged) else let row = { row_fields = List.map fst fields; row_more = newvar(); row_bound = !bound; row_closed = posi; row_fixed = false; @@ -2848,9 +2870,11 @@ let rec subtype_rec env trace t1 t2 cstrs = subtype_list env trace tl1 tl2 cstrs | (Tconstr(p1, [], _), Tconstr(p2, [], _)) when Path.same p1 p2 -> cstrs - | (Tconstr(p1, tl1, abbrev1), _) when generic_abbrev env p1 -> + | (Tconstr(p1, tl1, abbrev1), _) + when generic_abbrev env p1 && not (has_constr_row' env t1) -> subtype_rec env trace (expand_abbrev env t1) t2 cstrs - | (_, Tconstr(p2, tl2, abbrev2)) when generic_abbrev env p2 -> + | (_, Tconstr(p2, tl2, abbrev2)) + when generic_abbrev env p2 && not (has_constr_row' env t2) -> subtype_rec env trace t1 (expand_abbrev env t2) cstrs | (Tconstr(p1, tl1, _), Tconstr(p2, tl2, _)) when Path.same p1 p2 -> begin try @@ -2878,7 +2902,8 @@ let rec subtype_rec env trace t1 t2 cstrs = | (Tvariant row1, Tvariant row2) -> let row1 = row_repr row1 and row2 = row_repr row2 in begin try - if not row1.row_closed then raise Exit; + if not row1.row_closed || row1.row_more.desc <> Tvar + || row2.row_more.desc <> Tvar then raise Exit; let r1, r2, pairs = merge_row_fields row1.row_fields row2.row_fields in if filter_row_fields false r1 <> [] then raise Exit; @@ -2965,6 +2990,8 @@ let rec unalias_object ty = newty2 ty.level ty.desc | Tunivar -> ty + | Tconstr _ -> + newty2 ty.level Tvar | _ -> assert false diff --git a/typing/includecore.ml b/typing/includecore.ml index 0c98acdd0..b81774b2c 100644 --- a/typing/includecore.ml +++ b/typing/includecore.ml @@ -40,6 +40,63 @@ let value_descriptions env vd1 vd2 = let private_flags priv1 priv2 = match (priv1, priv2) with (Private, Public) -> false | (_, _) -> true +(* Inclusion between manifest types (particularly for fixed types) *) + +let is_absrow env ty = + match ty.desc with + Tconstr(Pident id, _, _) -> + Btype.is_row_name (Ident.name id) && + begin match Ctype.expand_head env ty with + {desc=Tobject _|Tvariant _} -> true + | _ -> false + end + | _ -> false + +let type_manifest env ty1 params1 ty2 params2 = + let ty1' = Ctype.expand_head env ty1 and ty2' = Ctype.expand_head env ty2 in + match ty1'.desc, ty2'.desc with + Tvariant row1, Tvariant row2 when is_absrow env (Btype.row_more row2) -> + let row1 = Btype.row_repr row1 and row2 = Btype.row_repr row2 in + Ctype.equal env true (ty1::params1) (row2.row_more::params2) && + (match row1.row_more with {desc=Tvar|Tconstr _} -> true | _ -> false) && + let r1, r2, pairs = + Ctype.merge_row_fields row1.row_fields row2.row_fields in + (not row2.row_closed || + row1.row_closed && Ctype.filter_row_fields false r1 = []) && + List.for_all + (fun (_,f) -> match Btype.row_field_repr f with + Rabsent | Reither _ -> true | Rpresent _ -> false) + r2 && + let to_equal = ref (List.combine params1 params2) in + List.for_all + (fun (_, f1, f2) -> + match Btype.row_field_repr f1, Btype.row_field_repr f2 with + Rpresent(Some t1), + (Rpresent(Some t2) | Reither(false, [t2], _, _)) -> + to_equal := (t1,t2) :: !to_equal; true + | Rpresent None, (Rpresent None | Reither(true, [], _, _)) -> true + | Reither(c1,tl1,_,_), Reither(c2,tl2,_,_) + when List.length tl1 = List.length tl2 && c1 = c2 -> + to_equal := List.combine tl1 tl2 @ !to_equal; true + | Rabsent, (Reither _ | Rabsent) -> true + | _ -> false) + pairs && + let tl1, tl2 = List.split !to_equal in + Ctype.equal env true tl1 tl2 + | Tobject (fi1, _), Tobject (fi2, _) + when is_absrow env (snd(Ctype.flatten_fields fi2)) -> + let (fields2,rest2) = Ctype.flatten_fields fi2 in + Ctype.equal env true (ty1::params1) (rest2::params2) && + let (fields1,rest1) = Ctype.flatten_fields fi1 in + (match rest1 with {desc=Tnil|Tvar|Tconstr _} -> true | _ -> false) && + let pairs, miss1, miss2 = Ctype.associate_fields fields1 fields2 in + miss2 = [] && + let tl1, tl2 = + List.split (List.map (fun (_,_,t1,_,t2) -> t1, t2) pairs) in + Ctype.equal env true (params1 @ tl1) (params2 @ tl2) + | _ -> + Ctype.equal env true (ty1 :: params1) (ty2 :: params2) + (* Inclusion between type declarations *) let type_declarations env id decl1 decl2 = @@ -72,8 +129,7 @@ let type_declarations env id decl1 decl2 = (_, None) -> Ctype.equal env true decl1.type_params decl2.type_params | (Some ty1, Some ty2) -> - Ctype.equal env true (ty1::decl1.type_params) - (ty2::decl2.type_params) + type_manifest env ty1 decl1.type_params ty2 decl2.type_params | (None, Some ty2) -> let ty1 = Btype.newgenty (Tconstr(Pident id, decl2.type_params, ref Mnil)) @@ -81,11 +137,9 @@ let type_declarations env id decl1 decl2 = Ctype.equal env true decl1.type_params decl2.type_params && Ctype.equal env false [ty1] [ty2] end && - begin decl2.type_kind <> Type_abstract || decl2.type_manifest <> None || List.for_all2 (fun (co1,cn1,ct1) (co2,cn2,ct2) -> (not co1 || co2) && (not cn1 || cn2)) decl1.type_variance decl2.type_variance - end (* Inclusion between exception declarations *) diff --git a/typing/includemod.ml b/typing/includemod.ml index cf89fc9d7..810c555f2 100644 --- a/typing/includemod.ml +++ b/typing/includemod.ml @@ -206,6 +206,15 @@ and signatures env subst sig1 sig2 = end | item2 :: rem -> let (id2, name2) = item_ident_name item2 in + let name2, report = + match name2 with + Field_type s when let l = String.length s in + l >= 4 && String.sub s (l-4) 4 = "#row" -> + (* Do not report in case of failure, + as the main type will generate an error *) + Field_type (String.sub s 0 (String.length s - 4)), false + | _ -> name2, true + in begin try let (id1, item1, pos1) = Tbl.find name2 comps1 in let new_subst = @@ -222,7 +231,9 @@ and signatures env subst sig1 sig2 = pair_components new_subst ((item1, item2, pos1) :: paired) unpaired rem with Not_found -> - pair_components subst paired (Missing_field id2 :: unpaired) rem + let unpaired = + if report then Missing_field id2 :: unpaired else unpaired in + pair_components subst paired unpaired rem end in (* Do the pairing and checking, and return the final coercion *) simplify_structure_coercion (pair_components subst [] [] sig2) diff --git a/typing/oprint.ml b/typing/oprint.ml index 43ab1bdac..55178d89b 100644 --- a/typing/oprint.ml +++ b/typing/oprint.ml @@ -358,7 +358,7 @@ and print_out_sig_item ppf = fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name !out_type ty pr_prims prims -and print_out_type_decl kwd ppf (name, args, ty, constraints) = +and print_out_type_decl kwd ppf (name, args, ty, priv, constraints) = let print_constraints ppf params = List.iter (fun (ty1, ty2) -> @@ -390,24 +390,25 @@ and print_out_type_decl kwd ppf (name, args, ty, constraints) = let print_private ppf = function Asttypes.Private -> fprintf ppf "private " | Asttypes.Public -> () in - let rec print_out_tkind = function - | Otyp_abstract -> - fprintf ppf "@[<2>@[<hv 2>%t@]%a@]" print_name_args print_constraints - constraints - | Otyp_record (lbls, priv) -> - fprintf ppf "@[<2>@[<hv 2>%t = %a{%a@;<1 -2>}@]%a@]" print_name_args + let rec print_out_tkind ppf = function + | Otyp_abstract -> () + | Otyp_record lbls -> + fprintf ppf " = %a{%a@;<1 -2>}" print_private priv (print_list_init print_out_label (fun ppf -> fprintf ppf "@ ")) lbls - print_constraints constraints - | Otyp_sum (constrs, priv) -> - fprintf ppf "@[<2>@[<hv 2>%t =@;<1 2>%a%a@]%a@]" print_name_args + | Otyp_sum constrs -> + fprintf ppf " =@;<1 2>%a%a" print_private priv (print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs - print_constraints constraints | ty -> - fprintf ppf "@[<2>@[<hv 2>%t =@ %a@]%a@]" print_name_args !out_type - ty print_constraints constraints in - print_out_tkind ty + fprintf ppf " =@;<1 2>%a%a" + print_private priv + !out_type ty + in + fprintf ppf "@[<2>@[<hv 2>%t%a@]%a@]" + print_name_args + print_out_tkind ty + print_constraints constraints and print_out_constr ppf (name, tyl) = match tyl with [] -> fprintf ppf "%s" name diff --git a/typing/outcometree.mli b/typing/outcometree.mli index 6347befdc..c7031912b 100644 --- a/typing/outcometree.mli +++ b/typing/outcometree.mli @@ -52,9 +52,9 @@ type out_type = | Otyp_constr of out_ident * out_type list | Otyp_manifest of out_type * out_type | Otyp_object of (string * out_type) list * bool option - | Otyp_record of (string * bool * out_type) list * Asttypes.private_flag + | Otyp_record of (string * bool * out_type) list | Otyp_stuff of string - | Otyp_sum of (string * out_type list) list * Asttypes.private_flag + | Otyp_sum of (string * out_type list) list | Otyp_tuple of out_type list | Otyp_var of bool * string | Otyp_variant of @@ -91,7 +91,7 @@ and out_sig_item = | Osig_type of out_type_decl * out_rec_status | Osig_value of string * out_type * string list and out_type_decl = - string * (string * (bool * bool)) list * out_type * + string * (string * (bool * bool)) list * out_type * Asttypes.private_flag * (out_type * out_type) list and out_rec_status = | Orec_not diff --git a/typing/printtyp.ml b/typing/printtyp.ml index e6f800252..1edb8a115 100644 --- a/typing/printtyp.ml +++ b/typing/printtyp.ml @@ -437,6 +437,7 @@ and tree_of_typfields sch rest = function let rest = match rest.desc with | Tvar | Tunivar -> Some (is_non_gen sch rest) + | Tconstr _ -> Some false | Tnil -> None | _ -> fatal_error "typfields (1)" in @@ -531,26 +532,25 @@ let rec tree_of_type_decl id decl = | _ -> "?" in let type_defined decl = - if List.exists2 - (fun ty x -> x <> (true,true,true) && - (decl.type_kind = Type_abstract && ty_manifest = None - || (repr ty).desc <> Tvar)) + let abstr = + match decl.type_kind with + Type_abstract -> + begin match decl.type_manifest with + None -> true + | Some ty -> has_constr_row ty + end + | Type_variant(_,p) | Type_record(_,_,p) -> + p = Private + in + let vari = + List.map2 + (fun ty (co,cn,ct) -> + if abstr || (repr ty).desc <> Tvar then (co,cn) else (true,true)) decl.type_params decl.type_variance - then - let vari = List.map (fun (co,cn,ct) -> (co,cn)) decl.type_variance in - (Ident.name id, - List.combine - (List.map (fun ty -> type_param (tree_of_typexp false ty)) params) - vari) - else - let ty = - tree_of_typexp false - (Btype.newgenty (Tconstr(Pident id, params, ref Mnil))) - in - match ty with - | Otyp_constr (Oide_ident id, tyl) -> - (id, List.map (fun ty -> (type_param ty, (true, true))) tyl) - | _ -> ("?", []) + in + (Ident.name id, + List.map2 (fun ty cocn -> type_param (tree_of_typexp false ty), cocn) + params vari) in let tree_of_manifest ty1 = match ty_manifest with @@ -559,19 +559,21 @@ let rec tree_of_type_decl id decl = in let (name, args) = type_defined decl in let constraints = tree_of_constraints params in - let ty = + let ty, priv = match decl.type_kind with | Type_abstract -> begin match ty_manifest with - | None -> Otyp_abstract - | Some ty -> tree_of_typexp false ty + | None -> (Otyp_abstract, Public) + | Some ty -> + tree_of_typexp false ty, + (if has_constr_row ty then Private else Public) end | Type_variant(cstrs, priv) -> - tree_of_manifest (Otyp_sum (List.map tree_of_constructor cstrs, priv)) + tree_of_manifest (Otyp_sum (List.map tree_of_constructor cstrs)), priv | Type_record(lbls, rep, priv) -> - tree_of_manifest (Otyp_record (List.map tree_of_label lbls, priv)) + tree_of_manifest (Otyp_record (List.map tree_of_label lbls)), priv in - (name, args, ty, constraints) + (name, args, ty, priv, constraints) and tree_of_constructor (name, args) = (name, tree_of_typlist false args) @@ -785,6 +787,8 @@ and tree_of_signature = function | [] -> [] | Tsig_value(id, decl) :: rem -> tree_of_value_description id decl :: tree_of_signature rem + | Tsig_type(id, _, _) :: rem when is_row_name (Ident.name id) -> + tree_of_signature rem | Tsig_type(id, decl, rs) :: rem -> Osig_type(tree_of_type_decl id decl, tree_of_rec rs) :: tree_of_signature rem diff --git a/typing/subst.ml b/typing/subst.ml index 782179b6b..809393e3b 100644 --- a/typing/subst.ml +++ b/typing/subst.ml @@ -106,14 +106,18 @@ let rec typexp s ty = Tlink ty2 | _ -> let dup = - s.for_saving || more.level = generic_level || static_row row in + s.for_saving || more.level = generic_level || static_row row || + match more.desc with Tconstr _ -> true | _ -> false in (* Various cases for the row variable *) let more' = - match more.desc with Tsubst ty -> ty - | _ -> + match more.desc with + Tsubst ty -> ty + | Tconstr _ -> typexp s more + | Tunivar | Tvar -> save_desc more more.desc; if s.for_saving then newpersty more.desc else if dup && more.desc <> Tunivar then newgenvar () else more + | _ -> assert false in (* Register new type first for recursion *) more.desc <- Tsubst(newgenty(Ttuple[more';ty'])); diff --git a/typing/typecore.ml b/typing/typecore.ml index 869de177b..21e42eea8 100644 --- a/typing/typecore.ml +++ b/typing/typecore.ml @@ -818,6 +818,8 @@ let self_coercion = ref ([] : (Path.t * Location.t list ref) list) (* Typing of expressions *) let unify_exp env exp expected_ty = + (* Format.eprintf "@[%a@ %a@]@." Printtyp.raw_type_expr exp.exp_type + Printtyp.raw_type_expr expected_ty; *) try unify env exp.exp_type expected_ty with diff --git a/typing/typedecl.ml b/typing/typedecl.ml index 2567eb37f..bcf86e369 100644 --- a/typing/typedecl.ml +++ b/typing/typedecl.ml @@ -40,6 +40,7 @@ type error = | Not_an_exception of Longident.t | Bad_variance | Unavailable_type_constructor of Path.t + | Bad_fixed_type of string exception Error of Location.t * error @@ -76,6 +77,28 @@ let is_float env ty = {desc = Tconstr(p, _, _)} -> Path.same p Predef.path_float | _ -> false +(* Set the row variable in a fixed type *) +let set_fixed_row env loc p decl = + let tm = + match decl.type_manifest with + None -> assert false + | Some t -> Ctype.expand_head env t + in + let rv = + match tm.desc with + Tvariant row -> + tm.desc <- Tvariant {row with row_fixed = true}; + if Btype.static_row row then Btype.newgenty Tnil + else Btype.row_more row + | Tobject (ty, _) -> + snd (Ctype.flatten_fields ty) + | _ -> + raise (Error (loc, Bad_fixed_type "is not an object or variant")) + in + if rv.desc <> Tvar then + raise (Error (loc, Bad_fixed_type "has no row variable")); + rv.desc <- Tconstr (p, decl.type_params, ref Mnil) + (* Translate one type declaration *) module StringSet = @@ -104,7 +127,7 @@ let transl_declaration env (name, sdecl) id = type_arity = List.length params; type_kind = begin match sdecl.ptype_kind with - Ptype_abstract -> + Ptype_abstract | Ptype_private -> Type_abstract | Ptype_variant (cstrs, priv) -> let all_constrs = ref StringSet.empty in @@ -145,7 +168,8 @@ let transl_declaration env (name, sdecl) id = begin match sdecl.ptype_manifest with None -> None | Some sty -> - let ty = transl_simple_type env true sty in + let ty = + transl_simple_type env (sdecl.ptype_kind <> Ptype_private) sty in if Ctype.cyclic_abbrev env id ty then raise(Error(sdecl.ptype_loc, Recursive_abbrev name)); Some ty @@ -160,7 +184,12 @@ let transl_declaration env (name, sdecl) id = raise(Error(loc, Unconsistent_constraint tr))) cstrs; Ctype.end_def (); - + if sdecl.ptype_kind = Ptype_private then begin + let (p, _) = + try Env.lookup_type (Longident.Lident(Ident.name id ^ "#row")) env + with Not_found -> assert false in + set_fixed_row env sdecl.ptype_loc p decl + end; (id, decl) (* Generalize a type declaration *) @@ -218,7 +247,7 @@ let check_constraints env (_, sdecl) (_, decl) = | Type_variant (l, _) -> let rec find_pl = function Ptype_variant(pl, _) -> pl - | Ptype_record _ | Ptype_abstract -> assert false + | Ptype_record _ | Ptype_abstract | Ptype_private -> assert false in let pl = find_pl sdecl.ptype_kind in List.iter @@ -234,7 +263,7 @@ let check_constraints env (_, sdecl) (_, decl) = | Type_record (l, _, _) -> let rec find_pl = function Ptype_record(pl, _) -> pl - | Ptype_variant _ | Ptype_abstract -> assert false + | Ptype_variant _ | Ptype_abstract | Ptype_private -> assert false in let pl = find_pl sdecl.ptype_kind in let rec get_loc name = function @@ -464,7 +493,11 @@ let compute_variance_decl env sharp decl (required, loc) = end; let priv = match decl.type_kind with - Type_abstract -> Public + Type_abstract -> + begin match decl.type_manifest with + Some ty when not (Btype.has_constr_row ty) -> Public + | _ -> Private + end | Type_variant (_, priv) | Type_record (_, _, priv) -> priv in List.iter2 @@ -540,6 +573,18 @@ let compute_variance_decls env cldecls = (* Translate a set of mutually recursive type declarations *) let transl_type_decl env name_sdecl_list = + (* Add dummy types for fixed rows *) + let fixed_types = + List.filter (fun (_,sd) -> sd.ptype_kind = Ptype_private) name_sdecl_list + in + let name_sdecl_list = + List.map + (fun (name,sdecl) -> + name^"#row", + {sdecl with ptype_kind = Ptype_abstract; ptype_manifest = None}) + fixed_types + @ name_sdecl_list + in (* Create identifiers. *) let id_list = List.map (fun (name, _) -> Ident.create name) name_sdecl_list @@ -637,7 +682,7 @@ let transl_value_decl env valdecl = (* Translate a "with" constraint -- much simplified version of transl_type_decl. *) -let transl_with_constraint env sdecl = +let transl_with_constraint env row_path sdecl = reset_type_variables(); Ctype.begin_def(); let params = @@ -653,6 +698,7 @@ let transl_with_constraint env sdecl = with Ctype.Unify tr -> raise(Error(loc, Unconsistent_constraint tr))) sdecl.ptype_cstrs; + let no_row = sdecl.ptype_kind <> Ptype_private in let decl = { type_params = params; type_arity = List.length params; @@ -660,11 +706,15 @@ let transl_with_constraint env sdecl = type_manifest = begin match sdecl.ptype_manifest with None -> None - | Some sty -> Some(transl_simple_type env true sty) + | Some sty -> + Some(transl_simple_type env no_row sty) end; type_variance = []; } in + begin match row_path with None -> () + | Some p -> set_fixed_row env sdecl.ptype_loc p decl + end; if Ctype.closed_type_decl decl <> None then raise(Error(sdecl.ptype_loc, Unbound_type_var)); let decl = @@ -771,3 +821,5 @@ let report_error ppf = function "In this definition, expected parameter variances are not satisfied" | Unavailable_type_constructor p -> fprintf ppf "The definition of type %a@ is unavailable" Printtyp.path p + | Bad_fixed_type r -> + fprintf ppf "This fixed type %s" r diff --git a/typing/typedecl.mli b/typing/typedecl.mli index cab8dc52a..a29b402e1 100644 --- a/typing/typedecl.mli +++ b/typing/typedecl.mli @@ -18,23 +18,23 @@ open Types open Format val transl_type_decl: - Env.t -> (string * Parsetree.type_declaration) list -> + Env.t -> (string * Parsetree.type_declaration) list -> (Ident.t * type_declaration) list * Env.t val transl_exception: - Env.t -> Parsetree.exception_declaration -> exception_declaration + Env.t -> Parsetree.exception_declaration -> exception_declaration val transl_exn_rebind: - Env.t -> Location.t -> Longident.t -> Path.t * exception_declaration + Env.t -> Location.t -> Longident.t -> Path.t * exception_declaration val transl_value_decl: - Env.t -> Parsetree.value_description -> value_description + Env.t -> Parsetree.value_description -> value_description val transl_with_constraint: - Env.t -> Parsetree.type_declaration -> type_declaration + Env.t -> Path.t option -> Parsetree.type_declaration -> type_declaration val abstract_type_decl: int -> type_declaration val approx_type_decl: - Env.t -> (string * Parsetree.type_declaration) list -> + Env.t -> (string * Parsetree.type_declaration) list -> (Ident.t * type_declaration) list val check_recmod_typedecl: Env.t -> Location.t -> Ident.t list -> Path.t -> type_declaration -> unit @@ -65,6 +65,7 @@ type error = | Not_an_exception of Longident.t | Bad_variance | Unavailable_type_constructor of Path.t + | Bad_fixed_type of string exception Error of Location.t * error diff --git a/typing/typemod.ml b/typing/typemod.ml index 15c4c35c0..e63eb155c 100644 --- a/typing/typemod.ml +++ b/typing/typemod.ml @@ -68,16 +68,50 @@ let rm node = (* Merge one "with" constraint in a signature *) +let rec add_rec_types env = function + Tsig_type(id, decl, Trec_next) :: rem -> + add_rec_types (Env.add_type id decl env) rem + | _ -> env + +let check_type_decl env id row_id newdecl decl rs rem = + let env = Env.add_type id newdecl env in + let env = + match row_id with None -> env | Some id -> Env.add_type id newdecl env in + let env = if rs = Trec_not then env else add_rec_types env rem in + Includemod.type_declarations env id newdecl decl + let merge_constraint initial_env loc sg lid constr = - let rec merge env sg namelist = + let rec merge env sg namelist row_id = match (sg, namelist, constr) with ([], _, _) -> raise(Error(loc, With_no_component lid)) + | (Tsig_type(id, decl, rs) :: rem, [s], + Pwith_type ({ptype_kind = Ptype_private} as sdecl)) + when Ident.name id = s -> + let decl_row = + { type_params = + List.map (fun _ -> Btype.newgenvar()) sdecl.ptype_params; + type_arity = List.length sdecl.ptype_params; + type_kind = Type_abstract; + type_manifest = None; + type_variance = + List.map (fun (c,n) -> (c,n,n)) sdecl.ptype_variance } + and id_row = Ident.create (s^"#row") in + let initial_env = Env.add_type id_row decl_row initial_env in + let newdecl = Typedecl.transl_with_constraint + initial_env (Some(Pident id_row)) sdecl in + check_type_decl env id row_id newdecl decl rs rem; + let decl_row = {decl_row with type_params = newdecl.type_params} in + let rs' = if rs = Trec_first then Trec_not else rs in + Tsig_type(id_row, decl_row, rs') :: Tsig_type(id, newdecl, rs) :: rem | (Tsig_type(id, decl, rs) :: rem, [s], Pwith_type sdecl) when Ident.name id = s -> - let newdecl = Typedecl.transl_with_constraint initial_env sdecl in - Includemod.type_declarations env id newdecl decl; + let newdecl = Typedecl.transl_with_constraint initial_env None sdecl in + check_type_decl env id row_id newdecl decl rs rem; Tsig_type(id, newdecl, rs) :: rem + | (Tsig_type(id, decl, rs) :: rem, [s], Pwith_type sdecl) + when Ident.name id = s ^ "#row" -> + merge env rem namelist (Some id) | (Tsig_module(id, mty, rs) :: rem, [s], Pwith_module lid) when Ident.name id = s -> let (path, mty') = type_module_path initial_env loc lid in @@ -86,12 +120,12 @@ let merge_constraint initial_env loc sg lid constr = Tsig_module(id, newmty, rs) :: rem | (Tsig_module(id, mty, rs) :: rem, s :: namelist, _) when Ident.name id = s -> - let newsg = merge env (extract_sig env loc mty) namelist in + let newsg = merge env (extract_sig env loc mty) namelist None in Tsig_module(id, Tmty_signature newsg, rs) :: rem | (item :: rem, _, _) -> - item :: merge (Env.add_item item env) rem namelist in + item :: merge (Env.add_item item env) rem namelist row_id in try - merge initial_env sg (Longident.flatten lid) + merge initial_env sg (Longident.flatten lid) None with Includemod.Error explanation -> raise(Error(loc, With_mismatch(lid, explanation))) @@ -103,6 +137,12 @@ let map_rec fn decls rem = | [] -> rem | d1 :: dl -> fn Trec_first d1 :: map_end (fn Trec_next) dl rem +let rec map_rec' fn decls rem = + match decls with + | (id,_ as d1) :: dl when Btype.is_row_name (Ident.name id) -> + fn Trec_not d1 :: map_rec' fn dl rem + | _ -> map_rec fn decls rem + (* Auxiliary for translating recursively-defined module types. Return a module type that approximates the shape of the given module type AST. Retain only module, type, and module type @@ -138,7 +178,7 @@ let approx_modtype transl_mty init_env smty = | Psig_type sdecls -> let decls = Typedecl.approx_type_decl env sdecls in let rem = approx_sig env srem in - map_rec (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem + map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem | Psig_module(name, smty) -> let mty = approx_mty env smty in let (id, newenv) = Env.enter_module name mty env in @@ -272,7 +312,7 @@ and transl_signature env sg = sdecls; let (decls, newenv) = Typedecl.transl_type_decl env sdecls in let rem = transl_sig newenv srem in - map_rec (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem + map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls rem | Psig_exception(name, sarg) -> let arg = Typedecl.transl_exception env sarg in let (id, newenv) = Env.enter_exception name arg env in @@ -554,7 +594,7 @@ and type_structure anchor env sstr = enrich_type_decls anchor decls env newenv in let (str_rem, sig_rem, final_env) = type_struct newenv' srem in (Tstr_type decls :: str_rem, - map_rec (fun rs (id, info) -> Tsig_type(id, info, rs)) decls sig_rem, + map_rec' (fun rs (id, info) -> Tsig_type(id, info, rs)) decls sig_rem, final_env) | {pstr_desc = Pstr_exception(name, sarg)} :: srem -> let arg = Typedecl.transl_exception env sarg in |