Skip to content

New anonymous class definition will be duplicated at each inline site #22951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
goshacodes opened this issue Apr 9, 2025 · 3 comments
Open
Labels
area:inline area:reporting Error reporting including formatting, implicit suggestions, etc itype:bug

Comments

@goshacodes
Copy link

goshacodes commented Apr 9, 2025

Compiler version

3.3.5

Minimized code

trait JsonWriter[T] {
   def writeValues(value: T, out: TokenWriter): Unit
}

object JsonWriter:
  inline def derived[T]: JsonWriter[T] = new JsonWriter[T]:
    def writeValues(value: T, out: TokenWriter): Unit = () // here should be some macro code
}

Output

Warning

New anonymous class definition will be duplicated at each inline site

Expectation

No warning. Disabling warning in all project may cause that I miss correct warnings

Why I expect no warning?

  1. Because for different types generated body may vary for performance reasons. (Not full example, just to explain)
case class Foo(foo: String)

new JsonWriter[Foo]:
  def writeValues(value: Foo, out: TokenWriter): Unit =
    tokenWriter.writeFieldName("foo")
    tokenWriter.writeString(value.foo)
  
case class Bar(bar: Int)

new JsonWriter[Bar]:
  def writeValues(value: Bar, out: TokenWriter): Unit =
    tokenWriter.writeFieldName("bar")
    tokenWriter.writeint(value.bar)
  1. Creating class now allows to pass some compile time configuration to derivation
sealed trait WriterBuilder[A]:
  def rename[B](field: A => B)(rename: String): WriterBuilder[A]
  def fieldStyle(style: FieldStyle): WriterBuilder[A]

object WriterBuilder:
  @scala.annotation.compileTimeOnly(
    "Should be declared as inline given or provided directly to derives"
  )
  def apply[A](using
      mirror: scala.deriving.Mirror.ProductOf[A]
  ): WriterBuilder[A] =
    throw IllegalStateException(
      "Config must be an inlined given or provided directly to 'derived'"
    )

Usage is:

given JsonWriter[Foo] = JsonWriter.derived {
  WriterBuilder[Foo].rename(_.foo)("baz") 
}

// and now it should generate

new JsonWriter[Foo]:
  def writeValues(value: Foo, out: TokenWriter): Unit =
    tokenWriter.writeFieldName("baz")
    tokenWriter.writeString(value.foo)
  
@goshacodes goshacodes added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 9, 2025
@som-snytt
Copy link
Contributor

This is what @nowarn is for. This is a warning at definition and not at expansion. (The latter works with nowarn now.)

@goshacodes
Copy link
Author

This means users won't see it even if I leave it without @nowarn?

This is what @nowarn is for. This is a warning at definition and not at expansion

@bishabosha
Copy link
Member

bishabosha commented Apr 10, 2025

also, if you want to specialize then its better to create those specialized examples at definition site, rather than every user getting a new class defnitions - the reason this warning was created was because it caused significant code cache bloating in jvm for larger apps like lichess.org when they first migrated to Scala 3

@Gedochao Gedochao added area:reporting Error reporting including formatting, implicit suggestions, etc area:inline and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Apr 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:inline area:reporting Error reporting including formatting, implicit suggestions, etc itype:bug
Projects
None yet
Development

No branches or pull requests

4 participants