-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #2833: Fixes to harmonize #2843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
7953479
28481bf
45b7f14
41c4428
af81f87
6d208c5
196769f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
layout: doc-page | ||
title: Dropped: Weak Conformance | ||
--- | ||
|
||
In some situations, Scala used a {\em 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 as expression like this have type `List[Double]`: | ||
|
||
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 | ||
types `(Double, Double, Int, Double)` would be `AnyVal`, hence the list | ||
expression would be given type `List[AnyVal]`. | ||
|
||
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 n: 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[Double]`, a `List[AnyVal` seems to be an equally valid -- and | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing closing bracket: |
||
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 rule is: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this rule have a name? Is it a new Dotty feature? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed it so say that it is new. It does not have a name (yet). |
||
|
||
- If a list of expressions `Es` appears as one of | ||
|
||
- the elements of a vararg parameter, or | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens when it's not a vararg parameter list? def add[T](a: T, b: T): List[T] = List(a, b)
add(1.0f, 1L) // Double? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, AnyVal. |
||
- 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 above the types of all expressions in `Es`. Here | ||
_above_ and _least_ are interpreted according to the ordering given | ||
below. | ||
|
||
|
||
Double | ||
/ \ | ||
Long Float | ||
\ / | ||
Int | ||
/ \ | ||
Short Char | ||
| | ||
Byte | ||
|
||
If these widenings lead to all expressions `Es` having the same type, | ||
we use the transformed list of expressions instead of `Es`, otherwise | ||
we use `Es` unchanged. | ||
|
||
__Examples:__ | ||
|
||
inline val b: Byte = 3 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good if there was some explanation of how the rules differ between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if this is |
||
inline val s: Short = 33 | ||
def f(): Int = b + s | ||
List(b, s, 'a') : List[Int] | ||
List(b, s, 'a', f()): List[Int] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to note here that the type is |
||
List(1.0f, 'a', 0) : List[Float] | ||
List(1.0f, 1L) : List[Double] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a |
||
List(1.0f, 1L, f()) : List[AnyVal] | ||
|
||
The expression on the 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 expressions are left unchanged. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you can use latex code in our documentation. You should be able to write
*weak conformance*
instead which should be rendered as weak conformance.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. That comes from switching context from writing a paper with LaTex...