Skip to content

Overridden member type does not conform to type projection on supertype #8338

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
Jasper-M opened this issue Feb 18, 2020 · 3 comments · Fixed by #15959
Closed

Overridden member type does not conform to type projection on supertype #8338

Jasper-M opened this issue Feb 18, 2020 · 3 comments · Fixed by #15959
Milestone

Comments

@Jasper-M
Copy link
Contributor

Jasper-M commented Feb 18, 2020

minimized code

object test {
  trait B { type X; def mkX(i: Int): B#X }
  val b: B = new B { type X = Int; def mkX(i: Int): X = i }
}

Compilation output

-- Error: test.scala:3:39 ------------------------------------------------------
3 |  val b: B = new B { type X = Int; def mkX(i: Int): X = i }
  |                                       ^
  |        error overriding method mkX in trait B of type (i: Int): test.B#X;
  |          method mkX of type (i: Int): X has incompatible type
1 error found

expectation

Should compile. Note that this already compiles:

trait B { type X; def mkX(i: Int): X }
val b: B = new B { type X = Int; def mkX(i: Int): X = i }
implicitly[b.X <:< B#X]

From the outside X is a subtype of B#X but inside new B { } not.

Related issue: #538

@odersky
Copy link
Contributor

odersky commented Mar 1, 2020

B#X in the first line means: "some unknown X in some unknown B". The X on the second line is an alias for Int. There is no ground for reasoning that "some unknown X in some unknown B" is a supertype of Int. I believe Scala-2's subtype checker uses faulty reasoning here.

@odersky odersky closed this as completed Mar 1, 2020
@Jasper-M
Copy link
Contributor Author

Jasper-M commented Jun 22, 2020

@odersky The reasoning is that

  1. "some unknown X in some unknown B" is a supertype of "X in this specific B", and
  2. "X in this specific B" happens to be equal to Int.

Anyway regardless of Int which complicates things, take this example:

scala> object test {                                                            
     |   trait B { type X; def mkX(i: Int): B#X }
     |   val b: B = new B { def mkX(i: Int): X = ??? }    // X(original) <:< B#X
     | }
// defined object test                                                                         

scala> object test {                                                            
     |   trait B { type X; def mkX(i: Int): B#X }
     |   val b: B = new B { override type X; def mkX(i: Int): X = ??? }    // Not[X(override) <:< B#X]
     | }
3 |  val b: B = new B { override type X; def mkX(i: Int): X = ??? }
  |                                          ^
  |        error overriding method mkX in trait B of type (i: Int): test.B#X;
  |          method mkX of type (i: Int): X has incompatible type

scala> object test {                                                            
     |   trait B { type X; def mkX(i: Int): X }
     |   val b: B = new B { override type X; def mkX(i: Int): X = ??? }    // X(override) <:< X(original)
     | }
// defined object test

Why does override type X change anything about the subtype relationship between X and B#X? If the X in new B { ... } is now a different X than in trait B, does that mean I am actually shadowing X instead of overriding it? If I am shadowing X then why does the 3rd snippet compile?

It looks like X(override) <:< X(original) and X(original) <:< B#X, but Not[X(override) <:< B#X].

@odersky
Copy link
Contributor

odersky commented Sep 4, 2022

@Jasper-M Your reasoning was right; it took me a while to realize that.

odersky added a commit that referenced this issue Sep 12, 2022
Fixes #15931

This also fixes #8338, which was mis-classified as a neg test before.
@Kordyjan Kordyjan added this to the 3.2.2 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.

3 participants