Selaa lähdekoodia

[typer] pass mapping functions to `valid_redefinition`

closes #5890
Simon Krajewski 4 vuotta sitten
vanhempi
commit
8c882e3ca8
2 muutettua tiedostoa jossa 64 lisäystä ja 8 poistoa
  1. 11 8
      src/typing/typeloadCheck.ml
  2. 53 0
      tests/unit/src/unit/issues/Issue5890.hx

+ 11 - 8
src/typing/typeloadCheck.ml

@@ -46,7 +46,7 @@ let is_generic_parameter ctx c =
 	with Not_found ->
 		false
 
-let valid_redefinition ctx f1 t1 f2 t2 = (* child, parent *)
+let valid_redefinition ctx map1 map2 f1 t1 f2 t2 = (* child, parent *)
 	let valid t1 t2 =
 		Type.unify t1 t2;
 		if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]);
@@ -71,8 +71,8 @@ let valid_redefinition ctx f1 t1 f2 t2 = (* child, parent *)
 						let check monos =
 							List.iter2 (fun t1 t2  ->
 								try
-									let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 t1) in
-									let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 t2) in
+									let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 (map2 t1)) in
+									let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 (map1 t2)) in
 									type_eq EqStrict t1 t2
 								with Unify_error l ->
 									raise (Unify_error (Unify_custom "Constraints differ" :: l))
@@ -205,7 +205,8 @@ let check_overriding ctx c f =
 			if (has_class_field_flag f2 CfFinal) then display_error ctx ("Cannot override final method " ^ i) p;
 			try
 				let t = apply_params csup.cl_params params t in
-				valid_redefinition ctx f f.cf_type f2 t;
+				let map = TClass.get_map_function csup params in
+				valid_redefinition ctx map map f f.cf_type f2 t;
 			with
 				Unify_error l ->
 					display_error ctx ("Field " ^ i ^ " overrides parent class with different or incomplete type") p;
@@ -251,7 +252,7 @@ let check_overriding ctx c f =
 let class_field_no_interf c i =
 	try
 		let f = PMap.find i c.cl_fields in
-		f.cf_type , f
+		(fun t -> t),f.cf_type , f
 	with Not_found ->
 		match c.cl_super with
 		| None ->
@@ -259,7 +260,8 @@ let class_field_no_interf c i =
 		| Some (c,tl) ->
 			(* rec over class_field *)
 			let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in
-			apply_params c.cl_params tl t , f
+			let map = TClass.get_map_function c tl in
+			map,apply_params c.cl_params tl t , f
 
 let rec return_flow ctx e =
 	let error() =
@@ -352,7 +354,7 @@ module Inheritance = struct
 			let t = (apply_params intf.cl_params params f.cf_type) in
 			let is_overload = ref false in
 			try
-				let t2, f2 = class_field_no_interf c i in
+				let map2, t2, f2 = class_field_no_interf c i in
 				let t2, f2 =
 					if f2.cf_overloads <> [] || has_class_field_flag f2 CfOverload then
 						let overloads = Overloads.get_overloads ctx.com c i in
@@ -374,7 +376,8 @@ module Inheritance = struct
 					else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
 						display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p
 					else try
-						valid_redefinition ctx f2 t2 f (apply_params intf.cl_params params f.cf_type)
+						let map1 = TClass.get_map_function  intf params in
+						valid_redefinition ctx map1 map2 f2 t2 f (apply_params intf.cl_params params f.cf_type)
 					with
 						Unify_error l ->
 							if not (Meta.has Meta.CsNative c.cl_meta && (has_class_flag c CExtern)) then begin

+ 53 - 0
tests/unit/src/unit/issues/Issue5890.hx

@@ -0,0 +1,53 @@
+package unit.issues;
+
+class Issue5890 extends unit.Test {
+	function test() {
+		new ReporterImplSuc2();
+		noAssert();
+	}
+}
+
+interface Reporter<TDef> {
+	public function shoot<T:TDef>(ctx:T):Void;
+}
+
+class ReporterImpl<A, TDef> implements Reporter<TDef> {
+	public function shoot<T:TDef>(ctx:T):Void {}
+}
+
+class Impl2 implements Reporter<Int> {
+	public function shoot<T:Int>(a:T) {}
+}
+
+class ReporterImplSuc<TDef, A> extends ReporterImpl<A, TDef> implements Reporter<TDef> {}
+
+class ReporterImplSuc2 extends ReporterImpl<Int, String> implements Reporter<String> {
+	public function new() {}
+}
+
+class HierarchyImpl implements ISuc<Float> {
+	public function shoot<A:Float>(a:A) {
+		trace(a + 5);
+	}
+}
+
+class HierarchyImpl2<T> implements ISuc<T> {
+	public function shoot<A:T>(a:A) {}
+}
+
+interface IBase2<T> {
+	function shoot<A:T>(a:A):Void;
+}
+
+interface OtherBase {}
+interface ISuc<T> extends IBase2<T> extends OtherBase {}
+class StatBase<T:{}> {}
+class ShotContext<TDef:{}, T:StatBase<TDef>> {}
+
+interface WeaponReporter<TDef:{}> {
+	public function shoot<T:StatBase<TDef>>(ctx:ShotContext<TDef, T>):Void;
+}
+
+class StatWeaponReporterImpl<TDef:{}> implements WeaponReporter<TDef> {
+	public function shoot<T:StatBase<TDef>>(ctx:ShotContext<TDef, T>):Void {}
+}