2
0
Эх сурвалжийг харах

Explicitly apply default type parameter (#12002)

* Implement default type param skipping

* [tests] add tests for 11164

* cleanup

* Improve error handling

* [tests] update tests

* [tests] add test for new error messages
Rudy Ges 6 сар өмнө
parent
commit
df26571bb2

+ 2 - 0
src/syntax/grammar.ml

@@ -709,6 +709,8 @@ and parse_complex_type_inner ctx allow_named s = match%parser s with
 		in
 		in
 		let p = punion p1 p2 in
 		let p = punion p1 p2 in
 		CTPath (make_ptp (mk_type_path ~params:[TPType hint] (["haxe"],"Rest")) p),p
 		CTPath (make_ptp (mk_type_path ~params:[TPType hint] (["haxe"],"Rest")) p),p
+	| [ (Kwd Default,p) ] ->
+		CTPath (make_ptp (mk_type_path (["$"],"_hx_default")) p),p
 	| [ dollar_ident as n ] ->
 	| [ dollar_ident as n ] ->
 		(match%parser s with
 		(match%parser s with
 		| [ (DblDot,_); [%let t = parse_complex_type ctx] ] when allow_named->
 		| [ (DblDot,_); [%let t = parse_complex_type ctx] ] when allow_named->

+ 14 - 3
src/typing/typeload.ml

@@ -299,7 +299,7 @@ let rec load_params ctx info params p =
 	let is_rest = info.build_kind = BuildGenericBuild && (match info.build_params with [{ttp_name="Rest"}] -> true | _ -> false) in
 	let is_rest = info.build_kind = BuildGenericBuild && (match info.build_params with [{ttp_name="Rest"}] -> true | _ -> false) in
 	let is_java_rest = ctx.com.platform = Jvm && info.build_extern in
 	let is_java_rest = ctx.com.platform = Jvm && info.build_extern in
 	let is_rest = is_rest || is_java_rest in
 	let is_rest = is_rest || is_java_rest in
-	let load_param t =
+	let load_param t ttp =
 		match t with
 		match t with
 		| TPExpr e ->
 		| TPExpr e ->
 			let name = (match fst e with
 			let name = (match fst e with
@@ -314,6 +314,16 @@ let rec load_params ctx info params p =
 			let c = mk_class ctx.m.curmod ([],name) p (pos e) in
 			let c = mk_class ctx.m.curmod ([],name) p (pos e) in
 			c.cl_kind <- KExpr e;
 			c.cl_kind <- KExpr e;
 			TInst (c,[]),pos e
 			TInst (c,[]),pos e
+		| TPType (CTPath({ path = { tpackage = ["$"]; tname = "_hx_default" }}),p) ->
+			(match ttp with
+				| Some { ttp_default = Some def } -> def,p
+				| Some ttp ->
+					raise_typing_error (Printf.sprintf "Invalid default, type parameter %s has no default value" ttp.ttp_name) p
+				| None when is_rest ->
+					raise_typing_error "Cannot use default with rest type parameters" p
+				| None ->
+					raise_typing_error ("Too many type parameters for " ^ s_type_path info.build_path) p
+			)
 		| TPType t ->
 		| TPType t ->
 			load_complex_type ctx true LoadNormal t,pos t
 			load_complex_type ctx true LoadNormal t,pos t
 	in
 	in
@@ -321,7 +331,7 @@ let rec load_params ctx info params p =
 	let rec loop tl1 tl2 is_rest = match tl1,tl2 with
 	let rec loop tl1 tl2 is_rest = match tl1,tl2 with
 		| t :: tl1,ttp:: tl2 ->
 		| t :: tl1,ttp:: tl2 ->
 			let name = ttp.ttp_name in
 			let name = ttp.ttp_name in
-			let t,pt = load_param t in
+			let t,pt = load_param t (Some ttp) in
 			let check_const c =
 			let check_const c =
 				let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in
 				let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in
 				let expects_expression = name = "Const" || Meta.has Meta.Const c.cl_meta in
 				let expects_expression = name = "Const" || Meta.has Meta.Const c.cl_meta in
@@ -360,7 +370,7 @@ let rec load_params ctx info params p =
 					t :: loop [] tl is_rest
 					t :: loop [] tl is_rest
 			end
 			end
 		| t :: tl,[] ->
 		| t :: tl,[] ->
-			let t,pt = load_param t in
+			let t,pt = load_param t None in
 			if is_rest then
 			if is_rest then
 				t :: loop tl [] true
 				t :: loop tl [] true
 			else if ignore_error ctx.com then
 			else if ignore_error ctx.com then
@@ -439,6 +449,7 @@ and load_complex_type' ctx allow_display mode (t,p) =
 	match t with
 	match t with
 	| CTParent t -> load_complex_type ctx allow_display mode t
 	| CTParent t -> load_complex_type ctx allow_display mode t
 	| CTPath { path = {tpackage = ["$"]; tname = "_hx_mono" }} -> spawn_monomorph ctx p
 	| CTPath { path = {tpackage = ["$"]; tname = "_hx_mono" }} -> spawn_monomorph ctx p
+	| CTPath { path = {tpackage = ["$"]; tname = "_hx_default" }} -> raise_typing_error "Invalid type : default" p
 	| CTPath ptp -> load_instance ~allow_display ctx ptp ParamNormal mode
 	| CTPath ptp -> load_instance ~allow_display ctx ptp ParamNormal mode
 	| CTOptional _ -> raise_typing_error "Optional type not allowed here" p
 	| CTOptional _ -> raise_typing_error "Optional type not allowed here" p
 	| CTNamed _ -> raise_typing_error "Named type not allowed here" p
 	| CTNamed _ -> raise_typing_error "Named type not allowed here" p

+ 5 - 0
tests/misc/projects/Issue11164/Macro.hx

@@ -0,0 +1,5 @@
+class Macro {
+	public static function build() {
+		return macro :Any;
+	}
+}

+ 29 - 0
tests/misc/projects/Issue11164/Main.hx

@@ -0,0 +1,29 @@
+typedef A<K = String, V> = haxe.ds.BalancedTree<K,V>;
+
+class B<T1 = Int, T2 = String, T3> {}
+
+class DefaultGeneric<T = String> {
+	public function new() {}
+}
+
+class Main {
+	static function main() {
+		var a:A<default,Int> = null;
+		$type(a);
+
+		var b:B<Bool,default,Int> = null;
+		$type(b);
+
+		var c = new DefaultGeneric();
+		$type(c);
+
+		var d = new DefaultGeneric<default>();
+		$type(d);
+
+		var e:DefaultGeneric = new DefaultGeneric();
+		$type(e);
+
+		var f:DefaultGeneric<default> = new DefaultGeneric();
+		$type(f);
+	}
+}

+ 5 - 0
tests/misc/projects/Issue11164/Main2.hx

@@ -0,0 +1,5 @@
+class Main2 {
+	static function main() {
+		var b:Array<default> = [];
+	}
+}

+ 3 - 0
tests/misc/projects/Issue11164/Main3.hx

@@ -0,0 +1,3 @@
+typedef B = default;
+
+function main() {}

+ 3 - 0
tests/misc/projects/Issue11164/Main4.hx

@@ -0,0 +1,3 @@
+typedef default = String;
+
+function main() {}

+ 3 - 0
tests/misc/projects/Issue11164/Main5.hx

@@ -0,0 +1,3 @@
+function main() {
+	var a:default;
+}

+ 2 - 0
tests/misc/projects/Issue11164/Main6.hx

@@ -0,0 +1,2 @@
+typedef Foo = Array<String, default>
+function main() {}

+ 5 - 0
tests/misc/projects/Issue11164/Main7.hx

@@ -0,0 +1,5 @@
+@:genericBuild(Macro.build())
+private class Foo<Rest> {}
+private typedef Bar = Foo<Int, default>
+
+function main() {}

+ 3 - 0
tests/misc/projects/Issue11164/compile.hxml

@@ -0,0 +1,3 @@
+-main Main
+-D message.reporting=pretty
+-D message.no-color

+ 36 - 0
tests/misc/projects/Issue11164/compile.hxml.stderr

@@ -0,0 +1,36 @@
+[WARNING] Main.hx:12: characters 9-10
+
+ 12 |   $type(a);
+    |         ^
+    | A<String, Int>
+
+[WARNING] Main.hx:15: characters 9-10
+
+ 15 |   $type(b);
+    |         ^
+    | B<Bool, String, Int>
+
+[WARNING] Main.hx:18: characters 9-10
+
+ 18 |   $type(c);
+    |         ^
+    | DefaultGeneric<Unknown<0>>
+
+[WARNING] Main.hx:21: characters 9-10
+
+ 21 |   $type(d);
+    |         ^
+    | DefaultGeneric<String>
+
+[WARNING] Main.hx:24: characters 9-10
+
+ 24 |   $type(e);
+    |         ^
+    | DefaultGeneric<String>
+
+[WARNING] Main.hx:27: characters 9-10
+
+ 27 |   $type(f);
+    |         ^
+    | DefaultGeneric<String>
+

+ 3 - 0
tests/misc/projects/Issue11164/compile2-fail.hxml

@@ -0,0 +1,3 @@
+-main Main2
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile2-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main2.hx:3: characters 15-22
+
+ 3 |   var b:Array<default> = [];
+   |               ^^^^^^^
+   | Invalid default, type parameter T has no default value
+

+ 3 - 0
tests/misc/projects/Issue11164/compile3-fail.hxml

@@ -0,0 +1,3 @@
+-main Main3
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile3-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main3.hx:1: characters 13-20
+
+ 1 | typedef B = default;
+   |             ^^^^^^^
+   | Invalid type : default
+

+ 3 - 0
tests/misc/projects/Issue11164/compile4-fail.hxml

@@ -0,0 +1,3 @@
+-main Main4
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile4-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main4.hx:1: characters 9-16
+
+ 1 | typedef default = String;
+   |         ^^^^^^^
+   | Unexpected keyword "default"
+

+ 3 - 0
tests/misc/projects/Issue11164/compile5-fail.hxml

@@ -0,0 +1,3 @@
+-main Main5
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile5-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main5.hx:2: characters 8-15
+
+ 2 |  var a:default;
+   |        ^^^^^^^
+   | Invalid type : default
+

+ 3 - 0
tests/misc/projects/Issue11164/compile6-fail.hxml

@@ -0,0 +1,3 @@
+-main Main6
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile6-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main6.hx:1: characters 29-36
+
+ 1 | typedef Foo = Array<String, default>
+   |                             ^^^^^^^
+   | Too many type parameters for Array
+

+ 3 - 0
tests/misc/projects/Issue11164/compile7-fail.hxml

@@ -0,0 +1,3 @@
+-main Main7
+-D message.reporting=pretty
+-D message.no-color

+ 6 - 0
tests/misc/projects/Issue11164/compile7-fail.hxml.stderr

@@ -0,0 +1,6 @@
+[ERROR] Main7.hx:3: characters 32-39
+
+ 3 | private typedef Bar = Foo<Int, default>
+   |                                ^^^^^^^
+   | Cannot use default with rest type parameters
+