diff options
Diffstat (limited to 'typing/typeclass.ml')
-rw-r--r-- | typing/typeclass.ml | 126 |
1 files changed, 76 insertions, 50 deletions
diff --git a/typing/typeclass.ml b/typing/typeclass.ml index a0f9dd64ec..7301b1f9c6 100644 --- a/typing/typeclass.ml +++ b/typing/typeclass.ml @@ -88,9 +88,10 @@ let rec generalize_class_type = Tcty_constr (_, params, cty) -> List.iter Ctype.generalize params; generalize_class_type cty - | Tcty_signature {cty_self = sty; cty_vars = vars } -> + | Tcty_signature {cty_self = sty; cty_vars = vars; cty_inher = inher} -> Ctype.generalize sty; - Vars.iter (fun _ (_, ty) -> Ctype.generalize ty) vars + Vars.iter (fun _ (_, ty) -> Ctype.generalize ty) vars; + List.iter (fun (_,tl) -> List.iter Ctype.generalize tl) inher | Tcty_fun (_, ty, cty) -> Ctype.generalize ty; generalize_class_type cty @@ -172,7 +173,9 @@ let rec limited_generalize rv = | Tcty_signature sign -> Ctype.limited_generalize rv sign.cty_self; Vars.iter (fun _ (_, ty) -> Ctype.limited_generalize rv ty) - sign.cty_vars + sign.cty_vars; + List.iter (fun (_, tl) -> List.iter (Ctype.limited_generalize rv) tl) + sign.cty_inher | Tcty_fun (_, ty, cty) -> Ctype.limited_generalize rv ty; limited_generalize rv cty @@ -272,10 +275,15 @@ let make_method cl_num expr = (*******************************) -let rec class_type_field env self_type meths (val_sig, concr_meths) = +let rec class_type_field env self_type meths (val_sig, concr_meths, inher) = function Pctf_inher sparent -> let parent = class_type env sparent in + let inher = + match parent with + Tcty_constr (p, tl, _) -> (p, tl) :: inher + | _ -> inher + in let (cl_sig, concr_meths, _) = inheritance self_type env concr_meths Concr.empty sparent.pcty_loc parent @@ -285,7 +293,7 @@ let rec class_type_field env self_type meths (val_sig, concr_meths) = (fun lab (mut, ty) val_sig -> Vars.add lab (mut, ty) val_sig) cl_sig.cty_vars val_sig in - (val_sig, concr_meths) + (val_sig, concr_meths, inher) | Pctf_val (lab, mut, sty_opt, loc) -> let (mut, ty) = @@ -299,19 +307,19 @@ let rec class_type_field env self_type meths (val_sig, concr_meths) = | Some sty -> mut, transl_simple_type env false sty in - (Vars.add lab (mut, ty) val_sig, concr_meths) + (Vars.add lab (mut, ty) val_sig, concr_meths, inher) | Pctf_virt (lab, priv, sty, loc) -> declare_method env meths self_type lab priv sty loc; - (val_sig, concr_meths) + (val_sig, concr_meths, inher) | Pctf_meth (lab, priv, sty, loc) -> declare_method env meths self_type lab priv sty loc; - (val_sig, Concr.add lab concr_meths) + (val_sig, Concr.add lab concr_meths, inher) | Pctf_cstr (sty, sty', loc) -> type_constraint env sty sty' loc; - (val_sig, concr_meths) + (val_sig, concr_meths, inher) and class_signature env sty sign = let meths = ref Meths.empty in @@ -328,15 +336,16 @@ and class_signature env sty sign = end; (* Class type fields *) - let (val_sig, concr_meths) = + let (val_sig, concr_meths, inher) = List.fold_left (class_type_field env self_type meths) - (Vars.empty, Concr.empty) + (Vars.empty, Concr.empty, []) sign in {cty_self = self_type; cty_vars = val_sig; - cty_concr = concr_meths } + cty_concr = concr_meths; + cty_inher = inher} and class_type env scty = match scty.pcty_desc with @@ -350,7 +359,6 @@ and class_type env scty = let (params, clty) = Ctype.instance_class decl.clty_params decl.clty_type in - let sty = Ctype.self_type clty in if List.length params <> List.length styl then raise(Error(scty.pcty_loc, Parameter_arity_mismatch (lid, List.length params, @@ -376,10 +384,16 @@ and class_type env scty = module StringSet = Set.Make(struct type t = string let compare = compare end) let rec class_field cl_num self_type meths vars - (val_env, met_env, par_env, fields, concr_meths, warn_meths, inh_vals) = + (val_env, met_env, par_env, fields, concr_meths, warn_meths, + inh_vals, inher) = function Pcf_inher (sparent, super) -> let parent = class_expr cl_num val_env par_env sparent in + let inher = + match parent.cl_type with + Tcty_constr (p, tl, _) -> (p, tl) :: inher + | _ -> inher + in let (cl_sig, concr_meths, warn_meths) = inheritance self_type val_env concr_meths warn_meths sparent.pcl_loc parent.cl_type @@ -417,7 +431,7 @@ let rec class_field cl_num self_type meths vars in (val_env, met_env, par_env, lazy(Cf_inher (parent, inh_vars, inh_meths))::fields, - concr_meths, warn_meths, inh_vals) + concr_meths, warn_meths, inh_vals, inher) | Pcf_val (lab, mut, sexp, loc) -> if StringSet.mem lab inh_vals then @@ -435,12 +449,13 @@ let rec class_field cl_num self_type meths vars enter_val cl_num vars lab mut exp.exp_type val_env met_env par_env in (val_env, met_env, par_env, lazy(Cf_val (lab, id, exp)) :: fields, - concr_meths, warn_meths, inh_vals) + concr_meths, warn_meths, inh_vals, inher) | Pcf_virt (lab, priv, sty, loc) -> virtual_method val_env meths self_type lab priv sty loc; let warn_meths = Concr.remove lab warn_meths in - (val_env, met_env, par_env, fields, concr_meths, warn_meths, inh_vals) + (val_env, met_env, par_env, fields, concr_meths, warn_meths, + inh_vals, inher) | Pcf_meth (lab, priv, expr, loc) -> let (_, ty) = @@ -483,11 +498,12 @@ let rec class_field cl_num self_type meths vars Cf_meth (lab, texp) end in (val_env, met_env, par_env, field::fields, - Concr.add lab concr_meths, Concr.add lab warn_meths, inh_vals) + Concr.add lab concr_meths, Concr.add lab warn_meths, inh_vals, inher) | Pcf_cstr (sty, sty', loc) -> type_constraint val_env sty sty' loc; - (val_env, met_env, par_env, fields, concr_meths, warn_meths, inh_vals) + (val_env, met_env, par_env, fields, concr_meths, warn_meths, + inh_vals, inher) | Pcf_let (rec_flag, sdefs, loc) -> let (defs, val_env) = @@ -517,7 +533,7 @@ let rec class_field cl_num self_type meths vars ([], met_env, par_env) in (val_env, met_env, par_env, lazy(Cf_let(rec_flag, defs, vals))::fields, - concr_meths, warn_meths, inh_vals) + concr_meths, warn_meths, inh_vals, inher) | Pcf_init expr -> let expr = make_method cl_num expr in @@ -534,22 +550,24 @@ let rec class_field cl_num self_type meths vars Cf_init texp end in (val_env, met_env, par_env, field::fields, - concr_meths, warn_meths, inh_vals) + concr_meths, warn_meths, inh_vals, inher) and class_structure cl_num final val_env met_env loc (spat, str) = (* Environment for substructures *) let par_env = met_env in - (* Private self type more method access, with a dummy method preventing - it from being closed/escaped. *) + (* Self type, with a dummy method preventing it from being closed/escaped. *) let self_type = Ctype.newvar () in Ctype.unify val_env (Ctype.filter_method val_env dummy_method Private self_type) (Ctype.newty (Ttuple [])); + (* Private self is used for private method calls *) + let private_self = if final then Ctype.newvar () else self_type in + (* Self binder *) let (pat, meths, vars, val_env, meth_env, par_env) = - type_self_pattern cl_num self_type val_env met_env par_env spat + type_self_pattern cl_num private_self val_env met_env par_env spat in let public_self = pat.pat_type in @@ -568,30 +586,33 @@ and class_structure cl_num final val_env met_env loc (spat, str) = (* Copy known information to still empty self_type *) List.iter (fun (lab,kind,ty) -> + let k = + if Btype.field_kind_repr kind = Fpresent then Public else Private in try Ctype.unify val_env ty - (Ctype.filter_method val_env lab Public self_type) + (Ctype.filter_method val_env lab k self_type) with _ -> assert false) (get_methods public_self) end; (* Typing of class fields *) - let (_, _, _, fields, concr_meths, _, _) = + let (_, _, _, fields, concr_meths, _, _, inher) = List.fold_left (class_field cl_num self_type meths vars) (val_env, meth_env, par_env, [], Concr.empty, Concr.empty, - StringSet.empty) + StringSet.empty, []) str in Ctype.unify val_env self_type (Ctype.newvar ()); let sign = {cty_self = public_self; cty_vars = Vars.map (function (id, mut, ty) -> (mut, ty)) !vars; - cty_concr = concr_meths } in + cty_concr = concr_meths; + cty_inher = inher} in let methods = get_methods self_type in let priv_meths = List.filter (fun (_,kind,_) -> Btype.field_kind_repr kind <> Fpresent) methods in if final then begin - (* Unify public_self and a copy of self_type. self_type will not + (* Unify private_self and a copy of self_type. self_type will not be modified after this point *) Ctype.close_object self_type; let mets = virtual_methods {sign with cty_self = self_type} in @@ -599,11 +620,18 @@ and class_structure cl_num final val_env met_env loc (spat, str) = let self_methods = List.fold_right (fun (lab,kind,ty) rem -> - if lab = dummy_method then rem else - Ctype.newty(Tfield(lab, Btype.copy_kind kind, ty, rem))) + if lab = dummy_method then + (* allow public self and private self to be unified *) + match Btype.field_kind_repr kind with + Fvar r -> Btype.set_kind r Fabsent; rem + | _ -> rem + else + Ctype.newty(Tfield(lab, Btype.copy_kind kind, ty, rem))) methods (Ctype.newty Tnil) in - begin try Ctype.unify val_env public_self - (Ctype.newty (Tobject(self_methods, ref None))) + begin try + Ctype.unify val_env private_self + (Ctype.newty (Tobject(self_methods, ref None))); + Ctype.unify val_env public_self self_type with Ctype.Unify trace -> raise(Error(loc, Final_self_clash trace)) end; end; @@ -625,12 +653,7 @@ and class_structure cl_num final val_env met_env loc (spat, str) = let l1 = names priv_meths and l2 = names pub_meths' in let added = List.filter (fun x -> List.mem x l1) l2 in if added <> [] then - Location.prerr_warning loc - (Warnings.Other - (String.concat " " - ("the following private methods were made public implicitly:\n " - :: added))); - + Location.prerr_warning loc (Warnings.Implicit_public_methods added); {cl_field = fields; cl_meths = meths}, sign and class_expr cl_num val_env met_env scl = @@ -735,7 +758,7 @@ and class_expr cl_num val_env met_env scl = Ctype.end_def (); if Btype.is_optional l && all_labeled cl.cl_type then Location.prerr_warning pat.pat_loc - (Warnings.Other "This optional argument cannot be erased"); + Warnings.Unerasable_optional_argument; rc {cl_desc = Tclass_fun (pat, pv, cl, partial); cl_loc = scl.pcl_loc; cl_type = Tcty_fun (l, Ctype.instance pat.pat_type, cl.cl_type); @@ -948,10 +971,12 @@ let rec initial_env define_class approx Tcty_signature { cty_self = Ctype.newvar (); cty_vars = Vars.empty; - cty_concr = Concr.empty } + cty_concr = Concr.empty; + cty_inher = [] } in let dummy_class = {cty_params = []; (* Dummy value *) + cty_variance = []; cty_type = dummy_cty; (* Dummy value *) cty_path = unbound_class; cty_new = @@ -962,6 +987,7 @@ let rec initial_env define_class approx let env = Env.add_cltype ty_id {clty_params = []; (* Dummy value *) + clty_variance = []; clty_type = dummy_cty; (* Dummy value *) clty_path = unbound_class} ( if define_class then @@ -1076,11 +1102,14 @@ let class_infos define_class kind end; (* Class and class type temporary definitions *) + let cty_variance = List.map (fun _ -> true, true) params in let cltydef = {clty_params = params; clty_type = class_body typ; + clty_variance = cty_variance; clty_path = Path.Pident obj_id} and clty = {cty_params = params; cty_type = typ; + cty_variance = cty_variance; cty_path = Path.Pident obj_id; cty_new = match cl.pci_virt with @@ -1112,9 +1141,11 @@ let class_infos define_class kind let (params', typ') = Ctype.instance_class params typ in let cltydef = {clty_params = params'; clty_type = class_body typ'; + clty_variance = cty_variance; clty_path = Path.Pident obj_id} and clty = {cty_params = params'; cty_type = typ'; + cty_variance = cty_variance; cty_path = Path.Pident obj_id; cty_new = match cl.pci_virt with @@ -1193,16 +1224,11 @@ let final_decl env define_class let extract_type_decls (id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr, arity, pub_meths, coe, expr, required) decls = - ((obj_id, obj_abbr), required) :: ((cl_id, cl_abbr), required) :: decls - -let rec compact = function - [] -> [] - | a :: b :: l -> (a,b) :: compact l - | _ -> fatal_error "Typeclass.compact" + (obj_id, obj_abbr, cl_abbr, clty, cltydef, required) :: decls let merge_type_decls - (id, clty, ty_id, cltydef, _obj_id, _obj_abbr, _cl_id, _cl_abbr, - arity, pub_meths, coe, expr, req) ((obj_id, obj_abbr), (cl_id, cl_abbr)) = + (id, _clty, ty_id, _cltydef, obj_id, _obj_abbr, cl_id, _cl_abbr, + arity, pub_meths, coe, expr, req) (obj_abbr, cl_abbr, clty, cltydef) = (id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr, arity, pub_meths, coe, expr) @@ -1268,7 +1294,7 @@ let type_classes define_class approx kind env cls = let res = List.rev_map (final_decl env define_class) res in let decls = List.fold_right extract_type_decls res [] in let decls = Typedecl.compute_variance_decls env decls in - let res = List.map2 merge_type_decls res (compact decls) in + let res = List.map2 merge_type_decls res decls in let env = List.fold_left (final_env define_class) env res in let res = List.map (check_coercions env) res in (res, env) |