Prechádzať zdrojové kódy

keep `Method MethInline` for cf_kind even if inlining is disabled (#9668)

Aleksandr Kuzmenko 5 rokov pred
rodič
commit
ea42f81f93

+ 4 - 0
src/optimization/inline.ml

@@ -6,6 +6,10 @@ open Common
 open Typecore
 open Error
 
+let needs_inline ctx is_extern_class cf =
+	cf.cf_kind = Method MethInline
+	&& (ctx.g.doinline || is_extern_class || has_class_field_flag cf CfExtern)
+
 let mk_untyped_call name p params =
 	{
 		eexpr = TCall({ eexpr = TIdent name; etype = t_dynamic; epos = p }, params);

+ 22 - 12
src/optimization/inlineConstructors.ml

@@ -102,7 +102,7 @@ and inline_var = {
 	mutable iv_closed : bool (* Inline variables are marked as closed when the scope they were first assigned on ends, any appearance of this variable after it has been closed causes cancellation *)
 }
 
-and inline_object_field = 
+and inline_object_field =
 	| IOFInlineMethod of inline_object * inline_var * tclass * Type.tparams * tclass_field * tfunc
 	| IOFInlineVar of inline_var
 	| IOFNone
@@ -203,15 +203,16 @@ let inline_constructors ctx original_e =
 		Returns true if there are any potential inline objects in the expression.
 		It is used to save work before running mark_ctors and analyze_aliases.
 	*)
-	let rec check_for_ctors ?(force_inline=false) e = 
+	let rec check_for_ctors ?(force_inline=false) e =
 		let is_ctor, is_meta_inline = match e.eexpr, force_inline with
 			| TMeta((Meta.Inline,_,_),_), _ ->
 				false, true
 			| TObjectDecl _, _
 			| TArrayDecl _, _
-			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})})},_,_), _
 			| TNew _, true ->
 				true, false
+			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
+				Inline.needs_inline ctx c.cl_extern cf, false
 			| _ -> false, false
 		in
 		is_ctor || Type.check_expr (check_for_ctors ~force_inline:is_meta_inline) e
@@ -224,15 +225,20 @@ let inline_constructors ctx original_e =
 	let rec mark_ctors ?(force_inline=false) e : texpr =
 		let is_meta_inline = match e.eexpr with (TMeta((Meta.Inline,_,_),e)) -> true | _ -> false in
 		let e = Type.map_expr (mark_ctors ~force_inline:is_meta_inline) e in
+		let mark() =
+			incr curr_io_id;
+			let id_expr = (EConst(Int (string_of_int !curr_io_id)), e.epos) in
+			let meta = (Meta.InlineObject, [id_expr], e.epos) in
+			mk (TMeta(meta, e)) e.etype e.epos
+		in
 		match e.eexpr, force_inline with
 			| TObjectDecl _, _
 			| TArrayDecl _, _
-			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})})},_,_), _
 			| TNew _, true ->
-				incr curr_io_id;
-				let id_expr = (EConst(Int (string_of_int !curr_io_id)), e.epos) in
-				let meta = (Meta.InlineObject, [id_expr], e.epos) in
-				mk (TMeta(meta, e)) e.etype e.epos
+				mark()
+			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
+				if Inline.needs_inline ctx c.cl_extern cf then mark()
+				else e
 			| _ -> e
 	in
 
@@ -242,7 +248,7 @@ let inline_constructors ctx original_e =
 		The expression being analyzed should have been processed with mark_ctors before hand.
 
 		returns: Some(inline variable) if the expression being analyzed returns an inline variable. None otherwise.
-		
+
 		seen_ctors: used to avoid infinite constructor inlining loops.
 
 		captured: Wether the caller is ready to accept an inline variable. If analysis results in an inline
@@ -272,13 +278,17 @@ let inline_constructors ctx original_e =
 		let analyze_aliases_in_lvalue e = analyze_aliases seen_ctors captured true e in
 		let analyze_aliases_in_ctor cf captured e = analyze_aliases (cf::seen_ctors) captured false e in
 		let analyze_aliases captured e = analyze_aliases seen_ctors captured false e in
