@@ -203,8 +203,11 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
203203 override def traverse (tree : tpd.Tree )(using Context ): Unit =
204204 val newCtx = if tree.symbol.exists then ctx.withOwner(tree.symbol) else ctx
205205 tree match
206- case imp: tpd.Import =>
206+ case imp : tpd.Import =>
207207 unusedDataApply(_.registerImport(imp))
208+ imp.selectors.filter(_.isGiven).map(_.bound).collect {
209+ case untpd.TypedSplice (tree1) => tree1
210+ }.foreach(traverse(_)(using newCtx))
208211 traverseChildren(tree)(using newCtx)
209212 case ident : Ident =>
210213 prepareForIdent(ident)
@@ -450,13 +453,12 @@ object CheckUnused:
450453 val used = usedInScope.pop().toSet
451454 // used imports in this scope
452455 val imports = impInScope.pop()
453- val kept = used.filterNot { t =>
454- val (sym, isAccessible, optName, isDerived) = t
456+ val kept = used.filterNot { (sym, isAccessible, optName, isDerived) =>
455457 // keep the symbol for outer scope, if it matches **no** import
456458 // This is the first matching wildcard selector
457459 var selWildCard : Option [ImportSelector ] = None
458460
459- val exists = imports.exists { imp =>
461+ val matchedExplicitImport = imports.exists { imp =>
460462 sym.isInImport(imp, isAccessible, optName, isDerived) match
461463 case None => false
462464 case optSel@ Some (sel) if sel.isWildcard =>
@@ -467,11 +469,11 @@ object CheckUnused:
467469 unusedImport -= sel
468470 true
469471 }
470- if ! exists && selWildCard.isDefined then
472+ if ! matchedExplicitImport && selWildCard.isDefined then
471473 unusedImport -= selWildCard.get
472474 true // a matching import exists so the symbol won't be kept for outer scope
473475 else
474- exists
476+ matchedExplicitImport
475477 }
476478
477479 // if there's an outer scope
@@ -611,12 +613,17 @@ object CheckUnused:
611613 * return true
612614 */
613615 private def shouldSelectorBeReported (imp : tpd.Import , sel : ImportSelector )(using Context ): Boolean =
614- if ctx.settings.WunusedHas .strictNoImplicitWarn then
616+ ctx.settings.WunusedHas .strictNoImplicitWarn && (
615617 sel.isWildcard ||
616618 imp.expr.tpe.member(sel.name.toTermName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit )) ||
617619 imp.expr.tpe.member(sel.name.toTypeName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit ))
618- else
619- false
620+ )
621+
622+ extension (tree : ImportSelector )
623+ def boundTpe : Type = tree.bound match {
624+ case untpd.TypedSplice (tree1) => tree1.tpe
625+ case _ => NoType
626+ }
620627
621628 extension (sym : Symbol )
622629 /** is accessible without import in current context */
@@ -629,7 +636,7 @@ object CheckUnused:
629636 && c.owner.thisType.member(sym.name).alternatives.contains(sym)
630637 }
631638
632- /** Given an import and accessibility, return an option of selector that match import<->symbol */
639+ /** Given an import and accessibility, return selector that matches import<->symbol */
633640 private def isInImport (imp : tpd.Import , isAccessible : Boolean , symName : Option [Name ], isDerived : Boolean )(using Context ): Option [ImportSelector ] =
634641 val tpd .Import (qual, sels) = imp
635642 val dealiasedSym = dealias(sym)
@@ -642,9 +649,12 @@ object CheckUnused:
642649 def dealiasedSelector = if (isDerived) sels.flatMap(sel => selectionsToDealias.map(m => (sel, m.symbol))).collect {
643650 case (sel, sym) if dealias(sym) == dealiasedSym => sel
644651 }.headOption else None
645- def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given ) == sel.isGiven) || sym.is(Implicit )))
652+ def givenSelector = if sym.is(Given ) || sym.is(Implicit )
653+ then sels.filter(sel => sel.isGiven && ! sel.bound.isEmpty).find(sel => sel.boundTpe =:= sym.info)
654+ else None
655+ def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given ) == sel.isGiven && sel.bound.isEmpty) || sym.is(Implicit )))
646656 if qualHasSymbol && (! isAccessible || sym.isRenamedSymbol(symName)) && sym.exists then
647- selector.orElse(dealiasedSelector).orElse(wildcard) // selector with name or wildcard (or given)
657+ selector.orElse(dealiasedSelector).orElse(givenSelector).orElse( wildcard) // selector with name or wildcard (or given)
648658 else
649659 None
650660
0 commit comments