In some situations, Scala used a weak conformance relation when
testing type compatibility or computing the least upper bound of a set
of types. The principal motivation behind weak conformance was to
make an expression like this have type
List(1.0, math.sqrt(3.0), 0, -3.3) // : List[Double]
It's "obvious" that this should be a
List[Double]. However, without
some special provision, the least upper bound of the lists's element
(Double, Double, Int, Double) would be
AnyVal, hence the list
expression would be given type
A less obvious example is the following one, which was also typed as a
List[Double], using the weak conformance relation.
val n: Int = 3 val c: Char = 'X' val d: Double = math.sqrt(3.0) List(n, c, d) // used to be: List[Double], now: List[AnyVal]
Here, it is less clear why the type should be widened to
List[AnyVal] seems to be an equally valid -- and
more principled -- choice.
Weak conformance applies to all "numeric" types (including
independently of whether the expressions are literals or not. However,
in hindsight, the only intended use case is for integer literals to
be adapted to the type of the other expressions. Other types of numerics
have an explicit type annotation embedded in their syntax (
Chars) which ensures that their author really
meant them to have that specific type).
Therefore, Dotty drops the general notion of weak conformance, and
instead keeps one rule:
Int literals are adapted to other numeric
types if necessary.