Skip to content

Commit e424d7d

Browse files
committed
Detect summon inline
1 parent 1cd4636 commit e424d7d

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,5 @@ class Diagnostic(
112112
override def diagnosticRelatedInformation: JList[interfaces.DiagnosticRelatedInformation] =
113113
Collections.emptyList()
114114

115-
override def toString: String = s"$getClass at $pos L${pos.line}: $message"
115+
override def toString: String = s"$getClass at $pos L${pos.line+1}: $message"
116116
end Diagnostic

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
5151

5252
override def transformIdent(tree: Ident)(using Context): tree.type =
5353
if tree.symbol.exists then
54-
if !ignoreTree(tree) then
54+
// resolve if inlined at the position of the call, or is zero extent summon
55+
val resolving =
56+
refInfos.inlined.isEmpty
57+
|| tree.srcPos.isZeroExtentSynthetic
58+
|| refInfos.inlined.exists(_.sourcePos.contains(tree.srcPos.sourcePos))
59+
if resolving && !ignoreTree(tree) then
5560
resolveUsage(tree.symbol, tree.name, tree.typeOpt.importPrefix.skipPackageObject)
5661
else if tree.hasType then
5762
resolveUsage(tree.tpe.classSymbol, tree.name, tree.tpe.importPrefix.skipPackageObject)
@@ -108,8 +113,12 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
108113
case _ =>
109114
tree
110115

116+
override def prepareForInlined(tree: Inlined)(using Context): Context =
117+
refInfos.inlined.push(tree.call.srcPos)
118+
ctx
111119
override def transformInlined(tree: Inlined)(using Context): tree.type =
112-
if !tree.call.isEmpty then
120+
val _ = refInfos.inlined.pop()
121+
if !tree.call.isEmpty && phaseMode.eq(PhaseMode.Aggregate) then
113122
transformAllDeep(tree.call)
114123
tree
115124

@@ -432,6 +441,7 @@ object CheckUnused:
432441
defs.addOne((tree.symbol, tree.srcPos))
433442

434443
var isRepl = false // have we seen a REPL artifact? avoid import warning, for example
444+
val inlined = Stack.empty[SrcPos] // enclosing call.srcPos of inlined code
435445
end RefInfos
436446

437447
// Symbols already resolved in the given Context (with name and prefix of lookup)
@@ -809,6 +819,9 @@ object CheckUnused:
809819
|| imp.expr.tpe.member(sel.name.toTermName).hasAltWith(_.symbol.isCanEqual)
810820
)
811821

822+
extension (pos: SrcPos)
823+
def isZeroExtentSynthetic: Boolean = pos.span.isSynthetic && pos.span.start == pos.span.end
824+
812825
// incredibly, there is no "sort in place" for array
813826
extension [A <: AnyRef](arr: Array[A])
814827
def sorta[B](f: A => B)(using ord: Ordering[B]): arr.type =

tests/warn/i15503kb/power.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
object Power:
3+
import scala.concurrent.* // warn [taps mic]
4+
import scala.math.pow as power
5+
import scala.quoted.*
6+
inline def powerMacro(x: Double, inline n: Int): Double = ${ powerCode('x, 'n) }
7+
def powerCode(x: Expr[Double], n: Expr[Int])(using Quotes): Expr[Double] =
8+
n match
9+
case Expr(m) => unrolledPowerCode(x, m)
10+
case _ => '{ power($x, $n.toDouble) }
11+
def unrolledPowerCode(x: Expr[Double], n: Int)(using Quotes): Expr[Double] =
12+
n match
13+
case 0 => '{ 1.0 }
14+
case 1 => x
15+
case _ => '{ $x * ${ unrolledPowerCode(x, n - 1) } }

tests/warn/i15503kb/square.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//> using options -Wunused:all
2+
3+
object PowerUser:
4+
import scala.concurrent.* // warn [taps mic]
5+
import Power.*
6+
def square(x: Double): Double = powerMacro(x, 2)

0 commit comments

Comments
 (0)