Skip to content
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

Self type without type ascription introduces type requirements #16407

Closed
robmwalsh opened this issue Nov 24, 2022 · 5 comments · Fixed by #16648
Closed

Self type without type ascription introduces type requirements #16407

robmwalsh opened this issue Nov 24, 2022 · 5 comments · Fixed by #16648

Comments

@robmwalsh
Copy link

Compiler version

3.2.0

Minimized code

trait X { //missing requirement: self type Z[?] & X of trait X does not conform to self type Z[X.this.A] of required trait Z
  self: Z[?] => 
}

trait Z[A] extends X {
  self => // comment this to compile successfully
}

Output

compiler error:
missing requirement: self type Z[?] & X of trait X does not conform to self type Z[X.this.A]
of required trait Z

Expectation

The code should compile. Having a self type without a type ascription (i.e. just aliasing this) should not introduce any additional type requirements

Related comment from Aly https://discord.com/channels/632150470000902164/632150470000902166/1045191632049405992

@robmwalsh robmwalsh added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 24, 2022
@szymon-rd szymon-rd added area:typer and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 24, 2022
@szymon-rd
Copy link
Contributor

Thank you for reporting and reproduction!

@Kordyjan
Copy link
Contributor

Kordyjan commented Dec 7, 2022

I thought it may have been fixed in #16441, but the bug is still reproducible in 3.3.0-RC1-bin-20221206-cfcdefa-NIGHTLY.

@prolativ
Copy link
Contributor

prolativ commented Dec 7, 2022

It looks like extends X is not necessary to reproduce the problem:

trait X { //missing requirement: self type Z[?] & X of trait X does not conform to self type Z[X.this.A] of required trait Z
  self: Z[?] =>
}

trait Z[A] {
  self => // comment this to compile successfully
}

gives the same error message

@odersky
Copy link
Contributor

odersky commented Jan 10, 2023

Scala 3 requires that self types are "closed". See #702 that introduced this requirement. Closed means:
If class Z appears in the self type of some trait X then the self type of X must conform to the self type of Z. This example violates the condition. Z appears in the self type of X, but Z[?] does not conform to Z[A].

Going back to 2015, it seems the requirement was introduced to avoid a crash and to get some sanity about self type checking. I don't know whether lifting the requirement would constitute a soundness hold or not. But I believe it's better to be conservative.

Self type checking is only done if a self is declared explicitly. Here a simple name counts, it does not matter whether its type is inferred or not. I looked into it but it seems to be really hard to change this (and Scala 2 behaves the same, it's just that Scala 2 does not have the closedness requirement).

So the one remaining hole is: if closedness checking is really important, we should check classes with missing self types as well. If it is not important we should drop it.

odersky added a commit that referenced this issue Jan 12, 2023
#702 introduced a requirement that self types are closed. This means

> If trait X has self type S and C is a class symbol of S, then S also
conforms
to the self type of C.

An example that violates this requirement is
```scala
trait X { self: Y => } // error: missing requirement: self type Y & X of trait X does not conform to self type Z of required trait Y
trait Y { self: Z => }
trait Z
```
But it's no longer clear what the requirement should achieve. If we let
the example above typecheck and try to implement X with something like
```scala
class C extends X, Y
```
we would at that point get an error saying that `C` does not conform to
the self type Z of Y. So it would have to be
```scala
class C extends X, Y, Z
```
and this one looks fine.

The original change in #702 was made to avoid a crash in
pending/run/t7933.scala. Unfortunately, we cannot reproduce this anymore
since it depends on nsc.interpreter, which is no longer part of Scala
2.13.

Since we are no longer sure what the restriction should achieve I think
it's better to drop it for now. If people discover problems with code
that uses "open" self types, we can try to fix those problems, and if
that does not work, would fallback re-instituting the restriction. It's
not ideal, but I don't see another way.

Fixes #16407
@robmwalsh
Copy link
Author

Thanks for the explanation and the fix!

@Kordyjan Kordyjan added this to the 3.3.0 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants