I noticed that, yes. Perhaps this syntax would be more appropriate:
trait MagTrait {
type T <: String
}
type Mag = Mag.T
object Mag extends MagTrait {
opaque type T = String
}
Still, this use case “punches new holes in the typespace” (@kai), as it allows subtyping a final type. It is somewhat equivalent to this:
// illegal obviously
class Mag(s: String) extends String(s)
(though the two use cases differ in that the class
has a runtime presence and can override methods)
We really need to figure out if that use case is desirable, given that final types are explicitly intended not to be subtyped or inherited, and given the desire for classes to be final by default.
Edit:
I’m not sure whether the problem of this use case is with opaques or with the type bounds. How is it legal to express an upper type bound with a final?
final class A
type Sub <: A // what sense does this make?