问题
Following on from: How to Typecheck a DefDef
First, some snippets from my macro:
object log {
def err(msg: String): Unit = c.error(c.enclosingPosition, msg)
def warn(msg: String): Unit = c.warning(c.enclosingPosition, msg)
def info(msg: String): Unit = c.info(c.enclosingPosition, msg, force=true)
def rawInfo(name: String, obj: Any): Unit = info(name + " = " + showRaw(obj))
}
methodsIn(body) foreach { dd => //dd: DefDef
val name = dd.name.toString
log.rawInfo(name, dd)
log.rawInfo(name + ".rhs", dd.rhs)
try {
val typechecked = ctx.typecheck(dd.duplicate)
log.rawInfo(name + ".typechecked", typechecked)
log.info(name + ".typechecked.symbol = " + typechecked.symbol)
log.rawInfo(name + ".typechecked.symbol [raw]", typechecked.symbol)
log.info(name + ".typechecked.symbol.info = " + typechecked.symbol.info)
log.rawInfo(name + ".typechecked.symbol.info [raw]", typechecked.symbol.info)
log.rawInfo(name + ".typechecked.tpe", typechecked.tpe)
} catch { case e: Throwable => log.warn(e.toString)}
}
I then feed the macro with this class:
class BorgMe(@mymacro val param: Nanites) {
def one(s: String) = s
}
Yes... it's a paradise annotation macro. But I don't think that's relevant here.
What's confusing me is the log output from that code, which looks like:
one = DefDef(
Modifiers(),
TermName("one"),
List(),
List(List(ValDef(
Modifiers(PARAM),
TermName("s"),
Ident(TypeName("String")),
EmptyTree
))),
TypeTree(),
Ident(TermName("s"))
)
one.rhs = Ident(TermName("s"))
one.typechecked = DefDef(
Modifiers(),
TermName("one"),
List(),
List(List(ValDef(
Modifiers(PARAM),
TermName("s"),
TypeTree().setOriginal(
Select(
Select(
This(TypeName("scala")),
scala.Predef
),
TypeName("String")
)
),
EmptyTree
))),
TypeTree(),
Ident(TermName("s"))
)
one.typechecked.symbol = method one
one.typechecked.symbol [raw] = TermName("one")
one.typechecked.symbol.info = (s: String)String
one.typechecked.symbol.info [raw] =
MethodType(
List(TermName("s")),
TypeRef(
SingleType(ThisType(scala), scala.Predef),
TypeName("String"),
List()
)
)
one.typechecked.tpe = NoType
Given that the typecheck is succeeding, and we clearly have all the expected symbol info:
one.typechecked.symbol = method one
one.typechecked.symbol.info = (s: String)String
How come tpe
for the method is still coming out as NoType
?
one.typechecked.tpe = NoType
回答1:
That's just how scalac works. Typechecked definitions (i.e. subclasses of DefTree
) are assigned with NoType
. To the contrast, untyped definitions have null
in their tpe
(just like other untyped trees), so it's possible to discern them.
来源:https://stackoverflow.com/questions/22451181/why-does-typecheck-return-notype-even-when-its-calculated-a-valid-symbol