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

a path dependent type does not conform to its projection type #17064

Closed
ftucky opened this issue Mar 7, 2023 · 3 comments · Fixed by #17092
Closed

a path dependent type does not conform to its projection type #17064

ftucky opened this issue Mar 7, 2023 · 3 comments · Fixed by #17092
Assignees
Milestone

Comments

@ftucky
Copy link

ftucky commented Mar 7, 2023

Compiler version

3.2.2 , 3.3.0-RC3

Minimized code

class HiddenInner[+O<:Outer](val outer:O){
}

class Outer{
  type Inner = HiddenInner[this.type]
}

val o : Outer       = new Outer 
val a : o.Inner     = new o.Inner(o)
val b : Outer#Inner = a // DOES NOT COMPILE

Output

Found:    (a : o.Inner)
Required: Outer#Inner

Expectation

Code should compile: o.Inner conforms to Outer#Inner.
Note Outer is a class, so Outer#Inner is legal (sound) in scala3.

Compiles in scala 2.13.

Intention

The intention is to make Inner behave almost as inner class of Outer.

@ftucky ftucky added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Mar 7, 2023
@nicolasstucki nicolasstucki added area:typer and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Mar 8, 2023
@smarter
Copy link
Member

smarter commented Mar 11, 2023

This can be minimized to:

class Outer {
  type This = this.type
  val x: Outer#This = this // error
}

What's happening here is that type This = this.type is equivalent to type This >: this.type <: this.type, and when seen from outside the class scope, this type is approximated to the abstract type type This >: Nothing <: Outer which we conservatively assume has no subtypes but Nothing.

There is a discussion up at lampepfl/dotty-feature-requests#14 about relaxing the subtype checking for type projections which would fix this. The relaxed rule has been proved sound, but it still needs a SIP and some careful consideration of possible interactions with other features.

@smarter
Copy link
Member

smarter commented Mar 11, 2023

Note that we don't need the full power of lampepfl/dotty-feature-requests#14 for the original example in this issue, but the more limited rule mentioned in lampepfl/dotty-feature-requests#14 (comment):

Γ ⊨ p : T
------------------------ (Sel-<:-Proj)
Γ ⊨ p.A <: T#A

which should be even less controversial.

odersky added a commit to dotty-staging/dotty that referenced this issue Mar 12, 2023
We already implemented in essence the rule suggested in lampepfl/dotty-feature-requests#14:

```
Γ ⊨ p : T
------------------------ (Sel-<:-Proj)
Γ ⊨ p.A <: T#A
```

This rule is implemented in `isSubPrefix`. But we did not get to check that since we concluded prematurely that
an alias type would never match. The alias type in question in i17064.scala was

```scala
Outer#Inner
```
Since `Outer` is not a path, the asSeenFrom to recover the info of `Outer#Inner this got approximated with
a `Nothing` argument and therefore the alias failed. It is important in this case that we could still succeed
with a `isSubPrefix` test, which comes later. So we should not return `false` when the prefix is not a singleton.

Fixes scala#17064
odersky added a commit that referenced this issue Mar 25, 2023
We already implemented in essence the rule suggested in
lampepfl/dotty-feature-requests#14:

```
Γ ⊨ p : T
------------------------ (Sel-<:-Proj)
Γ ⊨ p.A <: T#A
```

This rule is implemented in `isSubPrefix`. But we did not get to check
that since we concluded prematurely that an alias type would never
match. The alias type in question in i17064.scala was

```scala
Outer#Inner
```
Since `Outer` is not a path, the asSeenFrom to recover the info of
`Outer#Inner` got approximated with a `Nothing` argument and therefore
the alias failed. It is important in this case that we could still
succeed with a `isSubPrefix` test, which comes later. So we should not
return `false` when the prefix is not a singleton.

Fixes #17064
@Misshigh77

This comment was marked as off-topic.

Dedelweiss pushed a commit to Dedelweiss/dotty that referenced this issue Apr 17, 2023
We already implemented in essence the rule suggested in lampepfl/dotty-feature-requests#14:

```
Γ ⊨ p : T
------------------------ (Sel-<:-Proj)
Γ ⊨ p.A <: T#A
```

This rule is implemented in `isSubPrefix`. But we did not get to check that since we concluded prematurely that
an alias type would never match. The alias type in question in i17064.scala was

```scala
Outer#Inner
```
Since `Outer` is not a path, the asSeenFrom to recover the info of `Outer#Inner this got approximated with
a `Nothing` argument and therefore the alias failed. It is important in this case that we could still succeed
with a `isSubPrefix` test, which comes later. So we should not return `false` when the prefix is not a singleton.

Fixes scala#17064
@Kordyjan Kordyjan added this to the 3.3.1 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.

6 participants