Browse Source

[jvm] build bridges instead of rewriting types

closes #9836
Simon Krajewski 5 years ago
parent
commit
f869eaaac4

+ 7 - 3
src/generators/genjvm.ml

@@ -2169,7 +2169,7 @@ class tclass_to_jvm gctx c = object(self)
 		if (has_class_flag c CAbstract) then jc#add_access_flag 0x0400; (* abstract *)
 		if Meta.has Meta.JvmSynthetic c.cl_meta then jc#add_access_flag 0x1000 (* synthetic *)
 
-	method private handle_relation_type_params =
+	method private build_bridges =
 		let map_type_params t =
 			let has_type_param = ref false in
 			let rec loop t = match follow t with
@@ -2255,7 +2255,11 @@ class tclass_to_jvm gctx c = object(self)
 		| fields,Some(c_sup,tl) ->
 			List.iter (fun cf_impl ->
 				match cf_impl.cf_kind,raw_class_field (fun cf -> apply_params c_sup.cl_params tl cf.cf_type) c_sup tl cf_impl.cf_name with
-				| (Method (MethNormal | MethInline)),(Some(c,tl),_,cf) -> check false cf cf_impl
+				| (Method (MethNormal | MethInline)),(Some(c,tl),_,cf) ->
+					if not (has_class_field_flag cf CfOverload) && jsignature_of_type gctx cf.cf_type <> jsignature_of_type gctx cf_impl.cf_type then
+						make_bridge cf_impl cf.cf_type
+					else
+						check false cf cf_impl
 				| _ -> ()
 			) fields
 		| _ ->
@@ -2519,7 +2523,7 @@ class tclass_to_jvm gctx c = object(self)
 		if not (has_class_flag c CInterface) then begin
 			self#generate_empty_ctor;
 			self#generate_implicit_ctors;
-			self#handle_relation_type_params;
+			self#build_bridges;
 		end;
 		self#generate_signature;
 		if gctx.dynamic_level > 0 && not (Meta.has Meta.NativeGen c.cl_meta) && not (has_class_flag c CInterface) then

+ 0 - 37
src/generators/genshared.ml

@@ -325,42 +325,6 @@ object(self)
 			super_call_fields = DynArray.to_list super_call_fields;
 		}
 
-	method check_overrides c = match List.filter (fun cf -> has_class_field_flag cf CfOverride) c.cl_ordered_fields with
-		| [] ->
-			()
-		| fields ->
-			let csup,map_type = match c.cl_super with
-				| Some(c,tl) -> c,apply_params c.cl_params tl
-				| None -> die "" __LOC__
-			in
-			let fix_covariant_return cf =
-				let tl = match follow cf.cf_type with
-					| TFun(tl,_) -> tl
-					| _ -> die "" __LOC__
-				in
-				match resolve_instance_overload false map_type csup cf.cf_name (List.map (fun (_,_,t) -> Texpr.Builder.make_null t null_pos) tl) with
-				| Some(_,cf',_) ->
-					let tr = match follow cf'.cf_type with
-						| TFun(_,tr) -> tr
-						| _ -> die "" __LOC__
-					in
-					cf.cf_type <- TFun(tl,tr);
-					cf.cf_expr <- begin match cf.cf_expr with
-						| Some ({eexpr = TFunction tf} as e) ->
-							Some {e with eexpr = TFunction {tf with tf_type = tr}}
-						| e ->
-							e
-					end;
-				| None ->
-					()
-					(* TODO: this should never happen if we get the unification right *)
-					(* Error.error "Could not find overload" cf.cf_pos *)
-			in
-			List.iter (fun cf ->
-				fix_covariant_return cf;
-				List.iter fix_covariant_return cf.cf_overloads
-			) fields
-
 	method preprocess_class (c : tclass) =
 		let has_dynamic_instance_method = ref false in
 		let has_field_init = ref false in
@@ -379,7 +343,6 @@ object(self)
 			| MStatic ->
 				()
 		in
-		self#check_overrides c;
 		List.iter (field MStatic) c.cl_ordered_statics;
 		List.iter (field MInstance) c.cl_ordered_fields;
 		match c.cl_constructor with

+ 1 - 0
tests/unit/.vscode/settings.json

@@ -1,5 +1,6 @@
 {
 	"haxe.configurations": [
+		{"label": "Java", "args": ["compile-java.hxml", "-cmd", "java -jar bin/java/TestMain-debug.jar"]},
 		{"label": "JavaScript", "args": ["compile-js.hxml", "-cmd", "node -e \"require('./bin/unit.js').unit.TestMain.main()\""]},
 		{"label": "JVM", "args": ["compile-jvm-only.hxml", "-cmd", "java -jar bin/unit.jar"]},
 		{"label": "Interp", "args": ["compile-macro.hxml"]},

+ 44 - 0
tests/unit/src/unit/issues/Issue9836.hx

@@ -0,0 +1,44 @@
+package unit.issues;
+
+private class Parent {
+	public function new() {}
+
+	public function contravariant(i:Int):Float {
+		return 0.0;
+	}
+
+	public function covariant():Float {
+		return 0.0;
+	}
+
+	public function variant(i:Int):Float {
+		return 0.0;
+	}
+}
+
+private class Child extends Parent {
+	override function contravariant(i:Float):Float {
+		return 1.0;
+	}
+
+	override function covariant():Float {
+		return 1.0;
+	}
+
+	override function variant(f:Float):Int {
+		return 1;
+	}
+}
+
+class Issue9836 extends unit.Test {
+	function test() {
+		var child = new Child();
+		var parent:Parent = child;
+		feq(1.0, parent.contravariant(0));
+		feq(1.0, child.contravariant(0));
+		feq(1.0, parent.covariant());
+		feq(1.0, child.covariant());
+		feq(1.0, parent.variant(0));
+		feq(1.0, child.variant(0));
+	}
+}