From 3997fd067968b56fda0157cc279711d3dee4f412 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 6 Dec 2025 02:56:57 -0800 Subject: [PATCH 1/2] test --- tests/warn/i24561/ext.scala | 5 +++++ tests/warn/i24561/macros.scala | 14 ++++++++++++++ tests/warn/i24561/main.scala | 7 +++++++ 3 files changed, 26 insertions(+) create mode 100644 tests/warn/i24561/ext.scala create mode 100644 tests/warn/i24561/macros.scala create mode 100644 tests/warn/i24561/main.scala diff --git a/tests/warn/i24561/ext.scala b/tests/warn/i24561/ext.scala new file mode 100644 index 000000000000..946e54859bce --- /dev/null +++ b/tests/warn/i24561/ext.scala @@ -0,0 +1,5 @@ +package ext + +case class Reader[F[_], A, B]() + +case class NonEmptyList() diff --git a/tests/warn/i24561/macros.scala b/tests/warn/i24561/macros.scala new file mode 100644 index 000000000000..fb1fd6c4289b --- /dev/null +++ b/tests/warn/i24561/macros.scala @@ -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] = ??? + () + } diff --git a/tests/warn/i24561/main.scala b/tests/warn/i24561/main.scala new file mode 100644 index 000000000000..36aac3d1cb3e --- /dev/null +++ b/tests/warn/i24561/main.scala @@ -0,0 +1,7 @@ +//> using options -Wunused:all +import ext.Reader +import ext.NonEmptyList + +@main def run = locally { + macros.demo +} From 7c935807efdb6217b93e87ee59ed6f021ad289f7 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 13 Aug 2026 13:09:04 -0700 Subject: [PATCH 2/2] Unused lookup ref only from current source --- .../tools/dotc/transform/CheckUnused.scala | 20 ++++++++++++++----- tests/warn/i24561/main.scala | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 842f32b882a6..97bc9054d665 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -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 = @@ -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. diff --git a/tests/warn/i24561/main.scala b/tests/warn/i24561/main.scala index 36aac3d1cb3e..c5063c56231c 100644 --- a/tests/warn/i24561/main.scala +++ b/tests/warn/i24561/main.scala @@ -1,6 +1,6 @@ //> using options -Wunused:all -import ext.Reader -import ext.NonEmptyList +import ext.Reader // warn +import ext.NonEmptyList // warn @main def run = locally { macros.demo