Skip to content

Commit 133dcb3

Browse files
committed
First cut at nowarn refinement members
1 parent c880a58 commit 133dcb3

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+20-2
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
150150
override def prepareForValDef(tree: ValDef)(using Context): Context =
151151
if !tree.symbol.is(Deferred) && tree.rhs.symbol != defn.Predef_undefined then
152152
refInfos.register(tree)
153+
tree.tpt match
154+
case RefinedTypeTree(_, refinements) => relax(tree.rhs, refinements)
155+
case _ =>
153156
ctx
154157
override def transformValDef(tree: ValDef)(using Context): tree.type =
155158
traverseAnnotations(tree.symbol)
@@ -170,11 +173,15 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
170173
override def prepareForDefDef(tree: DefDef)(using Context): Context =
171174
def trivial = tree.symbol.is(Deferred) || isUnconsuming(tree.rhs)
172175
def nontrivial = tree.symbol.isConstructor || tree.symbol.isAnonymousFunction
173-
if !nontrivial && trivial then refInfos.skip.addOne(tree.symbol)
176+
if !nontrivial && trivial then
177+
refInfos.skip.addOne(tree.symbol)
174178
if tree.symbol.is(Inline) then
175179
refInfos.inliners += 1
176180
else if !tree.symbol.is(Deferred) && tree.rhs.symbol != defn.Predef_undefined then
177181
refInfos.register(tree)
182+
tree.tpt match
183+
case RefinedTypeTree(_, refinements) => relax(tree.rhs, refinements)
184+
case _ =>
178185
ctx
179186
override def transformDefDef(tree: DefDef)(using Context): tree.type =
180187
traverseAnnotations(tree.symbol)
@@ -456,7 +463,7 @@ object CheckUnused:
456463
if !tree.name.isInstanceOf[DerivedName] then
457464
pats.addOne((tree.symbol, tree.namePos))
458465
case tree: NamedDefTree =>
459-
if (tree.symbol ne NoSymbol) && !tree.name.isWildcard then
466+
if (tree.symbol ne NoSymbol) && !tree.name.isWildcard && !tree.hasAttachment(NoWarn) then
460467
defs.addOne((tree.symbol, tree.namePos))
461468
case _ =>
462469
if tree.symbol ne NoSymbol then
@@ -851,6 +858,17 @@ object CheckUnused:
851858
args.foreach(traverse)
852859
case tree => traverseChildren(tree)
853860

861+
// NoWarn members in tree that correspond to refinements; currently uses only names.
862+
def relax(tree: Tree, refinements: List[Tree])(using Context): Unit =
863+
val names = refinements.collect { case named: NamedDefTree => named.name }.toSet
864+
val relaxer = new TreeTraverser:
865+
def traverse(tree: Tree)(using Context) =
866+
tree match
867+
case tree: NamedDefTree if names(tree.name) => tree.withAttachment(NoWarn, ())
868+
case _ =>
869+
traverseChildren(tree)
870+
relaxer.traverse(tree)
871+
854872
extension (nm: Name)
855873
inline def exists(p: Name => Boolean): Boolean = nm.ne(nme.NO_NAME) && p(nm)
856874
inline def isWildcard: Boolean = nm == nme.WILDCARD || nm.is(WildcardParamName)

Diff for: tests/semanticdb/metac.expect

+1-2
Original file line numberDiff line numberDiff line change
@@ -3494,7 +3494,7 @@ Text => empty
34943494
Language => Scala
34953495
Symbols => 12 entries
34963496
Occurrences => 33 entries
3497-
Diagnostics => 2 entries
3497+
Diagnostics => 1 entries
34983498
Synthetics => 4 entries
34993499

35003500
Symbols:
@@ -3550,7 +3550,6 @@ Diagnostics:
35503550
[14:20..14:23): [warning] Alphanumeric method foo is not declared infix; it should not be used as infix operator.
35513551
Instead, use method syntax .foo(...) or backticked identifier `foo`.
35523552
The latter can be rewritten automatically under -rewrite -source 3.4-migration.
3553-
[19:8..19:17): [warning] unused private member
35543553

35553554
Synthetics:
35563555
[12:2..12:6):user => reflectiveSelectable(*)

Diff for: tests/warn/i22681.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ class C:
1010
def run() = ()
1111
def g = v // warn effectively private member is unused
1212
def t = v // nowarn
13-
def u = v // warn despite structural type (TODO work around the limitation, at least for this example)
13+
def u = v // nowarn because leaked by refinement
14+
val v: Runnable { def u: Int } = new Runnable:
15+
private def v = 42 // avoid g judged too trivial to warn
16+
def run() = ()
17+
def u = v // nowarn because leaked by refinement

0 commit comments

Comments
 (0)