Browse Source

[typer] carry `force_inline` flag through AKUsing

closes #7886
Simon Krajewski 6 years ago
parent
commit
d477e6a329

+ 5 - 5
src/typing/calls.ml

@@ -412,7 +412,7 @@ let rec acc_get ctx g p =
 	| AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p
 	| AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p
 	| AKExpr e -> e
 	| AKExpr e -> e
 	| AKSet _ | AKAccess _ | AKFieldSet _ -> assert false
 	| AKSet _ | AKAccess _ | AKFieldSet _ -> assert false
-	| AKUsing (et,c,cf,e) when ctx.in_display ->
+	| AKUsing (et,c,cf,e,_) when ctx.in_display ->
 		(* Generate a TField node so we can easily match it for position/usage completion (issue #1968) *)
 		(* Generate a TField node so we can easily match it for position/usage completion (issue #1968) *)
 		let ec = type_module_type ctx (TClassDecl c) None p in
 		let ec = type_module_type ctx (TClassDecl c) None p in
 		let ec = {ec with eexpr = (TMeta((Meta.StaticExtension,[],null_pos),ec))} in
 		let ec = {ec with eexpr = (TMeta((Meta.StaticExtension,[],null_pos),ec))} in
@@ -421,7 +421,7 @@ let rec acc_get ctx g p =
 			| _ -> et.etype
 			| _ -> et.etype
 		in
 		in
 		mk (TField(ec,FStatic(c,cf))) t et.epos
 		mk (TField(ec,FStatic(c,cf))) t et.epos
-	| AKUsing (et,_,cf,e) ->
+	| AKUsing (et,_,cf,e,_) ->
 		(* build a closure with first parameter applied *)
 		(* build a closure with first parameter applied *)
 		(match follow et.etype with
 		(match follow et.etype with
 		| TFun (_ :: args,ret) ->
 		| TFun (_ :: args,ret) ->
@@ -523,12 +523,12 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 			| _ ->
 			| _ ->
 				error (s_type (print_context()) t ^ " cannot be called") p
 				error (s_type (print_context()) t ^ " cannot be called") p
 		)
 		)
-	| AKUsing (et,cl,ef,eparam) when Meta.has Meta.Generic ef.cf_meta ->
+	| AKUsing (et,cl,ef,eparam,forced_inline (* TOOD? *)) when Meta.has Meta.Generic ef.cf_meta ->
 		(match et.eexpr with
 		(match et.eexpr with
 		| TField(ec,fa) ->
 		| TField(ec,fa) ->
 			type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p
 			type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p
 		| _ -> assert false)
 		| _ -> assert false)
-	| AKUsing (et,cl,ef,eparam) ->
+	| AKUsing (et,cl,ef,eparam,force_inline) ->
 		begin match ef.cf_kind with
 		begin match ef.cf_kind with
 		| Method MethMacro ->
 		| Method MethMacro ->
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
@@ -553,7 +553,7 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 					end
 					end
 				| _ -> assert false
 				| _ -> assert false
 			in
 			in
-			make_call ctx et (eparam :: params) r p
+			make_call ctx ~force_inline et (eparam :: params) r p
 		end
 		end
 	| AKMacro (ethis,cf) ->
 	| AKMacro (ethis,cf) ->
 		if ctx.macro_depth > 300 then error "Stack overflow" p;
 		if ctx.macro_depth > 300 then error "Stack overflow" p;

+ 7 - 7
src/typing/fields.ml

@@ -134,7 +134,7 @@ let field_access ctx mode f fmode t e p =
 			let e = mk (TField(e,fmode)) t p in
 			let e = mk (TField(e,fmode)) t p in
 			let ethis = get_this ctx p in
 			let ethis = get_this ctx p in
 			let ethis = {ethis with etype = TAbstract(a,List.map snd a.a_params)} in
 			let ethis = {ethis with etype = TAbstract(a,List.map snd a.a_params)} in
-			AKUsing(e,ctx.curclass,f,ethis)
+			AKUsing(e,ctx.curclass,f,ethis,false)
 		| _ ->
 		| _ ->
 			(match m, mode with
 			(match m, mode with
 			| MethInline, _ -> AKInline (e,f,fmode,t)
 			| MethInline, _ -> AKInline (e,f,fmode,t)
@@ -208,7 +208,7 @@ let field_access ctx mode f fmode t e p =
 					(* let t = apply_params a.a_params pl (field_type ctx c [] f p) in *)
 					(* let t = apply_params a.a_params pl (field_type ctx c [] f p) in *)
 					let t = (field_type ctx c [] f p) in
 					let t = (field_type ctx c [] f p) in
 					let ef = mk (TField (e,FStatic (c,f))) t p in
 					let ef = mk (TField (e,FStatic (c,f))) t p in
-					AKUsing (ef,c,f,this)
+					AKUsing (ef,c,f,this,false)
 				end else
 				end else
 					AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [this.etype] t) p) [this] t p)
 					AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [this.etype] t) p) [this] t p)
 			end else if mode = MSet then
 			end else if mode = MSet then
