-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Tweak and implement weak conformance replacement #5371
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 all commits
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 |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# Closure type miss match | ||
eff-dependent.scala | ||
|
||
# It seems we still harmonize types in fromTasty. Not sure where this happens | ||
puzzle.scala |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,16 +16,16 @@ assigning a type to a constant expression. The new rule is: | |
|
||
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 | ||
|
||
- the expressions `Es` are partitioned into `Int` constants 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`, | ||
(which can be one of `Byte`, `Short`, `Char`, `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 | ||
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 | ||
|
@@ -36,11 +36,11 @@ __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] | ||
Array(b, 33, 5.5) : Array[Double] // b is an inline val | ||
Array(f(), 33, 5.5) : Array[AnyVal] // f() is not a constant | ||
Array(5, 11L) : Array[Long] | ||
Array(5, 11L, 5.5) : Array[AnyVal] // Long and Double found | ||
Array(1.0f, 2) : Array[Float] | ||
Array(1.0f, 1234567890): Array[AnyVal] // loss of precision | ||
Array(b, 33, 'a') : Array[Char] | ||
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. Why was this changed back from 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 thought we agreed that a Char literal should not be converted to another numeric type, same as a Float or a Double is not converted. But this case is different: It's an Int constant that is converted to a Char type. Same as it could be converted to a Short or Byte type. I agree that Char feels strange, but the fact is it is a member of Java's numeric hierarchy, so I believe it's better to be consistent. We do allow:
So it's inconsistent to not also allow this in harmonization. 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 see now that
Somehow I overlooked this before. So we'd either have to put |
||
Array(5.toByte, 11) : Array[Byte] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
53.0 | ||
53.0 | ||
5 | ||
5 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// no longer a puzzler, now prints 5, 5 | ||
object Test { | ||
|
||
def main(args: Array[String]): Unit = { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
object Test extends App { | ||
inline val b = 33 | ||
|
||
locally { | ||
def f(): Int = b + 1 | ||
val x1 = List(b, 33, 5.5) ; x1: List[Double] // b is an inline val | ||
val x2 = List(f(), 33, 5.5) ; x2: List[AnyVal] // f() is not a constant | ||
val x3 = List(5, 11L) ; x3: List[Long] | ||
val x4 = List(5, 11L, 5.5) ; x4: List[AnyVal] // Long and Double found | ||
val x5 = List(1.0f, 2) ; x5: List[Float] | ||
val x6 = List(1.0f, 1234567890); x6: List[AnyVal] // loss of precision | ||
val x7 = List(b, 33, 'a') ; x7: List[Char] | ||
val x8 = List(5.toByte, 11) ; x8: List[Byte] | ||
|
||
val x9: List[AnyVal] = List(1.0f, 0) | ||
assert(x9(0).getClass == classOf[java.lang.Float]) | ||
assert(x9(1).getClass == classOf[java.lang.Float]) // expected type not fully defined, since `List` is covariant | ||
val x10 = List[Any](1.0f, 0) | ||
assert(x10(0).getClass == classOf[java.lang.Float]) | ||
assert(x10(1).getClass == classOf[java.lang.Integer]) | ||
} | ||
|
||
locally { | ||
def f(): Int = b + 1 | ||
val x1 = Array(b, 33, 5.5) ; x1: Array[Double] // b is an inline val | ||
val x2 = Array(f(), 33, 5.5) ; x2: Array[AnyVal] // f() is not a constant | ||
val x3 = Array(5, 11L) ; x3: Array[Long] | ||
val x4 = Array(5, 11L, 5.5) ; x4: Array[AnyVal] // Long and Double found | ||
val x5 = Array(1.0f, 2) ; x5: Array[Float] | ||
val x6 = Array(1.0f, 1234567890); x6: Array[AnyVal] // loss of precision | ||
val x7 = Array(b, 33, 'a') ; x7: Array[Char] | ||
val x8 = Array(5.toByte, 11) ; x8: Array[Byte] | ||
|
||
val x9: Array[AnyVal] = Array(1.0f, 0) | ||
assert(x9(0).getClass == classOf[java.lang.Float]) | ||
assert(x9(1).getClass == classOf[java.lang.Integer]) // expected type fully defined since Array is nonvariant | ||
val x10 = Array[Any](1.0f, 0) | ||
assert(x10(0).getClass == classOf[java.lang.Float]) | ||
assert(x10(1).getClass == classOf[java.lang.Integer]) | ||
} | ||
|
||
locally { | ||
def f(): Int = b + 1 | ||
val x1 = if (true) b else if (true) 33 else 5.5 ; x1: Double // b is an inline val | ||
val x2 = if (true) f() else if (true) 33 else 5.5) ; x2: AnyVal // f() is not a constant | ||
val x3 = if (true) 5 else 11L) ; x3: Long | ||
val x4 = if (true) 5 else if (true) 11L else 5.5) ; x4: AnyVal // Long and Double found | ||
val x5 = if (true) 1.0f else 2) ; x5: Float | ||
val x6 = if (true) 1.0f else 1234567890) ; x6: AnyVal // loss of precision | ||
val x7 = if (true) b else if (true) 33 else 'a') ; x7: Char | ||
val x8 = if (true) 5.toByte else 11) ; x8: Byte | ||
} | ||
} |
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.
What about
Byte
s andShort
s? (andChar
s, if they are considered numeric after all?)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.
These are covered under
c.convertTo(cls.typeRef) != null