summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-02 06:41:31 -0800
committerPaul Phillips <paulp@improving.org>2012-01-02 14:37:36 -0800
commit451e1dc2da16c1bb5a7a59488865df9294eeaf3e (patch)
treedcbae11619389a16115d005ab2fc9bfdf5c4ba8d /src/compiler
parentbeb875187914b12b1b9dbb5621447067e2926c7c (diff)
downloadscala-451e1dc2da16c1bb5a7a59488865df9294eeaf3e.tar.gz
scala-451e1dc2da16c1bb5a7a59488865df9294eeaf3e.tar.bz2
scala-451e1dc2da16c1bb5a7a59488865df9294eeaf3e.zip
Added -Xlog-implicit-conversions.
New command line option prints a message whenever the compiler inserts an implicit conversion. Implicit parameters are not under consideration here, since the primary motivation is to make it easy to inspect your code for unintentional conversions, since they can have dramatic performance implications. class A { def f(xs: Array[Byte]) = xs.size def g(xs: Array[Byte]) = xs.length } % scalac -Xlog-implicit-conversions logImplicits.scala 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 ^
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala3
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala8
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ScalaDoc.scala8
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala4
-rw-r--r--src/compiler/scala/tools/nsc/reporters/Reporter.scala23
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala14
11 files changed, 46 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