Skip to content

Stop reporting static forwarders - #987

Merged
lrytz merged 1 commit into
scala-garden:mainfrom
lrytz:skip-static-forwarders
Sep 17, 2026
Merged

lrytz merged 1 commit into
scala-garden:mainfrom
lrytz:skip-static-forwarders

Conversation

@lrytz

@lrytz lrytz commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

A static forwarder on a companion class lets Java code call an object's method, and MiMa does not protect Java clients elsewhere. Changing an object's method was reported twice, once for the forwarder, and Scala 2 dropping the forwarder of a method made private[foo] was reported as a break. MiMa now checks only the object's method.

@lrytz

lrytz commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

@kitbellew

The static forwarders are Java interop, which MiMa generally does not check. So skipping them seems more consistent.

We do have mimaReportSignatureProblems as opt-in, but these additional checks are not clearly for about Java interop; IIRC it was added to catch Scala incompatibilities (f: (A, B) to f: (B, A) change). For reliable Scala compatibility checking, I think https://github.com/scalacenter/tasty-mima is the right solution.

We could consider adding a "java API mode" to MiMa, that would have to cover a lot more than the static forwarders.

So IMO, skipping them is the most consistent thing to do.

A static forwarder on a companion class lets Java code call an object's
method, and MiMa does not protect Java clients elsewhere. Changing an object's
method was reported twice, once for the forwarder, and Scala 2 dropping the
forwarder of a method made private[foo] was reported as a break. MiMa now
checks only the object's method.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lrytz
lrytz force-pushed the skip-static-forwarders branch from 4edd562 to a01aec2 Compare September 17, 2026 15:47
@lrytz
lrytz merged commit 7103d11 into scala-garden:main Sep 17, 2026
12 checks passed

@kitbellew kitbellew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minutes too late while I was discussing it with claude. Still, here is the answer we prepared.

Agreed: stop reporting static forwarders and check only the object's method. MiMa should not report what cannot break a Scala caller.

  • A Scala caller never links to a forwarder: A.foo() compiles to A$.MODULE$.foo(). Only Java and Kotlin link to A.foo.
  • MiMa already skips a private[foo] method, which is public in bytecode and callable from Java. The boundary is the Scala API, and the forwarder is not in it.
  • The forwarder has no entry in the pickle, so #986 had to copy the object method's visibility onto it. Skipping it removes that bookkeeping.
  • Every change in forwarder emission has produced reports no Scala caller can hit:
    • #388 (scalac stopped forwarding bridges in 2.12.8 and 2.13.0)
    • scala/scala3#10842 (Scala 3 keeps the forwarder of a private[foo] method)
    • #532 (a class gains a method named like an object method, and the forwarder is dropped).

Caveats to undo:

  • #367 and #532 decided the opposite: a missing forwarder is a break for Java and Kotlin callers.
  • #381 asked to filter static reports without losing them.

- Claude (paraphrasing Albert)

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants