Skip to content

Commit

Permalink
Internal type parameter changes (#11436)
Browse files Browse the repository at this point in the history
* use tclass equality instead of Type.t

* change type parameter handling

* fix gencommon a bit

* remove redundant name

* fix gencommon param cloning

* make sure lazies are resolved at some point
  • Loading branch information
Simn authored Dec 19, 2023
1 parent 45268f7 commit 541259e
Show file tree
Hide file tree
Showing 39 changed files with 279 additions and 341 deletions.
9 changes: 7 additions & 2 deletions src/codegen/codegen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,13 @@ let fix_override com c f fd =
(* Flash generates type parameters with a single constraint as that constraint type, so we
have to detect this case and change the variable (issue #2712). *)
begin match follow v.v_type with
| TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash ->
if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
| TInst({cl_kind = KTypeParameter ttp} as cp,_) when com.platform = Flash ->
begin match get_constraints ttp with
| [tc] ->
if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
| _ ->
()
end
| _ ->
()
end;
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/gencommon/castDetect.ml
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ let do_unsafe_cast gen from_t to_t e =
| _ -> raise Not_found
in
match gen.gfollow#run_f from_t, gen.gfollow#run_f to_t with
| TInst({ cl_kind = KTypeParameter tl },_), t2 when List.exists (fun t -> unifies t t2) tl ->
| TInst({ cl_kind = KTypeParameter ttp },_), t2 when List.exists (fun t -> unifies t t2) (get_constraints ttp) ->
mk_cast to_t (mk_cast t_dynamic e)
| from_t, to_t when gen.gspecial_needs_cast to_t from_t ->
mk_cast to_t e
Expand Down
15 changes: 4 additions & 11 deletions src/codegen/gencommon/closuresToClass.ml
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,7 @@ let rec get_type_params acc t =
get_type_params acc ( Abstract.get_underlying_type a pl)
| TAnon a ->
PMap.fold (fun cf acc ->
let params = List.map (fun tp -> match follow tp.ttp_type with
| TInst(c,_) -> c
| _ -> die "" __LOC__) cf.cf_params
in
let params = List.map (fun tp -> tp.ttp_class) cf.cf_params in
List.filter (fun t -> not (List.memq t params)) (get_type_params acc cf.cf_type)
) a.a_fields acc
| TType(_, [])
Expand Down Expand Up @@ -396,7 +393,7 @@ let configure gen ft =
in

(*let cltypes = List.map (fun cl -> (snd cl.cl_path, TInst(map_param cl, []) )) tparams in*)
let cltypes = List.map (fun cl -> mk_type_param (snd cl.cl_path) (TInst(cl, [])) None) tparams in
let cltypes = List.map (fun cl -> mk_type_param cl None None) tparams in

(* create a new class that extends abstract function class, with a ctor implementation that will setup all captured variables *)
let cfield = match gen.gcurrent_classfield with
Expand Down Expand Up @@ -613,14 +610,10 @@ let configure gen ft =

let monos = List.map (fun t -> apply_params types (List.map (fun _ -> t_dynamic) types) t) monos in

let same_cl t1 t2 = match follow t1, follow t2 with
| TInst(c,_), TInst(c2,_) -> c == c2
| _ -> false
in
let passoc = List.map2 (fun tp m -> tp.ttp_type,m) types monos in
let passoc = List.map2 (fun tp m -> tp.ttp_class,m) types monos in
let cltparams = List.map (fun tp ->
try
snd (List.find (fun (t2,_) -> same_cl tp.ttp_type t2) passoc)
snd (List.find (fun (t2,_) -> tp.ttp_class == t2) passoc)
with | Not_found -> tp.ttp_type) cls.cl_params
in
{ e with eexpr = TNew(cls, cltparams, List.rev captured) }
Expand Down
8 changes: 4 additions & 4 deletions src/codegen/gencommon/dynamicFieldAccess.ml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ let priority = solve_deps name [DAfter DynamicOperators.priority]
*)
let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) =
let is_nondynamic_tparam fexpr f = match follow fexpr.etype with
| TInst({ cl_kind = KTypeParameter(tl) }, _) ->
List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl
| TInst({ cl_kind = KTypeParameter(ttp) }, _) ->
List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) (get_constraints ttp)
| _ -> false
in

