Skip to content

Commit cd3cfce

Browse files
authored
Merge pull request #5358 from dotty-staging/new-spec-for-weak-conformance
New specification for dropped weak conformance.
2 parents 77dc93e + ca413d3 commit cd3cfce

File tree

2 files changed

+59
-59
lines changed

2 files changed

+59
-59
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
layout: doc-page
3+
title: Dropped: Weak Conformance - More Details
4+
---
5+
6+
To simplify the underlying type theory, Dotty drops the notion of weak
7+
conformance altogether. Instead, it provides more flexibility when
8+
assigning a type to a constant expression. The new rule is:
9+
10+
- If a list of expressions `Es` appears as one of
11+
12+
- the elements of a vararg parameter, or
13+
- the alternatives of an if-then-else or match expression, or
14+
- the body and catch results of a try expression,
15+
16+
17+
and all expressions have primitive numeric types, but they do not
18+
all have the same type, then the following is attempted:
19+
20+
- the expressions `Es` are partitioned into `Int` literals on the
21+
one hand, and all other expressions on the other hand
22+
- if all the other expressions have the same numeric type `T`
23+
(which can be one of `Byte`, `Short`, `Int`, `Long`, `Float`,
24+
`Double`), possibly after widening, and if none of the `Int`
25+
literals would incur a loss of precision when converted to `T`,
26+
then they are thus converted (the other expressions are left
27+
unchanged regardless)
28+
- otherwise, the expressions `Es` are used unchanged
29+
30+
A loss of precision occurs for an `Int -> Float` conversion of a constant
31+
`c` if `c.toFloat.toInt != c`. For an `Int -> Byte` conversion it occurs
32+
if `c.toByte.toInt != c`. For an `Int -> Short` conversion, it occurs
33+
if `c.toShort.toInt != c`.
34+
35+
__Examples:__
36+
37+
inline val b = 33
38+
def f(): Int = b + 1
39+
List(b, 33, 5.5) : List[Double] // b is an inline val
40+
List(f(), 33, 5.5) : List[AnyVal] // f() is not a constant
41+
List(5, 11L) : List[Long]
42+
List(5, 11L, 5.5) : List[AnyVal] // Long and Double found
43+
List(1.0f, 2) : List[Float]
44+
List(1.0f, 1234567890): List[AnyVal] // loss of precision
45+
List(b, 33, 'a') : List[AnyVal] // Char is not a numeric
46+
List(5.toByte, 11) : List[Byte]

docs/docs/reference/dropped/weak-conformance.md

+13-59
Original file line numberDiff line numberDiff line change
@@ -27,62 +27,16 @@ Here, it is less clear why the type should be widened to
2727
`List[Double]`, a `List[AnyVal]` seems to be an equally valid -- and
2828
more principled -- choice.
2929

30-
To simplify the underlying type theory, Dotty drops the notion of weak
31-
conformance altogether. Instead, it provides more flexibility when
32-
assigning a type to a constant expression. The new rule is:
33-
34-
- If a list of expressions `Es` appears as one of
35-
36-
- the elements of a vararg parameter, or
37-
- the alternatives of an if-then-else or match expression, or
38-
- the body and catch results of a try expression,
39-
40-
41-
and all expressions have primitive numeric types, but they do not
42-
all have the same type, then the following is attempted: Every
43-
constant expression `E` in `Es` is widened to the least primitive
44-
numeric value type equal to or above the types of all expressions in `Es`,
45-
if that can be done without a loss of precision. Here
46-
_above_ and _least_ are interpreted according to the ordering given
47-
below.
48-
49-
50-
Double
51-
/ \
52-
Long Float
53-
\ /
54-
Int
55-
/ \
56-
Short Char
57-
|
58-
Byte
59-
60-
A loss of precision occurs for an `Int -> Float` conversion of a constant
61-
`c` if `c.toFloat.toInt != c`. For a `Long -> Double` conversion it occurs
62-
if `c.toDouble.toLong != c`.
63-
64-
If these widenings lead to all widened expressions having the same type,
65-
we use the widened expressions instead of `Es`, otherwise we use `Es` unchanged.
66-
67-
__Examples:__
68-
69-
inline val b = 33
70-
def f(): Int = b + 1
71-
List(b, 33, 'a') : List[Int]
72-
List(b, 33, 'a', f()) : List[Int]
73-
List(1.0f, 'a', 0) : List[Float]
74-
List(1.0f, 1L) : List[Double]
75-
List(1.0f, 1L, f()) : List[AnyVal]
76-
List(1.0f, 1234567890): List[AnyVal]
77-
78-
The expression on the second-to-last line has type `List[AnyVal]`,
79-
since widenings only affect constants. Hence, `1.0f` and `1L` are
80-
widened to `Double`, but `f()` still has type `Int`. The elements
81-
don't agree on a type after widening, hence the elements are left
82-
unchanged.
83-
84-
The expression on the last line has type `List[AnyVal]` because
85-
`1234567890` cannot be converted to a `Float` without a loss of
86-
precision.
87-
88-
30+
Weak conformance applies to all "numeric" types (including `Char`), and
31+
independently of whether the expressions are literals or not. However,
32+
in hindsight, the only intended use case is for *integer literals* to
33+
be adapted to the type of the other expressions. Other types of numerics
34+
have an explicit type annotation embedded in their syntax (`f`, `d`,
35+
`.`, `L` or `'` for `Char`s) which ensures that their author really
36+
meant them to have that specific type).
37+
38+
Therefore, Dotty drops the general notion of weak conformance, and
39+
instead keeps one rule: `Int` literals are adapted to other numeric
40+
types if necessary.
41+
42+
[More details](weak-conformance-spec.html)

0 commit comments

Comments
 (0)