New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type mismatch calling interface with method override #12892
Comments
In Scala 2, concrete definitions override abstract declarations, even when defined in Java. That changed in Scala 3, so this compiles under dotty. Not sure whether Scala 2 should complain about the types, but possibly it's just a limitation. |
@som-snytt thanks for your response. As background, this limitation disrupts compatibility with the builder mechanism in aws-sdk-java-v2 Since version 2.21.0 released 5 days ago. |
+1 this is a bug report for the Using the following Java interfaces and class, public interface InterfaceA {
InterfaceA anotherMethod();
default InterfaceA defaultedMethod() {
return this;
}
}
public interface InterfaceB extends InterfaceA {
@Override
InterfaceB anotherMethod();
@Override
InterfaceB defaultedMethod();
}
public class InterfaceBImpl implements InterfaceB {
@Override
public InterfaceB anotherMethod() {
return this;
}
@Override
public InterfaceB defaultedMethod() {
return this;
}
public InterfaceB doSomething() {
return this;
}
public static InterfaceBImpl instance() {
return new InterfaceBImpl();
}
} This method compiles and works fine in Java. public static void main(String[] args) {
InterfaceBImpl.instance()
.doSomething()
.anotherMethod()
.defaultedMethod()
.anotherMethod();
} Whereas using Scala: def getInterfaceB(): InterfaceB =
InterfaceBImpl
.instance()
.doSomething()
.anotherMethod()
.defaultedMethod()
.anotherMethod() I get an error similar to
|
Did it change in Scala 3? scala> trait T { def m: T = this }
trai// defined trait T
scala> trait U extends T { override def m: U }
-- [E164] Declaration Error: ---------------------------------------------------
1 |trait U extends T { override def m: U }
| ^
| error overriding method m in trait U of type => U;
| method m in trait T of type => T has incompatible type
| (Note that method m in trait U of type => U is abstract,
| and is therefore overridden by concrete method m in trait T of type => T)
|
| longer explanation available when compiling with `-explain`
1 error found You're right that the test works in Scala 3, so probably it just supports Java better? |
@lrytz no it actually changed in Dotty. |
OK I must be confusing some things.
The 3.4 spec still says
|
We know the spec is a big fat lie! There is an early ticket where Allan Renucci (spelling) notes the discrepancy, and then it was adopted "because that is how Java does it". At some point, I noted that it was not like "sipped", but absorbed by osmosis, but I think it was intended all along to remedy the defect in Scala 2, where it was a limitation. (I understand the limitation is about tracking bounds in overrides or something, but I never went back as I intended to do, to understand exactly what.) (As LeVar Burton says, "Don't take my word for it." I think I'm awake right now?) |
After looking at this a bunch more I find it confusing how things work on Scala 3. Here it tells me
But then it tells me
Anyway.. like @dwijnand I don't see the problem with Scala 2's approach, except for supporting Java (this ticket). Maybe we can change the lookup rules for Java? The override checking should be unaffected: interface A { default A m() { return this; } }
interface B extends A { @Override B m(); }
|
Reproduction steps
Scala version: 2.13.12
Java interfaces:
Problem
Do compile in Java:
Do not compile in Scala:
Result:
Java and Scala implementation should have the same behavior.
The text was updated successfully, but these errors were encountered: