Skip to content

Commit

Permalink
Fix wunused false positive on CanEqual
Browse files Browse the repository at this point in the history
  • Loading branch information
szymon-rd committed Oct 3, 2023
1 parent 09ea77e commit 64b55e7
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
24 changes: 18 additions & 6 deletions compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dotty.tools.dotc.transform

import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Symbols.*
import dotty.tools.dotc.ast.tpd.{Inlined, TreeTraverser}
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.ast.untpd.ImportSelector
Expand Down Expand Up @@ -423,12 +424,12 @@ object CheckUnused:
if !tpd.languageImport(imp.expr).nonEmpty && !imp.isGeneratedByEnum && !isTransparentAndInline(imp) then
impInScope.top += imp
unusedImport ++= imp.selectors.filter { s =>
!shouldSelectorBeReported(imp, s) && !isImportExclusion(s)
!shouldSelectorBeReported(imp, s) && !isImportExclusion(s) && !isImportIgnored(imp, s)
}

/** Register (or not) some `val` or `def` according to the context, scope and flags */
def registerDef(memDef: tpd.MemberDef)(using Context): Unit =
if memDef.isValidMemberDef then
if memDef.isValidMemberDef && !isDefIgnored(memDef) then
if memDef.isValidParam then
if memDef.symbol.isOneOf(GivenOrImplicit) then
if !paramsToSkip.contains(memDef.symbol) then
Expand All @@ -439,7 +440,7 @@ object CheckUnused:
localDefInScope += memDef
else if memDef.shouldReportPrivateDef then
privateDefInScope += memDef

/** Register pattern variable */
def registerPatVar(patvar: tpd.Bind)(using Context): Unit =
if !patvar.symbol.isUnusedAnnot then
Expand Down Expand Up @@ -507,7 +508,6 @@ object CheckUnused:

def getUnused(using Context): UnusedResult =
popScope()

val sortedImp =
if ctx.settings.WunusedHas.imports || ctx.settings.WunusedHas.strictNoImplicitWarn then
unusedImport.map(d => UnusedSymbol(d.srcPos, d.name, WarnTypes.Imports)).toList
Expand Down Expand Up @@ -643,9 +643,21 @@ object CheckUnused:
sel.isWildcard ||
imp.expr.tpe.member(sel.name.toTermName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit)) ||
imp.expr.tpe.member(sel.name.toTypeName).alternatives.exists(_.symbol.isOneOf(GivenOrImplicit))
)

)

/**
* Ignore CanEqual imports
*/
private def isImportIgnored(imp: tpd.Import, sel: ImportSelector)(using Context): Boolean =
(sel.isWildcard && imp.expr.tpe.allMembers.exists(p => p.symbol.typeRef.baseClasses.exists(_.derivesFrom(defn.CanEqualClass)))) ||
(imp.expr.tpe.member(sel.name.toTermName).alternatives
.exists(p => p.symbol.isOneOf(GivenOrImplicit) && p.symbol.typeRef.baseClasses.exists(_.derivesFrom(defn.CanEqualClass))))

/**
* Ignore definitions of CanEqual given
*/
private def isDefIgnored(memDef: tpd.MemberDef)(using Context): Boolean =
memDef.symbol.isOneOf(GivenOrImplicit) && memDef.symbol.typeRef.baseClasses.exists(_.derivesFrom(defn.CanEqualClass))

extension (tree: ImportSelector)
def boundTpe: Type = tree.bound match {
Expand Down
21 changes: 21 additions & 0 deletions tests/pos/i17762.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//> using options -Xfatal-warnings -Wunused:all

class SomeType

def testIt(st1: SomeType, st2: SomeType): Boolean =
given CanEqual[SomeType, SomeType] = CanEqual.derived
st1 == st2

object HasCanEqual:
given f: CanEqual[SomeType, SomeType] = CanEqual.derived

object UsesCanEqual:
import HasCanEqual.given
def testIt(st1: SomeType, st2: SomeType): Boolean =
st1 == st2

object UsesCanEqual2:
import HasCanEqual.f

def testIt(st1: SomeType, st2: SomeType): Boolean =
st1 == st2

0 comments on commit 64b55e7

Please sign in to comment.