{"action":"created","issue":{"url":"https://api.github.com/repos/scala/scala/issues/4369","labels_url":"https://api.github.com/repos/scala/scala/issues/4369/labels{/name}","comments_url":"https://api.github.com/repos/scala/scala/issues/4369/comments","events_url":"https://api.github.com/repos/scala/scala/issues/4369/events","html_url":"https://github.com/scala/scala/pull/4369","id":59393901,"number":4369,"title":"Adjust parameter order of static accessor method in Delambdafy","user":{"login":"retronym","id":65551,"avatar_url":"https://avatars.githubusercontent.com/u/65551?v=3","gravatar_id":"","url":"https://api.github.com/users/retronym","html_url":"https://github.com/retronym","followers_url":"https://api.github.com/users/retronym/followers","following_url":"https://api.github.com/users/retronym/following{/other_user}","gists_url":"https://api.github.com/users/retronym/gists{/gist_id}","starred_url":"https://api.github.com/users/retronym/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retronym/subscriptions","organizations_url":"https://api.github.com/users/retronym/orgs","repos_url":"https://api.github.com/users/retronym/repos","events_url":"https://api.github.com/users/retronym/events{/privacy}","received_events_url":"https://api.github.com/users/retronym/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/scala/scala/milestones/48","html_url":"https://github.com/scala/scala/milestones/2.11.7","labels_url":"https://api.github.com/repos/scala/scala/milestones/48/labels","id":985497,"number":48,"title":"2.11.7","description":"Merge to 2.11.x.\r\n","creator":{"login":"adriaanm","id":91083,"avatar_url":"https://avatars.githubusercontent.com/u/91083?v=3","gravatar_id":"","url":"https://api.github.com/users/adriaanm","html_url":"https://github.com/adriaanm","followers_url":"https://api.github.com/users/adriaanm/followers","following_url":"https://api.github.com/users/adriaanm/following{/other_user}","gists_url":"https://api.github.com/users/adriaanm/gists{/gist_id}","starred_url":"https://api.github.com/users/adriaanm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adriaanm/subscriptions","organizations_url":"https://api.github.com/users/adriaanm/orgs","repos_url":"https://api.github.com/users/adriaanm/repos","events_url":"https://api.github.com/users/adriaanm/events{/privacy}","received_events_url":"https://api.github.com/users/adriaanm/received_events","type":"User","site_admin":false},"open_issues":17,"closed_issues":3,"state":"open","created_at":"2015-02-19T00:12:20Z","updated_at":"2015-03-01T12:19:41Z","due_on":"2015-06-01T07:00:00Z","closed_at":null},"comments":1,"created_at":"2015-03-01T12:19:40Z","updated_at":"2015-03-02T00:32:59Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/scala/scala/pulls/4369","html_url":"https://github.com/scala/scala/pull/4369","diff_url":"https://github.com/scala/scala/pull/4369.diff","patch_url":"https://github.com/scala/scala/pull/4369.patch"},"body":"Under `-Ydelambdafy:method`, a public, static accessor method is\ncreated to expose the private method containing the body of the\nlambda.\n\nCurrently this accessor method has its parameters in the same order\nstructure as those of the lambda body method.\n\nWhat is this order? There are three categories of parameters:\n\n  1. lambda parameters\n  2. captured parameters (added by lambdalift)\n  3. self parameters (added to lambda bodies that end up in trait\n     impl classes by mixin, and added unconditionally to the static\n     accessor method.)\n\nThese are currently emitted in order #3, #1, #2.\n\nHere are examples of the current behaviour:\n\nBEFORE (trait):\n\n```\n% cat sandbox/test.scala\ntrait Test {\n  def member: A\n  def foo {\n    val local = new B\n    (arg: C) => \"\" + arg + member + local\n  }\n}\n\n% qscalac -Ydelambdafy:method sandbox/test.scala && echo ':javap -private Test$class' | qscala\n\nscala> :javap -private Test$class\nCompiled from \"test.scala\"\npublic abstract class Test$class {\n  public static void foo(Test);\n  private static final java.lang.String $anonfun$1(Test, C, B);\n  public static void $init$(Test);\n  public static final java.lang.String accessor$1(Test, C, B);\n}\n```\n\nBEFORE (class):\n\n```\n% cat sandbox/test.scala\nabstract class Test {\n  def member: A\n  def foo {\n    val local = new B\n    (arg: C) => \"\" + arg + member + local\n  }\n}\n% qscalac -Ydelambdafy:method sandbox/test.scala && echo ':javap -private Test' | qscala\n\nscala> :javap -private Test\nCompiled from \"test.scala\"\npublic abstract class Test {\n  public abstract A member();\n  public void foo();\n  private final java.lang.String $anonfun$1(C, B);\n  public Test();\n  public static final java.lang.String accessor$1(Test, C, B);\n}\n```\n\nContrasting the class case with Java:\n\n```\n% cat sandbox/Test.java\npublic abstract class Test {\n  public static class A {};\n  public static class B {};\n  public static class C {};\n  public static interface I {\n    public abstract Object c(C arg);\n  }\n  public abstract A member();\n  public void test() {\n    B local = new B();\n    I i1 = (C arg) -> \"\" + member() + local;\n  }\n}\n\n% javac -d . sandbox/Test.java && javap -private Test\nCompiled from \"Test.java\"\npublic abstract class Test {\n  public Test();\n  public abstract Test$A member();\n  public void test();\n  private java.lang.Object lambda$test$0(Test$B, Test$C);\n}\n```\n\nWe can see that in Java 8 lambda parameters come first. If we\nwant to use Java's LambdaMetafactory to spin up our anoymous FunctionN\nsubclasses on the fly, a signature must change.\n\nI can see three options for change:\n\n  1. Adjust `Mixin` to always append the `$this` parameter, rather\n     than prepending it.\n  2. More conservatively, do this just for lambda bodies\n  3. Adjust the parameters of the accessor method only. The body\n     of this method can permute params before calling the lambda\n     body method.\n\nThis commit implements option #3. This is the lowest risk / impact\nto pave the way for experimentation with indy lambdas. But it isn't\nideal as a long term solution, as indy lambdas actually don't need\nthe accessor method at all, private methods can be used directly\nby LambdaMetaFactory, saving a little indirection.\n\nOption #1 might be worth a shot on the 2.12.x branch. Option #2 might\neven be feasible on 2.11.x.\n\nI've included a test that shows this in all in action. However, that\nis currently disabled, as we don't have a partest category for tests\nthat require Java 8.\n\nReview by @gkossakowski"},"comment":{"url":"https://api.github.com/repos/scala/scala/issues/comments/76641232","html_url":"https://github.com/scala/scala/pull/4369#issuecomment-76641232","issue_url":"https://api.github.com/repos/scala/scala/issues/4369","id":76641232,"user":{"login":"retronym","id":65551,"avatar_url":"https://avatars.githubusercontent.com/u/65551?v=3","gravatar_id":"","url":"https://api.github.com/users/retronym","html_url":"https://github.com/retronym","followers_url":"https://api.github.com/users/retronym/followers","following_url":"https://api.github.com/users/retronym/following{/other_user}","gists_url":"https://api.github.com/users/retronym/gists{/gist_id}","starred_url":"https://api.github.com/users/retronym/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retronym/subscriptions","organizations_url":"https://api.github.com/users/retronym/orgs","repos_url":"https://api.github.com/users/retronym/repos","events_url":"https://api.github.com/users/retronym/events{/privacy}","received_events_url":"https://api.github.com/users/retronym/received_events","type":"User","site_admin":false},"created_at":"2015-03-02T00:32:59Z","updated_at":"2015-03-02T00:32:59Z","body":"I've [triggered](https://jenkins-dbuild.typesafe.com:8499/job/Community-2.11.x-manual/140/parameters/) a community build based on this PR using `-Ydelambdafy:method`."}}