2016-02-17 6 views
4

Когда я пытаюсь добавить макрос аннотацию к моему делу класса:Как применить аннотацию макроса к классу case с привязкой к контексту?

@macid case class CC[A: T](val x: A) 

Я получаю ошибку:

private[this] not allowed for case class parameters 

@macid только тождественная функция, определяемая как Whitebox StaticAnnotation:

import scala.language.experimental.macros 
import scala.reflect.macros.whitebox.Context 
import scala.annotation.StaticAnnotation 
class macid extends StaticAnnotation { 
    def macroTransform(annottees: Any*): Any = macro macidMacro.impl 
} 
object macidMacro { 
    def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { 
    new Macros[c.type](c).macidMacroImpl(annottees.toList) 
    } 
} 
class Macros[C <: Context](val c: C) { 
    import c.universe._ 
    def macidMacroImpl(annottees: List[c.Expr[Any]]): c.Expr[Any] = 
    annottees(0) 
} 

Неангутный код работает:

case class CC[A: T](val x: A) 

Она работает, если удалить контекст, связанный:

@macid case class CC[A](val x: A) 

То, что происходит в контексте неизбежно будет обессахаренная в частный параметр. Следующий Обессахаренный код получает ту же ошибку:

@macid case class CC[A](val x: A)(implicit aIsT: T[A]) 

Чтобы получить рабочий код, который я сделать неявный параметр общественности val:

@macid case class CC[A](val x: A)(implicit val aIsT: T[A]) 

Так что мои вопросы: Что такое правильный путь для макро-аннотации к границы контекста поддержки? Почему компилятор выполняет проверку не-private-parameters-of-case-classes кода, генерируемого макрокомандой, но не выполняет проверку обычного кода?

Варианты Scala версии 2.11.7 и 2.12.0-M3 сообщают об ошибке. Все приведенные выше примеры кода компилируются и выполняются, как ожидалось, в 2.11.3.

ответ

2

Похоже на ошибку. Вот дерево, как видно макросом:

case class CC[A] extends scala.Product with scala.Serializable { 
    <caseaccessor> <paramaccessor> val x: A = _; 
    implicit <synthetic> <caseaccessor> <paramaccessor> private[this] val evidence$1: T[A] = _; 
    def <init>(x: A)(implicit evidence$1: T[A]) = { 
    super.<init>(); 
    () 
    } 
} 

И через время работы Reflection API:

case class CC[A] extends Product with Serializable { 
    <caseaccessor> <paramaccessor> val x: A = _; 
    implicit <synthetic> <paramaccessor> private[this] val evidence$1: $read.T[A] = _; 
    def <init>(x: A)(implicit evidence$1: $read.T[A]) = { 
    super.<init>(); 
    () 
    } 
}; 

Первый имеет дополнительный <caseaccessor> флаг на evidence$1, когда он не должен. Кажется, что все неявные параметры классов case ошибочно заданы этим флагом.

+0

Похоже на ошибку, но это сбивает с толку, потому что трудно сказать, что означает ''. Мне кажется, что только параметры в первом списке параметров конструктора должны быть помечены '' s, потому что только первый список параметров сопоставляется при сопоставлении разбиений. Неявный параметр находится во втором списке параметров, поэтому он не должен быть ''. –

+0

@SII_of_SII Да, это так. Только параметры первого списка параметров класса case должны иметь этот флаг. Я заметил, что эта проблема также возникает, если у вас есть второй список параметров в классе case (не подразумевается). –