Skip to content

Commit 4219db2

Browse files
committed
WUnused: Fix for symbols with synthetic names and unused transparent inlines
1 parent d640193 commit 4219db2

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

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

Lines changed: 26 additions & 1 deletion
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}
@@ -432,6 +432,20 @@ object CheckUnused:
432432
else
433433
exists
434434
}
435+
436+
// not report unused transparent inline imports
437+
for {
438+
imp <- imports
439+
sel <- imp.selectors
440+
} {
441+
if unusedImport.contains(sel) then
442+
val tpd.Import(qual, _) = imp
443+
val importedMembers = qual.tpe.member(sel.name).alternatives.map(_.symbol)
444+
val isTransparentAndInline = importedMembers.exists(s => s.is(Transparent) && s.is(Inline))
445+
if isTransparentAndInline then
446+
unusedImport -= sel
447+
}
448+
435449
// if there's an outer scope
436450
if usedInScope.nonEmpty then
437451
// we keep the symbols not referencing an import in this scope
@@ -450,6 +464,7 @@ object CheckUnused:
450464
*/
451465
def getUnused(using Context): UnusedResult =
452466
popScope()
467+
453468
val sortedImp =
454469
if ctx.settings.WunusedHas.imports || ctx.settings.WunusedHas.strictNoImplicitWarn then
455470
unusedImport.map(d => d.srcPos -> WarnTypes.Imports).toList
@@ -460,34 +475,39 @@ object CheckUnused:
460475
localDefInScope
461476
.filterNot(d => d.symbol.usedDefContains)
462477
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
478+
.filterNot(d => containsSyntheticSuffix(d.symbol))
463479
.map(d => d.namePos -> WarnTypes.LocalDefs).toList
464480
else
465481
Nil
466482
val sortedExplicitParams =
467483
if ctx.settings.WunusedHas.explicits then
468484
explicitParamInScope
469485
.filterNot(d => d.symbol.usedDefContains)
486+
.filterNot(d => containsSyntheticSuffix(d.symbol))
470487
.map(d => d.namePos -> WarnTypes.ExplicitParams).toList
471488
else
472489
Nil
473490
val sortedImplicitParams =
474491
if ctx.settings.WunusedHas.implicits then
475492
implicitParamInScope
476493
.filterNot(d => d.symbol.usedDefContains)
494+
.filterNot(d => containsSyntheticSuffix(d.symbol))
477495
.map(d => d.namePos -> WarnTypes.ImplicitParams).toList
478496
else
479497
Nil
480498
val sortedPrivateDefs =
481499
if ctx.settings.WunusedHas.privates then
482500
privateDefInScope
483501
.filterNot(d => d.symbol.usedDefContains)
502+
.filterNot(d => containsSyntheticSuffix(d.symbol))
484503
.map(d => d.namePos -> WarnTypes.PrivateMembers).toList
485504
else
486505
Nil
487506
val sortedPatVars =
488507
if ctx.settings.WunusedHas.patvars then
489508
patVarsInScope
490509
.filterNot(d => d.symbol.usedDefContains)
510+
.filterNot(d => containsSyntheticSuffix(d.symbol))
491511
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
492512
.map(d => d.namePos -> WarnTypes.PatVars).toList
493513
else
@@ -500,6 +520,11 @@ object CheckUnused:
500520
end getUnused
501521
//============================ HELPERS ====================================
502522

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

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,34 @@ package foo.test.i16925:
209209
_ = println(i) // OK
210210
} yield ()
211211

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)
239+
212240
package foo.test.i16679a:
213241
object myPackage:
214242
trait CaseClassName[A]:

0 commit comments

Comments
 (0)