@@ -10,7 +10,7 @@ import dotty.tools.dotc.core.Decorators.{em, i}
10
10
import dotty .tools .dotc .core .Flags .*
11
11
import dotty .tools .dotc .core .Phases .Phase
12
12
import dotty .tools .dotc .core .StdNames
13
- import dotty .tools .dotc .report
13
+ import dotty .tools .dotc .{ ast , report }
14
14
import dotty .tools .dotc .reporting .Message
15
15
import dotty .tools .dotc .typer .ImportInfo
16
16
import dotty .tools .dotc .util .{Property , SrcPos }
@@ -430,6 +430,20 @@ object CheckUnused:
430
430
else
431
431
exists
432
432
}
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
+
433
447
// if there's an outer scope
434
448
if usedInScope.nonEmpty then
435
449
// we keep the symbols not referencing an import in this scope
@@ -448,6 +462,7 @@ object CheckUnused:
448
462
*/
449
463
def getUnused (using Context ): UnusedResult =
450
464
popScope()
465
+
451
466
val sortedImp =
452
467
if ctx.settings.WunusedHas .imports || ctx.settings.WunusedHas .strictNoImplicitWarn then
453
468
unusedImport.map(d => d.srcPos -> WarnTypes .Imports ).toList
@@ -458,34 +473,39 @@ object CheckUnused:
458
473
localDefInScope
459
474
.filterNot(d => d.symbol.usedDefContains)
460
475
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
476
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
461
477
.map(d => d.namePos -> WarnTypes .LocalDefs ).toList
462
478
else
463
479
Nil
464
480
val sortedExplicitParams =
465
481
if ctx.settings.WunusedHas .explicits then
466
482
explicitParamInScope
467
483
.filterNot(d => d.symbol.usedDefContains)
484
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
468
485
.map(d => d.namePos -> WarnTypes .ExplicitParams ).toList
469
486
else
470
487
Nil
471
488
val sortedImplicitParams =
472
489
if ctx.settings.WunusedHas .implicits then
473
490
implicitParamInScope
474
491
.filterNot(d => d.symbol.usedDefContains)
492
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
475
493
.map(d => d.namePos -> WarnTypes .ImplicitParams ).toList
476
494
else
477
495
Nil
478
496
val sortedPrivateDefs =
479
497
if ctx.settings.WunusedHas .privates then
480
498
privateDefInScope
481
499
.filterNot(d => d.symbol.usedDefContains)
500
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
482
501
.map(d => d.namePos -> WarnTypes .PrivateMembers ).toList
483
502
else
484
503
Nil
485
504
val sortedPatVars =
486
505
if ctx.settings.WunusedHas .patvars then
487
506
patVarsInScope
488
507
.filterNot(d => d.symbol.usedDefContains)
508
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
489
509
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
490
510
.map(d => d.namePos -> WarnTypes .PatVars ).toList
491
511
else
@@ -498,6 +518,11 @@ object CheckUnused:
498
518
end getUnused
499
519
// ============================ HELPERS ====================================
500
520
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(" $" )
501
526
/**
502
527
* Is the the constructor of synthetic package object
503
528
* Should be ignored as it is always imported/used in package
0 commit comments