Add andThen to Function2..Function22 and FunctionXXL#26077
Open
He-Pin wants to merge 1 commit into
Open
Conversation
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
Contributor
|
Per |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirror
java.util.function.BiFunction.andThenfor Scala's higher-arity function types. Port of scala/scala#11121.def andThen[A](g: R => A): (T1, .., Tn) => Ato each ofFunction2..Function22(default trait method,@unspecialized).def andThen(g: Object => Object): FunctionXXL^{this, g}toscala.runtime.FunctionXXL. The capture-polymorphic return type is required because the SAM body capturesthisandg.Function1[(K, V1), Unit]mixin from the privateaccumclass insideHashMap.iadd: onceFunction2carries a defaultandThen, mixing in both produces a clash between the two trait-default implementations. The iterator loop is inlined to awhileto replace the Function1 dispatch.andThenondotty.tools.dotc.core.SymDenotations.LazyType, which extends bothFunction1[Symbol, LazyType]andFunction2[(TermSymbol, ClassSymbol), LazyType], to disambiguate the inherited members. Composition is not meaningful for a symbol completer, so the override throwsUnsupportedOperationException.ScalaLibraryPluginso thescala2-libraryproject (whose compiled binaries replace ours for specialized synthetics) also carriesandThen. The Scala 2 backport will land in a separate PR; this in-tree source patch keeps the present change self-contained until it does.ReversedMissingMethodProblemfilters for the 22 new default methods.Test plan
testCompilation function-andthenpasses (tests/run/function-andthen.scalacoversFunction2,Function3,Function22, type-changing chains, evaluation order, fresh-instance return, interaction withtupled/curried, andFunctionXXLat arity 23).scala2-libraryrecompiles with patched sources;Function2.classexposesandThen.scala-library-nonbootstrappedrebuilds 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.