Skip to content

Add andThen to Function2..Function22 and FunctionXXL#26077

Open
He-Pin wants to merge 1 commit into
scala:mainfrom
He-Pin:add-function-andthen
Open

Add andThen to Function2..Function22 and FunctionXXL#26077
He-Pin wants to merge 1 commit into
scala:mainfrom
He-Pin:add-function-andthen

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented May 17, 2026

Summary

Mirror java.util.function.BiFunction.andThen for Scala's higher-arity function types. Port of scala/scala#11121.

  • Adds def andThen[A](g: R => A): (T1, .., Tn) => A to each of Function2..Function22 (default trait method, @unspecialized).
  • Adds def andThen(g: Object => Object): FunctionXXL^{this, g} to scala.runtime.FunctionXXL. The capture-polymorphic return type is required because the SAM body captures this and g.
  • Drops the Function1[(K, V1), Unit] mixin from the private accum class inside HashMap.iadd: once Function2 carries a default andThen, mixing in both produces a clash between the two trait-default implementations. The iterator loop is inlined to a while to replace the Function1 dispatch.
  • Overrides andThen on dotty.tools.dotc.core.SymDenotations.LazyType, which extends both Function1[Symbol, LazyType] and Function2[(TermSymbol, ClassSymbol), LazyType], to disambiguate the inherited members. Composition is not meaningful for a symbol completer, so the override throws UnsupportedOperationException.
  • Patches the extracted Scala 2 library sources in ScalaLibraryPlugin so the scala2-library project (whose compiled binaries replace ours for specialized synthetics) also carries andThen. The Scala 2 backport will land in a separate PR; this in-tree source patch keeps the present change self-contained until it does.
  • Adds MiMa ReversedMissingMethodProblem filters for the 22 new default methods.

Test plan

  • testCompilation function-andthen passes (tests/run/function-andthen.scala covers Function2, Function3, Function22, type-changing chains, evaluation order, fresh-instance return, interaction with tupled / curried, and FunctionXXL at arity 23).
  • scala2-library recompiles with patched sources; Function2.class exposes andThen.
  • scala-library-nonbootstrapped rebuilds cleanly with the new binaries.

Notes

A dedicated Scala 2.13 backport will follow. The plugin-side source patch is the bridge that keeps this PR runnable in isolation until that lands; once it does, the patch can be removed.

Motivation:
Mirror `java.util.function.BiFunction.andThen` for Scala's higher-arity
function types. Previously only `Function1` provided `andThen`; users of
multi-argument functions had to either `.tupled.andThen(g).untupled`-style
detours or hand-write the wiring. This is a port of scala/scala#11121.

Modification:
- Add `def andThen[A](g: R => A): (T1, .., Tn) => A` to each of
  `Function2..Function22` (annotated `@unspecialized`, default impl on the
  trait so existing implementers get it for free).
- Add `def andThen(g: Object => Object): FunctionXXL^{this, g}` to
  `scala.runtime.FunctionXXL`. The capture-polymorphic return type is
  required because the SAM body captures `this` and `g`.
- Drop the `Function1[(K, V1), Unit]` mixin from the private `accum` class
  inside `HashMap.iadd`. Once `Function2` carries a default `andThen`,
  mixing in both `Function1` and `Function2` produces a clash between the
  two trait-default implementations. Inlining the iterator loop replaces
  the apply-via-Function1 path. Mirrors the equivalent fix in scala/scala.
- Override `andThen` on `core.SymDenotations.LazyType` (which extends both
  `Function1[Symbol, LazyType]` and `Function2[(TermSymbol, ClassSymbol), LazyType]`)
  to disambiguate the inherited members across the 30+ `LazyType` subclasses;
  composition via `andThen` is not meaningful for a symbol completer, so the
  override throws `UnsupportedOperationException`.
- Patch the extracted Scala 2 library sources in `ScalaLibraryPlugin`
  (`Function2..22.scala` and `HashMap.scala`) so the `scala2-library`
  project, whose compiled binaries replace ours for specialized synthetics,
  also exposes `andThen`. The Scala 2 backport will land in a separate PR;
  the source patch keeps this PR self-contained until it does.
- Add MiMa `ReversedMissingMethodProblem` filters for the 21 new default
  methods on `Function2..22` and `FunctionXXL`.

Result:
`tests/run/function-andthen.scala` covers `Function2.andThen`, sanity at
`Function3` and `Function22`, type-changing chained `andThen`, evaluation
order, fresh-instance return, interaction with `tupled` / `curried`, and
`FunctionXXL` at arity 23. All assertions pass under
`testCompilation function-andthen`.

References:
scala/scala#11121
@He-Pin He-Pin requested a review from a team as a code owner May 17, 2026 13:46
@SolalPirelli
Copy link
Copy Markdown
Contributor

Per CONTRIBUTING.md, please refer to https://nightly.scala-lang.org/docs/contributing/procedures/contributing-to-stdlib.html

@SolalPirelli SolalPirelli added the needs-slc This change needs to go through the Standard Library Changes (SLC) process. label May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-slc This change needs to go through the Standard Library Changes (SLC) process.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants