Parcourir la source

support @:using on typedefs (#9749)

Dmitrii Maganov il y a 5 ans
Parent
commit
8fe9ba6598
3 fichiers modifiés avec 62 ajouts et 5 suppressions
  1. 16 4
      src/typing/fields.ml
  2. 1 1
      src/typing/typeloadModule.ml
  3. 45 0
      tests/unit/src/unit/issues/Issue9749.hx

+ 16 - 4
src/typing/fields.ml

@@ -253,10 +253,10 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 		| None -> raise Not_found
 	in
 	let type_field_by_et f e t =
-		f { e with etype = t } (follow t)
+		f { e with etype = t } (follow_without_type t)
 	in
 	let type_field_by_e f e =
-		f e (follow e.etype)
+		f e (follow_without_type e.etype)
 	in
 	let rec type_field_by_list f = function
 		| [] -> raise Not_found
@@ -277,6 +277,9 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 		let f () = type_field_by_et f e (Abstract.get_underlying_type ~return_first:true a tl) in
 		type_field_by_forward f Meta.Forward a
 	in
+	let type_field_by_typedef f e td tl =
+		f e (follow_without_type (apply_params td.t_params tl td.t_type))
+	in
 	let type_field_by_interfaces e c =
 		(* For extern lib types we didn't go through check_interfaces and check_abstract_class, which handles some field
 		   generation. We instead do this lazily here by browsing the implemented interfaces (issue #9768). *)
@@ -291,6 +294,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 	let rec type_field_by_type e t =
 		let field_access = field_access e in
 		match t with
+		| TType (td,tl) -> type_field_by_typedef type_field_by_type e td tl
 		| TInst (c,tl) ->
 			(try
 				snd (class_field_with_access e c tl)
@@ -413,6 +417,12 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 			loop (t_infos mt).mt_using
 		) t e in
 		match t with
+		| TType (td,tl) ->
+			(try
+				type_field_by_extension()
+			with Not_found ->
+				type_field_by_typedef type_field_by_type_extension e td tl
+			)
 		| TInst _ when e.eexpr = TConst TSuper -> raise Not_found
 		| TMono _ -> raise Not_found
 		| TAbstract (a,tl) ->
@@ -436,6 +446,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 				| _ -> die "" __LOC__
 		) t e in
 		match t with
+		| TType (td,tl) -> type_field_by_typedef type_field_by_module_extension e td tl
 		| TInst _ when e.eexpr = TConst TSuper -> raise Not_found
 		| TMono r ->
 			(match Monomorph.classify_constraints r with
@@ -452,6 +463,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 	in
 	let rec type_field_by_fallback e t =
 		match t with
+		| TType (td,tl) -> type_field_by_typedef type_field_by_fallback e td tl
 		| TInst (c,tl) ->
 			(try
 				let rec loop c tl = match c with
@@ -479,7 +491,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 			)
 		| _ -> raise Not_found
 	in
-	let t = follow e.etype in
+	let t = follow_without_type e.etype in
 	try
 		type_field_by_type e t
 	with Not_found -> try
@@ -495,7 +507,7 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 				|| List.exists (fun (_,_,cf) -> cf.cf_name = i) a.a_unops
 				|| List.exists (fun cf -> cf.cf_name = i) a.a_array
 			in
-			match t with
+			match follow t with
 			| TAnon { a_status = { contents = Statics { cl_kind = KAbstractImpl a } } }
 			| TInst ({ cl_kind = KAbstractImpl a },_)
 			| TAbstract (a,_) when has_special_field a ->

+ 1 - 1
src/typing/typeloadModule.ml

@@ -280,7 +280,6 @@ let module_pass_1 ctx m tdecls loadp =
 		| ETypedef d ->
 			let name = fst d.d_name in
 			check_type_name name d.d_meta;
-			if has_meta Meta.Using d.d_meta then error "@:using on typedef is not allowed" p;
 			has_declaration := true;
 			let priv = List.mem EPrivate d.d_flags in
 			let path = make_path name priv d.d_meta p in
@@ -841,6 +840,7 @@ let init_module_type ctx context_init (decl,p) =
 			| None -> Monomorph.bind r tt;
 			| Some _ -> die "" __LOC__);
 		| _ -> die "" __LOC__);
+		TypeloadFields.build_module_def ctx (TTypeDecl t) t.t_meta (fun _ -> []) context_init (fun _ -> error "@:build on typedef is not allowed" p);
 		if ctx.com.platform = Cs && t.t_meta <> [] then
 			delay ctx PTypeField (fun () ->
 				let metas = StrictMeta.check_strict_meta ctx t.t_meta in

+ 45 - 0
tests/unit/src/unit/issues/Issue9749.hx

@@ -0,0 +1,45 @@
+package unit.issues;
+using Issue9749.Issue9749_XTools;
+
+class Issue9749 extends Test {
+  function test() {
+    var x = {x: 0};
+    var y: TypeY = x;
+    var a: TypeA = x;
+    var b: TypeB = x;
+    var c: TypeC = x;
+    var d: TypeD = x;
+    eq('X', x.tool());
+    eq('X', y.tool());
+    eq('A', a.tool());
+    eq('B', b.tool());
+    eq('C', c.tool());
+    eq('C', d.tool());
+  }
+}
+
+private typedef TypeY = {x: Int};
+
+@:using(Issue9749.Issue9749_TypeATools) private typedef TypeA = {x: Int};
+
+@:using(Issue9749.Issue9749_TypeBTools) private typedef TypeB = {x: Int};
+
+@:using(Issue9749.Issue9749_TypeCTools) private typedef TypeC = TypeB;
+
+private typedef TypeD = TypeC;
+
+class Issue9749_XTools {
+  public static function tool(x: {x: Int}) return 'X';
+}
+
+class Issue9749_TypeATools {
+  public static function tool(a: {x: Int}) return 'A';
+}
+
+class Issue9749_TypeBTools {
+  public static function tool(b: {x: Int}) return 'B';
+}
+
+class Issue9749_TypeCTools {
+  public static function tool(c: {x: Int}) return 'C';
+}