Browse Source

[dce] keep constructor if any instance field is kept (fixes #6062) (#6690)

* [dce] keep constructor if any instance field is kept (fixes #6062)

* [dce] keep constructor if super constructor is kept (fixes #6062 even more)

* improved test case (#6062)

* mark constructor as kept if instance field is marked (#6062)

* removed obsolete check from keep_field (#6062)

* and obsolete function

* comment [skip ci]

* cleanup
Alexander Kuzmenko 7 years ago
parent
commit
2ee49deb4c
2 changed files with 42 additions and 3 deletions
  1. 17 3
      src/optimization/dce.ml
  2. 25 0
      tests/unit/src/unit/issues/Issue6062.hx

+ 17 - 3
src/optimization/dce.ml

@@ -83,13 +83,23 @@ let keep_whole_enum dce en =
 	Meta.has Meta.Keep en.e_meta
 	|| not (dce.full || is_std_file dce en.e_module.m_extra.m_file || has_meta Meta.Dce en.e_meta)
 
-(* check if a field is kept *)
-let keep_field dce cf c is_static =
+(*
+	Check if a field is kept.
+	`keep_field` is checked to determine the DCE entry points, i.e. all fields that have `@:keep` or kept for other reasons.
+	And then it is used at the end to check which fields can be filtered from their classes.
+*)
+let rec keep_field dce cf c is_static =
 	Meta.has Meta.Keep cf.cf_meta
 	|| Meta.has Meta.Used cf.cf_meta
 	|| cf.cf_name = "__init__"
 	|| not (is_physical_field cf)
 	|| (not is_static && overrides_extern_field cf c)
+	|| (
+		cf.cf_name = "new"
+		&& match c.cl_super with (* parent class kept constructor *)
+			| Some ({ cl_constructor = Some ctor } as csup, _) -> keep_field dce ctor csup false
+			| _ -> false
+	)
 
 (* marking *)
 
@@ -134,7 +144,11 @@ and mark_field dce c cf stat =
 			| None -> add cf
 			| Some (c,_) -> mark_field dce c cf stat
 		end else
-			add cf
+			add cf;
+		if not stat then
+			match c.cl_constructor with
+				| None -> ()
+				| Some ctor -> mark_field dce c ctor false
 	end
 
 let rec update_marked_class_fields dce c =

+ 25 - 0
tests/unit/src/unit/issues/Issue6062.hx

@@ -0,0 +1,25 @@
+package unit.issues;
+
+class Issue6062 extends unit.Test {
+	function test() {
+		var child = Type.createInstance(Child, []);
+		t(child.parentFn());
+		t(Parent.tmp);
+	}
+}
+
+private class Parent {
+	static public var tmp:Bool = false;
+
+	public var parentFn = function() return true;
+
+	function new() {
+		tmp = OnlyParentNewReferencesMe.field;
+	}
+}
+
+private class Child extends Parent {}
+
+private class OnlyParentNewReferencesMe {
+	static public var field = true;
+}