Skip to content

Intersection type with refined type member as upper bound does not compile #4623

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
pweisenburger opened this issue Jun 5, 2018 · 5 comments

Comments

@pweisenburger
Copy link
Contributor

The following code compiles using Scala:

trait Test {
  type A <: Any { type T }
  type B <: Any { type T }
  type C <: A with B { type T }
}

Dotty produces the following compiler error:

4 |  type C <: A with B { type T }
  |            ^
  |            class Any is extended twice

Notably, the following code compiles:

trait Test {
  type A <: Any
  type B <: Any
  type C <: A with B
}
@smarter
Copy link
Member

smarter commented Jun 5, 2018

More succinctly, the issue is that we cannot type:

Any with Any { type T }

(or any other refinement that looks like X with X { ... })
Because typedRefinedTypeTree will type the following synthetic trait (using desugar.refinedTypeToClass):

trait <refinement> extends Any with Any { type T }

and we do not allow the same class to appear twice in the extends clause. I don't think we can relax this restriction for the synthetic <refinement> traits, since that probably breaks assumptions somewhere else. Instead it might be possible to normalize the extends clause we generate to not contain the same class twice (but event that is not trivial if we want List[Any] with List[String] { type T } to compile).

@pweisenburger
Copy link
Contributor Author

Okay, I see the problem. However, since you can easily construct concrete types for the abstract type members, I think you would assume that the code compiles.

and we do not allow the same class to appear twice in the extends clause

Is it important to disallow multiple appearances of the same type? This means the following does not compile:

trait L[+T]
trait T extends L[Any] with L[String]

But this does:

trait L[+T]
trait A extends L[Any]
trait B extends L[String]
trait T extends A with B

Naively, both variants look similar. For both, L appears twice in the set of base types. Would it make sense to define linearization in a way that L appears only once in the linearization of trait T extends L[Any] with L[String] to solve those kinds of issues? I guess that's what's happening for trait T extends A with B.

it might be possible to normalize the extends clause we generate to not contain the same class twice

Isn't the logic that is already implemented to compute the linearization basically what is required here; or do I see that wrong?

@smarter
Copy link
Member

smarter commented Jun 5, 2018

Right, so maybe we can indeed lift this restriction just for typing refinements and nothing bad will happen. (It could also be lifted in general but there's no reason for a user to write trait T extends L[Any] with L[String], it's more likely to be a mistake).

@pweisenburger
Copy link
Contributor Author

Thanks, sounds good :-)

It could also be lifted in general but there's no reason for a user to write trait T extends L[Any] with L[String], it's more likely to be a mistake

That's true, I agree.

@Blaisorblade
Copy link
Contributor

Instead it might be possible to normalize the extends clause we generate to not contain the same class twice (but event that is not trivial if we want List[Any] with List[String] { type T } to compile).

(It could also be lifted in general but there's no reason for a user to write trait T extends L[Any] with L[String], it's more likely to be a mistake).

Or it could arise through type aliases that arise elsewhere and are hard to modify. I'm fine with forbidding direct appearances, though that could also be just a warning.

(I thought #4557 was related, but on a closer look it's probably not).

odersky added a commit that referenced this issue Jun 10, 2018
Fix #4623: Don't check for repeated parents in refinement classes
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

3 participants