Skip to content

Inline SAM conversions can generate lots of code #16497

Closed
@odersky

Description

@odersky

Compiler version

All 3.x versions

Minimized example

Here's some code that illustrates a problem found in Lichess:

class Item(x: String)

inline given Conversion[String, Item] = Item(_)

inline given Conversion[String, Int] with
  def apply(x: String) = Item(x)

Output

Here's the code generated for the first version:

    final inline given def given_Conversion_String_Item:
      Conversion[String, Item] =
      {
        def $anonfun(_$1: String): Item = new Item(_$1)
        closure($anonfun:Conversion[String, Item])
      }:Conversion[String, Item]

And here's the code generated for the 2nd version:

    given class given_Conversion_String_Int() extends Conversion[String, Int]()
       {
      def apply(x: String): Int = new Item(x)
    }
    final inline given def given_Conversion_String_Int:
      given_Conversion_String_Int =
      new given_Conversion_String_Int():given_Conversion_String_Int

The first version generates an anonymous function for the SAM-type Conversion, which will be expanded to an anonymous class later. Since the conversion is inline, this means that every one of its invocations will generate an anonymous class. This can lead to increased code pressure without the user noticing the problem, since all invocations are implicit. It's probably this what caused the increased code size in the Lichess port to Scala 3.

The second version does not have this problem. There's a single class generated and every inline conversion just creates a new object instance.

Question

Should we prevent the first version or at least warn about it? I see the following possibilities:

  • Don't allow inline givens with a SAM closure as the right hand side. Suggest the rewriting to explicit apply.
  • Warn about inline givens with a SAM closure as the right hand side, with the same suggestion.
  • Silently rewrite the first version to the second.

What do people think? Which of these should be preferred?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions