Skip to content

Commit

Permalink
Merge pull request #7708 from dotty-staging/fix-#7630
Browse files Browse the repository at this point in the history
Fix #7630: Use weak conformance in overloading resolution
  • Loading branch information
odersky authored Dec 11, 2019
2 parents 731ee3c + 1b50493 commit 4c76479
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 21 deletions.
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,8 @@ trait Applications extends Compatibility {
* argument trees.
*/
class ApplicableToTreesDirectly(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context) extends ApplicableToTrees(methRef, targs, args, resultType)(ctx) {
override def argOK(arg: TypedArg, formal: Type): Boolean = argType(arg, formal) <:< formal.widenExpr
override def argOK(arg: TypedArg, formal: Type): Boolean =
argType(arg, formal) relaxed_<:< formal.widenExpr
}

/** Subclass of Application for applicability tests with value argument types. */
Expand Down
46 changes: 32 additions & 14 deletions tests/neg/harmonize.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import collection.mutable.ArrayBuffer
object Test {

def main(args: Array[String]) = {
Expand Down Expand Up @@ -50,20 +51,37 @@ object Test {

}

inline val b = 33
def f(): Int = b + 1
val a1 = Array(b, 33, 'a')
val b1: Array[Int] = a1 // error: no widening
val a2 = Array(b, 33, 'a', f())
val b2: Array[Int] = a2 // error: no widening
val a3 = Array(1.0f, 'a', 0)
val b3: Array[Float] = a3 // error: no widening
val a4 = Array(1.0f, 1L)
val b4: Array[Double] = a4 // error: no widening
val a5 = Array(1.0f, 1L, f())
val b5: Array[AnyVal] = a5
val a6 = Array(1.0f, 1234567890)
val b6: Array[AnyVal] = a6
def arraytest =
inline val b = 33
def f(): Int = b + 1
val a1 = Array(b, 33, 'a')
val b1: Array[Int] = a1 // OK, Array constructor selection uses weak conformance
val a2 = Array(b, 33, 'a', f())
val b2: Array[Int] = a2 // OK, Array constructor selection uses weak conformance
val a3 = Array(1.0f, 'a', 0)
val b3: Array[Float] = a3 // OK, Array constructor selection uses weak conformance
val a4 = Array(1.0f, 1L)
val b4: Array[Double] = a4 // error: Array[Float] is picked
val a5 = Array(1.0f, 1L, f())
val b5: Array[AnyVal] = a5 // error: Array[Float] is picked
val a6 = Array(1.0f, 1234567890)
val b6: Array[AnyVal] = a6 // error: Array[Float] is picked

def arrayBufferTest =
inline val b = 33
def f(): Int = b + 1
val a1 = ArrayBuffer(b, 33, 'a')
val b1: ArrayBuffer[Int] = a1 // error: no widening
val a2 = ArrayBuffer(b, 33, 'a', f())
val b2: ArrayBuffer[Int] = a2 // error: no widening
val a3 = ArrayBuffer(1.0f, 'a', 0)
val b3: ArrayBuffer[Float] = a3 // error: no widening
val a4 = ArrayBuffer(1.0f, 1L)
val b4: ArrayBuffer[Double] = a4 // error: no widening
val a5 = ArrayBuffer(1.0f, 1L, f())
val b5: ArrayBuffer[AnyVal] = a5
val a6 = ArrayBuffer(1.0f, 1234567890)
val b6: ArrayBuffer[AnyVal] = a6

def totalDuration(results: List[Long], cond: Boolean): Long =
results.map(r => if (cond) r else 0).sum
Expand Down
1 change: 1 addition & 0 deletions tests/run/i7630.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2
19 changes: 19 additions & 0 deletions tests/run/i7630.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
object Asserts {
def assertEquals(expected: Any, actual: Any): Unit = {
println(1)
assert(expected.equals(actual), s"expected $expected but got $actual")
}

def assertEquals(expected: Long, actual: Long): Unit = {
println(2)
assert(expected == actual, s"expected $expected but got $actual")
}
}

object Test {
def main(args: Array[String]): Unit = {
def foo(): Long = 42L

Asserts.assertEquals(42, foo()) // an Int and a Long
}
}
34 changes: 28 additions & 6 deletions tests/run/weak-conformance.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import collection.mutable.ArrayBuffer
object Test extends App {
inline val b = 33

Expand All @@ -22,14 +23,35 @@ object Test extends App {

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 x1 = ArrayBuffer(b, 33, 5.5) ; x1: ArrayBuffer[Double] // b is an inline val
val x2 = ArrayBuffer(f(), 33, 5.5) ; x2: ArrayBuffer[AnyVal] // f() is not a constant
val x3 = ArrayBuffer(5, 11L) ; x3: ArrayBuffer[Long]
val x4 = ArrayBuffer(5, 11L, 5.5) ; x4: ArrayBuffer[AnyVal] // Long and Double found
val x5 = ArrayBuffer(1.0f, 2) ; x5: ArrayBuffer[Float]
val x6 = ArrayBuffer(1.0f, 1234567890); x6: ArrayBuffer[AnyVal] // loss of precision
val x7 = ArrayBuffer(b, 33, 'a') ; x7: ArrayBuffer[Char]
val x8 = ArrayBuffer(5.toByte, 11) ; x8: ArrayBuffer[Byte]

val x9: ArrayBuffer[AnyVal] = ArrayBuffer(1.0f, 0)
assert(x9(0).getClass == classOf[java.lang.Float])
assert(x9(1).getClass == classOf[java.lang.Integer]) // expected type fully defined since ArrayBuffer is nonvariant
val x10 = ArrayBuffer[Any](1.0f, 0)
assert(x10(0).getClass == classOf[java.lang.Float])
assert(x10(1).getClass == classOf[java.lang.Integer])
}

locally {
// Arrays behave differently from lists since they have overloaded constructors, and weak
// conformance does apply for selecting one. See Issue #7630.
def f(): Int = b + 1
val x1 = Array(b, 33, 5.5) ; x1: Array[Double]
val x2 = Array(f(), 33, 5.5) ; x2: Array[Double]
val x3 = Array(5, 11L) ; x3: Array[Long]
val x4 = Array(5, 11L, 5.5) ; x4: Array[AnyVal] // Long and Double found
val x4 = Array(5, 11L, 5.5) ; x4: Array[Double]
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 x6 = Array(1.0f, 1234567890); x6: Array[Float]
val x7 = Array(b, 33, 'a') ; x7: Array[Int]
val x8 = Array(5.toByte, 11) ; x8: Array[Int]

val x9: Array[AnyVal] = Array(1.0f, 0)
assert(x9(0).getClass == classOf[java.lang.Float])
Expand Down

0 comments on commit 4c76479

Please sign in to comment.