Skip to content

Commit

Permalink
Merge branch 'main' into fix/wunused/annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulCoral committed Feb 18, 2023
2 parents 4cc4339 + b5b24d9 commit 4750edc
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 26 deletions.
57 changes: 31 additions & 26 deletions compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ class CheckUnused extends MiniPhase:
*/
private val _key = Property.Key[UnusedData]

extension (k: Property.Key[UnusedData])
private def unusedDataApply[U](f: UnusedData => U)(using Context): Context =
ctx.property(_key).foreach(f)
ctx
private def getUnusedData(using Context): Option[UnusedData] =
ctx.property(_key)
private def unusedDataApply[U](f: UnusedData => U)(using Context): Context =
ctx.property(_key).foreach(f)
ctx
private def getUnusedData(using Context): Option[UnusedData] =
ctx.property(_key)

override def phaseName: String = CheckUnused.phaseName

Expand All @@ -72,7 +71,7 @@ class CheckUnused extends MiniPhase:
// ========== END + REPORTING ==========

override def transformUnit(tree: tpd.Tree)(using Context): tpd.Tree =
_key.unusedDataApply(ud => reportUnused(ud.getUnused))
unusedDataApply(ud => reportUnused(ud.getUnused))
tree

// ========== MiniPhase Prepare ==========
Expand All @@ -83,14 +82,14 @@ class CheckUnused extends MiniPhase:

override def prepareForIdent(tree: tpd.Ident)(using Context): Context =
if tree.symbol.exists then
_key.unusedDataApply(_.registerUsed(tree.symbol, Some(tree.name)))
unusedDataApply(_.registerUsed(tree.symbol, Some(tree.name)))
else if tree.hasType then
_key.unusedDataApply(_.registerUsed(tree.tpe.classSymbol, Some(tree.name)))
unusedDataApply(_.registerUsed(tree.tpe.classSymbol, Some(tree.name)))
else
ctx

override def prepareForSelect(tree: tpd.Select)(using Context): Context =
_key.unusedDataApply(_.registerUsed(tree.symbol, Some(tree.name)))
unusedDataApply(_.registerUsed(tree.symbol, Some(tree.name)))

override def prepareForBlock(tree: tpd.Block)(using Context): Context =
pushInBlockTemplatePackageDef(tree)
Expand All @@ -102,7 +101,7 @@ class CheckUnused extends MiniPhase:
pushInBlockTemplatePackageDef(tree)