Expand All @@ -68,8 +68,8 @@ let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texp
(* class types *)
| TField(fexpr, f) when is_nondynamic_tparam fexpr f ->
(match follow fexpr.etype with
| TInst( ({ cl_kind = KTypeParameter(tl) } as tp_cl), tp_tl) ->
let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl) in
| TInst( ({ cl_kind = KTypeParameter(ttp) } as tp_cl), tp_tl) ->
let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) (get_constraints ttp)) in
{ e with eexpr = TField(mk_cast t (run fexpr), f) }
| _ -> Globals.die "" __LOC__)

Expand Down
4 changes: 2 additions & 2 deletions src/codegen/gencommon/enumToClass.ml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ struct
| _ -> ());
let c_types =
if handle_type_params then
List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
List.map clone_param en.e_params
else
[]
in
Expand All @@ -120,7 +120,7 @@ struct
| TFun(params,ret) ->
let dup_types =
if handle_type_params then
List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
List.map clone_param en.e_params
else
[]
in
Expand Down
7 changes: 5 additions & 2 deletions src/codegen/gencommon/gencommon.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1137,11 +1137,14 @@ let mk_class_field ?(static = false) name t public pos kind params =
(* this helper just duplicates the type parameter class, which is assumed that cl is. *)
(* This is so we can use class parameters on function parameters, without running the risk of name clash *)
(* between both *)
let map_param cl =
let clone_param ttp =
let cl = ttp.ttp_class in
let ret = mk_class cl.cl_module (fst cl.cl_path, snd cl.cl_path ^ "_c") cl.cl_pos null_pos in
ret.cl_implements <- cl.cl_implements;
ret.cl_kind <- cl.cl_kind;
ret
let ttp = mk_type_param ret ttp.ttp_default ttp.ttp_constraints in
ret.cl_kind <- KTypeParameter ttp;
ttp

let get_cl_t t =
match follow t with | TInst (cl,_) -> cl | _ -> die "" __LOC__
Expand Down
17 changes: 8 additions & 9 deletions src/codegen/gencommon/overloadingConstructor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,15 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
| false ->
let static_ctor_name = make_static_ctor_name cl in
(* create the static constructor *)
let ctor_types = List.map (fun tp -> {tp with ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
let ctor_types = List.map clone_param cl.cl_params in
let ctor_type_params = extract_param_types ctor_types in
List.iter (function {ttp_type=TInst(c,[])} -> (
match c.cl_kind with
| KTypeParameter (hd :: tail) ->
let before = hd :: tail in
let after = List.map (apply_params cl.cl_params ctor_type_params) (before) in
c.cl_kind <- KTypeParameter(after)
| _ -> ())
| _ -> ()) ctor_types;
List.iter (fun ttp -> match get_constraints ttp with
| [] ->
()
| before ->
let after = List.map (apply_params cl.cl_params ctor_type_params) before in
ttp.ttp_constraints <- Some (lazy after)
) ctor_types;
let me = alloc_var "__hx_this" (TInst(cl, extract_param_types ctor_types)) in
add_var_flag me VCaptured;

Expand Down
15 changes: 7 additions & 8 deletions src/codegen/gencommon/realTypeParams.ml
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,9 @@ let set_hxgeneric gen md =
if not ret then begin
match md with
| TClassDecl c ->
let set_hxgeneric tp = match follow tp.ttp_type with
| TInst(c,_) ->
c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta
| _ -> ()
let set_hxgeneric tp =
let c = tp.ttp_class in
c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta
in
List.iter set_hxgeneric c.cl_params;
let rec handle_field cf =
Expand Down Expand Up @@ -400,7 +399,7 @@ struct

let rec loop curcls params level reverse_params =
if (level <> 0 || (has_class_flag curcls CInterface) || (has_class_flag curcls CAbstract) ) && params <> [] && is_hxgeneric (TClassDecl curcls) then begin
let cparams = List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) curcls.cl_params in
let cparams = List.map clone_param curcls.cl_params in
let name = get_cast_name curcls in
if not (PMap.mem name cl.cl_fields) then begin
let reverse_params = List.map (apply_params curcls.cl_params params) reverse_params in
Expand Down Expand Up @@ -459,7 +458,7 @@ struct
let create_cast_cfield gen cl name =
reset_temps();
let basic = gen.gcon.basic in
let cparams = List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
let cparams = List.map clone_param cl.cl_params in
let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in
let params = extract_param_types cparams in

Expand Down Expand Up @@ -590,7 +589,7 @@ struct
let create_static_cast_cf gen iface cf =
let p = iface.cl_pos in
let basic = gen.gcon.basic in
let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cf.cf_params in
let cparams = List.map clone_param cf.cf_params in
let me_type = TInst(iface,[]) in
let cfield = mk_class_field ~static:true "__hx_cast" (TFun(["me",false,me_type], t_dynamic)) false iface.cl_pos (Method MethNormal) (cparams) in
let params = extract_param_types cparams in
Expand Down Expand Up @@ -637,7 +636,7 @@ struct
let implement_stub_cast cthis iface tl =
let name = get_cast_name iface in
if not (PMap.mem name cthis.cl_fields) then begin
let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) iface.cl_params in
let cparams = List.map clone_param iface.cl_params in
let field = mk_class_field name (TFun([],t_dynamic)) false iface.cl_pos (Method MethNormal) cparams in
let this = { eexpr = TConst TThis; etype = TInst(cthis, extract_param_types cthis.cl_params); epos = cthis.cl_pos } in
field.cf_expr <- Some {
Expand Down
14 changes: 4 additions & 10 deletions src/codegen/gencommon/renameTypeParameters.ml
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,16 @@ let run types =
end else found_types := PMap.add name true !found_types
in

let get_cls t =
match follow t with
| TInst(cl,_) -> cl
| _ -> Globals.die "" __LOC__
in

let iter_types tp =
let cls = get_cls tp.ttp_type in
let cls = tp.ttp_class in
let orig = cls.cl_path in
check_type (snd orig) (fun name -> cls.cl_path <- (fst orig, name))
in

let save_params save params =
List.fold_left (fun save tp ->
let cls = get_cls tp.ttp_type in
(cls.cl_path,tp.ttp_type) :: save) save params
let cls = tp.ttp_class in
(cls.cl_path,tp.ttp_class) :: save) save params
in

