Skip to content

Commit 9751d19

Browse files
committed
Merge pull request scala#3225 from som-snytt/issue/8013-interp-nowarn
SI-8013 Nowarn on macro str interpolation
2 parents d938f59 + 1b45418 commit 9751d19

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5113,12 +5113,24 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
51135113

51145114
// Warn about likely interpolated strings which are missing their interpolators
51155115
def warnMissingInterpolator(lit: Literal): Unit = if (!isPastTyper) {
5116+
// attempt to avoid warning about trees munged by macros
5117+
def isMacroExpansion = {
5118+
// context.tree is not the expandee; it is plain new SC(ps).m(args)
5119+
//context.tree exists (t => (t.pos includes lit.pos) && hasMacroExpansionAttachment(t))
5120+
// testing pos works and may suffice
5121+
//openMacros exists (_.macroApplication.pos includes lit.pos)
5122+
// tests whether the lit belongs to the expandee of an open macro
5123+
openMacros exists (_.macroApplication.attachments.get[MacroExpansionAttachment] match {
5124+
case Some(MacroExpansionAttachment(_, t: Tree)) => t exists (_ == lit)
5125+
case _ => false
5126+
})
5127+
}
51165128
// attempt to avoid warning about the special interpolated message string
51175129
// for implicitNotFound or any standard interpolation (with embedded $$).
51185130
def isRecognizablyNotForInterpolation = context.enclosingApply.tree match {
51195131
case Apply(Select(Apply(RefTree(_, nme.StringContext), _), _), _) => true
51205132
case Apply(Select(New(RefTree(_, tpnme.implicitNotFound)), _), _) => true
5121-
case _ => false
5133+
case _ => isMacroExpansion
51225134
}
51235135
def requiresNoArgs(tp: Type): Boolean = tp match {
51245136
case PolyType(_, restpe) => requiresNoArgs(restpe)
@@ -5149,12 +5161,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
51495161
}
51505162

51515163
def typedLiteral(tree: Literal) = {
5152-
if (settings.lint)
5153-
warnMissingInterpolator(tree)
5164+
if (settings.lint) warnMissingInterpolator(tree)
51545165

5155-
tree setType (
5156-
if (tree.value.tag == UnitTag) UnitTpe
5157-
else ConstantType(tree.value))
5166+
tree setType (if (tree.value.tag == UnitTag) UnitTpe else ConstantType(tree.value))
51585167
}
51595168

51605169
def typedSingletonTypeTree(tree: SingletonTypeTree) = {

test/files/pos/t8013.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings -Xlint
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* scalac: -Xfatal-warnings -Xlint
3+
*/
4+
package t8013
5+
6+
// unsuspecting user of perverse macro
7+
trait User {
8+
import Perverse.Impervolator
9+
val foo = "bar"
10+
Console println p"Hello, $foo"
11+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
package t8013
3+
4+
// perverse macro to confuse Xlint
5+
6+
import scala.language.experimental.macros
7+
import scala.reflect.macros.{ BlackboxContext => Context }
8+
9+
object Perverse {
10+
11+
implicit class Impervolator(sc: StringContext) {
12+
def p(args: Any*): String = macro pImpl
13+
}
14+
15+
// turn a nice interpolation into something that looks
16+
// nothing like an interpolation or anything we might
17+
// recognize, but which includes a "$id" in an apply.
18+
def pImpl(c: Context)(args: c.Expr[Any]*): c.Expr[String] = {
19+
import c.universe._
20+
val macroPos = c.macroApplication.pos
21+
val text = macroPos.lineContent substring macroPos.column
22+
val tt = Literal(Constant(text))
23+
val tree = q"t8013.Perverse.pervert($tt)"
24+
c.Expr[String](tree)
25+
}
26+
27+
// identity doesn't seem very perverse in this context
28+
//def pervert(text: String): String = text
29+
def pervert(text: String): String = {
30+
Console println s"Perverting [$text]"
31+
text
32+
}
33+
}

0 commit comments

Comments
 (0)