Skip to content

Commit

Permalink
support @:using on typedefs
Browse files Browse the repository at this point in the history
  • Loading branch information
vonagam committed Jul 28, 2020
1 parent a1ea0b3 commit c1c1b45
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
20 changes: 16 additions & 4 deletions src/typing/fields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,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
Expand All @@ -280,6 +280,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). *)
Expand All @@ -294,6 +297,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)
Expand Down Expand Up @@ -416,6 +420,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) ->
Expand All @@ -439,6 +449,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
Expand All @@ -455,6 +466,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
Expand Down Expand Up @@ -482,7 +494,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
Expand All @@ -498,7 +510,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 ->
Expand Down
2 changes: 1 addition & 1 deletion src/typing/typeloadModule.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/src/unit/issues/Issue9749.hx
Original file line number Diff line number Diff line change
@@ -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';
}

0 comments on commit c1c1b45

Please sign in to comment.