summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2013-12-03 13:31:13 -0800
committerSom Snytt <som.snytt@gmail.com>2013-12-04 12:25:16 -0800
commit1b454185c44a0817a1f30c3d93a91b16805ce84b (patch)
tree29dde89e788abfa1ebdb6d7949c7553045422daf
parent6c63ab153651f7946ece5740d52e0f2b701e349d (diff)
downloadscala-1b454185c44a0817a1f30c3d93a91b16805ce84b.tar.gz
scala-1b454185c44a0817a1f30c3d93a91b16805ce84b.tar.bz2
scala-1b454185c44a0817a1f30c3d93a91b16805ce84b.zip
SI-8013 Nowarn on macro str interpolation
When warning about stray "foo $bar" under `-Xlint`, which may be missing an interpolator id, suppress the warning if we're in the middle of a macro expansion, since we have no useful heuristic to apply to the expanded tree. The test for whether the string is part of an expanded tree is to check all open macros for an expanded tree that contains the literal tree under scrutiny. (This is deemed more paranoid than looking for a macro application that is an enclosing position.)
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala21
-rw-r--r--test/files/pos/t8013.flags1
-rw-r--r--test/files/pos/t8013/inpervolated_2.scala11
-rw-r--r--test/files/pos/t8013/inpervolator_1.scala33
4 files changed, 60 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6d799b0098..a77c2ff830 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -5107,12 +5107,24 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// Warn about likely interpolated strings which are missing their interpolators
def warnMissingInterpolator(lit: Literal): Unit = if (!isPastTyper) {
+ // attempt to avoid warning about trees munged by macros
+ def isMacroExpansion = {
+ // context.tree is not the expandee; it is plain new SC(ps).m(args)
+ //context.tree exists (t => (t.pos includes lit.pos) && hasMacroExpansionAttachment(t))
+ // testing pos works and may suffice
+ //openMacros exists (_.macroApplication.pos includes lit.pos)
+ // tests whether the lit belongs to the expandee of an open macro
+ openMacros exists (_.macroApplication.attachments.get[MacroExpansionAttachment] match {
+ case Some(MacroExpansionAttachment(_, t: Tree)) => t exists (_ == lit)
+ case _ => false
+ })
+ }
// attempt to avoid warning about the special interpolated message string
// for implicitNotFound or any standard interpolation (with embedded $$).
def isRecognizablyNotForInterpolation = context.enclosingApply.tree match {
case Apply(Select(Apply(RefTree(_, nme.StringContext), _), _), _) => true
case Apply(Select(New(RefTree(_, tpnme.implicitNotFound)), _), _) => true
- case _ => false
+ case _ => isMacroExpansion
}
def requiresNoArgs(tp: Type): Boolean = tp match {
case PolyType(_, restpe) => requiresNoArgs(restpe)
@@ -5143,12 +5155,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
def typedLiteral(tree: Literal) = {
- if (settings.lint)
- warnMissingInterpolator(tree)
+ if (settings.lint) warnMissingInterpolator(tree)
- tree setType (
- if (tree.value.tag == UnitTag) UnitTpe
- else ConstantType(tree.value))
+ tree setType (if (tree.value.tag == UnitTag) UnitTpe else ConstantType(tree.value))
}
def typedSingletonTypeTree(tree: SingletonTypeTree) = {
diff --git a/test/files/pos/t8013.flags b/test/files/pos/t8013.flags
new file mode 100644
index 0000000000..954eaba352
--- /dev/null
+++ b/test/files/pos/t8013.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -Xlint
diff --git a/test/files/pos/t8013/inpervolated_2.scala b/test/files/pos/t8013/inpervolated_2.scala
new file mode 100644
index 0000000000..90e571b42c
--- /dev/null
+++ b/test/files/pos/t8013/inpervolated_2.scala
@@ -0,0 +1,11 @@
+/*
+ * scalac: -Xfatal-warnings -Xlint
+ */
+package t8013
+
+// unsuspecting user of perverse macro
+trait User {
+ import Perverse.Impervolator
+ val foo = "bar"
+ Console println p"Hello, $foo"
+}
diff --git a/test/files/pos/t8013/inpervolator_1.scala b/test/files/pos/t8013/inpervolator_1.scala
new file mode 100644
index 0000000000..fb71571afc
--- /dev/null
+++ b/test/files/pos/t8013/inpervolator_1.scala
@@ -0,0 +1,33 @@
+
+package t8013
+
+// perverse macro to confuse Xlint
+
+import scala.language.experimental.macros
+import scala.reflect.macros.{ BlackboxContext => Context }
+
+object Perverse {
+
+ implicit class Impervolator(sc: StringContext) {
+ def p(args: Any*): String = macro pImpl
+ }
+
+ // turn a nice interpolation into something that looks
+ // nothing like an interpolation or anything we might
+ // recognize, but which includes a "$id" in an apply.
+ def pImpl(c: Context)(args: c.Expr[Any]*): c.Expr[String] = {
+ import c.universe._
+ val macroPos = c.macroApplication.pos
+ val text = macroPos.lineContent substring macroPos.column
+ val tt = Literal(Constant(text))
+ val tree = q"t8013.Perverse.pervert($tt)"
+ c.Expr[String](tree)
+ }
+
+ // identity doesn't seem very perverse in this context
+ //def pervert(text: String): String = text
+ def pervert(text: String): String = {
+ Console println s"Perverting [$text]"
+ text
+ }
+}