diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/CompilationUnits.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/CompileServer.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Driver.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ScalaDoc.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DocFactory.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/REPL.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/reporters/Reporter.scala | 23 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 14 | ||||
-rw-r--r-- | test/files/neg/logImplicits.check | 19 | ||||
-rw-r--r-- | test/files/neg/logImplicits.flags | 1 | ||||
-rw-r--r-- | test/files/neg/logImplicits.scala | 25 |
14 files changed, 91 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 470207fd35..940d115b2f 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -74,6 +74,9 @@ trait CompilationUnits { self: Global => * It is empty up to phase 'icode'. */ val icode: LinkedHashSet[icodes.IClass] = new LinkedHashSet + + def echo(pos: Position, msg: String) = + reporter.echo(pos, msg) def error(pos: Position, msg: String) = reporter.error(pos, msg) diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index b10ac78ac7..6393ade146 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -136,9 +136,9 @@ class StandardCompileServer extends SocketServer { } if (command.shouldStopWithInfo) - reporter.info(null, command.getInfoMessage(newGlobal(newSettings, reporter)), true) + reporter.echo(command.getInfoMessage(newGlobal(newSettings, reporter))) else if (command.files.isEmpty) - reporter.info(null, command.usageMsg, true) + reporter.echo(command.usageMsg) else { if (isCompilerReusable) { info("[Reusing existing Global instance.]") diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index db95c1442b..0c52954a0b 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -24,8 +24,8 @@ abstract class Driver { protected def doCompile(compiler: Global) { if (command.files.isEmpty) { - reporter.info(null, command.usageMsg, true) - reporter.info(null, compiler.pluginOptionsHelp, true) + reporter.echo(command.usageMsg) + reporter.echo(compiler.pluginOptionsHelp) } else { val run = new compiler.Run() run compile command.files @@ -40,14 +40,14 @@ abstract class Driver { settings = command.settings if (settings.version.value) { - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) } else if (processSettingsHook()) { val compiler = newCompiler() try { if (reporter.hasErrors) reporter.flush() else if (command.shouldStopWithInfo) - reporter.info(null, command.getInfoMessage(compiler), true) + reporter.echo(command.getInfoMessage(compiler)) else doCompile(compiler) } catch { diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 2dd32e355b..c388a62644 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -159,7 +159,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb // nearly every trait really must go. For now using globalError. def error(msg: String) = globalError(msg) def globalError(msg: String) = reporter.error(NoPosition, msg) - def inform(msg: String) = reporter.info(NoPosition, msg, true) + def inform(msg: String) = reporter.echo(msg) def warning(msg: String) = if (opt.fatalWarnings) globalError(msg) else reporter.warning(NoPosition, msg) diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala index a9330b053b..4fa2cc71e5 100644 --- a/src/compiler/scala/tools/nsc/ScalaDoc.scala +++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala @@ -30,17 +30,17 @@ class ScalaDoc { def hasFiles = command.files.nonEmpty || docSettings.uncompilableFiles.nonEmpty if (docSettings.version.value) - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) else if (docSettings.Xhelp.value) - reporter.info(null, command.xusageMsg, true) + reporter.echo(command.xusageMsg) else if (docSettings.Yhelp.value) - reporter.info(null, command.yusageMsg, true) + reporter.echo(command.yusageMsg) else if (docSettings.showPlugins.value) reporter.warning(null, "Plugins are not available when using Scaladoc") else if (docSettings.showPhases.value) reporter.warning(null, "Phases are restricted when using Scaladoc") else if (docSettings.help.value || !hasFiles) - reporter.info(null, command.usageMsg, true) + reporter.echo(command.usageMsg) else try { if (docSettings.target.value == "msil") msilLibPath foreach (x => docSettings.assemrefs.value += (pathSeparator + x)) diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala index 5a510803ed..9a025b0d14 100644 --- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -96,7 +96,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor val documentError: PartialFunction[Throwable, Unit] = { case NoCompilerRunException => - reporter.info(NoPosition, "No documentation generated with unsucessful compiler run", false) + reporter.info(null, "No documentation generated with unsucessful compiler run", false) case _: ClassNotFoundException => () } diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index 81d4faa36e..1d78cc6e1c 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -37,7 +37,7 @@ object REPL { reporter = new ConsoleReporter(settings) val command = new CompilerCommand(args.toList, settings) if (command.settings.version.value) - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) else { try { object compiler extends Global(command.settings, reporter) { @@ -48,7 +48,7 @@ object REPL { return } if (command.shouldStopWithInfo) { - reporter.info(null, command.getInfoMessage(compiler), true) + reporter.echo(command.getInfoMessage(compiler)) } else { run(compiler) } diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index 12306606e4..f19a285d7c 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -47,14 +47,23 @@ abstract class Reporter { finally incompleteHandler = saved } - var cancelled = false - def hasErrors = ERROR.count > 0 || cancelled - def hasWarnings = WARNING.count > 0 + var cancelled = false + def hasErrors = ERROR.count > 0 || cancelled + def hasWarnings = WARNING.count > 0 - def info(pos: Position, msg: String, force: Boolean) { info0(pos, msg, INFO, force) } - def warning(pos: Position, msg: String ) { withoutTruncating(info0(pos, msg, WARNING, false)) } - def error(pos: Position, msg: String ) { withoutTruncating(info0(pos, msg, ERROR, false)) } - def incompleteInputError(pos: Position, msg: String ) { + /** For sending a message which should not be labeled as a warning/error, + * but also shouldn't require -verbose to be visible. + */ + def echo(msg: String): Unit = info(NoPosition, msg, true) + def echo(pos: Position, msg: String): Unit = info(pos, msg, true) + + /** Informational messages, suppressed unless -verbose or force=true. */ + def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force) + + /** Warnings and errors. */ + def warning(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, WARNING, false)) + def error(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, ERROR, false)) + def incompleteInputError(pos: Position, msg: String): Unit = { if (incompleteHandled) incompleteHandler(pos, msg) else error(pos, msg) } diff --git a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala index 800af55861..f55d0684c8 100644 --- a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala +++ b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala @@ -13,8 +13,6 @@ import scala.tools.util.AbstractTimer * timings. */ class ReporterTimer(reporter: Reporter) extends AbstractTimer { - def issue(msg: String, duration: Long) = reporter.info(null, "[" + msg + " in " + duration + "ms]", false) - } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 7fcfb6fc6d..a712f4cba2 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -67,6 +67,7 @@ trait ScalaSettings extends AbsScalaSettings val future = BooleanSetting ("-Xfuture", "Turn on future language features.") val genPhaseGraph = StringSetting ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "") val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.") + val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.") val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None) val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.") val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9991836344..a7ad140fc1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -969,7 +969,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { return typed(Select(tree, meth), mode, pt) } if (coercion != EmptyTree) { - debuglog("inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe) + def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe + if (settings.logImplicitConv.value) + unit.echo(tree.pos, msg) + + debuglog(msg) return newTyper(context.makeImplicit(context.reportAmbiguousErrors)).typed( new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt) } @@ -1056,7 +1060,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } inferView(qual, qual.tpe, searchTemplate, true) match { case EmptyTree => qual - case coercion => typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) + case coercion => + if (settings.logImplicitConv.value) + unit.echo(qual.pos, + "applied implicit conversion from %s to %s = %s".format( + qual.tpe, searchTemplate, coercion.symbol.defString)) + + typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) } } else qual diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check new file mode 100644 index 0000000000..d98422dacb --- /dev/null +++ b/test/files/neg/logImplicits.check @@ -0,0 +1,19 @@ +logImplicits.scala:2: applied implicit conversion from xs.type to ?{val size: ?} = implicit def byteArrayOps(xs: Array[Byte]): scala.collection.mutable.ArrayOps[Byte] + def f(xs: Array[Byte]) = xs.size + ^ +logImplicits.scala:7: applied implicit conversion from String("abc") to ?{val map: ?} = implicit def augmentString(x: String): scala.collection.immutable.StringOps + def f = "abc" map (_ + 1) + ^ +logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert:(p: String("abc"))Int + math.max(122, x: Int) + ^ +logImplicits.scala:19: applied implicit conversion from Int(1) to ?{val ->: ?} = implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] + def f = (1 -> 2) + "c" + ^ +logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{val +: ?} = implicit def any2stringadd(x: Any): scala.runtime.StringAdd + def f = (1 -> 2) + "c" + ^ +logImplicits.scala:22: error: class Un needs to be abstract, since method unimplemented is not defined +class Un { + ^ +one error found diff --git a/test/files/neg/logImplicits.flags b/test/files/neg/logImplicits.flags new file mode 100644 index 0000000000..97e5ae94ef --- /dev/null +++ b/test/files/neg/logImplicits.flags @@ -0,0 +1 @@ +-Xlog-implicit-conversions
\ No newline at end of file diff --git a/test/files/neg/logImplicits.scala b/test/files/neg/logImplicits.scala new file mode 100644 index 0000000000..fb5dd8a025 --- /dev/null +++ b/test/files/neg/logImplicits.scala @@ -0,0 +1,25 @@ +class A { + def f(xs: Array[Byte]) = xs.size + def g(xs: Array[Byte]) = xs.length +} + +class B { + def f = "abc" map (_ + 1) +} + +object C { + final val x = "abc" + + implicit def convert(p: x.type): Int = 123 + + math.max(122, x: Int) +} + +class D { + def f = (1 -> 2) + "c" +} + +class Un { + // forcing post-typer failure, since we're only interested in the output from the above + def unimplemented: Int +}
\ No newline at end of file |