@@ -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 }
@@ -432,6 +432,20 @@ object CheckUnused:
432
432
else
433
433
exists
434
434
}
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
+
435
449
// if there's an outer scope
436
450
if usedInScope.nonEmpty then
437
451
// we keep the symbols not referencing an import in this scope
@@ -450,6 +464,7 @@ object CheckUnused:
450
464
*/
451
465
def getUnused (using Context ): UnusedResult =
452
466
popScope()
467
+
453
468
val sortedImp =
454
469
if ctx.settings.WunusedHas .imports || ctx.settings.WunusedHas .strictNoImplicitWarn then
455
470
unusedImport.map(d => d.srcPos -> WarnTypes .Imports ).toList
@@ -460,34 +475,39 @@ object CheckUnused:
460
475
localDefInScope
461
476
.filterNot(d => d.symbol.usedDefContains)
462
477
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
478
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
463
479
.map(d => d.namePos -> WarnTypes .LocalDefs ).toList
464
480
else
465
481
Nil
466
482
val sortedExplicitParams =
467
483
if ctx.settings.WunusedHas .explicits then
468
484
explicitParamInScope
469
485
.filterNot(d => d.symbol.usedDefContains)
486
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
470
487
.map(d => d.namePos -> WarnTypes .ExplicitParams ).toList
471
488
else
472
489
Nil
473
490
val sortedImplicitParams =
474
491
if ctx.settings.WunusedHas .implicits then
475
492
implicitParamInScope
476
493
.filterNot(d => d.symbol.usedDefContains)
494
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
477
495
.map(d => d.namePos -> WarnTypes .ImplicitParams ).toList
478
496
else
479
497
Nil
480
498
val sortedPrivateDefs =
481
499
if ctx.settings.WunusedHas .privates then
482
500
privateDefInScope
483
501
.filterNot(d => d.symbol.usedDefContains)
502
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
484
503
.map(d => d.namePos -> WarnTypes .PrivateMembers ).toList
485
504
else
486
505
Nil
487
506
val sortedPatVars =
488
507
if ctx.settings.WunusedHas .patvars then
489
508
patVarsInScope
490
509
.filterNot(d => d.symbol.usedDefContains)
510
+ .filterNot(d => containsSyntheticSuffix(d.symbol))
491
511
.filterNot(d => usedInPosition.exists { case (pos, name) => d.span.contains(pos.span) && name == d.symbol.name})
492
512
.map(d => d.namePos -> WarnTypes .PatVars ).toList
493
513
else
@@ -500,6 +520,11 @@ object CheckUnused:
500
520
end getUnused
501
521
// ============================ HELPERS ====================================
502
522
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(" $" )
503
528
/**
504
529
* Is the the constructor of synthetic package object
505
530
* Should be ignored as it is always imported/used in package
0 commit comments