From 981ea25443a676abd7d93fe2468868ab976f2ed7 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 1 Feb 2025 17:08:59 -0800 Subject: [PATCH 1/3] Status quo [Cherry-picked 451ec1b2213cb2df3683832b193e335c8785a909] --- tests/warn/i21805.scala | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/warn/i21805.scala diff --git a/tests/warn/i21805.scala b/tests/warn/i21805.scala new file mode 100644 index 000000000000..f53b899c0176 --- /dev/null +++ b/tests/warn/i21805.scala @@ -0,0 +1,31 @@ +//> using options -Wunused:imports + +def i23967: Boolean = { + //import scala.compiletime.testing.typeCheckErrors + import scala.compiletime.testing.* // warn + typeChecks("2 + 2") +} + +package p: + val code = """"hello, world"""" +package c: + class C(i: Int) + +package q: + import c.* // warn should be nowarn + import p.* // warn should be nowarn + import scala.compiletime.testing.* + def test() = typeCheckErrors("""println(C("hello, world"))""") + def ok() = typeChecks("println(code)") + inline def f(inline i: Int) = 42 + i + +package i23967b: + package ok: + import scala.compiletime.testing.* // warn + def test() = typeChecks("42 + 27") + package nok: + import scala.compiletime.testing.typeChecks // warn + def test() = typeChecks("42 + 27") + +@main def Test = println: + q.f(27) From e1868313e0e8ee8f3db4e0ca370d4ee07d3b0d42 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 22 Sep 2025 20:22:52 -0700 Subject: [PATCH 2/3] Ignore compiletime.testing for now [Cherry-picked 4d28ffda5d83d3168bdfca70f559ae956122cfd3] --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 5 +++++ tests/warn/i21805.scala | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index c5fcfadba2c2..487acc564816 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -473,6 +473,7 @@ object CheckUnused: if inliners == 0 && languageImport(imp.expr).isEmpty && !imp.isGeneratedByEnum + && !imp.isCompiletimeTesting && !ctx.owner.name.isReplWrapperName then imps.put(imp, ()) @@ -1003,6 +1004,10 @@ object CheckUnused: def isGeneratedByEnum: Boolean = imp.symbol.exists && imp.symbol.owner.is(Enum, butNot = Case) + /** No mechanism for detection yet. */ + def isCompiletimeTesting: Boolean = + imp.expr.symbol == defn.CompiletimeTestingPackage//.moduleClass + extension (pos: SrcPos) def isZeroExtentSynthetic: Boolean = pos.span.isSynthetic && pos.span.isZeroExtent def isSynthetic: Boolean = pos.span.isSynthetic && pos.span.exists diff --git a/tests/warn/i21805.scala b/tests/warn/i21805.scala index f53b899c0176..4fdcae85910d 100644 --- a/tests/warn/i21805.scala +++ b/tests/warn/i21805.scala @@ -2,7 +2,7 @@ def i23967: Boolean = { //import scala.compiletime.testing.typeCheckErrors - import scala.compiletime.testing.* // warn + import scala.compiletime.testing.* // nowarn typeChecks("2 + 2") } @@ -21,10 +21,10 @@ package q: package i23967b: package ok: - import scala.compiletime.testing.* // warn + import scala.compiletime.testing.* // nowarn def test() = typeChecks("42 + 27") package nok: - import scala.compiletime.testing.typeChecks // warn + import scala.compiletime.testing.typeChecks // nowarn def test() = typeChecks("42 + 27") @main def Test = println: From caf2731b9b509c9a4cd4d13036b0dd4ef4ad13e6 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 15 Oct 2025 10:36:35 -0700 Subject: [PATCH 3/3] Import of compiletime.testing nullifies unused lint [Cherry-picked b3256812e6da4cba643a2685ce606ded40374acf] --- .../src/dotty/tools/dotc/transform/CheckUnused.scala | 11 ++++++++--- tests/warn/i21805.scala | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 487acc564816..41fbd888b641 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -473,10 +473,12 @@ object CheckUnused: if inliners == 0 && languageImport(imp.expr).isEmpty && !imp.isGeneratedByEnum - && !imp.isCompiletimeTesting && !ctx.owner.name.isReplWrapperName then - imps.put(imp, ()) + if imp.isCompiletimeTesting then + isNullified = true + else + imps.put(imp, ()) case tree: Bind => if !tree.name.isInstanceOf[DerivedName] && !tree.name.is(WildcardParamName) then if tree.hasAttachment(NoWarn) then @@ -506,6 +508,9 @@ object CheckUnused: asss.addOne(sym) else refs.addOne(sym) + + // currently compiletime.testing is completely erased, so ignore the unit + var isNullified = false end RefInfos // Names are resolved by definitions and imports, which have four precedence levels: @@ -520,7 +525,7 @@ object CheckUnused: inline def weakerThan(q: Precedence): Boolean = p > q inline def isNone: Boolean = p == NoPrecedence - def reportUnused()(using Context): Unit = + def reportUnused()(using Context): Unit = if !refInfos.isNullified then for (msg, pos, origin) <- warnings do if origin.isEmpty then report.warning(msg, pos) else report.warning(msg, pos, origin) diff --git a/tests/warn/i21805.scala b/tests/warn/i21805.scala index 4fdcae85910d..9d991d35efc8 100644 --- a/tests/warn/i21805.scala +++ b/tests/warn/i21805.scala @@ -1,4 +1,4 @@ -//> using options -Wunused:imports +//> using options -Wunused:all def i23967: Boolean = { //import scala.compiletime.testing.typeCheckErrors @@ -12,8 +12,8 @@ package c: class C(i: Int) package q: - import c.* // warn should be nowarn - import p.* // warn should be nowarn + import c.* // nowarn, unit is nullified + import p.* // nowarn import scala.compiletime.testing.* def test() = typeCheckErrors("""println(C("hello, world"))""") def ok() = typeChecks("println(code)")