Browse Source

[typer] revert tvar change, no longer allow forced inline on local functions

closes #7521
Simon Krajewski 6 years ago
parent
commit
489019adaa

+ 10 - 10
src/codegen/gencommon/closuresToClass.ml

@@ -191,29 +191,29 @@ let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfu
 				| None -> Type.map_expr run e
 				| Some tparam_anon_decl ->
 					(match (vv, ve) with
-						| ({ v_extra = Some( _ :: _, _,_) } as v), Some ({ eexpr = TFunction tf } as f)
-						| ({ v_extra = Some( _ :: _, _,_) } as v), Some { eexpr = TArrayDecl([{ eexpr = TFunction tf } as f]) | TCall({ eexpr = TIdent "__array__" }, [{ eexpr = TFunction tf } as f]) } -> (* captured transformation *)
+						| ({ v_extra = Some( _ :: _, _) } as v), Some ({ eexpr = TFunction tf } as f)
+						| ({ v_extra = Some( _ :: _, _) } as v), Some { eexpr = TArrayDecl([{ eexpr = TFunction tf } as f]) | TCall({ eexpr = TIdent "__array__" }, [{ eexpr = TFunction tf } as f]) } -> (* captured transformation *)
 							tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr };
 							{ e with eexpr = TBlock([]) }
 						| _ ->
 							Type.map_expr run { e with eexpr = TVar(vv, ve) })
 					)
-			| TBinop(OpAssign, { eexpr = TLocal({ v_extra = Some(_ :: _, _,_) } as v)}, ({ eexpr= TFunction tf } as f)) when is_some tparam_anon_decl ->
+			| TBinop(OpAssign, { eexpr = TLocal({ v_extra = Some(_ :: _, _) } as v)}, ({ eexpr= TFunction tf } as f)) when is_some tparam_anon_decl ->
 				(match tparam_anon_decl with
 					| None -> assert false
 					| Some tparam_anon_decl ->
 						tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr };
 						{ e with eexpr = TBlock([]) }
 				)
-			| TLocal ({ v_extra = Some( _ :: _, _, _) } as v) ->
+			| TLocal ({ v_extra = Some( _ :: _, _) } as v) ->
 				(match tparam_anon_acc with
 				| None -> Type.map_expr run e
 				| Some tparam_anon_acc -> tparam_anon_acc v e false)
-			| TArray ( ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _, _) } as v) } as expr), _) -> (* captured transformation *)
+			| TArray ( ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _) } as v) } as expr), _) -> (* captured transformation *)
 				(match tparam_anon_acc with
 				| None -> Type.map_expr run e
 				| Some tparam_anon_acc -> tparam_anon_acc v { expr with etype = e.etype } false)
-			| TMeta((Meta.Custom ":tparamcall",_,_),({ eexpr=TLocal ({ v_extra = Some( _ :: _, _, _) } as v) } as expr)) ->
+			| TMeta((Meta.Custom ":tparamcall",_,_),({ eexpr=TLocal ({ v_extra = Some( _ :: _, _) } as v) } as expr)) ->
 				(match tparam_anon_acc with
 				| None -> Type.map_expr run e
 				| Some tparam_anon_acc -> tparam_anon_acc v expr true)
@@ -333,12 +333,12 @@ let get_captured expr =
 				Type.iter traverse expr
 			| TVar (v, opt) ->
 				(match v.v_extra with
-					| Some(_ :: _, _, _) -> ()
+					| Some(_ :: _, _) -> ()
 					| _ ->
 						check_params v.v_type);
 				Hashtbl.add ignored v.v_id v;
 				ignore(Option.map traverse opt)
-			| TLocal { v_extra = Some( (_ :: _ ),_,_) } ->
+			| TLocal { v_extra = Some( (_ :: _ ),_) } ->
 				()
 			| TLocal(( { v_capture = true } ) as v) ->
 				(if not (Hashtbl.mem ignored v.v_id || Hashtbl.mem ret v.v_id) then begin check_params v.v_type; Hashtbl.replace ret v.v_id expr end);
@@ -523,7 +523,7 @@ let configure gen ft =
 
 		(match tvar with
 		| None -> ()
-		| Some ({ v_extra = Some(_ :: _, _, _) } as v) ->
+		| Some ({ v_extra = Some(_ :: _, _) } as v) ->
 			Hashtbl.add tvar_to_cdecl v.v_id (cls,captured)
 		| _ -> ());
 
