Skip to content

Method in trait not a legal implementation in inheriting class #4819

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

Closed
allanrenucci opened this issue Jul 20, 2018 · 9 comments
Closed

Method in trait not a legal implementation in inheriting class #4819

allanrenucci opened this issue Jul 20, 2018 · 9 comments

Comments

@allanrenucci
Copy link
Contributor

allanrenucci commented Jul 20, 2018

trait Iterable[+A]

trait IterableOps[+A, +CC[_], +C] {
  def concat[B >: A](suffix: Iterable[B]): CC[B] = ???
}

trait SetOps[A, +CC[X], +C <: SetOps[A, CC, C]]  {
  def concat(that: Iterable[A]): C = ???
}

class ChampHashSet[A] extends SetOps[A, ChampHashSet, ChampHashSet[A]] with
    IterableOps[A, ChampHashSet, ChampHashSet[A]]
-- Error: tests/allan/Test.scala:15:6 ------------------------------------------
15 |class ChampHashSet[A] extends SetOps[A, ChampHashSet, ChampHashSet[A]] with
   |      ^
   |method concat in trait IterableOps is not a legal implementation of `concat' in class ChampHashSet
   |  its type             [B >: A](suffix: Iterable[B]): ChampHashSet[B]
   |  does not conform to  (that: Iterable[A]): ChampHashSet[A]
one error found
@Blaisorblade

This comment has been minimized.

@smarter

This comment has been minimized.

@smarter
Copy link
Member

smarter commented Jul 20, 2018

trait IterableOps[+A, +CC[_], +C] {
  def concat[B >: A](suffix: Iterable[B]): CC[B] = ???
}

ends up with a concat method whose erased type is:

def concat(suffix: Iterable): Object

whereas with:

trait SetOps[A, +CC[X], +C <: SetOps[A, CC, C]]  {
  def concat(that: Iterable[A]): C = ???
}

the erasure of concat is:

def concat(that: Iterable): SetOps

So in ChampHashSet we should be able to inherit from both of them and get two overloads for concat. This is what happens in scalac but in Dotty this is prevented by RefChecks for some reason.

@Blaisorblade
Copy link
Contributor

Sorry I was too quick and hopeful and misunderstood this completely...

@allanrenucci
Copy link
Contributor Author

allanrenucci commented Jul 20, 2018

cc/ @julienrf Is is intended to be an overload in the standard library?

Dotty was happy before scala/scala#6909 scala/scala#6776

@smarter
Copy link
Member

smarter commented Jul 20, 2018

Here's a minimization:

trait One[X]  {
  def concat(suffix: Int): X = ???
}

trait Two[Y <: Foo] {
  def concat[Dummy](suffix: Int): Y = ???
}

class Foo extends One[Foo] with Two[Foo]

Any attempt at simplifying this further (avoiding f-bounded polymorphism, removing the parameter lists from the methods, ...) compiles properly, so there's probably a subtle bug somewhere.

@julienrf
Copy link
Contributor

@allanrenucci Yes, since Set is invariant its natural concat signature is without the B >: A type parameter.

@smarter
Copy link
Member

smarter commented Jul 21, 2018

The problem is in Denotation#&, when we try to merge the denotations of sym1 = Two#concat and sym2 = One#concat:
https://github.com/lampepfl/dotty/blob/89ab4990863da45d0862f0c69cb1d31235c4e1ac/compiler/src/dotty/tools/dotc/core/Denotations.scala#L528-L532
This calls infoMeet which will return the info of sym2 because it prefers MethodTypes over PolyTypes:
https://github.com/lampepfl/dotty/blob/89ab4990863da45d0862f0c69cb1d31235c4e1ac/compiler/src/dotty/tools/dotc/core/Denotations.scala#L394-L402
We then construct a JointRefDenotation using this info:
https://github.com/lampepfl/dotty/blob/89ab4990863da45d0862f0c69cb1d31235c4e1ac/compiler/src/dotty/tools/dotc/core/Denotations.scala#L545
But note that at this point, sym is the symbol of Two#concat (whose type is a PolyType) and jointInfo is the info of One#concat (whose type is a MethodType) so we're creating a very weird denotation. This then fails in RefChecks.

@odersky Does it really ever makes sense to merge a denotation with a MethodType and a denotation with a PolyType? Why not always return a MultiDenotation in these cases?

@allanrenucci allanrenucci assigned smarter and unassigned odersky Jul 23, 2018
@allanrenucci allanrenucci added this to the 0.10 Tech Preview milestone Jul 23, 2018
smarter added a commit to dotty-staging/dotty that referenced this issue Jul 23, 2018
When merging a denotation with a PolyType and a denotation with a
MethodType, `infoMeet` will return the MethodType info, but the symbol
that is then used to create the `JointRefDenotation` can come from
either denotation, if it comes from the PolyType one, the resulting
denotation is inconsistent, this resulted in RefChecks errors.

We fix this by simply returning either of the denotation when `infoMeet`
returning either of their info. This is only a workaround and not a
proper fix for scala#4819 as it doesn't allow tests/neg/i4819.scala to
compile, see the comments in the file.
smarter added a commit to dotty-staging/dotty that referenced this issue Jul 23, 2018
When merging a denotation with a PolyType and a denotation with a
MethodType, `infoMeet` will return the MethodType info, but the symbol
that is then used to create the `JointRefDenotation` can come from
either denotation, if it comes from the PolyType one, the resulting
denotation is inconsistent, this resulted in RefChecks errors.

We fix this by making `preferSym` consistent with `infoMeet`. This is
only a workaround and not a proper fix for scala#4819 as it doesn't allow
tests/neg/i4819.scala to compile, see the comments in the file.
smarter added a commit that referenced this issue Jul 25, 2018
Workaround #4819: Avoid creating incorrect JointRefDenotations
@smarter smarter removed this from the 0.10 Tech Preview milestone Jul 25, 2018
@smarter
Copy link
Member

smarter commented Jul 25, 2018

Original problem fixed by #4829, follow-up in #4840

@smarter smarter closed this as completed Jul 25, 2018
smarter added a commit to dotty-staging/dotty that referenced this issue Jan 4, 2019
…ations"

This partially reverts 4e695fb which is
no longer needed after this PR (we no longer try to merge in a single
denotation a PolyType and a MethodType).
smarter added a commit to dotty-staging/dotty that referenced this issue Jan 4, 2019
…ations"

This partially reverts 4e695fb which is
no longer needed after this PR (scala#5622), because we no longer try to
merge in a single denotation a PolyType and a MethodType.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants