diff --git a/docs/docs/reference/dropped/weak-conformance-spec.md b/docs/docs/reference/dropped/weak-conformance-spec.md new file mode 100644 index 000000000000..4993768c88a5 --- /dev/null +++ b/docs/docs/reference/dropped/weak-conformance-spec.md @@ -0,0 +1,46 @@ +--- +layout: doc-page +title: Dropped: Weak Conformance - More Details +--- + +To simplify the underlying type theory, Dotty drops the notion of weak +conformance altogether. Instead, it provides more flexibility when +assigning a type to a constant expression. The new rule is: + + - If a list of expressions `Es` appears as one of + + - the elements of a vararg parameter, or + - the alternatives of an if-then-else or match expression, or + - the body and catch results of a try expression, + + + and all expressions have primitive numeric types, but they do not + all have the same type, then the following is attempted: + + - the expressions `Es` are partitioned into `Int` literals on the + one hand, and all other expressions on the other hand + - if all the other expressions have the same numeric type `T` + (which can be one of `Byte`, `Short`, `Int`, `Long`, `Float`, + `Double`), possibly after widening, and if none of the `Int` + literals would incur a loss of precision when converted to `T`, + then they are thus converted (the other expressions are left + unchanged regardless) + - otherwise, the expressions `Es` are used unchanged + + A loss of precision occurs for an `Int -> Float` conversion of a constant + `c` if `c.toFloat.toInt != c`. For an `Int -> Byte` conversion it occurs + if `c.toByte.toInt != c`. For an `Int -> Short` conversion, it occurs + if `c.toShort.toInt != c`. + +__Examples:__ + + inline val b = 33 + def f(): Int = b + 1 + List(b, 33, 5.5) : List[Double] // b is an inline val + List(f(), 33, 5.5) : List[AnyVal] // f() is not a constant + List(5, 11L) : List[Long] + List(5, 11L, 5.5) : List[AnyVal] // Long and Double found + List(1.0f, 2) : List[Float] + List(1.0f, 1234567890): List[AnyVal] // loss of precision + List(b, 33, 'a') : List[AnyVal] // Char is not a numeric + List(5.toByte, 11) : List[Byte] diff --git a/docs/docs/reference/dropped/weak-conformance.md b/docs/docs/reference/dropped/weak-conformance.md index 0c796f9e2cd9..aaa61adf415d 100644 --- a/docs/docs/reference/dropped/weak-conformance.md +++ b/docs/docs/reference/dropped/weak-conformance.md @@ -27,62 +27,16 @@ Here, it is less clear why the type should be widened to `List[Double]`, a `List[AnyVal]` seems to be an equally valid -- and more principled -- choice. -To simplify the underlying type theory, Dotty drops the notion of weak -conformance altogether. Instead, it provides more flexibility when -assigning a type to a constant expression. The new rule is: - - - If a list of expressions `Es` appears as one of - - - the elements of a vararg parameter, or - - the alternatives of an if-then-else or match expression, or - - the body and catch results of a try expression, - - - and all expressions have primitive numeric types, but they do not - all have the same type, then the following is attempted: Every - constant expression `E` in `Es` is widened to the least primitive - numeric value type equal to or above the types of all expressions in `Es`, - if that can be done without a loss of precision. Here - _above_ and _least_ are interpreted according to the ordering given - below. - - - Double - / \ - Long Float - \ / - Int - / \ - Short Char - | - Byte - - A loss of precision occurs for an `Int -> Float` conversion of a constant - `c` if `c.toFloat.toInt != c`. For a `Long -> Double` conversion it occurs - if `c.toDouble.toLong != c`. - - If these widenings lead to all widened expressions having the same type, - we use the widened expressions instead of `Es`, otherwise we use `Es` unchanged. - -__Examples:__ - - inline val b = 33 - def f(): Int = b + 1 - List(b, 33, 'a') : List[Int] - List(b, 33, 'a', f()) : List[Int] - List(1.0f, 'a', 0) : List[Float] - List(1.0f, 1L) : List[Double] - List(1.0f, 1L, f()) : List[AnyVal] - List(1.0f, 1234567890): List[AnyVal] - -The expression on the second-to-last line has type `List[AnyVal]`, -since widenings only affect constants. Hence, `1.0f` and `1L` are -widened to `Double`, but `f()` still has type `Int`. The elements -don't agree on a type after widening, hence the elements are left -unchanged. - -The expression on the last line has type `List[AnyVal]` because -`1234567890` cannot be converted to a `Float` without a loss of -precision. - - +Weak conformance applies to all "numeric" types (including `Char`), and +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 (`f`, `d`, +`.`, `L` or `'` for `Char`s) 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. + +[More details](weak-conformance-spec.html)