1

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
4

1 回答 1

2

这就是 scalac 的工作原理。类型检查的定义(即 的子类DefTree)分配有NoType。相比之下,无类型定义nulltpe就像其他无类型树一样),因此可以识别它们。

于 2014-03-17T10:18:30.980 回答