summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala41
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala8
-rw-r--r--src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala23
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplProps.scala3
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplReporter.scala18
-rw-r--r--test/files/neg/t8890.check4
-rw-r--r--test/files/neg/t8890.scala11
8 files changed, 89 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index 0b218b711c..5bf611a7b0 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -29,7 +29,7 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
case INFO => null
}
- private def clabel(severity: Severity): String = {
+ protected def clabel(severity: Severity): String = {
val label0 = label(severity)
if (label0 eq null) "" else label0 + ": "
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 20e462bbce..866ca37303 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -885,22 +885,31 @@ trait ContextErrors {
val WrongNumber, NoParams, ArgsDoNotConform = Value
}
- private def issueAmbiguousTypeErrorUnlessErroneous(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): Unit =
- if (!(pre.isErroneous || sym1.isErroneous || sym2.isErroneous)) {
- if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) {
- val methodName = nme.defaultGetterToMethod(sym1.name)
- context.issueAmbiguousError(AmbiguousTypeError(sym1.enclClass.pos,
- "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName +
- " define default arguments"))
- } else {
- context.issueAmbiguousError(AmbiguousTypeError(pos,
- ("ambiguous reference to overloaded definition,\n" +
- "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) +
- "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) +
- "\nmatch " + rest)
- ))
- }
- }
+ private def issueAmbiguousTypeErrorUnlessErroneous(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): Unit = {
+ // To avoid stack overflows (SI-8890), we MUST (at least) report when either `validTargets` OR `ambiguousSuppressed`
+ // More details:
+ // If `!context.ambiguousErrors`, `reporter.issueAmbiguousError` (which `context.issueAmbiguousError` forwards to)
+ // buffers ambiguous errors. In this case, to avoid looping, we must issue even if `!validTargets`. (TODO: why?)
+ // When not buffering (and thus reporting to the user), we shouldn't issue unless `validTargets`,
+ // otherwise we report two different errors that trace back to the same root cause,
+ // and unless `validTargets`, we don't know for sure the ambiguity is real anyway.
+ val validTargets = !(pre.isErroneous || sym1.isErroneous || sym2.isErroneous)
+ val ambiguousBuffered = !context.ambiguousErrors
+ if (validTargets || ambiguousBuffered)
+ context.issueAmbiguousError(
+ if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) {
+ val methodName = nme.defaultGetterToMethod(sym1.name)
+ AmbiguousTypeError(sym1.enclClass.pos,
+ s"in ${sym1.enclClass}, multiple overloaded alternatives of $methodName define default arguments")
+
+ } else {
+ AmbiguousTypeError(pos,
+ "ambiguous reference to overloaded definition,\n" +
+ s"both ${sym1.fullLocationString} of type ${pre.memberType(sym1)}\n" +
+ s"and ${sym2.fullLocationString} of type ${pre.memberType(sym2)}\n" +
+ s"match $rest")
+ })
+ }
def AccessError(tree: Tree, sym: Symbol, ctx: Context, explanation: String): AbsTypeError =
AccessError(tree, sym, ctx.enclClass.owner.thisType, ctx.enclClass.owner, explanation)
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 72c907305a..6e18682494 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -412,8 +412,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
private def readOneLine() = {
+ import scala.io.AnsiColor.{ MAGENTA, RESET }
out.flush()
- in readLine prompt
+ in readLine (
+ if (replProps.colorOk)
+ MAGENTA + prompt + RESET
+ else
+ prompt
+ )
}
/** The main read-eval-print loop for the repl. It calls
diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
index a37cdc2ec8..bcba7b6dfd 100644
--- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -102,6 +102,18 @@ trait MemberHandlers {
class GenericHandler(member: Tree) extends MemberHandler(member)
+ import scala.io.AnsiColor.{ BOLD, BLUE, GREEN, RESET }
+
+ def color(c: String, s: String) =
+ if (replProps.colorOk) string2code(BOLD) + string2code(c) + s + string2code(RESET)
+ else s
+
+ def colorName(s: String) =
+ color(BLUE, string2code(s))
+
+ def colorType(s: String) =
+ color(GREEN, string2code(s))
+
class ValHandler(member: ValDef) extends MemberDefHandler(member) {
val maxStringElements = 1000 // no need to mkString billions of elements
override def definesValue = true
@@ -119,15 +131,20 @@ trait MemberHandlers {
if (replProps.vids) s"""" + f"@$${System.identityHashCode($path)}%8x" + """"
else ""
- """ + "%s%s: %s = " + %s""".format(string2code(prettyName), vidString, string2code(req typeOf name), resultString)
+ val nameString = colorName(prettyName) + vidString
+ val typeString = colorType(req typeOf name)
+ s""" + "$nameString: $typeString = " + $resultString"""
}
}
}
class DefHandler(member: DefDef) extends MemberDefHandler(member) {
override def definesValue = flattensToEmpty(member.vparamss) // true if 0-arity
- override def resultExtractionCode(req: Request) =
- if (mods.isPublic) codegenln(name, ": ", req.typeOf(name)) else ""
+ override def resultExtractionCode(req: Request) = {
+ val nameString = colorName(name)
+ val typeString = colorType(req typeOf name)
+ if (mods.isPublic) s""" + "$nameString: $typeString\\n"""" else ""
+ }
}
abstract class MacroHandler(member: DefDef) extends MemberDefHandler(member) {
diff --git a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
index 36e6dbbccc..8c4faf7278 100644
--- a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
@@ -13,6 +13,9 @@ class ReplProps {
private def bool(name: String) = BooleanProp.keyExists(name)
private def int(name: String) = IntProp(name)
+ // This property is used in TypeDebugging. Let's recycle it.
+ val colorOk = bool("scala.color")
+
val info = bool("scala.repl.info")
val debug = bool("scala.repl.debug")
val trace = bool("scala.repl.trace")
diff --git a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
index 88372334d6..e6f5a4089e 100644
--- a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
@@ -32,6 +32,24 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i
override def warning(pos: Position, msg: String): Unit = withoutTruncating(super.warning(pos, msg))
override def error(pos: Position, msg: String): Unit = withoutTruncating(super.error(pos, msg))
+ import scala.io.AnsiColor.{ RED, YELLOW, RESET }
+
+ def severityColor(severity: Severity): String = severity match {
+ case ERROR => RED
+ case WARNING => YELLOW
+ case INFO => RESET
+ }
+
+ override def print(pos: Position, msg: String, severity: Severity) {
+ val prefix = (
+ if (replProps.colorOk)
+ severityColor(severity) + clabel(severity) + RESET
+ else
+ clabel(severity)
+ )
+ printMessage(pos, prefix + msg)
+ }
+
override def printMessage(msg: String) {
// Avoiding deadlock if the compiler starts logging before
// the lazy val is complete.
diff --git a/test/files/neg/t8890.check b/test/files/neg/t8890.check
new file mode 100644
index 0000000000..1b69d6cf30
--- /dev/null
+++ b/test/files/neg/t8890.check
@@ -0,0 +1,4 @@
+t8890.scala:6: error: not found: type Str
+ def bar(x: Str): Unit = ???
+ ^
+one error found
diff --git a/test/files/neg/t8890.scala b/test/files/neg/t8890.scala
new file mode 100644
index 0000000000..cbdeb11d43
--- /dev/null
+++ b/test/files/neg/t8890.scala
@@ -0,0 +1,11 @@
+package foo
+
+class A {
+ /** The other */
+ def bar(x: Int): Unit = ???
+ def bar(x: Str): Unit = ???
+}
+
+class B {
+ (new A).bar(0)
+} \ No newline at end of file