@@ -202,8 +202,11 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
202202 override def traverse (tree : tpd.Tree )(using Context ): Unit =
203203 val newCtx = if tree.symbol.exists then ctx.withOwner(tree.symbol) else ctx
204204 tree match
205- case imp: tpd.Import =>
205+ case imp : tpd.Import =>
206206 unusedDataApply(_.registerImport(imp))
207+ imp.selectors.filter(_.isGiven).map(_.bound).collect {
208+ case untpd.TypedSplice (tree1) => tree1
209+ }.foreach(traverse(_)(using newCtx))
207210 traverseChildren(tree)(using newCtx)
208211 case ident : Ident =>
209212 prepareForIdent(ident)
@@ -449,13 +452,12 @@ object CheckUnused:
449452 val used = usedInScope.pop().toSet
450453 // used imports in this scope
451454 val imports = impInScope.pop()
452- val kept = used.filterNot { t =>
453- val (sym, isAccessible, optName, isDerived) = t
455+ val kept = used.filterNot { (sym, isAccessible, optName, isDerived) =>
454456 // keep the symbol for outer scope, if it matches **no** import
455457 // This is the first matching wildcard selector
456458 var selWildCard : Option [ImportSelector ] = None
457459
458- val exists = imports.exists { imp =>
460+ val matchedExplicitImport = imports.exists { imp =>
459461 sym.isInImport(imp, isAccessible, optName, isDerived) match
460462 case None => false
461463 case optSel@ Some (sel) if sel.isWildcard =>
@@ -466,11 +468,11 @@ object CheckUnused:
466468 unusedImport -= sel
467469 true
468470 }
469- if ! exists && selWildCard.isDefined then
471+ if ! matchedExplicitImport && selWildCard.isDefined then
470472 unusedImport -= selWildCard.get
471473 true // a matching import exists so the symbol won't be kept for outer scope
472474 else
473- exists
475+ matchedExplicitImport
474476 }
475477
476478 // if there's an outer scope
@@ -610,12 +612,17 @@ object CheckUnused:
610612 * return true
611613 */
612614 private def shouldSelectorBeReported (imp : tpd.Import , sel : ImportSelector )(using Context ): Boolean =
613- if ctx.settings.WunusedHas .strictNoImplicitWarn then
615+ ctx.settings.WunusedHas .strictNoImplicitWarn && (
614616 sel.isWildcard ||
615617 imp.expr.tpe.member(sel.name.toTermName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit )) ||
616618 imp.expr.tpe.member(sel.name.toTypeName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit ))
617- else
618- false
619+ )
620+
621+ extension (tree : ImportSelector )
622+ def boundTpe : Type = tree.bound match {
623+ case untpd.TypedSplice (tree1) => tree1.tpe
624+ case _ => NoType
625+ }
619626
620627 extension (sym : Symbol )
621628 /** is accessible without import in current context */
@@ -628,7 +635,7 @@ object CheckUnused:
628635 && c.owner.thisType.member(sym.name).alternatives.contains(sym)
629636 }
630637
631- /** Given an import and accessibility, return an option of selector that match import<->symbol */
638+ /** Given an import and accessibility, return selector that matches import<->symbol */
632639 private def isInImport (imp : tpd.Import , isAccessible : Boolean , symName : Option [Name ], isDerived : Boolean )(using Context ): Option [ImportSelector ] =
633640 val tpd .Import (qual, sels) = imp
634641 val dealiasedSym = dealias(sym)
@@ -641,9 +648,12 @@ object CheckUnused:
641648 def dealiasedSelector = if (isDerived) sels.flatMap(sel => selectionsToDealias.map(m => (sel, m.symbol))).collect {
642649 case (sel, sym) if dealias(sym) == dealiasedSym => sel
643650 }.headOption else None
644- def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given ) == sel.isGiven) || sym.is(Implicit )))
651+ def givenSelector = if sym.is(Given ) || sym.is(Implicit )
652+ then sels.filter(sel => sel.isGiven && ! sel.bound.isEmpty).find(sel => sel.boundTpe =:= sym.info)
653+ else None
654+ def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given ) == sel.isGiven && sel.bound.isEmpty) || sym.is(Implicit )))
645655 if qualHasSymbol && (! isAccessible || sym.isRenamedSymbol(symName)) && sym.exists then
646- selector.orElse(dealiasedSelector).orElse(wildcard) // selector with name or wildcard (or given)
656+ selector.orElse(dealiasedSelector).orElse(givenSelector).orElse( wildcard) // selector with name or wildcard (or given)
647657 else
648658 None
649659
0 commit comments