2

I have a macro which enumerates the direct sub types of a sealed trait:

import scala.reflect.macros.Context
import language.experimental.macros

object Checker {
  def apply[A]: Unit = macro applyImpl[A]

  def applyImpl[A: c.WeakTypeTag](c: Context): c.Expr[Unit] = {
    val tpe = c.weakTypeOf[A].typeSymbol.asClass
    require (tpe.isSealed)
    tpe.typeSignature // SI-7046
    require (tpe.knownDirectSubclasses.nonEmpty)

    import c.universe._
    c.Expr[Unit](reify {} .tree)
  }
}

Then this works:

sealed trait A
case class A1(i: Int) extends A

object NotNested {
  val nada = Checker[A]
}

But this fails:

object Nested {
  sealed trait A
  case class A1(i: Int) extends A

  val nada = Checker[A]
}

[error] java.lang.IllegalArgumentException: requirement failed: 
        Did not find sub classes

I thought I ran into SI-7046, so I added the call to tpe.typeSignature, but that doesn't help apparently.

I need a work around for this using Scala 2.10.2. Somehow I must enforce some extra type trees to be initialised, I guess?

halfer
  • 19,824
  • 17
  • 99
  • 186
0__
  • 66,707
  • 21
  • 171
  • 266
  • If you can afford writing an explicit type ascription for `nada` then everything will work. For example, `val nada: Any = Checker[A]`. – Eugene Burmako Jun 18 '13 at 20:28
  • @Eugene Ok, of course I can afford that. Unfortunately I run into the missing sub class information in other places, too, now, even if the sub classes are all top level and I do use type ascriptions, and I use separate compilation units. The errors come and go depending how sbt does the incremental compilation. [For example in this file](https://github.com/iem-projects/PointLib/blob/composer_sh/src/main/scala/at/iem/point/sh/sketches/genetic/Formats.scala)—even if I add `: Format[X]`, sometimes it all breaks down, then I have to comment out all, and at some point it works again. – 0__ Jun 18 '13 at 20:34
  • Could you provide a reproduction for your current problem? Also, type ascriptions will only help with classes nested in the class that defines a macro. They shouldn't have any effect on anything else. – Eugene Burmako Jun 18 '13 at 20:55
  • @EugeneBurmako I filed bug [SI-7588](https://issues.scala-lang.org/browse/SI-7588), that has a minimised reproducible case. – 0__ Jun 18 '13 at 21:52
  • @0__ I have had this same exact problem for subclasses – Andy Jul 12 '13 at 23:48
  • Follow-up: did the existing answer below help at all? Was [this bug](https://issues.scala-lang.org/browse/SI-7046) the solution? For completeness, are you able to write an answer? – halfer Apr 30 '17 at 10:25

1 Answers1

0

A possible workaround is following (what do you think @EugeneBurmako).

val cls: ClassSymbol = sub.asClass

println(s"knownDirectSubclasses = ${cls.knownDirectSubclasses}")
// print "knownDirectSubclasses = Set()"

val subsub = cls.owner.typeSignature.decls.filter {
  case c: ClassSymbol =>
    cls != c && c.selfType.baseClasses.contains(cls)

  case _ => false
}

println(s"subsub = $subsub")
// print the actual sub classes
cchantep
  • 9,118
  • 3
  • 30
  • 41