summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 fb252c3058..8f43129af6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -5113,12 +5113,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)
@@ -5149,12 +5161,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
+ }
+}