Browse Source

[typer] distinguish multitype-to methods from real ones

see #10145
Aleksandr Kuzmenko 3 years ago
parent
commit
6222566cd8

+ 1 - 0
extra/CHANGES.txt

@@ -15,6 +15,7 @@
 	all : fixed errors on final vars modification with `+=`, `*=` etc operations (#10325)
 	all : fixed hanging of MainLoop.add on threaded targets (#10308, #10329)
 	all : fixed compiler crash when resolving overloads with not enough arguments (#10434)
+	all : fixed non-static `@:to` methods on `@:multiType` abstracts (#10145)
 	analyzer : fixed analyzer on overloads (#10405)
 	analyzer : fixed issues with fields initialization expressions (#10405)
 	display : improved code completion in anonymous objects declarations (#10414)

+ 1 - 1
src/context/abstractCast.ml

@@ -42,7 +42,7 @@ and do_check_cast ctx uctx tleft eright p =
 		rec_stack_loop cast_stack cf f ()
 	in
 	let make (a,tl,(tcf,cf)) =
-		if (Meta.has Meta.MultiType a.a_meta) then
+		if (Meta.has Meta.MultiType cf.cf_meta) then
 			mk_cast eright tleft p
 		else match a.a_impl with
 			| Some c -> recurse cf (fun () ->

+ 4 - 1
src/typing/typeloadFields.ml

@@ -1044,9 +1044,12 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 							| TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic
 							| m -> m
 					in
+					let is_multitype_cast = Meta.has Meta.MultiType a.a_meta && not fctx.is_abstract_member in
+					if is_multitype_cast && not (Meta.has Meta.MultiType cf.cf_meta) then
+						cf.cf_meta <- (Meta.MultiType,[],null_pos) :: cf.cf_meta;
 					let r = exc_protect ctx (fun r ->
 						r := lazy_processing (fun () -> t);
-						let args = if Meta.has Meta.MultiType a.a_meta then begin
+						let args = if is_multitype_cast then begin
 							let ctor = try
 								PMap.find "_new" c.cl_statics
 							with Not_found ->

+ 43 - 0
tests/unit/src/unit/issues/Issue10145.hx

@@ -0,0 +1,43 @@
+package unit.issues;
+
+// whatever
+#if !erase_generics
+private interface I<T> {
+	function get():T;
+}
+
+private class C<T> implements I<T> {
+	public var value:T;
+
+	public function new(value:T) {
+		this.value = value;
+	}
+
+	public function get():T {
+		return value;
+	}
+}
+
+@:multiType(T)
+private abstract A<T>(I<T>) {
+	public function new(value:T);
+
+	@:to static function ofInt(_:I<Int>, value:Int):C<Int> {
+		return new C(value);
+	}
+
+	@:to function toT():T {
+		return this.get();
+	}
+}
+#end
+
+class Issue10145 extends unit.Test {
+	#if !erase_generics
+	function test() {
+		var x = new A(10);
+		var y:Int = x;
+		eq(10, y);
+	}
+	#end
+}