Description
Compiler version
3.3.1
Minimized code (scala-cli scipts)
I'd like to have a type that expresses any Outer
's Foo.Data
. Two logical approaches fail.
//> using scala 3.3.1
class Outer:
object Foo:
case class Data(s : String)
case class Foo( count : Int )
// type AnyData = Outer#Foo.Data
//
// if uncommented...
// [error] ./cant-traverse-type.scala:8:25
// [error] end of toplevel definition expected but '.' found
// [error] type AnyData = Outer#Foo.Data
// type AnyData = Outer#Foo.type#Data
//
// if uncommented
// [error] ./cant-traverse-type.scala:15:25
// [error] end of toplevel definition expected but '.' found
// [error] type AnyData = Outer#Foo.type#Data
I thought that the issue might only be a parser issue with .
in the type projection paths, so tried a "bridge" workaround. The type alias declaration succeeds! Unfortunately, the compiler is unable to prove that the expected projections conform.
//> using scala 3.3.1
//> using option -explain
class Outer:
object Foo:
case class Data(s: String)
case class Foo(count: Int)
type FooData = Foo.Data
type AnyData = Outer#FooData // yay! compiles!
val o = new Outer
val ofd = new o.Foo.Data("Hello!")
// val ad : AnyData = ofd
//
// if uncommented
// [error] ./cant-traverse-bridge.scala:15:20
// [error] Found: (ofd : o.Foo.Data)
// [error] Required: AnyData
// [error]
// [error] Explanation
// [error] ===========
// [error]
// [error] Tree: ofd
// [error] I tried to show that
// [error] (ofd : o.Foo.Data)
// [error] conforms to
// [error] AnyData
// [error] but the comparison trace ended with `false`:
// [error]
// [error] ==> (ofd : o.Foo.Data) <: AnyData
// [error] ==> (ofd : o.Foo.Data) <: Outer#FooData
// [error] ==> o.Foo.Data <: Outer#FooData (left is approximated)
// [error] <== o.Foo.Data <: Outer#FooData (left is approximated) = false
// [error] <== (ofd : o.Foo.Data) <: Outer#FooData = false
// [error] <== (ofd : o.Foo.Data) <: AnyData = false
// [error]
// [error] The tests were made under the empty constraint
// [error] val ad : AnyData = ofd
// [error] ^^^
val ad : AnyData = ofd.asInstanceOf[AnyData] // compiles, but only with explicit cast
@main
def spew = println( ad.s ) // prints without error
Expectation
I expect that I'd be able to write a projection type that would abstract over the dependent singleton type Foo
. (In real life, I just want to write some functions accepting nested dependent classes and generate reports that would not depend on the identity of the enclosing instance.)
As shown, with the type-alias bridge, I can successfully cast to a projection type and work without. But the compiler can't recognize the conformity of the type without the cast.
Thanks!
Thanks to Alexandru Nedelcu, Aly, and SlowBrain on the Scala discord for helping me work through this.