Skip to content
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

Fix #7630: Use weak conformance in overloading resolution #7708

Merged
merged 3 commits into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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