@@ -10,7 +10,7 @@ import dotty.tools.dotc.core.Decorators.{em, i}
1010import dotty .tools .dotc .core .Flags .*
1111import dotty .tools .dotc .core .Phases .Phase
1212import dotty .tools .dotc .core .StdNames
13- import dotty .tools .dotc .report
13+ import dotty .tools .dotc .{ ast , report }
1414import dotty .tools .dotc .reporting .Message
1515import dotty .tools .dotc .typer .ImportInfo
1616import 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
0 commit comments