@@ -263,7 +263,7 @@ let rec using_field ctx mode e i p =
 					) monos cf.cf_params;
 					) monos cf.cf_params;
 					let et = type_module_type ctx (TClassDecl c) None p in
 					let et = type_module_type ctx (TClassDecl c) None p in
 					ImportHandling.maybe_mark_import_position ctx pc;
 					ImportHandling.maybe_mark_import_position ctx pc;
-					AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e)
+					AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e,false)
 				| _ ->
 				| _ ->
 					raise Not_found
 					raise Not_found
 			end
 			end
@@ -284,7 +284,7 @@ let rec using_field ctx mode e i p =
 		(* global using *)
 		(* global using *)
 		let acc = loop ctx.g.global_using in
 		let acc = loop ctx.g.global_using in
 		(match acc with
 		(match acc with
-		| AKUsing (_,c,_,_) -> add_dependency ctx.m.curmod c.cl_module
+		| AKUsing (_,c,_,_,_) -> add_dependency ctx.m.curmod c.cl_module
 		| _ -> assert false);
 		| _ -> assert false);
 		acc
 		acc
 	with Not_found ->
 	with Not_found ->
@@ -496,7 +496,7 @@ let rec type_field ?(resume=false) ctx e i p mode =
 				let f = PMap.find ("set_" ^ f.cf_name) c.cl_statics in
 				let f = PMap.find ("set_" ^ f.cf_name) c.cl_statics in
 				let t = field_type f in
 				let t = field_type f in
 				let ef = field_expr f t in
 				let ef = field_expr f t in
-				AKUsing (ef,c,f,e)
+				AKUsing (ef,c,f,e,false)
 			| (MGet | MCall), Var {v_read = AccNever} ->
 			| (MGet | MCall), Var {v_read = AccNever} ->
 				AKNo f.cf_name
 				AKNo f.cf_name
 			| (MGet | MCall), _ ->
 			| (MGet | MCall), _ ->
@@ -519,7 +519,7 @@ let rec type_field ?(resume=false) ctx e i p mode =
 					| _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") p
 					| _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") p
 				end;
 				end;
 				let ef = field_expr f t in
 				let ef = field_expr f t in
-				AKUsing (ef,c,f,e)
+				AKUsing (ef,c,f,e,false)
 			| MSet, _ ->
 			| MSet, _ ->
 				error "This operation is unsupported" p)
 				error "This operation is unsupported" p)
 		with Not_found -> try
 		with Not_found -> try
@@ -549,7 +549,7 @@ let rec type_field ?(resume=false) ctx e i p mode =
 				if is_write then
 				if is_write then
 					AKFieldSet(e,ef,i,r)
 					AKFieldSet(e,ef,i,r)
 				else
 				else
-					AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e)) [EConst (String i),p] NoValue p)
+					AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e,false)) [EConst (String i),p] NoValue p)
 			in
 			in
 			get_resolve (mode = MSet)
 			get_resolve (mode = MSet)
 		with Not_found ->
 		with Not_found ->

+ 9 - 8
src/typing/typer.ml

@@ -499,7 +499,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 				| _ -> assert false
 				| _ -> assert false
 			end;
 			end;
 			make_call ctx e1 [ethis;Texpr.Builder.make_string ctx.t fname null_pos;e2] t p
 			make_call ctx e1 [ethis;Texpr.Builder.make_string ctx.t fname null_pos;e2] t p
