Skip to content

Commit 05dd773

Browse files
committed
WUnused: Fix for symbols with synthetic names and unused transparent inlines
1 parent 424da9f commit 05dd773

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import dotty.tools.dotc.core.Decorators.{em, i}
1010
import dotty.tools.dotc.core.Flags.*
1111
import dotty.tools.dotc.core.Phases.Phase
1212
import dotty.tools.dotc.core.StdNames
13-
import dotty.tools.dotc.report
13+
import dotty.tools.dotc.{ast, report}
1414
import dotty.tools.dotc.reporting.Message
1515
import dotty.tools.dotc.typer.ImportInfo
1616
import dotty.tools.dotc.util.{Property, SrcPos}
@@ -430,6 +430,20 @@ object CheckUnused:
430430
else
431431
exists
432432
}
433+
434+
// not report unused transparent inline imports
435+
for {
436+
imp <- imports
437+
sel <- imp.selectors
438+
} {
439+
if unusedImport.contains(sel) then
440+
val tpd.Import(qual, _) = imp
441+
val importedMembers = qual.tpe.member(sel.name).alternatives.map(_.symbol)
442+
val isTransparentAndInline = importedMembers.exists(s => s.is(Transparent) && s.is(Inline))
443+
if isTransparentAndInline then
444+
unusedImport -= sel
445+
}
446+
433447
// if there's an outer scope
434448
if usedInScope.nonEmpty then
435449
// we keep the symbols not referencing an import in this scope
@@ -448,6 +462,7 @@ object CheckUnused:
448462
*/
449463
def getUnused(using Context): UnusedResult =
450464
popScope()
465+
451466
val sortedImp =
452467
if ctx.settings.WunusedHas.imports || ctx.settings.WunusedHas.strictNoImplicitWarn then
453468
unusedImport.map(d => d.srcPos -> WarnTypes.Imports).toList
@@ -458,34 +473,39 @@ object CheckUnused:
458473
localDefInScope
459474
.filterNot(d => d.symbol.usedDefContains)
460475
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
476+
.filterNot(d => containsSyntheticSuffix(d.symbol))
461477
.map(d => d.namePos -> WarnTypes.LocalDefs).toList
462478
else
463479
Nil
464480
val sortedExplicitParams =
465481
if ctx.settings.WunusedHas.explicits then
466482
explicitParamInScope
467483
.filterNot(d => d.symbol.usedDefContains)
484+
.filterNot(d => containsSyntheticSuffix(d.symbol))
468485
.map(d => d.namePos -> WarnTypes.ExplicitParams).toList
469486
else
470487
Nil
471488
val sortedImplicitParams =
472489
if ctx.settings.WunusedHas.implicits then
473490
implicitParamInScope
474491
.filterNot(d => d.symbol.usedDefContains)
492+
.filterNot(d => containsSyntheticSuffix(d.symbol))
475493
.map(d => d.namePos -> WarnTypes.ImplicitParams).toList
476494
else
477495
Nil
478496
val sortedPrivateDefs =
479497
if ctx.settings.WunusedHas.privates then
480498
privateDefInScope
481499
.filterNot(d => d.symbol.usedDefContains)
500+
.filterNot(d => containsSyntheticSuffix(d.symbol))
482501
.map(d => d.namePos -> WarnTypes.PrivateMembers).toList
483502
else
484503
Nil
485504
val sortedPatVars =
486505
if ctx.settings.WunusedHas.patvars then
487506
patVarsInScope
488507
.filterNot(d => d.symbol.usedDefContains)
508+
.filterNot(d => containsSyntheticSuffix(d.symbol))
489509
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
490510
.map(d => d.namePos -> WarnTypes.PatVars).toList
491511
else
@@ -498,6 +518,11 @@ object CheckUnused:
498518
end getUnused
499519
//============================ HELPERS ====================================
500520

521+
/**
522+
* Heuristic to detect synthetic suffixes in names of symbols
523+
*/
524+
private def containsSyntheticSuffix(symbol: Symbol)(using Context): Boolean =
525+
symbol.name.mangledString.contains("$")
501526
/**
502527
* Is the the constructor of synthetic package object
503528
* Should be ignored as it is always imported/used in package

tests/neg-custom-args/fatal-warnings/i15503i.scala

+29-1
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,32 @@ package foo.test.i16925:
207207
for {
208208
i <- 1 to 2 if true
209209
_ = println(i) // OK
210-
} yield ()
210+
} yield ()
211+
212+
package foo.test.i16863a:
213+
import scala.quoted.*
214+
def fn(using Quotes) =
215+
val x = Expr(1)
216+
'{ $x + 2 } // OK
217+
218+
package foo.test.i16863b:
219+
import scala.quoted.*
220+
def fn[A](using Quotes, Type[A]) = // OK
221+
val numeric = Expr.summon[Numeric[A]].getOrElse(???)
222+
'{ $numeric.fromInt(3) } // OK
223+
224+
package foo.test.i16863c:
225+
import scala.quoted.*
226+
def fn[A](expr: Expr[Any])(using Quotes) =
227+
val imp = expr match
228+
case '{ ${ _ }: a } => Expr.summon[Numeric[a]] // OK
229+
println(imp)
230+
231+
package foo.test.i16863d:
232+
import scala.quoted.*
233+
import scala.compiletime.asMatchable // OK
234+
def fn[A](using Quotes, Type[A]) =
235+
import quotes.reflect.*
236+
val imp = TypeRepr.of[A].widen.asMatchable match
237+
case Refinement(_,_,_) => ()
238+
println(imp)

0 commit comments

Comments
 (0)