Java unrecognized trait mixin method override
See original GitHub issueCompiler version: 3.0.1
Problem
Java cannot extend or implement an abstract class which has an abstract method overridden by a mixin trait.
trait A {
def foo: Int
}
trait B { self: A =>
override final def foo: Int = 1
}
abstract class JavaAWithB extends A with B
class Foo extends JavaAWithB { } // Foo must be abstract since it doesn't define `foo`
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
scala - Trait mixin with conflicting members: Why my code can ...
Since TA.play and TB.play are declared with override , it's clear that they intend to override the method play(): Unit that is in...
Read more >Compilation error when subclassing a class with methods ...
A mixin forwarder added to a class can fall into three categories: The forwarder is required to get the correct runtime semantics (e.g....
Read more >Simulating mixins in Kotlin - LinkedIn
The main inspiration for me to write this article is an approach to modeling common parts of Actions in Android applications - I...
Read more >A few notes about using Scala traits as mixins (construction ...
The order in which overridden trait methods are called when multiple traits are mixed in. Lesson: When multiple traits are mixed into a...
Read more >Documentation - Mixins - TypeScript
The pattern relies on using generics with class inheritance to extend a base class. TypeScript's best mixin support is done via the class...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
In fact, we do emit
foo
as non-final inB
(default methods cannot be final), and we also emit an override offoo
inJavaAWithB
even though it’s not required at runtime (for performance reasons: https://github.com/lampepfl/dotty/commit/6c6443086071774431dae93709b4102ce3c4d15e), but unlike Scala 2 we emit this override with theACC_SYNTHETIC
flag to hide it from Java, this is done because it avoids/fixes a lot of issues with Java generic signatures (cf https://github.com/lampepfl/dotty/commit/6d0f9ca3ae4c7130c1ee18e0e21f283ff6cb21f3) but it does indeed mean that when Java consumes a Scala class, it can incorrectly conclude that an override is missing.In fact, I first implemented this scheme in Scala 2 where it ended up being reverted because of this issue, I suggested a possible way forward at the time at https://github.com/scala/bug/issues/11512#issuecomment-489424170 but haven’t followed up since then, and I likely won’t have the time to do so anytime soon (but maybe @lrytz would be interested? 😃).
Note that while reverting https://github.com/lampepfl/dotty/commit/6d0f9ca3ae4c7130c1ee18e0e21f283ff6cb21f3 would fix this issue, it would also break a bunch of the tests in that commit, to keep these tests working some careful work on generic signature generation will be necessary.
Scala 2 does, yes: https://github.com/scala/scala/blob/0c011547b1ccf961ca427c3d3459955e618e93d5/src/compiler/scala/tools/nsc/transform/Mixin.scala#L176-L204 and the issues with that are recorded in https://github.com/scala/bug/issues/8905 and all the tests that had to be changed/removed in https://github.com/scala/scala/pull/8037.
Scala 3 doesn’t since the forwarders are always ACC_SYNTHETIC, and in https://github.com/scala/bug/issues/11512#issuecomment-489424170 I suggested we only make the forwarders that are required to please javac non-synthetic, that way even if our generic signatures are sometimes lacking, less code would be affected.