List.iter (function
Expand All @@ -82,7 +76,7 @@ let run types =
cl.cl_restore <- (fun () ->
res();
List.iter (fun (path,t) ->
let cls = get_cls t in
let cls = t in
cls.cl_path <- path) save
);
end
Expand Down
9 changes: 3 additions & 6 deletions src/codegen/overloads.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@ let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
| [],[] ->
true
| tp1 :: params1,tp2 :: params2 ->
let constraints_equal t1 t2 = match follow t1,follow t2 with
| TInst({cl_kind = KTypeParameter tl1},_),TInst({cl_kind = KTypeParameter tl2},_) ->
Ast.safe_for_all2 f_eq tl1 tl2
| _ ->
false
let constraints_equal ttp1 ttp2 =
Ast.safe_for_all2 f_eq (get_constraints ttp2) (get_constraints ttp2)
in
tp1.ttp_name = tp2.ttp_name && constraints_equal tp1.ttp_type tp2.ttp_type && loop params1 params2
tp1.ttp_name = tp2.ttp_name && constraints_equal tp1 tp2 && loop params1 params2
| [],_
| _,[] ->
false
Expand Down
7 changes: 4 additions & 3 deletions src/context/abstractCast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ let prepare_array_access_field ctx a pl cf p =
let monos = List.map (fun _ -> spawn_monomorph ctx p) cf.cf_params in
let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in
let check_constraints () =
List.iter2 (fun m tp -> match follow tp.ttp_type with
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
List.iter2 (fun m ttp -> match get_constraints ttp with
| [] ->
()
| constr ->
List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr
| _ -> ()
) monos cf.cf_params;
in
let get_ta() =
Expand Down
11 changes: 6 additions & 5 deletions src/context/display/displayFields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ let collect_static_extensions ctx items e p =
| TFun((_,_,t) :: args, ret) ->
begin try
let e = TyperBase.unify_static_extension ctx {e with etype = dup e.etype} t p in
List.iter2 (fun m tp -> match follow tp.ttp_type with
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
List.iter2 (fun m ttp -> match get_constraints ttp with
| [] ->
()
| constr ->
List.iter (fun tc -> unify_raise m (map tc) e.epos) constr
| _ -> ()
) monos f.cf_params;
if not (can_access ctx c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then
acc
Expand Down Expand Up @@ -157,9 +158,9 @@ let collect ctx e_ast e dk with_type p =
List.fold_left fold_constraints items l
in
fold_constraints items (Monomorph.classify_down_constraints m)
| TInst ({cl_kind = KTypeParameter tl},_) ->
| TInst ({cl_kind = KTypeParameter ttp},_) ->
(* Type parameters can access the fields of their constraints *)
List.fold_left (fun acc t -> loop acc t) items tl
List.fold_left (fun acc t -> loop acc t) items (get_constraints ttp)
| TInst(c0,tl) ->
(* For classes, browse the hierarchy *)
let fields = TClass.get_all_fields c0 tl in
Expand Down
6 changes: 2 additions & 4 deletions src/context/display/displayToplevel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,8 @@ let collect ctx tk with_type sort =
end;

(* type params *)
List.iter (fun tp -> match follow tp.ttp_type with
| TInst(c,_) ->
add (make_ci_type_param c (tpair tp.ttp_type)) (Some (snd c.cl_path))
| _ -> die "" __LOC__
List.iter (fun tp ->
add (make_ci_type_param tp.ttp_class (tpair tp.ttp_type)) (Some (snd tp.ttp_class.cl_path))
) ctx.type_params;

(* module types *)
Expand Down
4 changes: 2 additions & 2 deletions src/context/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,8 @@ let can_access ctx c cf stat =
loop c
(* access is also allowed of we access a type parameter which is constrained to our (base) class *)
|| (match c.cl_kind with
| KTypeParameter tl ->
List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) tl
| KTypeParameter ttp ->
List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) (get_constraints ttp)
| _ -> false)
|| (Meta.has Meta.PrivateAccess ctx.meta)

Expand Down
14 changes: 6 additions & 8 deletions src/core/display/completionItem.ml
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,14 @@ module CompletionModuleType = struct
in
let is_extern,is_final,is_abstract,kind,ctor = ctor_info mt in
let infos = t_infos mt in
let convert_type_param tp = match follow tp.ttp_type with
| TInst(c,_) -> {
tp_name = tp.ttp_name,null_pos;
let convert_type_param ttp =
{
tp_name = ttp.ttp_name,null_pos;
tp_params = [];
tp_constraints = None; (* TODO? *)
tp_default = None; (* TODO? *)
tp_meta = c.cl_meta
tp_meta = ttp.ttp_class.cl_meta
}
| _ ->
die "" __LOC__
in
{
pack = fst infos.mt_path;
Expand Down Expand Up @@ -784,11 +782,11 @@ let to_json ctx index item =
| ITExpression e -> "Expression",generate_texpr ctx e
| ITTypeParameter c ->
begin match c.cl_kind with
| KTypeParameter tl ->
| KTypeParameter ttp ->
"TypeParameter",jobject [
"name",jstring (snd c.cl_path);
"meta",generate_metadata ctx c.cl_meta;
"constraints",jlist (generate_type ctx) tl;
"constraints",jlist (generate_type ctx) (get_constraints ttp);
]
| _ -> die "" __LOC__
end
Expand Down
14 changes: 5 additions & 9 deletions src/core/json/genjson.ml
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,11 @@ and generate_type_path_with_params ctx mpath tpath tl meta =

(* type parameter *)

and generate_type_parameter ctx tp =
let generate_constraints () = match follow tp.ttp_type with
| TInst({cl_kind = KTypeParameter tl},_) -> generate_types ctx tl
| _ -> die "" __LOC__
in
and generate_type_parameter ctx ttp =
jobject [
"name",jstring tp.ttp_name;
"constraints",generate_constraints ();
"defaultType",jopt (generate_type ctx) tp.ttp_default;
"name",jstring ttp.ttp_name;
"constraints",generate_types ctx (get_constraints ttp);
"defaultType",jopt (generate_type ctx) ttp.ttp_default;
]

(* texpr *)
Expand Down Expand Up @@ -602,7 +598,7 @@ let generate_class ctx c =
let generate_class_kind ck =
let ctor,args = match ck with
| KNormal -> "KNormal",None
| KTypeParameter tl -> "KTypeParameter",Some (generate_types ctx tl)
| KTypeParameter ttp -> "KTypeParameter",Some (generate_types ctx (get_constraints ttp))
| KExpr e -> "KExpr",Some (generate_expr ctx e)
| KGeneric -> "KGeneric",None
| KGenericInstance(c,tl) -> "KGenericInstance",Some (generate_type_path_with_params ctx c.cl_module.m_path c.cl_path tl c.cl_meta)
Expand Down
Loading

0 comments on commit 541259e

Please sign in to comment.