override def prepareForValDef(tree: tpd.ValDef)(using Context): Context =
_key.unusedDataApply{ud =>
unusedDataApply{ud =>
// do not register the ValDef generated for `object`
traverseAnnotations(tree.symbol)
if !tree.symbol.is(Module) then
Expand All @@ -111,7 +110,7 @@ class CheckUnused extends MiniPhase:
}

override def prepareForDefDef(tree: tpd.DefDef)(using Context): Context =
_key.unusedDataApply{ ud =>
unusedDataApply{ ud =>
import ud.registerTrivial
tree.registerTrivial
traverseAnnotations(tree.symbol)
Expand All @@ -120,7 +119,7 @@ class CheckUnused extends MiniPhase:
}

override def prepareForTypeDef(tree: tpd.TypeDef)(using Context): Context =
_key.unusedDataApply{ ud =>
unusedDataApply{ ud =>
if !tree.symbol.is(Param) then // Ignore type parameter (as Scala 2)
traverseAnnotations(tree.symbol)
ud.registerDef(tree)
Expand All @@ -129,10 +128,10 @@ class CheckUnused extends MiniPhase:

override def prepareForBind(tree: tpd.Bind)(using Context): Context =
traverseAnnotations(tree.symbol)
_key.unusedDataApply(_.registerPatVar(tree))
unusedDataApply(_.registerPatVar(tree))

override def prepareForTypeTree(tree: tpd.TypeTree)(using Context): Context =
typeTraverser(_key.unusedDataApply).traverse(tree.tpe)
if !tree.isInstanceOf[tpd.InferredTypeTree] then typeTraverser(unusedDataApply).traverse(tree.tpe)
ctx

// ========== MiniPhase Transform ==========
Expand All @@ -150,27 +149,27 @@ class CheckUnused extends MiniPhase:
tree

override def transformValDef(tree: tpd.ValDef)(using Context): tpd.Tree =
_key.unusedDataApply(_.removeIgnoredUsage(tree.symbol))
unusedDataApply(_.removeIgnoredUsage(tree.symbol))
tree

override def transformDefDef(tree: tpd.DefDef)(using Context): tpd.Tree =
_key.unusedDataApply(_.removeIgnoredUsage(tree.symbol))
unusedDataApply(_.removeIgnoredUsage(tree.symbol))
tree

override def transformTypeDef(tree: tpd.TypeDef)(using Context): tpd.Tree =
_key.unusedDataApply(_.removeIgnoredUsage(tree.symbol))
unusedDataApply(_.removeIgnoredUsage(tree.symbol))
tree

// ---------- MiniPhase HELPERS -----------

private def pushInBlockTemplatePackageDef(tree: tpd.Block | tpd.Template | tpd.PackageDef)(using Context): Context =
_key.unusedDataApply { ud =>
unusedDataApply { ud =>
ud.pushScope(UnusedData.ScopeType.fromTree(tree))
}
ctx

private def popOutBlockTemplatePackageDef()(using Context): Context =
_key.unusedDataApply { ud =>
unusedDataApply { ud =>
ud.popScope()
}
ctx
Expand All @@ -193,7 +192,7 @@ class CheckUnused extends MiniPhase:
val newCtx = if tree.symbol.exists then ctx.withOwner(tree.symbol) else ctx
tree match
case imp:tpd.Import =>
_key.unusedDataApply(_.registerImport(imp))
unusedDataApply(_.registerImport(imp))
traverseChildren(tree)(using newCtx)
case ident: Ident =>
prepareForIdent(ident)
Expand All @@ -203,7 +202,7 @@ class CheckUnused extends MiniPhase:
traverseChildren(tree)(using newCtx)
case _: (tpd.Block | tpd.Template | tpd.PackageDef) =>
//! DIFFERS FROM MINIPHASE
_key.unusedDataApply { ud =>
unusedDataApply { ud =>
ud.inNewScope(ScopeType.fromTree(tree))(traverseChildren(tree)(using newCtx))
}
case t:tpd.ValDef =>
Expand All @@ -221,9 +220,10 @@ class CheckUnused extends MiniPhase:
case t: tpd.Bind =>
prepareForBind(t)
traverseChildren(tree)(using newCtx)
case _: tpd.InferredTypeTree =>
case t@tpd.TypeTree() =>
//! DIFFERS FROM MINIPHASE
typeTraverser(_key.unusedDataApply).traverse(t.tpe)
typeTraverser(unusedDataApply).traverse(t.tpe)
traverseChildren(tree)(using newCtx)
case _ =>
//! DIFFERS FROM MINIPHASE
Expand All @@ -233,9 +233,14 @@ class CheckUnused extends MiniPhase:

/** This is a type traverser which catch some special Types not traversed by the term traverser above */
private def typeTraverser(dt: (UnusedData => Any) => Unit)(using Context) = new TypeTraverser:
override def traverse(tp: Type): Unit = tp match
case AnnotatedType(_, annot) => dt(_.registerUsed(annot.symbol, None))
case _ => traverseChildren(tp)
override def traverse(tp: Type): Unit =
if tp.typeSymbol.exists then dt(_.registerUsed(tp.typeSymbol, Some(tp.typeSymbol.name)))
tp match
case AnnotatedType(_, annot) =>
dt(_.registerUsed(annot.symbol, None))
traverseChildren(tp)
case _ =>
traverseChildren(tp)

/** This traverse the annotations of the symbol */
private def traverseAnnotations(sym: Symbol)(using Context): Unit =
Expand Down
22 changes: 22 additions & 0 deletions tests/neg-custom-args/fatal-warnings/i16930.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// scalac: -Wunused:imports

trait Outer:
trait Used
trait Unused

object Test {
val outer: Outer = ???
import outer.{Used, Unused} // error
def foo(x: Any): Used = x.asInstanceOf[Used]
}

trait Outer1:
trait UnusedToo1
trait Unused1
def unusedToo1: UnusedToo1

object Test1 {
val outer1: Outer1 = ???
import outer1.{Unused1, UnusedToo1} // error // error
def foo() = outer1.unusedToo1 // in this case UnusedToo1 is not used explicitly, only inferred
}

0 comments on commit 4750edc

Please sign in to comment.