Description
We'd like to introduce a parametric top type (call it Top
for now) with the following properties:
Top
is a supertype ofAny
.Any
is the only class directly inheriting fromTop
.- The only member of
Top
isasInstanceOf
- To check a scrutinee
X
against a patternP
, bothX
andP
must be instances ofAny
.
The question is where Top
would replace Any
in the rest of the language. There are several choices.
Minimal Solution
Top
is just another type. We have to opt in when using it. For instance, we could write
opaque type IArray[+T] <: Top = Array[T]
This would close the hole described in #7314.
This solution is maximally backwards compatible with current Scala. But it has the downside that abstract or opaque types with Top
as upper bound are not very useful. They cannot be passed to any regular unbounded type parameter, since such parameters would have upper bound Any
.
Intermediate Solution
Opaque types have Top
as default upper bound. Type parameters and abstract types stay as they are. This would still be backwards compatible with Scala-2, since opaque types are a new construct. But the problems of usability of opaque types remain.
Maximal Solution
Unbounded abstract types, opaque types, and type parameters have Top
as upper bound, instead of Any
.
This means
- we cannot pattern match on such types anymore
- we cannot use the
==
, equals, hashCode, ortoString
defined inAny
on such types. On the other hand, we could re-introduce these methods as extension methods for these types, which was not possible before.
This is ultimately the most clear and useful solution, but it poses a lot of problems for migration and interoperability.
-
Migration: Lots of code will break. Think of HashMaps, for instance. We could alleviate some of the breakage by adding an implicit conversion from
Top
toAny
which would warn each time it is inserted. Not sure how much this would help. -
Interoperability: How should we interpret a Java or Scala-2 unbounded type parameter? If we assume bounds
Nothing..Any
this would again hamper the usefulness of Scala 3 parametric types. I.e. we could not even doxs.map(f)
ifxs
is of typeList[T]
andT
is unbounded. This looks unacceptable. If we assume boundsNothing..Top
, this means that we accept that the abstraction might be broken in Scala-2 or Java code. This is bad, but better than the alternative. One additional problem is that when reading Scala-2 code we not not even know whether a type parameter is bounded or whether it has explicitly givenNothing..Any
bounds. The two are indistinguishable in the pickle format. So we'd have to widen these bounds unconditionally toNothing..Top
.
Questions
- Is it at all feasible to introduce
Top
? - What is the best solution (or maybe we need a sequence of steps)?
- What is the migration story?
- What timeline is realistic for this?