Browse Source

[analyzer] don't drop @:pure metas after purity inference (fixes #9064)

Aleksandr Kuzmenko 5 years ago
parent
commit
bbe6b18069

+ 3 - 3
src/optimization/analyzer.ml

@@ -1098,9 +1098,9 @@ module Run = struct
 		let com = ctx.Typecore.com in
 		let com = ctx.Typecore.com in
 		let config = get_base_config com in
 		let config = get_base_config com in
 		with_timer config.detail_times ["other"] (fun () ->
 		with_timer config.detail_times ["other"] (fun () ->
-			let cfl = if config.optimize && config.purity_inference then with_timer config.detail_times ["optimize";"purity-inference"] (fun () -> Purity.infer com) else [] in
-			List.iter (run_on_type ctx config) types;
-			List.iter (fun cf -> cf.cf_meta <- List.filter (fun (m,_,_) -> m <> Meta.Pure) cf.cf_meta) cfl
+			if config.optimize && config.purity_inference then
+				with_timer config.detail_times ["optimize";"purity-inference"] (fun () -> Purity.infer com);
+			List.iter (run_on_type ctx config) types
 		)
 		)
 end
 end
 ;;
 ;;

+ 5 - 7
src/optimization/analyzerTexpr.ml

@@ -1286,12 +1286,10 @@ module Purity = struct
 				end
 				end
 			| _ -> ()
 			| _ -> ()
 		) com.types;
 		) com.types;
-		Hashtbl.fold (fun _ node acc ->
+		Hashtbl.iter (fun _ node ->
 			match node.pn_purity with
 			match node.pn_purity with
-			| Pure | MaybePure ->
-				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 :: acc
-			| _ ->
-				acc
-		) node_lut [];
+			| 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_lut;
 end
 end

+ 27 - 0
tests/misc/projects/Issue9064/Check.hx

@@ -0,0 +1,27 @@
+import haxe.macro.Type;
+import haxe.macro.Context;
+
+class Check {
+	static public function init() {
+		Context.onGenerate(function(types:Array<Type>) {
+			for(type in types) {
+				switch type {
+					case TInst(_.get() => cls, []) if(cls.name == 'Main'):
+						for(field in cls.statics.get()) {
+							if(field.name == 'testMeta') {
+								var pureCount = field.meta.extract(':pure').length;
+								if(pureCount != 1) {
+									Context.error('Main.testMeta is expected to have exactly one @:pure meta, got $pureCount', field.pos);
+									return;
+								}
+								//success
+								return;
+							}
+						}
+					case _:
+				}
+			}
+			Context.error('Main.testMeta not found', (macro {}).pos);
+		});
+	}
+}

+ 6 - 0
tests/misc/projects/Issue9064/Main.hx

@@ -0,0 +1,6 @@
+class Main {
+	static function main() {}
+
+	@:pure @:keep
+	static function testMeta() {}
+}

+ 4 - 0
tests/misc/projects/Issue9064/compile.hxml

@@ -0,0 +1,4 @@
+-main Main
+-D analyzer-optimize
+--macro Check.init()
+-js bin/test.js