Why do these type arguments not conform to a type refinement?
Asked Answered
M

3

3

Why does this Scala code fail to typecheck?

trait T { type A }
trait GenFoo[A0, S <: T { type A = A0 }]
trait Foo[S <: T] extends GenFoo[S#A, S]

I don't understand why "type arguments [S#A,S] do not conform to trait GenFoo's type parameter bounds [A0,S <: T{type A = A0}]". Is there a work-around?

Edit: As has been pointed out, the conformance error stems from the failure to verify S <: T{type A = S#A}. Daniel Sobral pointed to -explaintypes, which tells us:

S <: T{type A = S#A}?
  S <: T?
  true
  S specializes type A?
    this.A = this.A?
      S = this.type?
      false
    false
  false
false

I'm not sure how to interpret this.

Note that we get an illegal cyclic reference if we try to define,

trait Foo[S <: T { type A = S#A } ] extends GenFoo[S#A, S]

although the type refinement here doesn't seem to add any new information. (See also Why is this cyclic reference with a type projection illegal?)

My motivation is to create a trait Foo[S <: T] that specializes on S#A, as in: How to specialize on a type projection in Scala? To get this to work, I'm trying to surface S#A as an explicit parameter A0 in the implementation trait GenFoo, which can be specialized directly. I was hoping to apply the type refinement idea from Miles Sabin's answer to Why is this cyclic reference with a type projection illegal? but I run into this conformance error.

Macias answered 22/7, 2011 at 20:17 Comment(2)
Have you tried -explaintypes?Colatitude
Thanks for the pointer. I updated the question to include the output from -explaintypes.Macias
C
1

This seems to be the answer:

S specializes type A?

The question about specialize comes from here: T { type A = A0 }. This is the type T with type A specialized -- meaning, it is more restricted than the original T.

The answer to that question is no -- there's no constrains on S that it be specialized.

Colatitude answered 25/7, 2011 at 2:50 Comment(1)
The surprise to me is that there's a difference between S <: T and S <: T { type A = S#A }. Although the latter is specialized, it seems that this specialization adds no additional constraint on S. (Maybe a hint is that the latter yields an illegal cyclic reference error if one tries to use it directly.) Perhaps I am misunderstanding the meaning of the types, but it seems that this a practical, rather than fundamental, limitation in the Scala type system?Macias
A
1

I'm not an expert on this topic, I just played around with your code and found out that the problem is not the S#A part, but the S part.

If you write the code like this:

trait T { type A }
trait GenFoo[A0, S <: T] // the { type A = A0 } part is not there anymore
trait Foo[S <: T] extends GenFoo[S#A, S]

then it compiles, because S in Foo[S <: T] conforms to the S in GenFoo[A0, S <: T].

In your example the compiler knows that S is a subtype of T and therefore has the type A defined, but it does not come to the point, where it can verify that the A in S is the S#A.

Alverson answered 22/7, 2011 at 20:17 Comment(0)
D
1

In order to conform to the type constraints, S would have to be a subtype of T { type A = A0 }, but it is only a subtype of T.

Drue answered 22/7, 2011 at 20:41 Comment(1)
But in this case A0 = S#A, so I would expect S <: T { type A = S#A }Macias
C
1

This seems to be the answer:

S specializes type A?

The question about specialize comes from here: T { type A = A0 }. This is the type T with type A specialized -- meaning, it is more restricted than the original T.

The answer to that question is no -- there's no constrains on S that it be specialized.

Colatitude answered 25/7, 2011 at 2:50 Comment(1)
The surprise to me is that there's a difference between S <: T and S <: T { type A = S#A }. Although the latter is specialized, it seems that this specialization adds no additional constraint on S. (Maybe a hint is that the latter yields an illegal cyclic reference error if one tries to use it directly.) Perhaps I am misunderstanding the meaning of the types, but it seems that this a practical, rather than fundamental, limitation in the Scala type system?Macias

© 2022 - 2024 — McMap. All rights reserved.