2
0
Эх сурвалжийг харах

Deal with _hx_new (#12005)

* rename to _hx_new

* test adjust

* add CfAbstractConstructor

* add a_constructor

* deal with overloads

* forgot one

* deal with a_constructor in hxb
Simon Krajewski 7 сар өмнө
parent
commit
6414bf87a0

+ 1 - 0
src/compiler/hxb/hxbReader.ml

@@ -1589,6 +1589,7 @@ class hxb_reader
 		a.a_read <- self#read_option (fun () -> self#read_field_ref);
 		a.a_write <- self#read_option (fun () -> self#read_field_ref);
 		a.a_call <- self#read_option (fun () -> self#read_field_ref);
+		a.a_constructor <- self#read_option (fun () -> self#read_field_ref);
 
 		a.a_ops <- self#read_list (fun () ->
 			let i = read_byte ch in

+ 1 - 0
src/compiler/hxb/hxbWriter.ml

@@ -1918,6 +1918,7 @@ module HxbWriter = struct
 		Chunk.write_option writer.chunk a.a_read (write_field_ref writer c CfrStatic );
 		Chunk.write_option writer.chunk a.a_write (write_field_ref writer c CfrStatic);
 		Chunk.write_option writer.chunk a.a_call (write_field_ref writer c CfrStatic);
+		Chunk.write_option writer.chunk a.a_constructor (write_field_ref writer c CfrStatic);
 
 		Chunk.write_list writer.chunk a.a_ops (fun (op, cf) ->
 			Chunk.write_u8 writer.chunk (binop_index op);

+ 1 - 1
src/core/abstract.ml

@@ -155,7 +155,7 @@ let rec follow_with_forward_ctor ?(build=false) t = match follow t with
 	| TAbstract(a,tl) as t ->
 		if build then build_abstract a;
 		if Meta.has Meta.ForwardNew a.a_meta && not (match a.a_impl with
-			| Some c -> PMap.mem "_new" c.cl_statics
+			| Some c -> a.a_constructor <> None
 			| None -> false
 		) then
 			follow_with_forward_ctor (get_underlying_type ~return_first:true a tl)

+ 5 - 8
src/core/display/completionItem.ml

@@ -182,14 +182,11 @@ module CompletionModuleType = struct
 			raise Exit
 
 	let of_module_type mt =
-		let actor a = match a.a_impl with
-			| None -> No
-			| Some c ->
-				try
-					let cf = PMap.find "_new" c.cl_statics in
-					if (has_class_flag c CExtern) || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate
-				with Not_found ->
-					No
+		let actor a = match a.a_impl,a.a_constructor with
+			| Some c,Some cf ->
+				if (has_class_flag c CExtern) || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate
+			| _ ->
+				No
 		in
 		let ctor c =
 			try

+ 1 - 1
src/core/inheritDoc.ml

@@ -181,7 +181,7 @@ and get_target_doc ctx e_target =
 			| TAbstract ({ a_impl = Some c }, _) ->
 				let c_opt, cf =
 					let field_name =
-						if field_name = "new" then "_new"
+						if field_name = "new" then "_hx_new"
 						else field_name
 					in
 					get_class_field c field_name

+ 1 - 0
src/core/tFunctions.ml

@@ -299,6 +299,7 @@ let null_abstract = {
 	a_read = None;
 	a_write = None;
 	a_call = None;
+	a_constructor = None;
 	a_extern = false;
 	a_enum = false;
 }

+ 1 - 0
src/core/tOther.ml

@@ -300,6 +300,7 @@ let mk_abstract m path pos name_pos =
 		a_this = mk_mono();
 		a_read = None;
 		a_write = None;
+		a_constructor = None;
 		a_extern = false;
 		a_enum = false;
 		a_call = None;

+ 3 - 1
src/core/tType.ml

@@ -382,6 +382,7 @@ and tabstract = {
 	mutable a_read : tclass_field option;
 	mutable a_write : tclass_field option;
 	mutable a_call : tclass_field option;
+	mutable a_constructor : tclass_field option;
 	mutable a_extern : bool;
 	mutable a_enum : bool;
 }
@@ -511,10 +512,11 @@ type flag_tclass_field =
 	| CfUsed (* Marker for DCE *)
 	| CfMaybeUsed (* Marker for DCE *)
 	| CfNoLookup (* Field cannot be accessed by-name. *)
+	| CfAbstractConstructor
 
 (* Order has to match declaration for printing*)
 let flag_tclass_field_names = [
-	"CfPublic";"CfStatic";"CfExtern";"CfFinal";"CfModifiesThis";"CfOverride";"CfAbstract";"CfOverload";"CfImpl";"CfEnum";"CfGeneric";"CfDefault";"CfPostProcessed";"CfUsed";"CfMaybeUsed";"CfNoLookup"
+	"CfPublic";"CfStatic";"CfExtern";"CfFinal";"CfModifiesThis";"CfOverride";"CfAbstract";"CfOverload";"CfImpl";"CfEnum";"CfGeneric";"CfDefault";"CfPostProcessed";"CfUsed";"CfMaybeUsed";"CfNoLookup";"CfAbstractConstructor"
 ]
 
 type flag_tenum =

+ 2 - 2
src/optimization/inline.ml

@@ -232,7 +232,7 @@ let inline_default_config cf t =
 let inline_config cls_opt cf call_args return_type =
 	match cls_opt with
 	| Some ({cl_kind = KAbstractImpl _}) when has_class_field_flag cf CfImpl ->
-		let t = if cf.cf_name = "_new" then
+		let t = if has_class_field_flag cf CfAbstractConstructor then
 			return_type
 		else if call_args = [] then
 			raise_typing_error "Invalid abstract implementation function" cf.cf_pos
@@ -580,7 +580,7 @@ class inline_state ctx ethis params cf f p = object(self)
 			(match follow ethis.etype with
 			| TAnon a -> (match !(a.a_status) with
 				| ClassStatics {cl_kind = KAbstractImpl a } when has_class_field_flag cf CfImpl ->
-					if cf.cf_name <> "_new" then begin
+					if not (has_class_field_flag cf CfAbstractConstructor) then begin
 						(* the first argument must unify with a_this for abstract implementation functions *)
 						let tb = (TFun(("",false,map_type a.a_this) :: (List.tl tl),tret)) in
 						unify_raise mt tb p

+ 1 - 1
src/typing/callUnification.ml

@@ -232,7 +232,7 @@ let unify_field_call ctx fa el_typed el p inline =
 			cfl,Some c,false,TClass.get_map_function c tl,(fun t -> t)
 		| FHAbstract(a,tl,c) ->
 			let map = apply_params a.a_params tl in
-			let tmap = if fa.fa_field.cf_name = "_new" (* TODO: BAD BAD BAD BAD *) then (fun t -> t) else (fun t -> map a.a_this) in
+			let tmap = if has_class_field_flag fa.fa_field CfAbstractConstructor then (fun t -> t) else (fun t -> map a.a_this) in
 			expand_overloads fa.fa_field,Some c,true,map,tmap
 	in
 	let is_forced_inline = is_forced_inline co fa.fa_field in

+ 1 - 1
src/typing/calls.ml

@@ -54,7 +54,7 @@ let make_call ctx e params t ?(force_inline=false) p =
 		(match cl, ctx.c.curclass.cl_kind, params with
 			| Some c, KAbstractImpl _, { eexpr = TLocal { v_meta = v_meta } } :: _ when c == ctx.c.curclass ->
 				if
-					f.cf_name <> "_new"
+					not (has_class_field_flag f CfAbstractConstructor)
 					&& has_meta Meta.This v_meta
 					&& has_class_field_flag f CfModifiesThis
 				then

+ 9 - 2
src/typing/fieldAccess.ml

@@ -163,8 +163,15 @@ let get_constructor_access c tl p =
 			| _ -> c, tl
 		in
 		let cf, fh = match c.cl_kind with
-			| KAbstractImpl a -> PMap.find "_new" c.cl_statics, FHAbstract(a,tl,c)
-			| _ -> Type.get_constructor c, FHInstance(c,tl)
+			| KAbstractImpl a ->
+				begin match a.a_constructor with
+					| None ->
+						raise Not_found
+					| Some cf ->
+						cf,FHAbstract(a,tl,c)
+				end
+			| _ ->
+				Type.get_constructor c, FHInstance(c,tl)
 		in
 		create e_static cf fh false p
 	with Not_found ->

+ 13 - 8
src/typing/typeloadFields.ml

@@ -54,6 +54,7 @@ type field_init_ctx = {
 	is_abstract : bool;
 	is_macro : bool;
 	is_abstract_member : bool;
+	is_abstract_constructor : bool;
 	is_display_field : bool;
 	is_field_debug : bool;
 	is_generic : bool;
@@ -271,7 +272,7 @@ let transform_abstract_field com this_t a_t a f =
 			);
 			f_type = Some a_t;
 		} in
-		{ f with cff_name = "_new",pos f.cff_name; cff_kind = FFun fu; cff_meta = meta }
+		{ f with cff_name = "_hx_new",pos f.cff_name; cff_kind = FFun fu; cff_meta = meta }
 	| FFun fu when not stat ->
 		if Meta.has Meta.From f.cff_meta then raise_typing_error "@:from cast functions must be static" f.cff_pos;
 		{ f with cff_kind = FFun fu }
@@ -529,6 +530,7 @@ let create_field_context ctx cctx cff is_display_file display_modifier =
 		is_field_debug = cctx.is_class_debug || Meta.has (Meta.Custom ":debug.typeload") cff.cff_meta;
 		display_modifier = display_modifier;
 		is_abstract_member = is_abstract_member;
+		is_abstract_constructor = is_abstract_member && fst cff.cff_name = "_hx_new";
 		is_generic = Meta.has Meta.Generic cff.cff_meta;
 		field_kind = field_kind;
 		do_bind = (((not ((has_class_flag c CExtern) || !is_extern) || is_inline) && not is_abstract && not (has_class_flag c CInterface)) || field_kind = CfrInit);
@@ -631,7 +633,7 @@ let check_field_display ctx fctx c cf =
 		let scope, cf = match c.cl_kind with
 			| KAbstractImpl _ ->
 				if has_class_field_flag cf CfImpl then
-					(if cf.cf_name = "_new" then
+					(if fctx.is_abstract_constructor then
 						CFSConstructor, {cf with cf_name = "new"}
 					else
 						CFSMember, cf)
@@ -927,6 +929,7 @@ let create_variable (ctx,cctx,fctx) c f cf t eo p =
 	cf
 
 let check_abstract (ctx,cctx,fctx) a c cf fd t ret p =
+	if fctx.is_abstract_constructor && a.a_constructor = None (* TODO: this is pretty dumb, it deals with the overload case *) then a.a_constructor <- Some cf;
 	let m = mk_mono() in
 	let ta = TAbstract(a,List.map (fun _ -> mk_mono()) a.a_params) in
 	let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in
@@ -978,10 +981,11 @@ let check_abstract (ctx,cctx,fctx) a c cf fd t ret p =
 			cf.cf_meta <- (Meta.MultiType,[],null_pos) :: cf.cf_meta;
 		let r = make_lazy ctx.g t (fun () ->
 			let args = if is_multitype_cast then begin
-				let ctor = try
-					PMap.find "_new" c.cl_statics
-				with Not_found ->
-					raise_typing_error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos
+				let ctor = match a.a_constructor with
+					| Some cf ->
+						cf
+					| None ->
+						raise_typing_error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos
 				in
 				(* delay ctx PFinal (fun () -> unify ctx m tthis f.cff_pos); *)
 				let args = match follow (monomorphs a.a_params ctor.cf_type) with
@@ -1087,7 +1091,7 @@ let check_abstract (ctx,cctx,fctx) a c cf fd t ret p =
 		| _ -> ();
 	in
 	List.iter check_meta cf.cf_meta;
-	if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false;
+	if fctx.is_abstract_constructor && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false;
 	if fd.f_expr = None then begin
 		if fctx.is_inline then missing_expression ctx.com fctx "Inline functions must have an expression" cf.cf_pos;
 		if fd.f_type = None then raise_typing_error ("Functions without expressions must have an explicit return type") cf.cf_pos;
@@ -1160,7 +1164,7 @@ let setup_args_ret ctx cctx fctx name fd p =
 		maybe_use_property_type fd.f_type (fun () -> match Lazy.force mk with MKGetter | MKSetter -> true | _ -> false) def
 	end in
 	let abstract_this = match cctx.abstract with
-		| Some a when fctx.is_abstract_member && name <> "_new" (* TODO: this sucks *) && not fctx.is_macro ->
+		| Some a when fctx.is_abstract_member && not fctx.is_abstract_constructor && not fctx.is_macro ->
 			Some a.a_this
 		| _ ->
 			None
@@ -1271,6 +1275,7 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 		add_class_field_flag cf CfAbstract;
 	end;
 	if fctx.is_abstract_member then add_class_field_flag cf CfImpl;
+	if fctx.is_abstract_constructor then add_class_field_flag cf CfAbstractConstructor;
 	if fctx.is_generic then add_class_field_flag cf CfGeneric;
 	begin match fctx.default with
 	| Some p ->

+ 1 - 0
src/typing/typeloadModule.ml

@@ -197,6 +197,7 @@ module ModuleLevel = struct
 						a_read = None;
 						a_write = None;
 						a_call = None;
+						a_constructor = None;
 						a_extern = List.mem AbExtern d.d_flags;
 						a_enum = List.mem AbEnum d.d_flags || p_enum_meta <> None;
 					} in

+ 1 - 1
src/typing/typer.ml

@@ -1479,7 +1479,7 @@ and type_array_comprehension ctx e with_type p =
 	]) v.v_type p
 
 and type_return ?(implicit=false) ctx e with_type p =
-	let is_abstract_ctor = ctx.e.curfun = FunMemberAbstract && ctx.f.curfield.cf_name = "_new" in
+	let is_abstract_ctor = ctx.e.curfun = FunMemberAbstract && has_class_field_flag ctx.f.curfield CfAbstractConstructor in
 	match e with
 	| None when is_abstract_ctor ->
 		let e_cast = mk (TCast(get_this ctx p,None)) ctx.e.ret p in

+ 1 - 1
src/typing/typerBase.ml

@@ -188,7 +188,7 @@ let assign_to_this_is_allowed ctx =
 		| KAbstractImpl _ ->
 			(match ctx.f.curfield.cf_kind with
 				| Method MethInline -> true
-				| Method _ when ctx.f.curfield.cf_name = "_new" -> true
+				| Method _ when has_class_field_flag ctx.f.curfield CfAbstractConstructor -> true
 				| _ -> false
 			)
 		| _ -> false

+ 1 - 1
src/typing/typerDisplay.ml

@@ -619,7 +619,7 @@ let handle_display ctx e_ast dk mode with_type =
 						| TClassDecl c -> has_constructor c
 						| TAbstractDecl a -> (match Abstract.follow_with_forward_ctor ~build:true (TAbstract(a,extract_param_types a.a_params)) with
 							| TInst(c,_) -> has_constructor c
-							| TAbstract({a_impl = Some c},_) -> PMap.mem "_new" c.cl_statics
+							| TAbstract(a,_) -> a.a_constructor <> None
 							| _ -> false)
 						| _ -> false
 						end

+ 1 - 1
tests/misc/projects/Issue11545/compile.hxml.stdout

@@ -1,3 +1,3 @@
 Macro.hx:21: main
-Macro.hx:21: _new
+Macro.hx:21: _hx_new
 Main.hx:4: abc

+ 1 - 1
tests/optimization/src/issues/Issue3713.hx

@@ -19,7 +19,7 @@ private class C<T> {
 
 class Issue3713 {
 	@:js('
-		var b = BImpl._new();
+		var b = BImpl._hx_new();
 		var c_x = 1;
 	')
 	@:analyzer(no_const_propagation, no_local_dce)