From ac570598b4bfda48c43fae6337d9cc61d2f71f0f Mon Sep 17 00:00:00 2001 From: Simon Krajewski Date: Tue, 30 Jan 2024 10:21:56 +0100 Subject: [PATCH 1/3] [typer] allow type parameters in rvalue functions see #11513 --- src/typing/typer.ml | 17 +++++++++++++++-- tests/unit/src/unit/issues/Issue11513.hx | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/unit/src/unit/issues/Issue11513.hx diff --git a/src/typing/typer.ml b/src/typing/typer.ml index 6fad5ed24a5..811455ff3b9 100644 --- a/src/typing/typer.ml +++ b/src/typing/typer.ml @@ -1221,7 +1221,13 @@ and type_local_function ctx kind f with_type p = let params = TypeloadFunction.type_function_params ctx f TPHLocal (match name with None -> "localfun" | Some (n,_) -> n) p in if params <> [] then begin if name = None then display_error ctx.com "Type parameters not supported in unnamed local functions" p; - if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p + begin match ctx.com.platform with + | Java | Cs -> + (* gencommon just can't *) + if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p + | _ -> + () + end end; let v,pname = (match name with | None -> None,p @@ -1323,6 +1329,13 @@ and type_local_function ctx kind f with_type p = | _ -> ()); let ft = TFun (targs,rt) in + let ft = match with_type with + | WithType.NoValue -> + ft + | _ -> + (* We want to apply params as if we accessed the function by name (see type_ident_raise). *) + apply_params params (Monomorph.spawn_constrained_monos (fun t -> t) params) ft + in let v = (match v with | None -> None | Some v -> @@ -1364,7 +1377,7 @@ and type_local_function ctx kind f with_type p = else [] in let exprs = - if is_rec then begin + if is_rec || (params <> [] && with_type <> WithType.NoValue) then begin if inline then display_error ctx.com "Inline function cannot be recursive" e.epos; (mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p) :: (mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p) :: diff --git a/tests/unit/src/unit/issues/Issue11513.hx b/tests/unit/src/unit/issues/Issue11513.hx new file mode 100644 index 00000000000..67c46b51532 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue11513.hx @@ -0,0 +1,24 @@ +package unit.issues; + +private enum abstract Message(Int) { + final move_to:Message<{x:Int, y:Int}>; +} + +private typedef Listener = { + function send(name:Message, body:TBody):Void; +} + +private final listener:Listener = { + send: function send(message:Message, body:T) { + switch (message) { + case move_to: + } + } +} + +class Issue11513 extends Test { + function test() { + listener.send(move_to, {x: 1, y: 2}); + noAssert(); + } +} From b06d6658384e244df4d481d6c99edc887fc24a71 Mon Sep 17 00:00:00 2001 From: Simon Krajewski Date: Tue, 30 Jan 2024 10:54:13 +0100 Subject: [PATCH 2/3] also support type params on unnamed functions --- src/typing/typer.ml | 49 +++++++++++++++--------- tests/unit/src/unit/issues/Issue11513.hx | 13 +++++++ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/typing/typer.ml b/src/typing/typer.ml index 811455ff3b9..96614a04b0d 100644 --- a/src/typing/typer.ml +++ b/src/typing/typer.ml @@ -1219,20 +1219,32 @@ and type_map_declaration ctx e1 el with_type p = and type_local_function ctx kind f with_type p = let name,inline = match kind with FKNamed (name,inline) -> Some name,inline | _ -> None,false in let params = TypeloadFunction.type_function_params ctx f TPHLocal (match name with None -> "localfun" | Some (n,_) -> n) p in - if params <> [] then begin - if name = None then display_error ctx.com "Type parameters not supported in unnamed local functions" p; - begin match ctx.com.platform with - | Java | Cs -> - (* gencommon just can't *) - if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p + let has_good_type_param_handling = match ctx.com.platform with + | Java -> + defined ctx.com Define.Jvm + | Cs -> + false | _ -> - () - end - end; - let v,pname = (match name with - | None -> None,p - | Some (v,pn) -> Some v,pn - ) in + true + in + if params <> [] && not has_good_type_param_handling then + if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p; + let vname,pname= match name with + | None -> + if params <> [] then begin + if has_good_type_param_handling then + Some(gen_local_prefix,VGenerated),null_pos + else begin + display_error ctx.com "Type parameters not supported in unnamed local functions" p; + None,p + end + end else + None,p + | Some (name,pn) -> + let origin = TVOLocalFunction in + check_local_variable_name ctx name origin p; + Some (name,VUser origin),pn + in let old_tp,old_in_loop = ctx.type_params,ctx.in_loop in ctx.type_params <- params @ ctx.type_params; if not inline then ctx.in_loop <- false; @@ -1336,13 +1348,14 @@ and type_local_function ctx kind f with_type p = (* We want to apply params as if we accessed the function by name (see type_ident_raise). *) apply_params params (Monomorph.spawn_constrained_monos (fun t -> t) params) ft in - let v = (match v with - | None -> None - | Some v -> - let v = (add_local_with_origin ctx TVOLocalFunction v ft pname) in + let v = match vname with + | None -> + None + | Some(vname,vkind) -> + let v = add_local ctx vkind vname ft pname in if params <> [] then v.v_extra <- Some (var_extra params None); Some v - ) in + in let curfun = match ctx.curfun with | FunStatic -> FunStatic | FunMemberAbstract diff --git a/tests/unit/src/unit/issues/Issue11513.hx b/tests/unit/src/unit/issues/Issue11513.hx index 67c46b51532..c95cb85f471 100644 --- a/tests/unit/src/unit/issues/Issue11513.hx +++ b/tests/unit/src/unit/issues/Issue11513.hx @@ -1,5 +1,6 @@ package unit.issues; +#if ((!java || jvm) && !cs) private enum abstract Message(Int) { final move_to:Message<{x:Int, y:Int}>; } @@ -16,9 +17,21 @@ private final listener:Listener = { } } +private final listener2:Listener = { + send: function(message:Message, body:T) { + switch (message) { + case move_to: + } + } +} +#end + class Issue11513 extends Test { function test() { + #if ((!java || jvm) && !cs) listener.send(move_to, {x: 1, y: 2}); + listener2.send(move_to, {x: 1, y: 2}); + #end noAssert(); } } From f175398a706b8e198262f31c8c43a452c97aeb36 Mon Sep 17 00:00:00 2001 From: Simon Krajewski Date: Wed, 7 Feb 2024 16:43:26 +0100 Subject: [PATCH 3/3] remove awkwardness --- tests/unit/src/unit/issues/Issue11513.hx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/unit/src/unit/issues/Issue11513.hx b/tests/unit/src/unit/issues/Issue11513.hx index c95cb85f471..0181b83162a 100644 --- a/tests/unit/src/unit/issues/Issue11513.hx +++ b/tests/unit/src/unit/issues/Issue11513.hx @@ -1,6 +1,5 @@ package unit.issues; -#if ((!java || jvm) && !cs) private enum abstract Message(Int) { final move_to:Message<{x:Int, y:Int}>; } @@ -24,14 +23,11 @@ private final listener2:Listener = { } } } -#end class Issue11513 extends Test { function test() { - #if ((!java || jvm) && !cs) listener.send(move_to, {x: 1, y: 2}); listener2.send(move_to, {x: 1, y: 2}); - #end noAssert(); } }