aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala9
-rw-r--r--tests/pos/inferOverloaded.scala41
2 files changed, 49 insertions, 1 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index 0ed6ed6b4..2cfe01616 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -1227,6 +1227,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def typeShape(tree: untpd.Tree): Type = tree match {
case untpd.Function(args, body) =>
defn.FunctionOf(args map Function.const(defn.AnyType), typeShape(body))
+ case Match(EmptyTree, _) =>
+ defn.PartialFunctionType.appliedTo(defn.AnyType :: defn.NothingType :: Nil)
case _ =>
defn.NothingType
}
@@ -1270,8 +1272,13 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def narrowBySize(alts: List[TermRef]): List[TermRef] =
alts filter (alt => sizeFits(alt, alt.widen))
+ def isFunArg(arg: untpd.Tree) = arg match {
+ case untpd.Function(_, _) | Match(EmptyTree, _) => true
+ case _ => false
+ }
+
def narrowByShapes(alts: List[TermRef]): List[TermRef] = {
- if (normArgs exists (_.isInstanceOf[untpd.Function]))
+ if (normArgs exists isFunArg)
if (hasNamedArg(args)) narrowByTrees(alts, args map treeShape, resultType)
else narrowByTypes(alts, normArgs map typeShape, resultType)
else
diff --git a/tests/pos/inferOverloaded.scala b/tests/pos/inferOverloaded.scala
new file mode 100644
index 000000000..e5e800644
--- /dev/null
+++ b/tests/pos/inferOverloaded.scala
@@ -0,0 +1,41 @@
+class MySeq[T] {
+ def map1[U](f: T => U): MySeq[U] = new MySeq[U]
+ def map2[U](f: T => U): MySeq[U] = new MySeq[U]
+}
+
+class MyMap[A, B] extends MySeq[(A, B)] {
+ def map1[C](f: (A, B) => C): MySeq[C] = new MySeq[C]
+ def map1[C, D](f: (A, B) => (C, D)): MyMap[C, D] = new MyMap[C, D]
+ def map1[C, D](f: ((A, B)) => (C, D)): MyMap[C, D] = new MyMap[C, D]
+
+ def foo(f: Function2[Int, Int, Int]): Unit = ()
+ def foo[R](pf: PartialFunction[(A, B), R]): MySeq[R] = new MySeq[R]
+}
+
+object Test {
+ val m = new MyMap[Int, String]
+
+ // This one already worked because it is not overloaded:
+ m.map2 { case (k, v) => k - 1 }
+
+ // These already worked because preSelectOverloaded eliminated the non-applicable overload:
+ m.map1(t => t._1)
+ m.map1((kInFunction, vInFunction) => kInFunction - 1)
+ val r1 = m.map1(t => (t._1, 42.0))
+ val r1t: MyMap[Int, Double] = r1
+
+ // These worked because the argument types are known for overload resolution:
+ m.map1({ case (k, v) => k - 1 }: PartialFunction[(Int, String), Int])
+ m.map2({ case (k, v) => k - 1 }: PartialFunction[(Int, String), Int])
+
+ // These ones did not work before, still don't work in dotty:
+ //m.map1 { case (k, v) => k }
+ //val r = m.map1 { case (k, v) => (k, k*10) }
+ //val rt: MyMap[Int, Int] = r
+ //m.foo { case (k, v) => k - 1 }
+
+ // Used to be ambiguous but overload resolution now favors PartialFunction
+ def h[R](pf: Function2[Int, String, R]): Unit = ()
+ def h[R](pf: PartialFunction[(Double, Double), R]): Unit = ()
+ h { case (a: Double, b: Double) => 42: Int }
+}