|
@@ -6,17 +6,16 @@ open Type
|
|
|
open Typecore
|
|
|
open Error
|
|
|
|
|
|
-exception Generic_Exception of string * pos
|
|
|
-
|
|
|
type generic_context = {
|
|
|
ctx : typer;
|
|
|
subst : (t * (t * texpr option)) list;
|
|
|
name : string;
|
|
|
p : pos;
|
|
|
mutable mg : module_def option;
|
|
|
+ generic_debug : bool;
|
|
|
}
|
|
|
|
|
|
-let make_generic ctx ps pt p =
|
|
|
+let make_generic ctx ps pt debug p =
|
|
|
let subst s = "_" ^ string_of_int (Char.code (String.get (Str.matched_string s) 0)) ^ "_" in
|
|
|
let ident_safe = Str.global_substitute (Str.regexp "[^a-zA-Z0-9_]") subst in
|
|
|
let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
|
|
@@ -27,7 +26,7 @@ let make_generic ctx ps pt p =
|
|
|
| KExpr e ->
|
|
|
let name = ident_safe (Ast.Printer.s_expr e) in
|
|
|
let e = type_expr {ctx with locals = PMap.empty} e WithType.value in
|
|
|
- name,(e.etype,Some e)
|
|
|
+ name,(t,Some e)
|
|
|
| _ ->
|
|
|
((ident_safe (s_type_path_underscore c.cl_path)) ^ (loop_tl top tl),(t,None))
|
|
|
end
|
|
@@ -62,7 +61,7 @@ let make_generic ctx ps pt p =
|
|
|
in
|
|
|
let rec loop acc_name acc_subst ttpl tl = match ttpl,tl with
|
|
|
| ttp :: ttpl,t :: tl ->
|
|
|
- let name,t = try process t with Exit -> raise (Generic_Exception (("Could not determine type for parameter " ^ ttp.ttp_name), p)) in
|
|
|
+ let name,t = try process t with Exit -> raise_typing_error ("Could not determine type for parameter " ^ ttp.ttp_name) p in
|
|
|
loop (name :: acc_name) ((follow ttp.ttp_type,t) :: acc_subst) ttpl tl
|
|
|
| [],[] ->
|
|
|
let name = String.concat "_" (List.rev acc_name) in
|
|
@@ -77,22 +76,33 @@ let make_generic ctx ps pt p =
|
|
|
name = name;
|
|
|
p = p;
|
|
|
mg = None;
|
|
|
+ generic_debug = debug;
|
|
|
}
|
|
|
|
|
|
-let rec generic_substitute_type gctx t =
|
|
|
+let rec generic_substitute_type' gctx allow_expr t =
|
|
|
match t with
|
|
|
| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
|
|
|
(* maybe loop, or generate cascading generics *)
|
|
|
- let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
|
|
|
- let t = f (List.map (generic_substitute_type gctx) tl2) in
|
|
|
+ let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c2) gctx.p in
|
|
|
+ let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl2) in
|
|
|
(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
|
|
|
t
|
|
|
| _ ->
|
|
|
try
|
|
|
- let t,_ = List.assq t gctx.subst in
|
|
|
- generic_substitute_type gctx t
|
|
|
+ let t,eo = List.assq t gctx.subst in
|
|
|
+ (* Somewhat awkward: If we allow expression types, use the original KExpr one. This is so
|
|
|
+ recursing into further KGeneric expands correctly. *)
|
|
|
+ begin match eo with
|
|
|
+ | Some e when not allow_expr ->
|
|
|
+ e.etype
|
|
|
+ | _ ->
|
|
|
+ generic_substitute_type' gctx false t
|
|
|
+ end
|
|
|
with Not_found ->
|
|
|
- Type.map (generic_substitute_type gctx) t
|
|
|
+ Type.map (generic_substitute_type' gctx allow_expr) t
|
|
|
+
|
|
|
+let generic_substitute_type gctx t =
|
|
|
+ generic_substitute_type' gctx false t
|
|
|
|
|
|
let generic_substitute_expr gctx e =
|
|
|
let vars = Hashtbl.create 0 in
|
|
@@ -108,8 +118,8 @@ let generic_substitute_expr gctx e =
|
|
|
let rec build_expr e =
|
|
|
let e = match e.eexpr with
|
|
|
| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
|
|
|
- let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in
|
|
|
- let t = f (List.map (generic_substitute_type gctx) tl) in
|
|
|
+ let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c) gctx.p in
|
|
|
+ let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl) in
|
|
|
begin match follow t with
|
|
|
| TInst(c',_) when c == c' ->
|
|
|
(* The @:generic class wasn't expanded, let's not recurse to avoid infinite loop (#6430) *)
|
|
@@ -159,7 +169,7 @@ let static_method_container gctx c cf p =
|
|
|
let pack = fst c.cl_path in
|
|
|
let name = (snd c.cl_path) ^ "_" ^ cf.cf_name ^ "_" ^ gctx.name in
|
|
|
try
|
|
|
- let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) true in
|
|
|
+ let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) ParamSpawnMonos in
|
|
|
match t with
|
|
|
| TInst(cg,_) -> cg
|
|
|
| _ -> raise_typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
|
|
@@ -213,6 +223,14 @@ let set_type_parameter_dependencies mg tl =
|
|
|
in
|
|
|
List.iter loop tl
|
|
|
|
|
|
+let build_instances ctx t p =
|
|
|
+ let rec loop t =
|
|
|
+ let t = Typeload.maybe_build_instance ctx t ParamNormal p in
|
|
|
+ Type.map loop t
|
|
|
+ in
|
|
|
+ loop t
|
|
|
+
|
|
|
+
|
|
|
let rec build_generic_class ctx c p tl =
|
|
|
let pack = fst c.cl_path in
|
|
|
let recurse = ref false in
|
|
@@ -233,15 +251,29 @@ let rec build_generic_class ctx c p tl =
|
|
|
if !recurse || not (ctx.com.display.dms_full_typing) then begin
|
|
|
TInst (c,tl) (* build a normal instance *)
|
|
|
end else begin
|
|
|
- let gctx = make_generic ctx c.cl_params tl p in
|
|
|
+ let gctx = make_generic ctx c.cl_params tl (Meta.has (Meta.Custom ":debug.generic") c.cl_meta) p in
|
|
|
let name = (snd c.cl_path) ^ "_" ^ gctx.name in
|
|
|
try
|
|
|
- let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) false in
|
|
|
+ let t = Typeload.load_instance ctx (mk_type_path (pack,name),p) ParamNormal in
|
|
|
match t with
|
|
|
| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
|
|
|
| _ -> raise_typing_error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p
|
|
|
with Error { err_message = Module_not_found path } when path = (pack,name) ->
|
|
|
let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
|
|
|
+ if gctx.generic_debug then begin
|
|
|
+ print_endline (Printf.sprintf "[GENERIC] Building @:generic class %s as %s with:" (s_type_path c.cl_path) name);
|
|
|
+ List.iter (fun (t1,(t2,eo)) ->
|
|
|
+ let name = match follow t1 with
|
|
|
+ | TInst(c,_) -> snd c.cl_path
|
|
|
+ | _ -> die "" __LOC__
|
|
|
+ in
|
|
|
+ let expr = match eo with
|
|
|
+ | None -> ""
|
|
|
+ | Some e -> Printf.sprintf " (expr: %s)" (s_expr_debug e)
|
|
|
+ in
|
|
|
+ print_endline (Printf.sprintf "[GENERIC] %s: %s%s" name (s_type_kind t2) expr);
|
|
|
+ ) gctx.subst
|
|
|
+ end;
|
|
|
ignore(c.cl_build()); (* make sure the super class is already setup *)
|
|
|
let mg = {
|
|
|
m_id = alloc_mid();
|
|
@@ -257,11 +289,12 @@ let rec build_generic_class ctx c p tl =
|
|
|
| Final
|
|
|
| Hack
|
|
|
| Internal
|
|
|
- | Keep
|
|
|
+ | Keep | KeepSub
|
|
|
| NoClosure | NullSafety
|
|
|
| Pure
|
|
|
| Struct | StructInit
|
|
|
- | Using ->
|
|
|
+ | Using
|
|
|
+ | AutoBuild ->
|
|
|
true
|
|
|
| _ ->
|
|
|
false
|
|
@@ -282,8 +315,7 @@ let rec build_generic_class ctx c p tl =
|
|
|
| _ -> die "" __LOC__
|
|
|
) ([],[]) cf_old.cf_params in
|
|
|
let gctx = {gctx with subst = param_subst @ gctx.subst} in
|
|
|
- let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *)
|
|
|
- remove_class_field_flag cf_new CfPostProcessed;
|
|
|
+ let cf_new = {cf_old with cf_pos = cf_old.cf_pos; cf_expr_unoptimized = None} in (* copy *)
|
|
|
(* Type parameter constraints are substituted here. *)
|
|
|
cf_new.cf_params <- List.rev_map (fun tp -> match follow tp.ttp_type with
|
|
|
| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
|
|
@@ -293,8 +325,13 @@ let rec build_generic_class ctx c p tl =
|
|
|
| _ -> die "" __LOC__
|
|
|
) params;
|
|
|
let f () =
|
|
|
+ ignore(follow cf_old.cf_type);
|
|
|
+ (* We update here because the follow could resolve some TLazy things that end up modifying flags, such as
|
|
|
+ the inferred CfOverride from #11010. *)
|
|
|
+ cf_new.cf_flags <- cf_old.cf_flags;
|
|
|
+ remove_class_field_flag cf_new CfPostProcessed;
|
|
|
+ if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] expanding %s" cf_old.cf_name);
|
|
|
let t = generic_substitute_type gctx cf_old.cf_type in
|
|
|
- ignore (follow t);
|
|
|
begin try (match cf_old.cf_expr with
|
|
|
| None ->
|
|
|
begin match cf_old.cf_kind with
|
|
@@ -310,6 +347,7 @@ let rec build_generic_class ctx c p tl =
|
|
|
) with Unify_error l ->
|
|
|
raise_typing_error (error_msg (Unify l)) cf_new.cf_pos
|
|
|
end;
|
|
|
+ if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass_field " " cf_new));
|
|
|
t
|
|
|
in
|
|
|
let r = exc_protect ctx (fun r ->
|
|
@@ -331,14 +369,9 @@ let rec build_generic_class ctx c p tl =
|
|
|
cg.cl_super <- (match c.cl_super with
|
|
|
| None -> None
|
|
|
| Some (cs,pl) ->
|
|
|
- let ts = follow (apply_params c.cl_params tl (TInst(cs,pl))) in
|
|
|
- let cs,pl = TypeloadCheck.Inheritance.check_extends ctx c ts p in
|
|
|
- match cs.cl_kind with
|
|
|
- | KGeneric ->
|
|
|
- (match build_generic_class ctx cs p pl with
|
|
|
- | TInst (cs,pl) -> Some (cs,pl)
|
|
|
- | _ -> die "" __LOC__)
|
|
|
- | _ -> Some(cs,pl)
|
|
|
+ let ts = build_instances ctx (follow (apply_params c.cl_params tl (TInst(cs,pl)))) p in
|
|
|
+ let cs,tl = TypeloadCheck.Inheritance.check_extends ctx c ts p in
|
|
|
+ Some(cs,tl)
|
|
|
);
|
|
|
TypeloadFunction.add_constructor ctx cg false p;
|
|
|
cg.cl_kind <- KGenericInstance (c,tl);
|
|
@@ -365,6 +398,8 @@ let rec build_generic_class ctx c p tl =
|
|
|
let n = get_short_name () in
|
|
|
cg.cl_meta <- (Meta.Native,[EConst(String (n,SDoubleQuotes)),p],null_pos) :: cg.cl_meta;
|
|
|
end;
|
|
|
+ cg.cl_using <- c.cl_using;
|
|
|
+ if gctx.generic_debug then print_endline (Printf.sprintf "[GENERIC] %s" (Printer.s_tclass " " cg));
|
|
|
TInst (cg,[])
|
|
|
end
|
|
|
|
|
@@ -378,8 +413,11 @@ let type_generic_function ctx fa fcc with_type p =
|
|
|
let cf = fcc.fc_field in
|
|
|
if cf.cf_params = [] then raise_typing_error "Function has no type parameters and cannot be generic" p;
|
|
|
begin match with_type with
|
|
|
- | WithType.WithType(t,_) -> unify ctx fcc.fc_ret t p
|
|
|
- | _ -> ()
|
|
|
+ | WithType.WithType(t,_) ->
|
|
|
+ (* In cases like #5482, we might have a return type that still needs expansion. *)
|
|
|
+ unify ctx (build_instances ctx fcc.fc_ret p) t p
|
|
|
+ | _ ->
|
|
|
+ ()
|
|
|
end;
|
|
|
let monos = fcc.fc_monos in
|
|
|
List.iter (fun t -> match follow t with
|
|
@@ -387,102 +425,100 @@ let type_generic_function ctx fa fcc with_type p =
|
|
|
| _ -> ()
|
|
|
) monos;
|
|
|
let el = fcc.fc_args in
|
|
|
- (try
|
|
|
- let gctx = make_generic ctx cf.cf_params monos p in
|
|
|
- let name = cf.cf_name ^ "_" ^ gctx.name in
|
|
|
- let unify_existing_field tcf pcf = try
|
|
|
- unify_raise tcf fcc.fc_type p
|
|
|
- with Error ({ err_message = Unify _; err_depth = depth } as err) ->
|
|
|
- raise (Error { err with err_sub = (make_error
|
|
|
- ~depth
|
|
|
- ~sub:[make_error ~depth:(depth+1) (Custom (compl_msg "Conflicting field was defined here")) pcf]
|
|
|
- (Custom ("Cannot create field " ^ name ^ " due to type mismatch"))
|
|
|
- p
|
|
|
- ) :: err.err_sub })
|
|
|
+ let gctx = make_generic ctx cf.cf_params monos (Meta.has (Meta.Custom ":debug.generic") cf.cf_meta) p in
|
|
|
+ let fc_type = build_instances ctx fcc.fc_type p in
|
|
|
+ let name = cf.cf_name ^ "_" ^ gctx.name in
|
|
|
+ let unify_existing_field tcf pcf = try
|
|
|
+ unify_raise tcf fc_type p
|
|
|
+ with Error ({ err_message = Unify _; err_depth = depth } as err) ->
|
|
|
+ raise (Error { err with err_sub = (make_error
|
|
|
+ ~depth
|
|
|
+ ~sub:[make_error ~depth:(depth+1) (Custom (compl_msg "Conflicting field was defined here")) pcf]
|
|
|
+ (Custom ("Cannot create field " ^ name ^ " due to type mismatch"))
|
|
|
+ p
|
|
|
+ ) :: err.err_sub })
|
|
|
+ in
|
|
|
+ let fa = try
|
|
|
+ let cf2 = if stat then
|
|
|
+ let cf2 = PMap.find name c.cl_statics in
|
|
|
+ unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
+ cf2
|
|
|
+ else
|
|
|
+ let cf2 = PMap.find name c.cl_fields in
|
|
|
+ unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
+ cf2
|
|
|
in
|
|
|
- let fa = try
|
|
|
- let cf2 = if stat then
|
|
|
- let cf2 = PMap.find name c.cl_statics in
|
|
|
- unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
- cf2
|
|
|
- else
|
|
|
- let cf2 = PMap.find name c.cl_fields in
|
|
|
- unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
- cf2
|
|
|
+ {fa with fa_field = cf2}
|
|
|
+ (*
|
|
|
+ java.Lib.array() relies on the ability to shadow @:generic function for certain types
|
|
|
+ see https://github.com/HaxeFoundation/haxe/issues/8393#issuecomment-508685760
|
|
|
+ *)
|
|
|
+ (* if cf.cf_name_pos = cf2.cf_name_pos then
|
|
|
+ cf2
|
|
|
+ else
|
|
|
+ error ("Cannot specialize @:generic because the generated function name is already used: " ^ name) p *)
|
|
|
+ with Not_found ->
|
|
|
+ let finalize_field c cf2 =
|
|
|
+ ignore(follow cf.cf_type);
|
|
|
+ let rec check e = match e.eexpr with
|
|
|
+ | TNew({cl_kind = KTypeParameter _} as c,_,_) when not (TypeloadCheck.is_generic_parameter ctx c) ->
|
|
|
+ (* TODO use sub error *)
|
|
|
+ display_error ctx.com "Only generic type parameters can be constructed" e.epos;
|
|
|
+ display_error ctx.com "While specializing this call" p;
|
|
|
+ | _ ->
|
|
|
+ Type.iter check e
|
|
|
in
|
|
|
- {fa with fa_field = cf2}
|
|
|
- (*
|
|
|
- java.Lib.array() relies on the ability to shadow @:generic function for certain types
|
|
|
- see https://github.com/HaxeFoundation/haxe/issues/8393#issuecomment-508685760
|
|
|
- *)
|
|
|
- (* if cf.cf_name_pos = cf2.cf_name_pos then
|
|
|
- cf2
|
|
|
- else
|
|
|
- error ("Cannot specialize @:generic because the generated function name is already used: " ^ name) p *)
|
|
|
- with Not_found ->
|
|
|
- let finalize_field c cf2 =
|
|
|
- ignore(follow cf.cf_type);
|
|
|
- let rec check e = match e.eexpr with
|
|
|
- | TNew({cl_kind = KTypeParameter _} as c,_,_) when not (TypeloadCheck.is_generic_parameter ctx c) ->
|
|
|
- (* TODO use sub error *)
|
|
|
- display_error ctx.com "Only generic type parameters can be constructed" e.epos;
|
|
|
- display_error ctx.com "While specializing this call" p;
|
|
|
- | _ ->
|
|
|
- Type.iter check e
|
|
|
- in
|
|
|
- cf2.cf_expr <- (match cf.cf_expr with
|
|
|
- | None ->
|
|
|
- display_error ctx.com "Recursive @:generic function" p; None;
|
|
|
- | Some e ->
|
|
|
- let e = generic_substitute_expr gctx e in
|
|
|
- check e;
|
|
|
- Some e
|
|
|
- );
|
|
|
- cf2.cf_kind <- cf.cf_kind;
|
|
|
- if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic;
|
|
|
- cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: cf.cf_meta
|
|
|
- in
|
|
|
- let mk_cf2 name =
|
|
|
- mk_field ~static:stat name fcc.fc_type cf.cf_pos cf.cf_name_pos
|
|
|
- in
|
|
|
- if stat then begin
|
|
|
- if Meta.has Meta.GenericClassPerMethod c.cl_meta then begin
|
|
|
- let c = static_method_container gctx c cf p in
|
|
|
- set_type_parameter_dependencies c.cl_module monos;
|
|
|
- let cf2 = try
|
|
|
- let cf2 = PMap.find cf.cf_name c.cl_statics in
|
|
|
- unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
- cf2
|
|
|
- with Not_found ->
|
|
|
- let cf2 = mk_cf2 cf.cf_name in
|
|
|
- c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
|
|
|
- c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
|
|
|
- finalize_field c cf2;
|
|
|
- cf2
|
|
|
- in
|
|
|
- {fa with fa_host = FHStatic c;fa_field = cf2;fa_on = Builder.make_static_this c p}
|
|
|
- end else begin
|
|
|
- set_type_parameter_dependencies c.cl_module monos;
|
|
|
- let cf2 = mk_cf2 name in
|
|
|
+ cf2.cf_expr <- (match cf.cf_expr with
|
|
|
+ | None ->
|
|
|
+ display_error ctx.com "Recursive @:generic function" p; None;
|
|
|
+ | Some e ->
|
|
|
+ let e = generic_substitute_expr gctx e in
|
|
|
+ check e;
|
|
|
+ Some e
|
|
|
+ );
|
|
|
+ cf2.cf_kind <- cf.cf_kind;
|
|
|
+ if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic;
|
|
|
+ cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: cf.cf_meta
|
|
|
+ in
|
|
|
+ let mk_cf2 name =
|
|
|
+ mk_field ~static:stat name fc_type cf.cf_pos cf.cf_name_pos
|
|
|
+ in
|
|
|
+ if stat then begin
|
|
|
+ if Meta.has Meta.GenericClassPerMethod c.cl_meta then begin
|
|
|
+ let c = static_method_container gctx c cf p in
|
|
|
+ set_type_parameter_dependencies c.cl_module monos;
|
|
|
+ let cf2 = try
|
|
|
+ let cf2 = PMap.find cf.cf_name c.cl_statics in
|
|
|
+ unify_existing_field cf2.cf_type cf2.cf_pos;
|
|
|
+ cf2
|
|
|
+ with Not_found ->
|
|
|
+ let cf2 = mk_cf2 cf.cf_name in
|
|
|
c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
|
|
|
c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
|
|
|
finalize_field c cf2;
|
|
|
- {fa with fa_field = cf2}
|
|
|
- end
|
|
|
+ cf2
|
|
|
+ in
|
|
|
+ {fa with fa_host = FHStatic c;fa_field = cf2;fa_on = Builder.make_static_this c p}
|
|
|
end else begin
|
|
|
set_type_parameter_dependencies c.cl_module monos;
|
|
|
let cf2 = mk_cf2 name in
|
|
|
- if has_class_field_flag cf CfOverride then add_class_field_flag cf2 CfOverride;
|
|
|
- c.cl_fields <- PMap.add cf2.cf_name cf2 c.cl_fields;
|
|
|
- c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields;
|
|
|
+ c.cl_statics <- PMap.add cf2.cf_name cf2 c.cl_statics;
|
|
|
+ c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics;
|
|
|
finalize_field c cf2;
|
|
|
{fa with fa_field = cf2}
|
|
|
end
|
|
|
- in
|
|
|
- let dispatch = new CallUnification.call_dispatcher ctx (MCall []) with_type p in
|
|
|
- dispatch#field_call fa el []
|
|
|
- with Generic_Exception (msg,p) ->
|
|
|
- raise_typing_error msg p)
|
|
|
+ end else begin
|
|
|
+ set_type_parameter_dependencies c.cl_module monos;
|
|
|
+ let cf2 = mk_cf2 name in
|
|
|
+ if has_class_field_flag cf CfOverride then add_class_field_flag cf2 CfOverride;
|
|
|
+ c.cl_fields <- PMap.add cf2.cf_name cf2 c.cl_fields;
|
|
|
+ c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields;
|
|
|
+ finalize_field c cf2;
|
|
|
+ {fa with fa_field = cf2}
|
|
|
+ end
|
|
|
+ in
|
|
|
+ let dispatch = new CallUnification.call_dispatcher ctx (MCall []) with_type p in
|
|
|
+ dispatch#field_call fa el []
|
|
|
|
|
|
;;
|
|
|
Typecore.type_generic_function_ref := type_generic_function
|