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/community-projects/shapeless-3 b/community-build/community-projects/shapeless-3 index 90f0c977b536..24e86dd290eb 160000 --- a/community-build/community-projects/shapeless-3 +++ b/community-build/community-projects/shapeless-3 @@ -1 +1 @@ -Subproject commit 90f0c977b536c06305496600b8b2014c9e8e3d86 +Subproject commit 24e86dd290eba9b27599936a7f338fac975f833d diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index ac13f0161c70..6f1c32beb822 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 33f5dcf1b1f5..e51f0a8b77ac 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 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 58692b1ee7d7..51556a5c93ac 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -3113,6 +3113,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 1fbe978a49b8..e504b14185da 100644 --- a/tests/neg/i13044.check +++ b/tests/neg/i13044.check @@ -1,5 +1,5 @@ --- Error: tests/neg/i13044.scala:65:40 --------------------------------------------------------------------------------- -65 | implicit def typeSchema: Schema[A] = Schema.gen // error // error +-- Error: tests/neg/i13044.scala:61:40 --------------------------------------------------------------------------------- +61 | 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:65:40 --------------------------------------------------------------------------------- -65 | implicit def typeSchema: Schema[A] = Schema.gen // error // error +-- Error: tests/neg/i13044.scala:61:40 --------------------------------------------------------------------------------- +61 | 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 42417a9096f9..2b00fc188f8c 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 329b81327288..f4d41c53d981 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