{"action":"created","issue":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/1694","repository_url":"https://api.github.com/repos/lampepfl/dotty","labels_url":"https://api.github.com/repos/lampepfl/dotty/issues/1694/labels{/name}","comments_url":"https://api.github.com/repos/lampepfl/dotty/issues/1694/comments","events_url":"https://api.github.com/repos/lampepfl/dotty/issues/1694/events","html_url":"https://github.com/lampepfl/dotty/issues/1694","id":188509311,"number":1694,"title":"Annotation macros in Dotty","user":{"login":"liufengyun","id":754633,"avatar_url":"https://avatars.githubusercontent.com/u/754633?v=3","gravatar_id":"","url":"https://api.github.com/users/liufengyun","html_url":"https://github.com/liufengyun","followers_url":"https://api.github.com/users/liufengyun/followers","following_url":"https://api.github.com/users/liufengyun/following{/other_user}","gists_url":"https://api.github.com/users/liufengyun/gists{/gist_id}","starred_url":"https://api.github.com/users/liufengyun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liufengyun/subscriptions","organizations_url":"https://api.github.com/users/liufengyun/orgs","repos_url":"https://api.github.com/users/liufengyun/repos","events_url":"https://api.github.com/users/liufengyun/events{/privacy}","received_events_url":"https://api.github.com/users/liufengyun/received_events","type":"User","site_admin":false},"labels":[{"id":21379541,"url":"https://api.github.com/repos/lampepfl/dotty/labels/itype:question","name":"itype:question","color":"cc317c","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2016-11-10T13:33:28Z","updated_at":"2016-12-15T20:41:38Z","closed_at":null,"body":"We had a discussion before about annotation macros, the idea then was to transform the following annotation macros:\r\n\r\n```Scala\r\nclass main extends scala.annotation.StaticAnnotation {\r\n    inline def apply(defn: Any): Any = meta {\r\n       body\r\n    }\r\n}\r\n```\r\nto:\r\n```Scala\r\nclass main extends scala.annotation.StaticAnnotation {\r\n    inline def apply(defn: Any): Any =  meta {\r\n       main$inline.meta3(defn)\r\n    }\r\n}\r\n\r\nobject main$inline {\r\n    def meta3(prefix:scala.meta.Stat)(defn: scala.meta.Stat): scala.meta.Stat = body\r\n}\r\n```\r\n\r\nThere are some problems with the scheme above. For example, given the code:\r\n\r\n```Scala\r\n@main\r\nclass Test {\r\n  println(\"hello, world!\")\r\n}\r\n```\r\n\r\nThe namer has a difficulty to determine whether `@main` is a macros or not and how to expand it. It needs to do as least follows:\r\n\r\n- resolve the name `main` to a symbol (`typedIndent`)\r\n    - **problem 1**: it doesn't work reliably if `main` is defined in the same compilation run\r\n- check if `main` extends `scala.annotation.StaticAnnotation`\r\n- check if `main` has a member `inline def apply(defn: Any): Any`, and rhs begins with `meta`.\r\n    - **problem 2**: Inspect syntactic tree to know some info about a compiled symbol is counter-intuitive, the info should be part of the symbol. Also, ASTs are not always available if `@main` is defined without tasty (e.g. Scala2).\r\n- inspect the body of `meta` to get the implementation method.\r\n    - **problem 3**: This seems to incur unnecessary complexity,  a simpler convention can be that the implementation is defined in `main$inline.meta`, thus no need to inspect ASTs, which can impose a performance penalty by deserializing tasty.\r\n\r\nIt seems that annotation macros are somewhat special, different from def macros, **inlining never happens for annotation macros**. It seems to me that current `paradise` implementation of annotation macros is simpler (avoids problem 2 & 3), it translates the code:\r\n```Scala\r\nclass main extends scala.annotation.StaticAnnotation {\r\n    inline def apply(defn: Any): Any = meta {\r\n       body\r\n    }\r\n}\r\n```\r\nto:\r\n```Scala\r\nclass main extends scala.annotation.StaticAnnotation {\r\n    inline def apply(defn: Any): Any =  ???\r\n}\r\n\r\nobject main$inline {\r\n    def apply(prefix:scala.meta.Stat)(defn: scala.meta.Stat): scala.meta.Stat = body\r\n}\r\n```\r\n\r\nMy question is:\r\n\r\n- Can we assume annotation macros are always compiled in a different run (problem 1)?\r\n- Can we follow paradise's way of handling annotation macros (simpler, avoids problem 2 & 3)?\r\n- During annotation macros transform, can we only transform `inline def apply(defn: Any): Any = meta {...}`, and ignore other possible `inline/meta` methods, as they don't make sense for annotation macros?\r\n\r\nWDYT @odersky @xeno-by @DarkDimius ?\r\n"},"comment":{"url":"https://api.github.com/repos/lampepfl/dotty/issues/comments/267438302","html_url":"https://github.com/lampepfl/dotty/issues/1694#issuecomment-267438302","issue_url":"https://api.github.com/repos/lampepfl/dotty/issues/1694","id":267438302,"user":{"login":"liufengyun","id":754633,"avatar_url":"https://avatars.githubusercontent.com/u/754633?v=3","gravatar_id":"","url":"https://api.github.com/users/liufengyun","html_url":"https://github.com/liufengyun","followers_url":"https://api.github.com/users/liufengyun/followers","following_url":"https://api.github.com/users/liufengyun/following{/other_user}","gists_url":"https://api.github.com/users/liufengyun/gists{/gist_id}","starred_url":"https://api.github.com/users/liufengyun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liufengyun/subscriptions","organizations_url":"https://api.github.com/users/liufengyun/orgs","repos_url":"https://api.github.com/users/liufengyun/repos","events_url":"https://api.github.com/users/liufengyun/events{/privacy}","received_events_url":"https://api.github.com/users/liufengyun/received_events","type":"User","site_admin":false},"created_at":"2016-12-15T20:41:38Z","updated_at":"2016-12-15T20:41:38Z","body":"Thanks @odersky . While I agree keeping it a method will be the simplest way, `meta` is different from `apply`, `unapply` and `copy`, because it's a **special symbol** from outside the compiler, `apply` and `unapply` are just **special names**.\r\n\r\nFor now I'm happy to keep it as a method, we can come back to this small decision later. It should be easy to change.\r\n"}}
{"actor":{"display_login":"liufengyun"}}