2017-10-09 11 views
1

におけるG [T] FORALL {タイプT} Iマクロ注釈を有する:[T] <マクロ

import language.experimental.macros 
import reflect.macros.whitebox.Context 

class annot extends StaticAnnotation { 
    def macroTransform(annottees: Any*): Any = macro annot.impl 
} 
object annot { 
    def impl(c: Context)(annottees: c.Tree*): c.Tree = ... 
} 

を私は次のように使用したい:

@annot case class A[B1, B2, ...](c: C) extends D1 with D2 with ... 

しかし(C <: D1 with D2 with ...) forAll { type B1; type B2; ... }

@annot case class OK1(i: Int) extends Any 
@annot case class NO1(s: String) extends AnyVal 
@annot case class OK2[A <: Other1, B[_]](bas: Other2[B[A]]) 
    extends (Other2[B[T]] forSome { type T <: Other1 }) 
type ConstLInt[A] = List[Int] 
@annot case class NO2[T](ts: List[T]) extends ConstLInt[T] // Only works if T = Int 

が、私は途中でそこに着くことができるかどうかD1, D2, ...場合に依存しないので、それだけで、動作するはずですは、その後、私の条件は、これは

@annot case class D[E[A] <: Seq[A]](ei: E[Int]) extends Seq[Int] 

でもない、私は一般化するにはどうすればよい

@annot case class D[E, C <: E](c: C) extends E // extends clause references E 

を可能にするのに十分を可能にするのに十分である

val fieldTypeE = c.typecheck(ExistentialTypeTree(fieldType, tparams), c.TYPEmode).tpe 
parents.forall(fieldTypeE <:< _) 

として私がチェックでき、 (C forSome { type B1; type B2; ... }) <: D1 with D2 with ...に相当します?ここで

答えて

0

はシンプルなソリューションです:

val implicitly = q"_root_.scala.Predef.implicitly" 
val <:< = tq"_root_.scala.Predef.<:<" 
val checks = parents.map { parent => 
    q"$implicitly[${<:<}[$fieldType, $parent]]" 
} 
// checks = Seq(q"implicitly[C <:< D1]", q"implicitly[C <:< D2]", ...) 
val checker = q"trait ${TypeName(c.freshName())} { ..$tparams; ..$checks }" 
// trait <syn> { 
// type B1 
// type B2 // Bring them into scope as abstract types (the forall part) 
// .. 
// implicitly[C <:< D1] 
// implicitly[C <:< D2] // Do checks against them, knowing only their constraints 
// .. 
// } 
c.typecheck(checker) 
関連する問題