@@ -591,7 +591,7 @@ let configure gen ft =
 				| _ -> assert false) captured
 			in
 			let types = match v.v_extra with
-				| Some(t,_,_) -> t
+				| Some(t,_) -> t
 				| _ -> assert false
 			in
 			let monos = List.map (fun _ -> mk_mono()) types in

+ 1 - 1
src/context/abstractCast.ml

@@ -237,7 +237,7 @@ let handle_abstract_casts ctx e =
 				let rec find_abstract e t = match follow t,e.eexpr with
 					| TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e
 					| _,TCast(e1,None) -> find_abstract e1 e1.etype
-					| _,TLocal {v_extra = Some(_,e',true)} ->
+					| _,TLocal {v_extra = Some(_,Some e')} ->
 						begin match follow e'.etype with
 						| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> a,pl,mk (TCast(e,None)) e'.etype e.epos
 						| _ -> raise Not_found

+ 8 - 9
src/core/json/genjson.ml

@@ -252,14 +252,13 @@ and generate_type_parameter ctx (s,t) =
 (* texpr *)
 
 and generate_tvar ctx v =
-	let generate_extra (params,e,inline) = jobject (
-		[
-			"params",jlist (generate_type_parameter ctx) params;
-			"expr",jobject [
-				("string",jstring (s_expr_pretty false "" false (s_type (print_context())) e))
-			];
-			"isInline",jbool inline;
-		]
+	let generate_extra (params,eo) = jobject (
+		("params",jlist (generate_type_parameter ctx) params) ::
+		(match eo with
+		| None -> []
+		| Some e ->	["expr",jobject [
+			("string",jstring (s_expr_pretty false "" false (s_type (print_context())) e))
+		]]);
 	) in
 	let fields = [
 		"id",jint v.v_id;
@@ -269,8 +268,8 @@ and generate_tvar ctx v =
 		"extra",jopt generate_extra v.v_extra;
 		"meta",generate_metadata ctx v.v_meta;
 		"pos",generate_pos ctx v.v_pos;
-		"isInline",jbool (match v.v_extra with Some (_,_,b) -> b | _ -> false);
 		"isFinal",jbool v.v_final;
+		"isInline",jbool (match v.v_extra with Some (_,Some _) -> true | _ -> false);
 	] in
 	let origin_to_int = function
 		| TVOLocalVariable -> 0

+ 3 - 3
src/core/type.ml

@@ -83,7 +83,7 @@ and tconstant =
 	| TThis
 	| TSuper
 
-and tvar_extra = (type_params * texpr * bool) option
+and tvar_extra = (type_params * texpr option) option
 
 and tvar_origin =
 	| TVOLocalVariable
@@ -1533,8 +1533,8 @@ module Printer = struct
 			"a_write",s_opt (fun cf -> cf.cf_name) a.a_write;
 		]
 
-	let s_tvar_extra (tl,e,_) =
-		Printf.sprintf "Some(%s, %s)" (s_type_params tl) (s_expr_ast true "" s_type e)
+	let s_tvar_extra (tl,eo) =
+		Printf.sprintf "Some(%s, %s)" (s_type_params tl) (s_opt (s_expr_ast true "" s_type) eo)
 
 	let s_tvar v =
 		s_record_fields "" [

+ 6 - 6
src/filters/capturedVars.ml

@@ -128,8 +128,8 @@ let captured_vars com e =
 			let tmp_used = ref used in
 			let rec browse = function
 				| Block f | Loop f | Function f -> f browse
-				| Use ({ v_extra = Some( _ :: _, _, _) })
-				| Assign ({ v_extra = Some( _ :: _, _, _) }) when com.platform = Cs || com.platform = Java ->
+				| Use ({ v_extra = Some( _ :: _, _) })
+				| Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || com.platform = Java ->
 					(* Java and C# deal with functions with type parameters in a different way *)
 					(* so they do should not be wrapped *)
 					()
@@ -219,8 +219,8 @@ let captured_vars com e =
 					incr depth;
 					f (collect_vars false);
 					decr depth;
-				| Use ({ v_extra = Some( _ :: _, _, _) })
-				| Assign ({ v_extra = Some( _ :: _, _, _) }) when com.platform = Cs || com.platform = Java ->
+				| Use ({ v_extra = Some( _ :: _, _) })
+				| Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || com.platform = Java ->
 					(* Java/C# use a special handling for functions with type parmaters *)
 					()
 				| Declare v ->
@@ -256,8 +256,8 @@ let captured_vars com e =
 			decr depth;
 		| Declare v ->
 			vars := PMap.add v.v_id !depth !vars;
-		| Use ({ v_extra = Some( _ :: _, _, _) })
-		| Assign ({ v_extra = Some( _ :: _, _, _) }) when com.platform = Cs || com.platform = Java ->
+		| Use ({ v_extra = Some( _ :: _, _) })
+		| Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || com.platform = Java ->
 			()
 		| Use v ->
 			(try

+ 1 - 1
src/generators/genjava.ml

@@ -2423,7 +2423,7 @@ let generate con =
 	TArrayTransform.configure gen (
 	fun e _ ->
 		match e.eexpr with
-			| TArray ({ eexpr = TLocal { v_extra = Some( _ :: _, _, _) } }, _) -> (* captured transformation *)
+			| TArray ({ eexpr = TLocal { v_extra = Some( _ :: _, _) } }, _) -> (* captured transformation *)
 				false
 			| TArray(e1, e2) ->
 				( match run_follow gen (follow e1.etype) with

+ 2 - 3
src/macro/macroApi.ml

@@ -1093,11 +1093,10 @@ and encode_tconst c =
 	encode_enum ITConstant tag pl
 
 and encode_tvar v =
-	let f_extra (pl,e,inline) =
+	let f_extra (pl,e) =
 		encode_obj [
 			"params",encode_type_params pl;
-			"expr",encode_texpr e;
-			"isInline",vbool inline;
+			"expr",vopt encode_texpr e
 		]
 	in
 	encode_obj [

+ 1 - 1
src/optimization/analyzerTexpr.ml

@@ -687,7 +687,7 @@ module Fusion = struct
 			let num_writes = state#get_writes v in
 			let can_be_used_as_value = can_be_used_as_value com e in
 			let is_compiler_generated = match v.v_kind with VUser _ | VInlined -> false | _ -> true in
-			let has_type_params = match v.v_extra with Some (tl,_,_) when tl <> [] -> true | _ -> false in
+			let has_type_params = match v.v_extra with Some (tl,_) when tl <> [] -> true | _ -> false in
 			let b = num_uses <= 1 &&
 			        num_writes = 0 &&
 			        can_be_used_as_value &&

+ 2 - 2
src/optimization/analyzerTypes.ml

@@ -210,11 +210,11 @@ module Graph = struct
 		} in
 		DynArray.add g.g_var_infos vi;
 		let i = DynArray.length g.g_var_infos - 1 in
-		v.v_extra <- Some([],mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos,false);
+		v.v_extra <- Some([],Some (mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos));
 		vi
 
 	let get_var_info g v = match v.v_extra with
-		| Some(_,{eexpr = TConst (TInt i32)},_) -> DynArray.get g.g_var_infos (Int32.to_int i32)
+		| Some(_,Some {eexpr = TConst (TInt i32)}) -> DynArray.get g.g_var_infos (Int32.to_int i32)
 		| _ ->
 			print_endline "Unbound variable, please report this";
 			print_endline (Printer.s_tvar v);

+ 1 - 1
src/optimization/inline.ml

@@ -394,7 +394,7 @@ class inline_state ctx ethis params cf f p = object(self)
 					_had_side_effect <- true;
 					l.i_force_temp <- true;
 				end;
-				if l.i_abstract_this then l.i_subst.v_extra <- Some ([],e,true);
+				if l.i_abstract_this then l.i_subst.v_extra <- Some ([],Some e);
 				loop ((l,e) :: acc) pl al false
 			| [], (v,opt) :: al ->
 				let l = self#declare v in

+ 17 - 18
src/typing/typer.ml

@@ -282,14 +282,6 @@ let unify_min ctx el =
 		if not ctx.untyped then display_error ctx (error_msg (Unify l)) p;
 		(List.hd el).etype
 
-let inline_local_function ctx v e params t p =
-	(* create a fake class with a fake field to emulate inlining *)
-	let c = mk_class ctx.m.curmod (["local"],v.v_name) e.epos null_pos in
-	let cf = { (mk_field v.v_name v.v_type e.epos null_pos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in
-	c.cl_extern <- true;
-	c.cl_fields <- PMap.add cf.cf_name cf PMap.empty;
-	AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, FInstance(c,[],cf), t)
-
 let rec type_ident_raise ctx i p mode =
 	match i with
 	| "true" ->
@@ -332,14 +324,20 @@ let rec type_ident_raise ctx i p mode =
 	try
 		let v = PMap.find i ctx.locals in
 		(match v.v_extra with
-		| Some (params,e,inline) ->
+		| Some (params,e) ->
 			let t = monomorphs params v.v_type in
-			(match e,inline with
-			| { eexpr = TFunction f },true when ctx.com.display.dms_inline ->
+			(match e with
+			| Some ({ eexpr = TFunction f } as e) when ctx.com.display.dms_inline ->
 				begin match mode with
 					| MSet -> error "Cannot set inline closure" p
 					| MGet -> error "Cannot create closure on inline closure" p
-					| MCall -> inline_local_function ctx v e params t p
+					| MCall ->
+						(* create a fake class with a fake field to emulate inlining *)
+						let c = mk_class ctx.m.curmod (["local"],v.v_name) e.epos null_pos in
+						let cf = { (mk_field v.v_name v.v_type e.epos null_pos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in
+						c.cl_extern <- true;
+						c.cl_fields <- PMap.add cf.cf_name cf PMap.empty;
+						AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, FInstance(c,[],cf), t)
 				end
 			| _ ->
 				AKExpr (mk (TLocal v) t p))
@@ -1980,7 +1978,7 @@ and type_local_function ctx name inline f with_type p =
 		| Some v ->
 			if starts_with v '$' then display_error ctx "Variable names starting with a dollar are not allowed" p;
 			let v = (add_local_with_origin ctx TVOLocalFunction v ft pname) in
-			if params <> [] then v.v_extra <- Some (params,(mk (TConst TNull) t_dynamic null_pos),false);
+			if params <> [] then v.v_extra <- Some (params,None);
 			Some v
 	) in
 	let curfun = match ctx.curfun with
@@ -2002,7 +2000,7 @@ and type_local_function ctx name inline f with_type p =
 	| Some v ->
 		Typeload.generate_value_meta ctx.com None (fun m -> v.v_meta <- m :: v.v_meta) f.f_args;
 		let open LocalUsage in
-		v.v_extra <- Some (params,e,inline);
+		if params <> [] || inline then v.v_extra <- Some (params,if inline then Some e else None);
 		let rec loop = function
 			| LocalUsage.Block f | LocalUsage.Loop f | LocalUsage.Function f -> f loop
 			| LocalUsage.Use v2 | LocalUsage.Assign v2 when v == v2 -> raise Exit
@@ -2248,10 +2246,11 @@ and type_call ctx e el (with_type:WithType.t) inline p =
 				| None ->
 					e
 				end;
-			| AKExpr {eexpr = TLocal ({v_extra = Some(params,({eexpr = TFunction _} as e1),_)} as v)} ->
-				let t = monomorphs params v.v_type in
-				inline_local_function ctx v e1 params t p
-			| _ -> e
+			| AKExpr {eexpr = TLocal _} ->
+				display_error ctx "Cannot force inline on local functions" p;
+				e
+			| _ ->
+				e
 		in
 		let e = build_call ctx e el with_type p in
 		e

+ 1 - 1
std/haxe/macro/Type.hx

@@ -753,7 +753,7 @@ typedef TVar = {
 		Special information which is internally used to keep track of closure.
 		information
 	**/
-	public var extra(default,never):Null<{params: Array<TypeParameter>, expr: TypedExpr, isInline: Bool}>;
+	public var extra(default,never):Null<{params: Array<TypeParameter>, expr: Null<TypedExpr>}>;
 
 	/**
 		The metadata of the variable.

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

@@ -35,36 +35,6 @@ class IssueInline {
 		testInline(3);
 	}
 
-	@:js('
-		var testInline = function(i) {return i + 1;};
-		TestJs.use(4);
-		TestJs.use(testInline(3));
-		testInline(3);
-	')
-	static function test2() {
-		function testInline(i:Int) {
-			return i + 1;
-		}
-		use(inline testInline(3));
-		inline testInline(3);
-		use(testInline(3));
-		testInline(3);
-	}
-
-	@:js('
-		TestJs.use(4);
-		TestJs.use(4);
-	')
-	static function test3() {
-		inline function testInline(i:Int) {
-			return i + 1;
-		}
-		use(inline testInline(3));
-		inline testInline(3);
-		use(testInline(3));
-		testInline(3);
-	}
-
 	@:js('
 		TestJs.use(1);
 		TestJs.use(2);