Skip to content

Intersection types are not commutative for overriding and overloading #5139

Closed
@panacekcz

Description

@panacekcz

Although A & B and B & A are claimed to be the same type, the are not the same for overriding and overloading.
It seems to be "caused" by erasue, which erases A & B to A and B & A to B.

Overriding

trait A
trait B

class Base{
  def m(ab: A&B) = ab
}
class Derived extends Base{
  override def m(ab: B&A) = ab // unexpected error
}

Output:

8 |  override def m(ab: B&A) = ab // unexpected error
  |               ^
  |       error overriding method m in class Base of type (ab: A & B): A & B;
  |         method m of type (ab: B & A): A & B has incompatible type

On the other hand, if the override is omitted, an error is correctly issued.

class Derived2 extends Base{
  def m(ab: B&A)=ab // OK - "needs override" error when expected
}

Also, when the first type in the intersection is the same (therefore erased type is the same), overriding works as expected:

trait C
class Base3{
  def m(abc: A&B&C) = abc
}
class Derived3 extends Base3{
  override def m(abc: A&C&B) = abc // OK - no error
}

Overloading

Similarly, overloading is allowed when the first type differs.

class Overload{
  def m(ab: A&B) = ab
  def m(ab: B&A) = ab // No error when expected
}

On the other hand, such methods cannot be called, as expected:

object Caller{
  Overload.m(new A with B) // OK - "ambiguous overload" error when expected
}

That seems to be the same behavior as with scalac.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions