Skip to content

Commit 3de187b

Browse files
authored
Merge pull request #457 from scala/backport-lts-3.3-23325
Backport "Take inferred or explicit refinement result for unused check" to 3.3 LTS
2 parents c78351f + d77facb commit 3de187b

File tree

3 files changed

+35
-21
lines changed

3 files changed

+35
-21
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
159159
override def prepareForValDef(tree: ValDef)(using Context): Context =
160160
if !tree.symbol.is(Deferred) && tree.rhs.symbol != defn.Predef_undefined then
161161
refInfos.register(tree)
162-
tree.tpt match
163-
case RefinedTypeTree(_, refinements) => relax(tree.rhs, refinements)
164-
case _ =>
162+
relax(tree.rhs, tree.tpt.tpe)
165163
ctx
166164
override def transformValDef(tree: ValDef)(using Context): tree.type =
167165
traverseAnnotations(tree.symbol)
@@ -183,9 +181,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
183181
refInfos.inliners += 1
184182
else if !tree.symbol.is(Deferred) && tree.rhs.symbol != defn.Predef_undefined then
185183
refInfos.register(tree)
186-
tree.tpt match
187-
case RefinedTypeTree(_, refinements) => relax(tree.rhs, refinements)
188-
case _ =>
184+
relax(tree.rhs, tree.tpt.tpe)
189185
ctx
190186
override def transformDefDef(tree: DefDef)(using Context): tree.type =
191187
traverseAnnotations(tree.symbol)
@@ -902,15 +898,21 @@ object CheckUnused:
902898
case tree => traverseChildren(tree)
903899

904900
// NoWarn members in tree that correspond to refinements; currently uses only names.
905-
def relax(tree: Tree, refinements: List[Tree])(using Context): Unit =
906-
val names = refinements.collect { case named: NamedDefTree => named.name }.toSet
907-
val relaxer = new TreeTraverser:
908-
def traverse(tree: Tree)(using Context) =
909-
tree match
910-
case tree: NamedDefTree if names(tree.name) => tree.withAttachment(NoWarn, ())
911-
case _ =>
912-
traverseChildren(tree)
913-
relaxer.traverse(tree)
901+
def relax(tree: Tree, tpe: Type)(using Context): Unit =
902+
def refinements(tpe: Type, names: List[Name]): List[Name] =
903+
tpe match
904+
case RefinedType(parent, refinedName, refinedInfo) => refinedName :: refinements(parent, names)
905+
case _ => names
906+
val refinedNames = refinements(tpe, Nil)
907+
if !refinedNames.isEmpty then
908+
val names = refinedNames.toSet
909+
val relaxer = new TreeTraverser:
910+
def traverse(tree: Tree)(using Context) =
911+
tree match
912+
case tree: NamedDefTree if names(tree.name) => tree.withAttachment(NoWarn, ())
913+
case _ =>
914+
traverseChildren(tree)
915+
relaxer.traverse(tree)
914916

915917
extension (nm: Name)
916918
inline def exists(p: Name => Boolean): Boolean = nm.ne(nme.NO_NAME) && p(nm)

tests/warn/i22681.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ trait T:
66

77
class C:
88
def f: Runnable { def u: Int } = new Runnable with T:
9-
private def v = 42 // avoid g judged too trivial to warn
109
def run() = ()
11-
def g = v // warn, effectively private member is unused
12-
def t = v // nowarn
13-
def u = v // nowarn because leaked by refinement
10+
def g = 42 // warn effectively private member is unused
11+
def t = 42 // nowarn
12+
def u = 42 // nowarn because leaked by refinement
1413
val v: Runnable { def u: Int } = new Runnable:
15-
private def v = 42 // avoid g judged too trivial to warn
1614
def run() = ()
17-
def u = v // nowarn because leaked by refinement
15+
def u = 42 // nowarn because leaked by refinement

tests/warn/i23323.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//> using options -Wunused:all
2+
3+
class C:
4+
val x = new reflect.Selectable:
5+
def f = 42
6+
def g = 27
7+
val y: Selectable = new reflect.Selectable:
8+
def f = 42 // warn
9+
def g = 27 // warn
10+
val z = new scala.Selectable:
11+
def f = 42
12+
def g = 27
13+
def selectDynamic(name: String): Any = ???
14+
def applyDynamic(name: String)(args: Any*): Any = ???

0 commit comments

Comments
 (0)