Skip to content

Commit 4c76479

Browse files
authored
Merge pull request #7708 from dotty-staging/fix-#7630
Fix #7630: Use weak conformance in overloading resolution
2 parents 731ee3c + 1b50493 commit 4c76479

File tree

5 files changed

+82
-21
lines changed

5 files changed

+82
-21
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,8 @@ trait Applications extends Compatibility {
666666
* argument trees.
667667
*/
668668
class ApplicableToTreesDirectly(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context) extends ApplicableToTrees(methRef, targs, args, resultType)(ctx) {
669-
override def argOK(arg: TypedArg, formal: Type): Boolean = argType(arg, formal) <:< formal.widenExpr
669+
override def argOK(arg: TypedArg, formal: Type): Boolean =
670+
argType(arg, formal) relaxed_<:< formal.widenExpr
670671
}
671672

672673
/** Subclass of Application for applicability tests with value argument types. */

tests/neg/harmonize.scala

+32-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import collection.mutable.ArrayBuffer
12
object Test {
23

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

5152
}
5253

53-
inline val b = 33
54-
def f(): Int = b + 1
55-
val a1 = Array(b, 33, 'a')
56-
val b1: Array[Int] = a1 // error: no widening
57-
val a2 = Array(b, 33, 'a', f())
58-
val b2: Array[Int] = a2 // error: no widening
59-
val a3 = Array(1.0f, 'a', 0)
60-
val b3: Array[Float] = a3 // error: no widening
61-
val a4 = Array(1.0f, 1L)
62-
val b4: Array[Double] = a4 // error: no widening
63-
val a5 = Array(1.0f, 1L, f())
64-
val b5: Array[AnyVal] = a5
65-
val a6 = Array(1.0f, 1234567890)
66-
val b6: Array[AnyVal] = a6
54+
def arraytest =
55+
inline val b = 33
56+
def f(): Int = b + 1
57+
val a1 = Array(b, 33, 'a')
58+
val b1: Array[Int] = a1 // OK, Array constructor selection uses weak conformance
59+
val a2 = Array(b, 33, 'a', f())
60+
val b2: Array[Int] = a2 // OK, Array constructor selection uses weak conformance
61+
val a3 = Array(1.0f, 'a', 0)
62+
val b3: Array[Float] = a3 // OK, Array constructor selection uses weak conformance
63+
val a4 = Array(1.0f, 1L)
64+
val b4: Array[Double] = a4 // error: Array[Float] is picked
65+
val a5 = Array(1.0f, 1L, f())
66+
val b5: Array[AnyVal] = a5 // error: Array[Float] is picked
67+
val a6 = Array(1.0f, 1234567890)
68+
val b6: Array[AnyVal] = a6 // error: Array[Float] is picked
69+
70+
def arrayBufferTest =
71+
inline val b = 33
72+
def f(): Int = b + 1
73+
val a1 = ArrayBuffer(b, 33, 'a')
74+
val b1: ArrayBuffer[Int] = a1 // error: no widening
75+
val a2 = ArrayBuffer(b, 33, 'a', f())
76+
val b2: ArrayBuffer[Int] = a2 // error: no widening
77+
val a3 = ArrayBuffer(1.0f, 'a', 0)
78+
val b3: ArrayBuffer[Float] = a3 // error: no widening
79+
val a4 = ArrayBuffer(1.0f, 1L)
80+
val b4: ArrayBuffer[Double] = a4 // error: no widening
81+
val a5 = ArrayBuffer(1.0f, 1L, f())
82+
val b5: ArrayBuffer[AnyVal] = a5
83+
val a6 = ArrayBuffer(1.0f, 1234567890)
84+
val b6: ArrayBuffer[AnyVal] = a6
6785

6886
def totalDuration(results: List[Long], cond: Boolean): Long =
6987
results.map(r => if (cond) r else 0).sum

tests/run/i7630.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2

tests/run/i7630.scala

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Asserts {
2+
def assertEquals(expected: Any, actual: Any): Unit = {
3+
println(1)
4+
assert(expected.equals(actual), s"expected $expected but got $actual")
5+
}
6+
7+
def assertEquals(expected: Long, actual: Long): Unit = {
8+
println(2)
9+
assert(expected == actual, s"expected $expected but got $actual")
10+
}
11+
}
12+
13+
object Test {
14+
def main(args: Array[String]): Unit = {
15+
def foo(): Long = 42L
16+
17+
Asserts.assertEquals(42, foo()) // an Int and a Long
18+
}
19+
}

tests/run/weak-conformance.scala

+28-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import collection.mutable.ArrayBuffer
12
object Test extends App {
23
inline val b = 33
34

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

2324
locally {
2425
def f(): Int = b + 1
25-
val x1 = Array(b, 33, 5.5) ; x1: Array[Double] // b is an inline val
26-
val x2 = Array(f(), 33, 5.5) ; x2: Array[AnyVal] // f() is not a constant
26+
val x1 = ArrayBuffer(b, 33, 5.5) ; x1: ArrayBuffer[Double] // b is an inline val
27+
val x2 = ArrayBuffer(f(), 33, 5.5) ; x2: ArrayBuffer[AnyVal] // f() is not a constant
28+
val x3 = ArrayBuffer(5, 11L) ; x3: ArrayBuffer[Long]
29+
val x4 = ArrayBuffer(5, 11L, 5.5) ; x4: ArrayBuffer[AnyVal] // Long and Double found
30+
val x5 = ArrayBuffer(1.0f, 2) ; x5: ArrayBuffer[Float]
31+
val x6 = ArrayBuffer(1.0f, 1234567890); x6: ArrayBuffer[AnyVal] // loss of precision
32+
val x7 = ArrayBuffer(b, 33, 'a') ; x7: ArrayBuffer[Char]
33+
val x8 = ArrayBuffer(5.toByte, 11) ; x8: ArrayBuffer[Byte]
34+
35+
val x9: ArrayBuffer[AnyVal] = ArrayBuffer(1.0f, 0)
36+
assert(x9(0).getClass == classOf[java.lang.Float])
37+
assert(x9(1).getClass == classOf[java.lang.Integer]) // expected type fully defined since ArrayBuffer is nonvariant
38+
val x10 = ArrayBuffer[Any](1.0f, 0)
39+
assert(x10(0).getClass == classOf[java.lang.Float])
40+
assert(x10(1).getClass == classOf[java.lang.Integer])
41+
}
42+
43+
locally {
44+
// Arrays behave differently from lists since they have overloaded constructors, and weak
45+
// conformance does apply for selecting one. See Issue #7630.
46+
def f(): Int = b + 1
47+
val x1 = Array(b, 33, 5.5) ; x1: Array[Double]
48+
val x2 = Array(f(), 33, 5.5) ; x2: Array[Double]
2749
val x3 = Array(5, 11L) ; x3: Array[Long]
28-
val x4 = Array(5, 11L, 5.5) ; x4: Array[AnyVal] // Long and Double found
50+
val x4 = Array(5, 11L, 5.5) ; x4: Array[Double]
2951
val x5 = Array(1.0f, 2) ; x5: Array[Float]
30-
val x6 = Array(1.0f, 1234567890); x6: Array[AnyVal] // loss of precision
31-
val x7 = Array(b, 33, 'a') ; x7: Array[Char]
32-
val x8 = Array(5.toByte, 11) ; x8: Array[Byte]
52+
val x6 = Array(1.0f, 1234567890); x6: Array[Float]
53+
val x7 = Array(b, 33, 'a') ; x7: Array[Int]
54+
val x8 = Array(5.toByte, 11) ; x8: Array[Int]
3355

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

0 commit comments

Comments
 (0)