From 54835b6fb19ab0758c7503fb6f0e990ee4c25491 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 17 Jun 2015 18:00:21 +0200 Subject: Take expected result type into account more often for overloading resolution Previously, the expected result type of a FunProto type was ignored and taken into account only in case of ambiguities. arrayclone-new.scala shows that this is not enough. In a case like val x: Array[Byte] = Array(1, 2) we typed 1, 2 to be Int, so overloading resulution would give the Array.apply of type (Int, Int*)Array[Int]. But that's a dead end, since Array[Int] is not a subtype of Array[Byte]. This commit proposes the following modified rule for overloading resulution: A method alternative is applicable if ... (as before), and if its result type is copmpatible with the expected type of the method application. The commit does not pre-select alternatives based on comparing with the expected result type. I tried that but it slowed down typechecking by a factor of at least 4. Instead, we proceed as usual, ignoring the result type except in case of ambiguities, but check whether the result of overloading resolution has a compatible result type. If that's not the case, we filter all alternatives for result type compatibility and try again. --- tests/run/arrayclone-new.scala | 109 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tests/run/arrayclone-new.scala (limited to 'tests/run/arrayclone-new.scala') diff --git a/tests/run/arrayclone-new.scala b/tests/run/arrayclone-new.scala new file mode 100644 index 000000000..8f66d1b31 --- /dev/null +++ b/tests/run/arrayclone-new.scala @@ -0,0 +1,109 @@ +import scala.reflect.ClassTag + +object Test extends dotty.runtime.LegacyApp{ + BooleanArrayClone; + ByteArrayClone; + ShortArrayClone; + CharArrayClone; + IntArrayClone; + LongArrayClone; + FloatArrayClone; + DoubleArrayClone; + ObjectArrayClone; + PolymorphicArrayClone; +} + +object BooleanArrayClone{ + val it : Array[Boolean] = Array(true, false); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = false; + assert(it(0) == true) +} + +object ByteArrayClone{ + val it : Array[Byte] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object ShortArrayClone{ + val it : Array[Short] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object CharArrayClone{ + val it : Array[Char] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object IntArrayClone{ + val it : Array[Int] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object LongArrayClone{ + val it : Array[Long] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object FloatArrayClone{ + val it : Array[Float] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object DoubleArrayClone{ + val it : Array[Double] = Array(1, 0); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = 0; + assert(it(0) == 1) +} + +object ObjectArrayClone{ + val it : Array[String] = Array("1", "0"); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = "0"; + assert(it(0) == "1") +} + +object PolymorphicArrayClone{ + def testIt[T](it : Array[T], one : T, zero : T) = { + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = zero; + assert(it(0) == one) + } + + testIt(Array("one", "two"), "one", "two"); + + class Mangler[T: ClassTag](ts : T*){ + // this will always be a BoxedAnyArray even after we've unboxed its contents. + val it = ts.toArray[T]; + } + + val mangled = new Mangler[Int](0, 1); + + val y : Array[Int] = mangled.it; // make sure it's unboxed + + testIt(mangled.it, 0, 1); +} + -- cgit v1.2.3