From c2eb000cd28713bb281ab1eb55bebb856ba5d218 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 8 Jul 2024 12:07:20 +0200 Subject: [PATCH 1/2] Add warning for anonymous inline classes (#16723) [Cherry-picked 8f84df8a73573af18562ddcde7bf5e279ce85dc2][modified] --- .../community-projects/shapeless-3 | 2 +- .../tools/dotc/printing/Formatting.scala | 4 +- .../tools/dotc/reporting/ErrorMessageID.scala | 1 + .../dotty/tools/dotc/reporting/messages.scala | 9 ++++ .../dotc/transform/PruneErasedDefs.scala | 12 +++++ tests/neg/i13044.check | 48 +++++++++---------- tests/neg/i13044.scala | 8 +--- tests/pos/i17314.scala | 3 +- tests/pos/not-looping-implicit.scala | 4 +- tests/run/i11050.scala | 12 +++-- tests/warn/i15503i.scala | 6 +-- tests/warn/i15503j.scala | 4 +- tests/warn/i16723.check | 6 +++ tests/warn/i16723.scala | 3 ++ tests/warn/i16723a.check | 6 +++ tests/warn/i16723a.scala | 17 +++++++ 16 files changed, 100 insertions(+), 45 deletions(-) create mode 100644 tests/warn/i16723.check create mode 100644 tests/warn/i16723.scala create mode 100644 tests/warn/i16723a.check create mode 100644 tests/warn/i16723a.scala diff --git a/community-build/community-projects/shapeless-3 b/community-build/community-projects/shapeless-3 index d27c5ba1ae51..24e86dd290eb 160000 --- a/community-build/community-projects/shapeless-3 +++ b/community-build/community-projects/shapeless-3 @@ -1 +1 @@ -Subproject commit d27c5ba1ae5111b85df2cfb65a26b9246c52570c +Subproject commit 24e86dd290eba9b27599936a7f338fac975f833d diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index c72f2199e635..54434b2b0ca9 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -42,7 +42,9 @@ object Formatting { trait CtxShow: def run(using Context): Shown - private inline def CtxShow(inline x: Context ?=> Shown) = new CtxShow { def run(using Context) = x(using ctx) } + private inline def CtxShow(inline x: Context ?=> Shown) = + class InlinedCtxShow extends CtxShow { def run(using Context) = x(using ctx) } + new InlinedCtxShow private def toStr[A: Show](x: A)(using Context): String = Shown.toStr(toShown(x)) private def toShown[A: Show](x: A)(using Context): Shown = Show[A].show(x).runCtxShow diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index c5aefead0bcc..904893911a6d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -208,6 +208,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case UnstableInlineAccessorID // errorNumber: 192 - unused in LTS case VolatileOnValID // errorNumber: 193 case ExtensionNullifiedByMemberID // errorNumber: 194 + case InlinedAnonClassWarningID // errorNumber: 195 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index f891cec1df67..679c47988199 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -3073,6 +3073,15 @@ extends SyntaxMsg(InlineGivenShouldNotBeFunctionID): | inline def apply(x: A) = x.toB """ +class InlinedAnonClassWarning()(using Context) + extends Message(InlinedAnonClassWarningID): + def kind = MessageKind.PotentialIssue + def msg(using Context) = "New anonymous class definition will be duplicated at each inline site" + def explain(using Context) = + i"""Anonymous class will be defined at each use site, which may lead to a larger number of classfiles. + | + |To inline class definitions, you may provide an explicit class name to avoid this warning.""" + class ValueDiscarding(tp: Type)(using Context) extends Message(ValueDiscardingID): def kind = MessageKind.PotentialIssue diff --git a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala index 9bb30926d45a..47eb70cb46d4 100644 --- a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala +++ b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala @@ -10,6 +10,7 @@ import Symbols.* import typer.RefChecks import MegaPhase.MiniPhase import ast.tpd +import reporting.InlinedAnonClassWarning import config.Feature import Decorators.* @@ -51,6 +52,17 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform => else cpy.ValDef(tree)(rhs = trivialErasedTree(tree.rhs)) override def transformDefDef(tree: DefDef)(using Context): Tree = + def checkNoInlineAnnoClasses(tree: DefDef)(using Context): Unit = + if tree.symbol.is(Inline) then + new TreeTraverser { + def traverse(tree: Tree)(using Context): Unit = + tree match + case tree: TypeDef if tree.symbol.isAnonymousClass => + report.warning(new InlinedAnonClassWarning(), tree.symbol.sourcePos) + case _ => traverseChildren(tree) + }.traverse(tree) + + checkNoInlineAnnoClasses(tree) checkErasedInExperimental(tree.symbol) if !tree.symbol.isEffectivelyErased || tree.rhs.isEmpty then tree else cpy.DefDef(tree)(rhs = trivialErasedTree(tree.rhs)) diff --git a/tests/neg/i13044.check b/tests/neg/i13044.check index c5584aadf767..69c61b06c353 100644 --- a/tests/neg/i13044.check +++ b/tests/neg/i13044.check @@ -1,5 +1,5 @@ --- Error: tests/neg/i13044.scala:50:40 --------------------------------------------------------------------------------- -50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error +-- Error: tests/neg/i13044.scala:46:40 --------------------------------------------------------------------------------- +46 | implicit def typeSchema: Schema[A] = Schema.gen // error // error | ^^^^^^^^^^ | given instance gen is declared as `inline`, but was not inlined | @@ -12,11 +12,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 @@ -24,11 +24,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 @@ -36,11 +36,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 @@ -48,11 +48,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 @@ -64,15 +64,15 @@ | ^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ -------------------------------------------------------------------------------------------------------------------- --- Error: tests/neg/i13044.scala:50:40 --------------------------------------------------------------------------------- -50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error +-- Error: tests/neg/i13044.scala:46:40 --------------------------------------------------------------------------------- +46 | implicit def typeSchema: Schema[A] = Schema.gen // error // error | ^^^^^^^^^^ | method recurse is declared as `inline`, but was not inlined | @@ -85,11 +85,11 @@ | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 @@ -97,11 +97,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 @@ -109,11 +109,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 @@ -121,11 +121,11 @@ | ^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 @@ -137,10 +137,10 @@ | ^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -31 | lazy val fields = recurse[m.MirroredElemTypes] +29 | lazy val fields = recurse[m.MirroredElemTypes] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -37 | inline given gen[A]: Schema[A] = derived +33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i13044.scala b/tests/neg/i13044.scala index 081b642c604c..ad7687bbf2b8 100644 --- a/tests/neg/i13044.scala +++ b/tests/neg/i13044.scala @@ -23,15 +23,11 @@ trait SchemaDerivation { inline summonInline[Mirror.Of[A]] match { case m: Mirror.SumOf[A] => lazy val subTypes = recurse[m.MirroredElemTypes] - new Schema[A] { - def build: A = ??? - } + ??? case m: Mirror.ProductOf[A] => lazy val fields = recurse[m.MirroredElemTypes] - new Schema[A] { - def build: A = ??? - } + ??? } inline given gen[A]: Schema[A] = derived diff --git a/tests/pos/i17314.scala b/tests/pos/i17314.scala index 2d0c409ced10..8ece4a3bd7ac 100644 --- a/tests/pos/i17314.scala +++ b/tests/pos/i17314.scala @@ -13,8 +13,9 @@ object circelike { inline final def derived[A](using conf: Configuration)(using inline mirror: Mirror.Of[A] ): ConfiguredCodec[A] = - new ConfiguredCodec[A]: + class InlinedConfiguredCodec extends ConfiguredCodec[A]: val codec = summonInline[Codec[URI]] // simplification + new InlinedConfiguredCodec } object foo { diff --git a/tests/pos/not-looping-implicit.scala b/tests/pos/not-looping-implicit.scala index 90fba9f807a7..ebaf25e760f2 100644 --- a/tests/pos/not-looping-implicit.scala +++ b/tests/pos/not-looping-implicit.scala @@ -24,10 +24,10 @@ object Schema { inline summonInline[Mirror.Of[A]] match { case m: Mirror.SumOf[A] => lazy val members = recurse[m.MirroredElemLabels, m.MirroredElemTypes]() - new Schema[A] {} + ??? case m: Mirror.ProductOf[A] => lazy val fields = recurse[m.MirroredElemLabels, m.MirroredElemTypes]() - new Schema[A] {} + ??? } inline given gen[A]: Schema[A] = derived[A] diff --git a/tests/run/i11050.scala b/tests/run/i11050.scala index 90a6ec84df85..027812c013c4 100644 --- a/tests/run/i11050.scala +++ b/tests/run/i11050.scala @@ -113,12 +113,14 @@ object Show: inline def show[T](x: T): String = summonInline[Show[T]].show(x) - transparent inline def derived[T](implicit ev: Mirror.Of[T]): Show[T] = new { - def show(x: T): String = inline ev match { - case m: Mirror.ProductOf[T] => showProduct(x.asInstanceOf[Product], m) - case m: Mirror.SumOf[T] => showCases[m.MirroredElemTypes](0)(x, m.ordinal(x)) + transparent inline def derived[T](implicit ev: Mirror.Of[T]): Show[T] = + class InlinedShow extends Show[T] { // provide name to anonymous class + def show(x: T): String = inline ev match { + case m: Mirror.ProductOf[T] => showProduct(x.asInstanceOf[Product], m) + case m: Mirror.SumOf[T] => showCases[m.MirroredElemTypes](0)(x, m.ordinal(x)) + } } - } + new InlinedShow transparent inline def showProduct[T](x: Product, m: Mirror.ProductOf[T]): String = constValue[m.MirroredLabel] + showElems[m.MirroredElemTypes, m.MirroredElemLabels](0, Nil)(x) diff --git a/tests/warn/i15503i.scala b/tests/warn/i15503i.scala index 8a8ed487477a..b7981e0e4206 100644 --- a/tests/warn/i15503i.scala +++ b/tests/warn/i15503i.scala @@ -247,7 +247,7 @@ package foo.test.i16679a: import scala.deriving.Mirror object CaseClassByStringName: inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassByStringName[A] = - new CaseClassByStringName[A]: + new CaseClassByStringName[A]: // warn def name: String = A.toString object secondPackage: @@ -263,7 +263,7 @@ package foo.test.i16679b: object CaseClassName: import scala.deriving.Mirror inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassName[A] = - new CaseClassName[A]: + new CaseClassName[A]: // warn def name: String = A.toString object Foo: @@ -279,7 +279,7 @@ package foo.test.i17156: package a: trait Foo[A] object Foo: - inline def derived[T]: Foo[T] = new Foo{} + inline def derived[T]: Foo[T] = new Foo{} // warn package b: import a.Foo diff --git a/tests/warn/i15503j.scala b/tests/warn/i15503j.scala index f5e15bb79f79..fa30601d8960 100644 --- a/tests/warn/i15503j.scala +++ b/tests/warn/i15503j.scala @@ -49,11 +49,11 @@ package foo.unused.summon.inlines: transparent inline given conflictInside: C = summonInline[A] - new {} + ??? transparent inline given potentialConflict: C = summonInline[B] - new {} + ??? val b: B = summon[B] val c: C = summon[C] \ No newline at end of file diff --git a/tests/warn/i16723.check b/tests/warn/i16723.check new file mode 100644 index 000000000000..ed8e55502a80 --- /dev/null +++ b/tests/warn/i16723.check @@ -0,0 +1,6 @@ +-- [E195] Potential Issue Warning: tests/warn/i16723.scala:3:2 --------------------------------------------------------- +3 | new Object {} // warn + | ^ + | New anonymous class definition will be duplicated at each inline site + | + | longer explanation available when compiling with `-explain` diff --git a/tests/warn/i16723.scala b/tests/warn/i16723.scala new file mode 100644 index 000000000000..32875f4edf36 --- /dev/null +++ b/tests/warn/i16723.scala @@ -0,0 +1,3 @@ +inline def foo = + class NotAnon + new Object {} // warn \ No newline at end of file diff --git a/tests/warn/i16723a.check b/tests/warn/i16723a.check new file mode 100644 index 000000000000..ba4794fac23e --- /dev/null +++ b/tests/warn/i16723a.check @@ -0,0 +1,6 @@ +-- [E195] Potential Issue Warning: tests/warn/i16723a.scala:5:38 ------------------------------------------------------- +5 |inline given Converter[Int, String] = new Converter { // warn + | ^ + | New anonymous class definition will be duplicated at each inline site + | + | longer explanation available when compiling with `-explain` diff --git a/tests/warn/i16723a.scala b/tests/warn/i16723a.scala new file mode 100644 index 000000000000..90aaeb868d4e --- /dev/null +++ b/tests/warn/i16723a.scala @@ -0,0 +1,17 @@ +trait Converter[A, B] { + def convert: A => B +} + +inline given Converter[Int, String] = new Converter { // warn + def convert = _.toString() +} + +def foo(using bar: Converter[Int, String]) = + "foo" + +@main +def main = + foo + foo + foo + foo \ No newline at end of file From 7a6b83be9fa929d186a61a5f290ac12f40fc0f88 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 8 Jul 2024 16:37:31 +0200 Subject: [PATCH 2/2] Suppress additional warnings existing in the LTS due to rejection of #17548 backport --- community-build/community-projects/scodec | 2 +- .../src/scala/dotty/communitybuild/projects.scala | 5 ++++- tests/warn/i16723b.scala | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/warn/i16723b.scala diff --git a/community-build/community-projects/scodec b/community-build/community-projects/scodec index 96a77ecaaf91..b74f2085f071 160000 --- a/community-build/community-projects/scodec +++ b/community-build/community-projects/scodec @@ -1 +1 @@ -Subproject commit 96a77ecaaf913f195bb4079966a2e9fb41ce214e +Subproject commit b74f2085f07165d84b32c39eb214c9cc838711cc diff --git a/community-build/src/scala/dotty/communitybuild/projects.scala b/community-build/src/scala/dotty/communitybuild/projects.scala index 846907a85762..49c0263f6c73 100644 --- a/community-build/src/scala/dotty/communitybuild/projects.scala +++ b/community-build/src/scala/dotty/communitybuild/projects.scala @@ -368,7 +368,10 @@ object projects: lazy val shapeless3 = SbtCommunityProject( project = "shapeless-3", - sbtTestCommand = "testJVM; testJS", + sbtTestCommand = List( + """set derivingJVM/scalacOptions += "-Wconf:msg=New anonymous class definition will be duplicated at each inline site:s" """, + """set derivingJS/scalacOptions += "-Wconf:msg=New anonymous class definition will be duplicated at each inline site:s" """, + "testJVM", "testJS").mkString("; "), sbtDocCommand = forceDoc("typeable", "deriving"), scalacOptions = SbtCommunityProject.scalacOptions.filter(_ != "-Ysafe-init"), // due to -Xfatal-warnings ) diff --git a/tests/warn/i16723b.scala b/tests/warn/i16723b.scala new file mode 100644 index 000000000000..2ee0dd000b4c --- /dev/null +++ b/tests/warn/i16723b.scala @@ -0,0 +1,14 @@ +// LTS specifc, not applicable to Next thanks to #17548 improvements +trait Empty[T]: + def empty: T + +object Empty: + inline def withOnly[F[_], R, T](f: [t <: T] => F[t] => R): R = f(null.asInstanceOf[F[T]]) + + def mkEmpty[T](t: T): Empty[T] = ??? + + inline given emptyGenC[A]: Empty[A] = + mkEmpty(withOnly[Empty, A, A]([a <: A] => (_: Empty[a]).empty)) // warn + +@main def Test = + Empty.emptyGenC[String]