Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,10 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha

override def transformTypeTree(tree: TypeTree)(using Context): tree.type =
tree.tpe match
case AnnotatedType(_, annot) => transformAllDeep(annot.tree)
case tpt if !tree.isInferred && tpt.typeSymbol.exists =>
resolveUsage(tpt.typeSymbol, tpt.typeSymbol.name, NoPrefix, tree.srcPos)
case _ =>
case AnnotatedType(_, annot) => transformAllDeep(annot.tree)
case tpt if !tree.isInferred && tpt.typeSymbol.exists =>
resolveUsage(tpt.typeSymbol, tpt.typeSymbol.name, NoPrefix, tree.srcPos)
case _ =>
tree

override def prepareForInlined(tree: Inlined)(using Context): Context =
Expand Down Expand Up @@ -424,9 +424,19 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
&& ctxsym.thisType.baseClasses.contains(sym.owner)
&& ctxsym.thisType.member(sym.name).hasAltWith(d => d.containsSym(sym) && !name.exists(_ != d.name))

def isHere =
val sourcePos = pos.sourcePos // SourcePosition of the referring tree
val here = ctx.compilationUnit.source
sourcePos.exists
&& sourcePos.source.exists
&& here.exists
&& sourcePos.source == here// both Source exist and compare equal

// Avoid spurious NoSymbol and also primary ctors which are never warned about.
// Selections C.this.toString should be already excluded, but backstopped here for eq, etc.
if !sym.exists || sym.isPrimaryConstructor || sym.isEffectiveRoot || defn.topClasses(sym.owner) then return
// Don't look up references if the tree position is not the current source (but is from a macro).
if !sym.exists || sym.isPrimaryConstructor || sym.isEffectiveRoot || defn.topClasses(sym.owner) || !isHere
then return

// Find the innermost, highest precedence. Contexts have no nesting levels but assume correctness.
// If the sym is an enclosing definition (the owner of a context), it does not count toward usages.
Expand Down
5 changes: 5 additions & 0 deletions tests/warn/i24561/ext.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ext

case class Reader[F[_], A, B]()

case class NonEmptyList()
14 changes: 14 additions & 0 deletions tests/warn/i24561/macros.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ext.Reader
import scala.quoted.*

object macros:
inline def demo: Unit = ${ demoImpl }

def demoImpl(
using Quotes
): Expr[Unit] =
'{
//val r: ext.Reader[Option, String, String] = ???
val r: Reader[Option, String, String] = ???
()
}
7 changes: 7 additions & 0 deletions tests/warn/i24561/main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//> using options -Wunused:all
import ext.Reader // warn
import ext.NonEmptyList // warn

@main def run = locally {
macros.demo
}
Loading