diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-03-14 13:43:22 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-03-14 15:41:29 -0700 |
commit | b310d8c2e862d0a0db505eed8a29c15520fba845 (patch) | |
tree | 64637d3598a9441640fa7245c94fecf1654cddbe | |
parent | efc0905f6b7a78bf3b454fbd9adb50aab5ffe20d (diff) | |
download | scala-b310d8c2e862d0a0db505eed8a29c15520fba845.tar.gz scala-b310d8c2e862d0a0db505eed8a29c15520fba845.tar.bz2 scala-b310d8c2e862d0a0db505eed8a29c15520fba845.zip |
SI-4492 More informative error when class not found on classpath
Position the error based on Select tree that failed to type check,
presumably due to an underlying MissingRequirementError, which has no position.
There are lots of other ways we could rewrap a MRE and supplement position info,
but that remains TODO. Jason's review comment is recorded in the code.
Also try to detect the case of a missing module and provide some advice,
as well as linking to the forthcoming 2.11 guide at
http://docs.scala-lang.org/overviews/core/scala-2.11.html.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/pickling/UnPickler.scala | 23 | ||||
-rw-r--r-- | test/files/neg/t5148.check | 8 | ||||
-rw-r--r-- | test/files/run/t6440.check | 8 | ||||
-rw-r--r-- | test/files/run/t6440b.check | 8 |
7 files changed, 44 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index d439bb5603..9715fdaf00 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -359,6 +359,14 @@ trait ContextErrors { //setError(sel) } + def SelectWithUnderlyingError(sel: Tree, err: AbsTypeError) = { + // if there's no position, this is likely the result of a MissingRequirementError + // use the position of the selection we failed to type check to report the original message + if (err.errPos == NoPosition) issueNormalTypeError(sel, err.errMsg) + else issueTypeError(err) + setError(sel) + } + //typedNew def IsAbstractError(tree: Tree, sym: Symbol) = { issueNormalTypeError(tree, sym + " is abstract; cannot be instantiated") diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 994a2a4f4f..8e1ceffecd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -103,7 +103,7 @@ trait Contexts { self: Analyzer => // there must be a scala.xml package when xml literals were parsed in this unit if (unit.hasXml && ScalaXmlPackage == NoSymbol) - unit.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see https://github.com/scala/scala/wiki/Scala-2.11#xml.") + unit.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see http://docs.scala-lang.org/overviews/core/scala-2.11.html#scala-xml.") // scala-xml needs `scala.xml.TopScope` to be in scope globally as `$scope` // We detect `scala-xml` by looking for `scala.xml.TopScope` and @@ -544,6 +544,8 @@ trait Contexts { self: Analyzer => if (checking) onTreeCheckerError(pos, msg) else unit.error(pos, msg) @inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) { + // TODO: are errors allowed to have pos == NoPosition?? + // if not, Jason suggests doing: val pos = err.errPos.orElse( { devWarning("Que?"); context.tree.pos }) if (settings.Yissuedebug) { log("issue error: " + err.errMsg) (new Exception).printStackTrace() diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9f3f257529..9f557f4aa5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4670,8 +4670,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case SilentTypeError(err: AccessTypeError) => (tree1, Some(err)) case SilentTypeError(err) => - context issue err - return setError(tree) + SelectWithUnderlyingError(tree, err) + return tree case SilentResultValue(treeAndPre) => (stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None) } diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 42f794736a..64a1a44722 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -229,6 +229,20 @@ abstract class UnPickler { NoSymbol } + def moduleAdvice(missing: String): String = { + val module = + if (missing.startsWith("scala.xml")) Some(("org.scala-lang.modules", "scala-xml")) + else if (missing.startsWith("scala.util.parsing")) Some(("org.scala-lang.modules", "scala-parser-combinators")) + else if (missing.startsWith("scala.swing")) Some(("org.scala-lang.modules", "scala-swing")) + else if (missing.startsWith("scala.util.continuations")) Some(("org.scala-lang.plugins", "scala-continuations-library")) + else None + + (module map { case (group, art) => + s"""\n(NOTE: It looks like the $art module is missing; try adding a dependency on "$group" : "$art". + | See http://docs.scala-lang.org/overviews/core/scala-2.11.html for more information.)""".stripMargin + } getOrElse "") + } + // (1) Try name. fromName(name) orElse { // (2) Try with expanded name. Can happen if references to private @@ -240,11 +254,12 @@ abstract class UnPickler { // (4) Call the mirror's "missing" hook. adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse { // (5) Create a stub symbol to defer hard failure a little longer. + val fullName = s"${owner.fullName}.$name" val missingMessage = - s"""|bad symbolic reference. A signature in $filename refers to ${name.longString} - |in ${owner.kindString} ${owner.fullName} which is not available. - |It may be completely missing from the current classpath, or the version on - |the classpath might be incompatible with the version used when compiling $filename.""".stripMargin + s"""|bad symbolic reference to $fullName encountered in class file '$filename'. + |Cannot access ${name.longString} in ${owner.kindString} ${owner.fullName}. The current classpath may be + |missing a definition for $fullName, or $filename may have been compiled against a version that's + |incompatible with the one found on the current classpath.${moduleAdvice(fullName)}""".stripMargin owner.newStubSymbol(name, missingMessage) } } diff --git a/test/files/neg/t5148.check b/test/files/neg/t5148.check index f426bd2010..8a667f4b88 100644 --- a/test/files/neg/t5148.check +++ b/test/files/neg/t5148.check @@ -1,5 +1,5 @@ -error: bad symbolic reference. A signature in Imports.class refers to type Request -in class scala.tools.nsc.interpreter.IMain which is not available. -It may be completely missing from the current classpath, or the version on -the classpath might be incompatible with the version used when compiling Imports.class. +error: bad symbolic reference to scala.tools.nsc.interpreter.IMain.Request encountered in class file 'Imports.class'. +Cannot access type Request in class scala.tools.nsc.interpreter.IMain. The current classpath may be +missing a definition for scala.tools.nsc.interpreter.IMain.Request, or Imports.class may have been compiled against a version that's +incompatible with the one found on the current classpath. one error found diff --git a/test/files/run/t6440.check b/test/files/run/t6440.check index 806279fb74..27d5d1380e 100644 --- a/test/files/run/t6440.check +++ b/test/files/run/t6440.check @@ -1,4 +1,4 @@ -pos: source-newSource1.scala,line-9,offset=109 bad symbolic reference. A signature in U.class refers to term pack1 -in package <root> which is not available. -It may be completely missing from the current classpath, or the version on -the classpath might be incompatible with the version used when compiling U.class. ERROR +pos: source-newSource1.scala,line-9,offset=109 bad symbolic reference to <root>.pack1 encountered in class file 'U.class'. +Cannot access term pack1 in package <root>. The current classpath may be +missing a definition for <root>.pack1, or U.class may have been compiled against a version that's +incompatible with the one found on the current classpath. ERROR diff --git a/test/files/run/t6440b.check b/test/files/run/t6440b.check index 9771ce5efb..0b642c2c35 100644 --- a/test/files/run/t6440b.check +++ b/test/files/run/t6440b.check @@ -1,4 +1,4 @@ -pos: NoPosition bad symbolic reference. A signature in U.class refers to type T -in package pack1 which is not available. -It may be completely missing from the current classpath, or the version on -the classpath might be incompatible with the version used when compiling U.class. ERROR +pos: NoPosition bad symbolic reference to pack1.T encountered in class file 'U.class'. +Cannot access type T in package pack1. The current classpath may be +missing a definition for pack1.T, or U.class may have been compiled against a version that's +incompatible with the one found on the current classpath. ERROR |