summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-06-05 20:36:51 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-06-08 15:23:10 +0200
commitc7491eb1c7d41c5eaecb20f9e2f82fd208a6713e (patch)
tree49093c1d1c8ba0857e845bdfc0aa5b3710d76787 /src/compiler
parentc74533ad6547befcfaf524dcb93c920f922c47e1 (diff)
downloadscala-c7491eb1c7d41c5eaecb20f9e2f82fd208a6713e.tar.gz
scala-c7491eb1c7d41c5eaecb20f9e2f82fd208a6713e.tar.bz2
scala-c7491eb1c7d41c5eaecb20f9e2f82fd208a6713e.zip
improves traces and error messages
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/TreePrinters.scala10
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala5
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reify.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala53
7 files changed, 51 insertions, 40 deletions
diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala
index b3e4318fdc..e5a98c6b4e 100644
--- a/src/compiler/scala/reflect/internal/TreePrinters.scala
+++ b/src/compiler/scala/reflect/internal/TreePrinters.scala
@@ -27,7 +27,9 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
val sym = tree.symbol
- if (sym != null && sym != NoSymbol) {
+ if (sym.name.toString == nme.ERROR.toString) {
+ "<" + quotedName(name, decoded) + ": error>"
+ } else if (sym != null && sym != NoSymbol) {
val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else ""
var suffix = ""
if (settings.uniqid.value) suffix += ("#" + sym.id)
@@ -167,6 +169,12 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
}
def printAnnotations(tree: Tree) {
+ if (inReflexiveMirror && tree.symbol != null && tree.symbol != NoSymbol)
+ // [Eugene++] todo. this is not 100% correct, but is necessary for sane printing
+ // the problem is that getting annotations doesn't automatically initialize the symbol
+ // so we might easily print something as if it doesn't have annotations, whereas it does
+ tree.symbol.initialize
+
val annots = tree.symbol.annotations match {
case Nil => tree.asInstanceOf[MemberDef].mods.annotations
case anns => anns
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
index 4466f281b8..6edadf3a47 100644
--- a/src/compiler/scala/reflect/reify/Errors.scala
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -10,7 +10,10 @@ trait Errors {
import mirror._
import definitions._
- def defaultErrorPosition = analyzer.enclosingMacroPosition
+ def defaultErrorPosition = {
+ val stack = currents collect { case t: Tree if t.pos != NoPosition => t.pos }
+ stack.headOption getOrElse analyzer.enclosingMacroPosition
+ }
// expected errors: these can happen if the user casually writes whatever.reify(...)
// hence we don't crash here, but nicely report a typechecking error and bail out asap
diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala
index e03ff5832c..0e0ce17bd0 100644
--- a/src/compiler/scala/reflect/reify/phases/Reify.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reify.scala
@@ -37,6 +37,7 @@ trait Reify extends Symbols
}
def currentQuantified = flatCollect(reifyStack.currents)({ case ExistentialType(quantified, _) => quantified })
def current = reifyStack.currents.head
+ def currents = reifyStack.currents
/**
* Reifies any supported value.
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index ce3106ab29..17d8def2e9 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -145,6 +145,8 @@ abstract class NodePrinters {
str.toString
}
def printModifiers(tree: MemberDef) {
+ // [Eugene++] there's most likely a bug here (?)
+ // see `TreePrinters.printAnnotations` for more information
val annots0 = tree.symbol.annotations match {
case Nil => tree.mods.annotations
case xs => xs map annotationInfoToString
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
index 605ecee6c7..7289a947f4 100644
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
@@ -15,7 +15,7 @@ import scala.collection.{ mutable, immutable }
*
* @author Lex Spoon
*/
-class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader)
+class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
extends ClassLoader(parent)
with ScalaClassLoader
{
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 217cadaab8..6a2a9b850c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1183,16 +1183,24 @@ trait Implicits {
// if ``pre'' is not a PDT, e.g. if someone wrote
// implicitly[scala.reflect.makro.Context#TypeTag[Int]]
// then we need to fail, because we don't know the prefix to use during type reification
- return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind))
+ // upd. we also need to fail silently, because this is a very common situation
+ // e.g. quite often we're searching for BaseUniverse#TypeTag, e.g. for a type tag in any universe
+ // so that if we find one, we could convert it to whatever universe we need by the means of the `in` method
+ // if no tag is found in scope, we end up here, where we ask someone to materialize the tag for us
+ // however, since the original search was about a tag with no particular prefix, we cannot proceed
+ // this situation happens very often, so emitting an error message here (even if only for -Xlog-implicits) would be too much
+ //return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind))
+ return SearchFailure
}
)
// todo. migrate hardcoded materialization in Implicits to corresponding implicit macros
- var materializer = atPos(pos.focus)(
- gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix))
- )
+ var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix)))
if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer))
if (context.macrosEnabled) success(materializer)
- else failure(materializer, "macros are disabled")
+ // don't call `failure` here. if macros are disabled, we just fail silently
+ // otherwise -Xlog-implicits will spam the long with zillions of "macros are disabled"
+ // this is ugly but temporary, since all this code will be removed once I fix implicit macros
+ else SearchFailure
}
private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index c10901cdce..c21222f450 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -186,6 +186,7 @@ trait Macros extends Traces {
macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos))
if (!typer.checkFeature(ddef.pos, MacrosFeature, immediate = true)) {
+ macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled")
ddef.symbol setFlag IS_ERROR
return EmptyTree
}
@@ -675,31 +676,20 @@ trait Macros extends Traces {
private def macroRuntime(macroDef: Symbol): Option[MacroRuntime] = {
macroTraceVerbose("looking for macro implementation: ")(macroDef)
if (fastTrack contains macroDef) {
- macroLogVerbose("macro expansion serviced by a fast track")
+ macroLogVerbose("macro expansion is serviced by a fast track")
Some(fastTrack(macroDef))
} else {
macroRuntimesCache.getOrElseUpdate(macroDef, {
val runtime = {
- macroTraceVerbose("looking for macro implementation: ")(macroDef)
macroTraceVerbose("macroDef is annotated with: ")(macroDef.annotations)
val ann = macroDef.getAnnotation(MacroImplAnnotation)
- if (ann == None) {
- macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef)
- return None
- }
+ if (ann == None) { macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef); return None }
val macroImpl = ann.get.args(0).symbol
- if (macroImpl == NoSymbol) {
- macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef)
- return None
- }
-
+ if (macroImpl == NoSymbol) { macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef); return None }
macroLogVerbose("resolved implementation %s at %s".format(macroImpl, macroImpl.pos))
- if (macroImpl.isErroneous) {
- macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef)
- return None
- }
+ if (macroImpl.isErroneous) { macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef); return None }
def loadMacroImpl(macroMirror: Mirror): Option[(Object, macroMirror.Symbol)] = {
try {
@@ -711,14 +701,8 @@ trait Macros extends Traces {
// however, the code below doesn't account for these guys, because it'd take a look of time to get it right
// for now I leave it as a todo and move along to more the important stuff
- macroTraceVerbose("loading implementation class from %s: ".format(macroMirror))(macroImpl.owner.fullName)
- macroTraceVerbose("classloader is: ")("%s of type %s".format(macroMirror.classLoader, if (macroMirror.classLoader != null) macroMirror.classLoader.getClass.toString else "primordial classloader"))
- def inferClasspath(cl: ClassLoader) = cl match {
- case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
- case null => "[" + scala.tools.util.PathResolver.Environment.javaBootClassPath + "]"
- case _ => "<unknown>"
- }
- macroTraceVerbose("classpath is: ")(inferClasspath(macroMirror.classLoader))
+ macroTraceVerbose("loading implementation class: ")(macroImpl.owner.fullName)
+ macroTraceVerbose("classloader is: ")(ReflectionUtils.show(macroMirror.classLoader))
// [Eugene] relies on the fact that macro implementations can only be defined in static classes
// [Martin to Eugene] There's similar logic buried in Symbol#flatname. Maybe we can refactor?
@@ -749,7 +733,7 @@ trait Macros extends Traces {
val implClass = macroMirror.classToJava(implClassSymbol)
val implSource = implClass.getProtectionDomain.getCodeSource
println("implClass is %s from %s".format(implClass, implSource))
- println("implClassLoader is %s with classpath %s".format(implClass.getClassLoader, inferClasspath(implClass.getClassLoader)))
+ println("implClassLoader is %s".format(implClass.getClassLoader, ReflectionUtils.show(implClass.getClassLoader)))
}
}
@@ -786,6 +770,9 @@ trait Macros extends Traces {
case ex: ClassNotFoundException =>
macroTraceVerbose("implementation class failed to load: ")(ex.toString)
None
+ case ex: NoSuchMethodException =>
+ macroTraceVerbose("implementation method failed to load: ")(ex.toString)
+ None
}
}
@@ -985,15 +972,17 @@ trait Macros extends Traces {
def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = {
def fail(what: String, tree: Tree): Tree = {
val err = typer.context.errBuffer.head
- this.fail(typer, tree, "failed to %s: %s at %s".format(what, err.errMsg, err.errPos))
+ this.fail(typer, tree, err.errPos, "failed to %s: %s".format(what, err.errMsg))
return expandee
}
val start = startTimer(macroExpandNanos)
incCounter(macroExpandCount)
try {
macroExpand1(typer, expandee) match {
- case Success(expanded) =>
+ case Success(expanded0) =>
try {
+ val expanded = expanded0 // virtpatmat swallows the local for expandee from the match
+ // so I added this dummy local for the ease of debugging
var expectedTpe = expandee.tpe
// [Eugene] weird situation. what's the conventional way to deal with it?
@@ -1046,11 +1035,11 @@ trait Macros extends Traces {
private def Skip(expanded: Tree) = Other(expanded)
private def Cancel(expandee: Tree) = Other(expandee)
private def Failure(expandee: Tree) = Other(expandee)
- private def fail(typer: Typer, expandee: Tree, msg: String = null) = {
+ private def fail(typer: Typer, expandee: Tree, pos: Position = NoPosition, msg: String = null) = {
def msgForLog = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg
macroLogLite("macro expansion has failed: %s".format(msgForLog))
- val pos = if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition
- if (msg != null) typer.context.error(pos, msg)
+ val errorPos = if (pos != NoPosition) pos else (if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition)
+ if (msg != null) typer.context.error(errorPos, msg)
typer.infer.setError(expandee)
Failure(expandee)
}
@@ -1069,7 +1058,7 @@ trait Macros extends Traces {
// if a macro implementation is incompatible or any of the arguments are erroneous
// there is no sense to expand the macro itself => it will only make matters worse
if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) {
- val reason = if (expandee.symbol.isErroneous) "incompatible macro implementation" else "erroneous arguments"
+ val reason = if (expandee.symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments"
macroTraceVerbose("cancelled macro expansion because of %s: ".format(reason))(expandee)
return Cancel(typer.infer.setError(expandee))
}
@@ -1105,7 +1094,7 @@ trait Macros extends Traces {
val undetparams = calculateUndetparams(expandee)
val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty
- def failExpansion(msg: String = null) = fail(typer, expandee, msg)
+ def failExpansion(msg: String = null) = fail(typer, expandee, msg = msg)
def performExpansion(args: List[Any]): MacroExpansionResult = {
val numErrors = reporter.ERROR.count
def hasNewErrors = reporter.ERROR.count > numErrors
@@ -1257,7 +1246,7 @@ trait Macros extends Traces {
None
}
} getOrElse realex.getMessage
- fail(typer, expandee, "exception during macro expansion: " + message)
+ fail(typer, expandee, msg = "exception during macro expansion: " + message)
}
}