Skip to content

Optimise simple tuple extraction #23224

Closed
@noti0na1

Description

@noti0na1
Member

Compiler version

3.7.2-RC1-bin-20250520-baac46c-NIGHTLY-git-baac46c

Minimized example

class Test:
  def f1: (Int, Int) = (1, 2)

  def test1 =
    val (a, b) = f1
    a + b

Output

After typer: scala compile --server=false -S 3.nightly -Xprint:typer tuples.scala

package <empty> {
  class Test() extends Object() {
    def f1: Tuple2[Int, Int] = Tuple2.apply[Int, Int](1, 2)
    def test1: Int =
      {
        val $1$: (Int, Int) =
          this.f1:(Int, Int) @unchecked match 
            {
              case Tuple2.unapply[Int, Int](a @ _, b @ _) =>
                Tuple2.apply[Int, Int](a, b)
            }
        val a: Int = $1$._1
        val b: Int = $1$._2
        a + b
      }
  }
}

After genBCode: scala compile --server=false -S 3.nightly -Xprint:genBCode tuples.scala

package <empty> {
  @SourceFile("tuples.scala") class Test extends Object {
    def <init>(): Unit =
      {
        super()
        ()
      }
    def f1(): Tuple2 = new Tuple2$mcII$sp(1, 2)
    def test1(): Int =
      {
        val $1$: Tuple2 =
          matchResult1[Tuple2]: 
            {
              case val x1: Tuple2 = this.f1():Tuple2
              if x1 ne null then
                {
                  case val a: Int = x1._1$mcI$sp()
                  case val b: Int = x1._2$mcI$sp()
                  return[matchResult1] new Tuple2$mcII$sp(a, b)
                }
               else ()
              throw new MatchError(x1)
            }
        val a: Int = $1$._1$mcI$sp()
        val b: Int = $1$._2$mcI$sp()
        a + b
      }
  }
}

Expectation

Calling _i on the tuple directly:

val $1$: (Int, Int) = this.f1:(Int, Int)
val a: Int = $1$._1
val b: Int = $1$._2
a + b

Activity

added
stat:needs triageEvery issue needs to have an "area" and "itype" label
area:desugarDesugaring happens after parsing but before typing, see desugar.scala
and removed
stat:needs triageEvery issue needs to have an "area" and "itype" label
on May 21, 2025
noti0na1

noti0na1 commented on May 21, 2025

@noti0na1
MemberAuthor

When typing a PatDef(mods, pats, tpt, rhs), instead of passing to desuger directly, we type check rhs first.

In makePatDef, we update tupleOptimizable, and we will apply optimisation if:

  • all branches are both tuples of arity N (tuple literals or tuple types)
  • pat is a tuple of N variables or wildcard patterns like (x1, x2, ..., xN)
self-assigned this
on Jun 13, 2025
added a commit that references this issue on Jul 11, 2025

Fix scala#23224: Optimize simple tuple extraction (scala#23373)

6f35f4a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:desugarDesugaring happens after parsing but before typing, see desugar.scalaitype:performance

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @noti0na1

    Issue actions

      Optimise simple tuple extraction · Issue #23224 · scala/scala3