Ver Fonte

add haxe.Constraints.Constructible (see #4761)

Simon Krajewski há 9 anos atrás
pai
commit
455070aa9b

+ 1 - 0
codegen.ml

@@ -319,6 +319,7 @@ let has_ctor_constraint c = match c.cl_kind with
 	| KTypeParameter tl ->
 	| KTypeParameter tl ->
 		List.exists (fun t -> match follow t with
 		List.exists (fun t -> match follow t with
 			| TAnon a when PMap.mem "new" a.a_fields -> true
 			| TAnon a when PMap.mem "new" a.a_fields -> true
+			| TAbstract({a_path=["haxe"],"Constructible"},_) -> true
 			| _ -> false
 			| _ -> false
 		) tl;
 		) tl;
 	| _ -> false
 	| _ -> false

+ 15 - 0
std/haxe/Constraints.hx

@@ -40,6 +40,21 @@ abstract Function(Dynamic) { }
 **/
 **/
 abstract FlatEnum(Dynamic) { }
 abstract FlatEnum(Dynamic) { }
 
 
+/**
+	This type unifies with any instance of classes that have a constructor
+	which
+		* is public and
+		* unifies with the type used for type parameter `T`.
+
+	If a type parameter A is assigned to a type parameter B which is constrained
+	to `Constructible<T>`, A must be explicitly constrained to
+	`Constructible<T>` as well.
+
+	It is intended to be used as a type parameter constraint. If used as a real
+	type, the underlying type will be `Dynamic`.
+**/
+abstract Constructible<T>(Dynamic) { }
+
 interface IMap<K,V> {
 interface IMap<K,V> {
 	public function get(k:K):Null<V>;
 	public function get(k:K):Null<V>;
 	public function set(k:K, v:V):Void;
 	public function set(k:K, v:V):Void;

+ 24 - 0
tests/misc/projects/Issue4364/Main.hx

@@ -0,0 +1,24 @@
+class C {
+	public var value:String;
+	public function new() {
+		value = "foo";
+	}
+}
+
+abstract A(C) to C {
+	public function f() {
+		return "bar";
+	}
+}
+
+@:generic
+class G<T:haxe.Constraints.Constructible<Void->Void>> {
+	public function new() {}
+	public function make():T return new T();
+}
+
+class Main {
+	static function main() {
+		var g = new G<A>();
+	}
+}

+ 3 - 0
tests/misc/projects/Issue4364/compile-fail.hxml

@@ -0,0 +1,3 @@
+-main Main
+-neko neko.n
+--no-output

+ 2 - 0
tests/misc/projects/Issue4364/compile-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main.hx:22: characters 10-20 : Constraint check failure for G.T
+Main.hx:22: characters 10-20 : A should be haxe.Constructible<Void -> Void>

+ 1 - 1
tests/unit/src/unit/TestType.hx

@@ -616,7 +616,7 @@ class TestType extends Test {
 		return Std.string(a) + Std.string(b);
 		return Std.string(a) + Std.string(b);
 	}
 	}
 
 
-	@:generic static function gf3 < A:{function new(s:String):Void;}, B:Array<A> > (a:A, b:B) {
+	@:generic static function gf3 < A:haxe.Constraints.Constructible<String -> Void>, B:Array<A> > (a:A, b:B) {
 		var clone = new A("foo");
 		var clone = new A("foo");
 		b.push(clone);
 		b.push(clone);
 		return b;
 		return b;

+ 0 - 29
tests/unit/src/unit/issues/Issue4364.hx

@@ -1,29 +0,0 @@
-package unit.issues;
-
-private class C {
-	public var value:String;
-	public function new() {
-		value = "foo";
-	}
-}
-
-private abstract A(C) to C {
-	public function f() {
-		return "bar";
-	}
-}
-
-@:generic
-private class G<T:{function new():Void;}> {
-	public function new() {}
-	public function make():T return new T();
-}
-
-class Issue4364 extends Test {
-	function test() {
-		var g = new G<A>();
-		var a = g.make();
-		eq("bar", a.f());
-		eq("foo", (a : C).value);
-	}
-}

+ 1 - 5
tests/unit/src/unit/issues/Issue4668.hx

@@ -1,10 +1,6 @@
 package unit.issues;
 package unit.issues;
 
 
-private typedef Constructible = {
-	function new(arg:String):Void;
-}
-
-private class GenericTest<T:Constructible> {
+private class GenericTest<T:haxe.Constraints.Constructible<String->Void>> {
 	public function new(){}
 	public function new(){}
 
 
 	@:generic
 	@:generic

+ 15 - 0
type.ml

@@ -1710,6 +1710,21 @@ let rec unify a b =
 		()
 		()
 	| TFun _, TAbstract ({ a_path = ["haxe"],"Function" },[]) ->
 	| TFun _, TAbstract ({ a_path = ["haxe"],"Function" },[]) ->
 		()
 		()
+	| TInst(c,tl),TAbstract({a_path = ["haxe"],"Constructible"},[t1]) ->
+		begin try
+			begin match c.cl_kind with
+				| KTypeParameter tl ->
+					(* type parameters require an equal Constructible constraint *)
+					if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq t1 t2 | _ -> false) tl) then error [cannot_unify a b]
+				| _ ->
+					let _,t,cf = class_field c tl "new" in
+					if not cf.cf_public then error [invalid_visibility "new"];
+					begin try unify t1 t
+					with Unify_error l -> error (cannot_unify a b :: l) end
+			end
+		with Not_found ->
+			error [has_no_field a "new"]
+		end
 	| TDynamic t , _ ->
 	| TDynamic t , _ ->
 		if t == a then
 		if t == a then
 			()
 			()

+ 2 - 0
typer.ml

@@ -3512,9 +3512,11 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| TAnon a ->
 				| TAnon a ->
 					(try
 					(try
 						unify ctx (PMap.find "new" a.a_fields).cf_type ct p;
 						unify ctx (PMap.find "new" a.a_fields).cf_type ct p;
+						ctx.com.warning "Structures with new are deprecated, use haxe.Constraints.Constructible instead" p;
 						true
 						true
 					with Not_found ->
 					with Not_found ->
 						 false)
 						 false)
+				| TAbstract({a_path = ["haxe"],"Constructible"},_) -> true
 				| TInst({cl_kind = KTypeParameter tl},_) -> List.exists loop tl
 				| TInst({cl_kind = KTypeParameter tl},_) -> List.exists loop tl
 				| _ -> false
 				| _ -> false
 			in
 			in