Skip to content

Commit b2f0fa1

Browse files
committed
Add warn Annotated Types and "new" kw
- Annotated types are reported as used - Some times class constructor "this" is used instead of apply It is registered as used - Some new tests
1 parent 95c8a40 commit b2f0fa1

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import dotty.tools.dotc.typer.ImportInfo
1616
import dotty.tools.dotc.util.Property
1717
import dotty.tools.dotc.transform.CheckUnused.UnusedData.UnusedResult
1818
import dotty.tools.dotc.core.Mode
19+
import dotty.tools.dotc.core.Types.TypeTraverser
20+
import dotty.tools.dotc.core.Types.Type
21+
import dotty.tools.dotc.core.Types.AnnotatedType
22+
import dotty.tools.dotc.core.Flags.flagsString
23+
import dotty.tools.dotc.core.Flags
1924

2025

2126

@@ -83,11 +88,19 @@ class CheckUnused extends Phase:
8388
case t: tpd.Bind =>
8489
unusedDataApply(_.registerPatVar(t))
8590
traverseChildren(tree)(using newCtx)
91+
case t@tpd.TypeTree() =>
92+
typeTraverser(unusedDataApply).traverse(t.tpe)
93+
traverseChildren(tree)(using newCtx)
8694
case _ =>
8795
traverseChildren(tree)(using newCtx)
8896
end traverse
8997
end traverser
9098

99+
private def typeTraverser(dt: (UnusedData => Any) => Unit)(using Context) = new TypeTraverser:
100+
override def traverse(tp: Type): Unit = tp match
101+
case AnnotatedType(_, annot) => dt(_.registerUsed(annot.symbol))
102+
case _ => traverseChildren(tp)
103+
91104
private def reportUnused(res: UnusedData.UnusedResult)(using Context): Unit =
92105
import CheckUnused.WarnTypes
93106
res.warnings.foreach { s =>
@@ -185,6 +198,8 @@ object CheckUnused:
185198
if !isConstructorOfSynth(sym) then
186199
usedInScope.top += sym -> sym.isAccessibleAsIdent
187200
usedDef += sym
201+
if sym.isConstructor && sym.exists then
202+
registerUsed(sym.owner) // constructor are "implicitly" imported with the class
188203

189204
/** Register a list of found (used) symbols */
190205
def registerUsed(syms: Seq[Symbol])(using Context): Unit =
@@ -343,7 +358,7 @@ object CheckUnused:
343358
val qualHasSymbol = qual.tpe.member(sym.name).symbol == sym
344359
def selector = sels.find(sel => sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name)
345360
def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given) == sel.isGiven) || sym.is(Implicit)))
346-
if qualHasSymbol && !isAccessible then
361+
if qualHasSymbol && !isAccessible && sym.exists then
347362
selector.orElse(wildcard) // selector with name or wildcard (or given)
348363
else
349364
None

tests/neg-custom-args/fatal-warnings/i15503a.scala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,19 @@ object Scala2ImplicitsGiven:
187187
val b = summon[Int]
188188
object G:
189189
import A.x // error
190-
val b = 1
190+
val b = 1
191+
192+
// -------------------------------------
193+
object TestNewKeyword:
194+
object Foo:
195+
class Aa[T](val x: T)
196+
object Bar:
197+
import Foo.Aa // OK
198+
val v = 1
199+
val a = new Aa(v)
200+
201+
// -------------------------------------
202+
object testAnnotatedType:
203+
import annotation.switch // OK
204+
val a = (??? : @switch) match
205+
case _ => ???

0 commit comments

Comments
 (0)