Singleton bound and type projections don't play nice with each other
See original GitHub issueIf a value tasty
has abstract type T
and T
is marked as being a singleton type (that is, currently, T <: Singleton
), I’d expect tasty.type = T
, because both types are singleton that contain tasty
. This currently fails in Scalac and Dotty (the Scala report is scala/bug#10905 — this is a copy, with Scalac output swapped with Dotty output).
A minimized example:
scala> trait A { type T; val prod: T; val cons: T => Int = _ => 0 }; trait Foo { type U <: Singleton with A; val tasty: U }
// defined trait A
// defined trait Foo
scala> val v: A = new A { type T = Int; val prod: T = 1}; val u: Foo = new Foo { type U = v.type; val tasty: U = v }
val v: A = anon$1@5416f8db
val u: Foo = anon$2@64e1377c
scala> u.tasty.cons(u.tasty.prod: u.U#T)
1 |u.tasty.cons(u.tasty.prod: u.U#T)
| ^^^^^^^^^^^^^^^^^^^
| found: u.U#T
| required: u.tasty.T
|
/cc @milessabin
Background
I ran into this while prototyping a heavily path-dependent API in Dotty (an early version of Tasty reflection), in relation to https://github.com/lampepfl/dotty/pull/4577/files/b315dbfa9f2d206cc26da75779388fca98faaabd#r191016341; the workaround involved turning defs into vals, which I suspect is acceptable here but potentially annoying when trying to save memory.
Alternatives
For the example above, enabling the definition of idempotent methods might be more general, if we ever get there.
Soundness
Not formally investigated, since nobody yet added to DOT either singleton types, type projections or singleton type variables.
Issue Analytics
- State:
- Created 5 years ago
- Comments:12 (11 by maintainers)
Top GitHub Comments
Is there a clear statement of the intended semantics of type projections, in Dotty or in DOT?
My intuitions in Scala were always that
T#U
ought to mean something liket.U forAll { val t: T }
if there were such a thing as aforAll
construct. But the implementation in Scala never aligned with that.https://github.com/scalaz/scalaz-plugin/issues/17 requests a similar feature and points out problems with
null
, since it inhabits singleton types — which it ideally shouldn’t? Iftasty: X
andX <: Singleton
buttasty = null
,tasty.type
isn’tX
. That’s annoying.Since we plan to forbid
x.A
forx = null
if we get null tracking, we could think about (1) making singletons non-nullable (yay!), which would fix the issue; (2) forbiddingx.type
forx
null (not needed for this issue, but seems highly questionable and a way to get back inx.A
forx
null).