-		let get_io_inline_method io fname = 
+		let get_io_inline_method io fname =
 			begin match io.io_kind with
 			| IOKCtor(ctor) ->
 				begin try
 					let f = PMap.find fname ctor.ioc_class.cl_fields in
 					begin match f.cf_params, f.cf_kind, f.cf_expr with
-					| [], Method MethInline, Some({eexpr = TFunction tf}) -> Some (ctor.ioc_class, ctor.ioc_tparams, f, tf)
+					| [], Method MethInline, Some({eexpr = TFunction tf}) ->
+						if Inline.needs_inline ctx ctor.ioc_class.cl_extern f then
+							Some (ctor.ioc_class, ctor.ioc_tparams, f, tf)
+						else
+							None
 					| _ -> None
 					end
 				with Not_found -> None
@@ -481,7 +491,7 @@ let inline_constructors ctx original_e =
 		| TCall(({eexpr=TField(ethis,fa)} as efield),call_args) ->
 			let fname = field_name fa in
 			let fiv = handle_field_case efield ethis fname (fun _ -> true) in
-			begin match fiv with 
+			begin match fiv with
 			| IOFInlineMethod(io,io_var,c,tl,cf,tf) ->
 				let argvs, pl = analyze_call_args call_args in
 				io.io_dependent_vars <- io.io_dependent_vars @ argvs;

+ 1 - 1
src/optimization/optimizer.ml

@@ -304,7 +304,7 @@ let rec reduce_loop ctx e =
 				(match inl with
 				| None -> reduce_expr ctx e
 				| Some e -> reduce_loop ctx e)
-			| {eexpr = TField(ef,(FStatic(cl,cf) | FInstance(cl,_,cf)))} when cf.cf_kind = Method MethInline && not (rec_stack_memq cf inline_stack) ->
+			| {eexpr = TField(ef,(FStatic(cl,cf) | FInstance(cl,_,cf)))} when needs_inline ctx cl.cl_extern cf && not (rec_stack_memq cf inline_stack) ->
 				begin match cf.cf_expr with
 				| Some {eexpr = TFunction tf} ->
 					let config = inline_config (Some cl) cf el e.etype in

+ 2 - 1
src/typing/calls.ml

@@ -29,7 +29,8 @@ let make_call ctx e params t ?(force_inline=false) p =
 				raise Exit
 		in
 		if not force_inline then begin
-			if f.cf_kind <> Method MethInline then raise Exit;
+			let is_extern_class = match cl with Some c -> c.cl_extern | _ -> false in
+			if not (Inline.needs_inline ctx is_extern_class f) then raise Exit;
 		end else begin
 			match cl with
 			| None ->

+ 1 - 5
src/typing/typeloadFields.ml

@@ -567,11 +567,7 @@ let create_field_context (ctx,cctx) c cff =
 		| _ ->
 			()
 	) cff.cff_meta;
-	let allow_inline = cctx.abstract <> None || match cff.cff_kind with
-		| FFun _ -> ctx.g.doinline || !is_extern || c.cl_extern
-		| _ -> true
-	in
-	let is_inline = allow_inline && List.mem_assoc AInline cff.cff_access in
+	let is_inline = List.mem_assoc AInline cff.cff_access in
 	let override = try Some (List.assoc AOverride cff.cff_access) with Not_found -> None in
 	let is_macro = List.mem_assoc AMacro cff.cff_access in
 	let field_kind = match fst cff.cff_name with

+ 18 - 0
tests/server/src/cases/display/issues/Issue9266.hx

@@ -0,0 +1,18 @@
+package cases.display.issues;
+
+class Issue9266 extends DisplayTestCase {
+	/**
+		class Main {
+			static public function main() {
+				te{-1-}st;
+			}
+
+			static public inline function test() {}
+		}
+	**/
+	function test(_) {
+		runHaxeJson([], DisplayMethods.Hover, {file: file, offset: offset(1)});
+		var result = parseHover().result;
+		Assert.equals('MethInline', result.item.args.field.kind.args);
+	}
+}