OK, I know this has nothing to do with the type system (which is orthogonal to OOP and class/trait extension), but this has caused quite a lot of boilerplate for me in the past, while adding such capability doesn’t appear to take a lot of effort:
(Example):
object NonExtendableTypes {
trait A
trait B
type C = A with B
trait D extends C // doesn't work
trait D extends A with B // works
type E = A { type Sub = Int }
trait F extends E // doesn't work
}
Instead of throwing an error, the compiler can easily create a temporary trait with the desired signature. The same mitigation has already been used for diamond inheritance long time ago, in Scala 2. So why is it hard to implement, given that it is totally consistent with the underlying type system?
which is meaningfully different in appearance from
class C extends A, B
I wonder if Scala 2’s experimental type macros, which never made it to the experimental stage, would have served this purpose? I remember seeing a bit of code along the lines of, “when we have type macros, we won’t know the actual parents yet anyway.”
An example point of confusion for me with aliases is that in Scala 2, they were deemed not to have companions, but in Scala 3, they do serve as “anchors”, so their companions are searched for implicits.
(Implicit search sounds like some sort of police action.)
That sounds tempting but no the compiler doesn’t work that way:
object TypeCompanionScope {
trait A
trait B
type C = A & B
object C {
implicit def empty[T <: C]: Seq[T] = Seq[T]()
}
class D extends A, B
summon[Seq[D]]
}
: No given instance of type Seq[com.tribbloids.spike.dotty.conjecture.TypeCompanionScope.D] was found for parameter x of method summon in object Predef
It has to be an opaque alias. (Sorry, it’s been a couple of years. I remember learning the “anchor” terminology at the reference docs.)
trait F[A]
object X:
opaque type T = Int
object T:
given F[T] = new F[T] { override def toString = "You found me!" }
@main def test() = println(summon[F[X.T]])
There was a ticket for Scala 2 that even got a Typelevel endorsement, but that was after the days of The Great Forking.
This is an example, for me, of something that seems reasonable to me but may be patently unsound to someone who has considered it in sufficient depth or abstraction.