Parcourir la source

do not cast abstract this arguments to themselves (closes #2713)

Simon Krajewski il y a 11 ans
Parent
commit
22e5a8f044
2 fichiers modifiés avec 40 ajouts et 4 suppressions
  1. 36 0
      tests/unit/issues/Issue2713.hx
  2. 4 4
      typer.ml

+ 36 - 0
tests/unit/issues/Issue2713.hx

@@ -0,0 +1,36 @@
+package unit.issues;
+import unit.Test;
+
+private abstract Vector<T>(Array<T>) {
+
+	public function new ():Void {
+		this = new Array<T>();
+	}
+
+	public function push(x:T):Int {
+		return this.push(x);
+	}
+
+	@:from static public inline function fromArray<T, U> (a:Array<U>):Vector<T> {
+		return cast a;
+	}
+
+	@:to public function toArray<T>():Array<T> {
+		return this;
+	}
+}
+
+
+class Issue2713 extends Test {
+	function test() {
+		var v:Vector<Int> = [1, 2, 3];
+		for (i in 0...2) {
+			v.push(i);
+		}
+		eq(1, v[0]);
+		eq(2, v[1]);
+		eq(3, v[2]);
+		eq(0, v[3]);
+		eq(1, v[4]);
+	}
+}

+ 4 - 4
typer.ml

@@ -3416,16 +3416,16 @@ and build_call ctx acc el (with_type:with_type) p =
 		| _ ->
 			let t = follow (field_type ctx cl [] ef p) in
 			(* for abstracts we have to apply their parameters to the static function *)
-			let t,tthis = match follow eparam.etype with
-				| TAbstract(a,tl) when Meta.has Meta.Impl ef.cf_meta -> apply_params a.a_types tl t,apply_params a.a_types tl a.a_this
-				| te -> t,te
+			let t,tthis,is_abstract_impl_call = match follow eparam.etype with
+				| TAbstract(a,tl) when Meta.has Meta.Impl ef.cf_meta -> apply_params a.a_types tl t,apply_params a.a_types tl a.a_this,true
+				| te -> t,te,false
 			in
 			let params,args,r,eparam = match t with
 				| TFun ((_,_,t1) :: args,r) ->
 					unify ctx tthis t1 eparam.epos;
 					let ef = prepare_using_field ef in
 					begin match unify_call_params ctx (Some (TInst(cl,[]),ef)) el args r p (ef.cf_kind = Method MethInline) with
-					| el,TFun(args,r) -> el,args,r,Codegen.Abstract.check_cast ctx t1 eparam eparam.epos
+					| el,TFun(args,r) -> el,args,r,(if is_abstract_impl_call then eparam else Codegen.Abstract.check_cast ctx t1 eparam eparam.epos)
 					| _ -> assert false
 					end
 				| _ -> assert false