-		| AKUsing(ef,_,_,et) ->
+		| AKUsing(ef,_,_,et,_) ->
 			(* this must be an abstract setter *)
 			(* this must be an abstract setter *)
 			let e2,ret = match follow ef.etype with
 			let e2,ret = match follow ef.etype with
 				| TFun([_;(_,_,t)],ret) ->
 				| TFun([_;(_,_,t)],ret) ->
@@ -582,7 +582,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 				mk (TVar (v,Some e)) ctx.t.tvoid p;
 				mk (TVar (v,Some e)) ctx.t.tvoid p;
 				e'
 				e'
 			]) t p
 			]) t p
-		| AKUsing(ef,c,cf,et) ->
+		| AKUsing(ef,c,cf,et,_) ->
 			(* abstract setter + getter *)
 			(* abstract setter + getter *)
 			let ta = match c.cl_kind with KAbstractImpl a -> TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) | _ -> assert false in
 			let ta = match c.cl_kind with KAbstractImpl a -> TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) | _ -> assert false in
 			let ret = match follow ef.etype with
 			let ret = match follow ef.etype with
@@ -1704,7 +1704,7 @@ and type_object_decl ctx fl with_type p =
 		mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos
 		mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos
 	)
 	)
 
 
-and type_new ctx path el with_type p =
+and type_new ctx path el with_type force_inline p =
 	let unify_constructor_call c params f ct = match follow ct with
 	let unify_constructor_call c params f ct = match follow ct with
 		| TFun (args,r) ->
 		| TFun (args,r) ->
 			(try
 			(try
@@ -1775,7 +1775,7 @@ and type_new ctx path el with_type p =
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 		let e = mk (TTypeExpr (TClassDecl c)) ta p in
 		let e = mk (TTypeExpr (TClassDecl c)) ta p in
 		let e = mk (TField (e,(FStatic (c,cf)))) ct p in
 		let e = mk (TField (e,(FStatic (c,cf)))) ct p in
-		make_call ctx e el t p
+		make_call ctx e el t ~force_inline p
 	| TInst (c,params) | TAbstract({a_impl = Some c},params) ->
 	| TInst (c,params) | TAbstract({a_impl = Some c},params) ->
 		let el,_,_ = build_constructor_call c params in
 		let el,_,_ = build_constructor_call c params in
 		mk (TNew (c,params,el)) t p
 		mk (TNew (c,params,el)) t p
@@ -2226,7 +2226,7 @@ and type_meta ctx m e1 with_type p =
 			| ECall(e1,el) ->
 			| ECall(e1,el) ->
 				type_call ctx e1 el WithType.value true p
 				type_call ctx e1 el WithType.value true p
 			| ENew (t,el) ->
 			| ENew (t,el) ->
-				let e = type_new ctx t el with_type p in
+				let e = type_new ctx t el with_type true p in
 				{e with eexpr = TMeta((Meta.Inline,[],null_pos),e)}
 				{e with eexpr = TMeta((Meta.Inline,[],null_pos),e)}
 			| EFunction(Some(_) as name,e1) ->
 			| EFunction(Some(_) as name,e1) ->
 				type_local_function ctx name true e1 with_type p
 				type_local_function ctx name true e1 with_type p
@@ -2253,14 +2253,15 @@ and type_call ctx e el (with_type:WithType.t) inline p =
 				| None ->
 				| None ->
 					e
 					e
 				end;
 				end;
+			| AKUsing(e,c,cf,ef,_) ->
+				AKUsing(e,c,cf,ef,true)
 			| AKExpr {eexpr = TLocal _} ->
 			| AKExpr {eexpr = TLocal _} ->
 				display_error ctx "Cannot force inline on local functions" p;
 				display_error ctx "Cannot force inline on local functions" p;
 				e
 				e
 			| _ ->
 			| _ ->
 				e
 				e
 		in
 		in
-		let e = build_call ctx e el with_type p in
-		e
+		build_call ctx e el with_type p
 	in
 	in
 	match e, el with
 	match e, el with
 	| (EConst (Ident "trace"),p) , e :: el ->
 	| (EConst (Ident "trace"),p) , e :: el ->
@@ -2435,7 +2436,7 @@ and type_expr ctx (e,p) (with_type:WithType.t) =
 	| ECall (e,el) ->
 	| ECall (e,el) ->
 		type_call ctx e el with_type false p
 		type_call ctx e el with_type false p
 	| ENew (t,el) ->
 	| ENew (t,el) ->
-		type_new ctx t el with_type p
+		type_new ctx t el with_type false p
 	| EUnop (op,flag,e) ->
 	| EUnop (op,flag,e) ->
 		type_unop ctx op flag e p
 		type_unop ctx op flag e p
 	| EFunction (name,f) ->
 	| EFunction (name,f) ->

+ 2 - 2
src/typing/typerBase.ml

@@ -15,7 +15,7 @@ type access_kind =
 	| AKSet of texpr * t * tclass_field
 	| AKSet of texpr * t * tclass_field
 	| AKInline of texpr * tclass_field * tfield_access * t
 	| AKInline of texpr * tclass_field * tfield_access * t
 	| AKMacro of texpr * tclass_field
 	| AKMacro of texpr * tclass_field
-	| AKUsing of texpr * tclass * tclass_field * texpr
+	| AKUsing of texpr * tclass * tclass_field * texpr * bool (* forced inline *)
 	| AKAccess of tabstract * tparams * tclass * texpr * texpr
 	| AKAccess of tabstract * tparams * tclass * texpr * texpr
 	| AKFieldSet of texpr * texpr * string * t
 	| AKFieldSet of texpr * texpr * string * t
 
 
@@ -144,7 +144,7 @@ let s_access_kind acc =
 	| AKSet(e,t,cf) -> Printf.sprintf "AKSet(%s, %s, %s)" (se e) (st t) cf.cf_name
 	| AKSet(e,t,cf) -> Printf.sprintf "AKSet(%s, %s, %s)" (se e) (st t) cf.cf_name
 	| AKInline(e,cf,fa,t) -> Printf.sprintf "AKInline(%s, %s, %s, %s)" (se e) cf.cf_name (sfa fa) (st t)
 	| AKInline(e,cf,fa,t) -> Printf.sprintf "AKInline(%s, %s, %s, %s)" (se e) cf.cf_name (sfa fa) (st t)
 	| AKMacro(e,cf) -> Printf.sprintf "AKMacro(%s, %s)" (se e) cf.cf_name
 	| AKMacro(e,cf) -> Printf.sprintf "AKMacro(%s, %s)" (se e) cf.cf_name
-	| AKUsing(e1,c,cf,e2) -> Printf.sprintf "AKMacro(%s, %s, %s, %s)" (se e1) (s_type_path c.cl_path) cf.cf_name (se e2)
+	| AKUsing(e1,c,cf,e2,b) -> Printf.sprintf "AKUsing(%s, %s, %s, %s, %b)" (se e1) (s_type_path c.cl_path) cf.cf_name (se e2) b
 	| AKAccess(a,tl,c,e1,e2) -> Printf.sprintf "AKAccess(%s, [%s], %s, %s, %s)" (s_type_path a.a_path) (String.concat ", " (List.map st tl)) (s_type_path c.cl_path) (se e1) (se e2)
 	| AKAccess(a,tl,c,e1,e2) -> Printf.sprintf "AKAccess(%s, [%s], %s, %s, %s)" (s_type_path a.a_path) (String.concat ", " (List.map st tl)) (s_type_path c.cl_path) (se e1) (se e2)
 	| AKFieldSet(_) -> ""
 	| AKFieldSet(_) -> ""
 
 

+ 18 - 0
tests/optimization/src/issues/IssueInline.hx

@@ -22,6 +22,16 @@ private class InlinePoint {
 	}
 	}
 }
 }
 
 
+private abstract InlineAbstract(Int) {
+	public function new(x:Int) {
+		this = x;
+	}
+
+	public function twice() {
+		return this * 2;
+	}
+}
+
 class IssueInline {
 class IssueInline {
 	@:js('
 	@:js('
 		TestJs.use(4);
 		TestJs.use(4);
@@ -55,6 +65,14 @@ class IssueInline {
 		use(x.y);
 		use(x.y);
 	}
 	}
 
 
+	@:js('
+		TestJs.use(24);
+	')
+	static function testAbstract() {
+		var a = inline new InlineAbstract(12);
+		use(inline a.twice());
+	}
+
 	@:pure(false)
 	@:pure(false)
 	static function testInline(i:Int) {
 	static function testInline(i:Int) {
 		return i + 1;
 		return i + 1;