浏览代码

don't inline Meta.Pure meta if it was added automatically (fixes #9690)

Aleksandr Kuzmenko 5 年之前
父节点
当前提交
1f9bf476dd

+ 4 - 2
src/context/purityState.ml

@@ -18,6 +18,7 @@ type t =
 	| Pure
 	| Impure
 	| MaybePure
+	| InferredPure
 	| ExpectPure of pos
 
 let get_purity_from_meta meta =
@@ -25,7 +26,7 @@ let get_purity_from_meta meta =
 		begin match Meta.get Meta.Pure meta with
 		| (_,[EConst(Ident s),p],_) ->
 			begin match s with
-			| "true" -> Pure
+			| "true" | "inferredPure" -> Pure
 			| "false" -> Impure
 			| "expect" -> ExpectPure p
 			| _ -> error ("Unsupported purity value " ^ s ^ ", expected true or false") p
@@ -39,7 +40,7 @@ let get_purity_from_meta meta =
 		MaybePure
 
 let get_purity c cf = match get_purity_from_meta cf.cf_meta with
-	| Pure -> Pure
+	| Pure | InferredPure -> Pure
 	| Impure -> Impure
 	| ExpectPure p -> ExpectPure p
 	| _ -> get_purity_from_meta c.cl_meta
@@ -63,5 +64,6 @@ let is_explicitly_impure fa = match fa with
 let to_string = function
 	| Pure -> "pure"
 	| Impure -> "impure"
+	| InferredPure -> "inferredPure"
 	| MaybePure -> "maybe"
 	| ExpectPure _ -> "expect"

+ 3 - 3
src/optimization/analyzerTexpr.ml

@@ -1070,7 +1070,7 @@ module Purity = struct
 	let rec taint node = match node.pn_purity with
 		| Impure -> ()
 		| ExpectPure p -> raise (Purity_conflict(node,p));
-		| MaybePure | Pure ->
+		| MaybePure | Pure | InferredPure ->
 			node.pn_purity <- Impure;
 			List.iter taint node.pn_dependents;
 			let rec loop c = match c.cl_super with
@@ -1095,7 +1095,7 @@ module Purity = struct
 		let check_field c cf =
 			let node' = get_node c cf in
 			match node'.pn_purity with
-				| Pure | ExpectPure _ -> ()
+				| Pure | InferredPure | ExpectPure _ -> ()
 				| Impure -> taint_raise node;
 				| MaybePure -> node'.pn_dependents <- node :: node'.pn_dependents
 		in
@@ -1186,7 +1186,7 @@ module Purity = struct
 		Hashtbl.iter (fun _ node ->
 			match node.pn_purity with
 			| Pure | MaybePure when not (List.exists (fun (m,_,_) -> m = Meta.Pure) node.pn_field.cf_meta) ->
-				node.pn_field.cf_meta <- (Meta.Pure,[EConst(Ident "true"),node.pn_field.cf_pos],node.pn_field.cf_pos) :: node.pn_field.cf_meta
+				node.pn_field.cf_meta <- (Meta.Pure,[EConst(Ident "inferredPure"),node.pn_field.cf_pos],node.pn_field.cf_pos) :: node.pn_field.cf_meta
 			| _ -> ()
 		) node_lut;
 end

+ 4 - 1
src/optimization/inline.ml

@@ -272,7 +272,10 @@ let inline_config cls_opt cf call_args return_type =
 
 let inline_metadata e meta =
 	let inline_meta e meta = match meta with
-		| (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos
+		| Meta.Deprecated,_,_ ->
+			mk (TMeta(meta,e)) e.etype e.epos
+		| Meta.Pure,[EConst(Ident ("true"|"false")),_],_ ->
+			mk (TMeta(meta,e)) e.etype e.epos
 		| _ -> e
 	in
 	List.fold_left inline_meta e meta

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

@@ -0,0 +1,18 @@
+package cases.issues;
+
+class Issue9690 extends TestCase {
+	function test(_) {
+		vfs.putContent('B.hx', getTemplate('issues/Issue9690/B.hx'));
+		vfs.putContent('Main.hx', getTemplate('issues/Issue9690/Main.hx.inline'));
+		var args = ['--main', 'Main', '-D', 'analyzer-optimize', '--js', 'test.js'];
+		runHaxe(args);
+		assertSuccess();
+		vfs.putContent('Main.hx', getTemplate('issues/Issue9690/Main.hx.no-inline'));
+		runHaxeJson([], ServerMethods.Invalidate, {file: new FsPath('Main.hx')});
+		runHaxe(args);
+		assertSuccess();
+		runHaxe(['--cmd', 'node test.js']);
+		Assert.isTrue(lastResult.hasError);
+		Assert.isTrue(lastResult.stderr.contains('Error: side effect!'));
+	}
+}

+ 5 - 0
tests/server/test/templates/issues/Issue9690/B.hx

@@ -0,0 +1,5 @@
+abstract B(Int) {
+	public inline function new(v) {
+		this = v;
+	}
+}

+ 25 - 0
tests/server/test/templates/issues/Issue9690/Main.hx.inline

@@ -0,0 +1,25 @@
+abstract A(Int) {
+	public inline function new() {
+		this = 42;
+	}
+
+	inline
+	public function f():B {
+		return new B(new C().f);
+	}
+}
+
+class C {
+	public final f:Int;
+
+	public function new() {
+		f = 3;
+		throw ("side effect!");
+	}
+}
+
+class Main {
+	static function main() {
+		new A().f();
+	}
+}

+ 25 - 0
tests/server/test/templates/issues/Issue9690/Main.hx.no-inline

@@ -0,0 +1,25 @@
+abstract A(Int) {
+	public inline function new() {
+		this = 42;
+	}
+
+	//inline
+	public function f():B {
+		return new B(new C().f);
+	}
+}
+
+class C {
+	public final f:Int;
+
+	public function new() {
+		f = 3;
+		throw ("side effect!");
+	}
+}
+
+class Main {
+	static function main() {
+		new A().f();
+	}
+}