summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2012-05-23 03:48:50 -0700
committerLukas Rytz <lukas.rytz@epfl.ch>2012-05-23 03:48:50 -0700
commit94e5d76fb8632de1b6c34df63cb2bf3f1cd46fe3 (patch)
tree435af93e0b56b6cf17e8d22b9fdc28b5cc23ccaa
parent0f198a63d2f1a141b43f40f639d5fff8697510d0 (diff)
parent8de2caa560d2c820269fd30207fdd22dd7e48c6b (diff)
downloadscala-94e5d76fb8632de1b6c34df63cb2bf3f1cd46fe3.tar.gz
scala-94e5d76fb8632de1b6c34df63cb2bf3f1cd46fe3.tar.bz2
scala-94e5d76fb8632de1b6c34df63cb2bf3f1cd46fe3.zip
Merge pull request #595 from som-snytt/ticket/3761-overload-byname-only
SI-3761: Overload resolution fails on by-name parameter
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala18
-rw-r--r--test/files/run/t3761-overload-byname.check6
-rw-r--r--test/files/run/t3761-overload-byname.scala23
3 files changed, 44 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 839cdee301..abe77ead9a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -305,9 +305,21 @@ trait Infer {
}
- def isCompatible(tp: Type, pt: Type): Boolean = {
+ /** "Compatible" means conforming after conversions.
+ * "Raising to a thunk" is not implicit; therefore, for purposes of applicability and
+ * specificity, an arg type `A` is considered compatible with cbn formal parameter type `=>A`.
+ * For this behavior, the type `pt` must have cbn params preserved; for instance, `formalTypes(removeByName = false)`.
+ *
+ * `isAsSpecific` no longer prefers A by testing applicability to A for both m(A) and m(=>A)
+ * since that induces a tie between m(=>A) and m(=>A,B*) [SI-3761]
+ */
+ private def isCompatible(tp: Type, pt: Type): Boolean = {
+ def isCompatibleByName(tp: Type, pt: Type): Boolean = pt match {
+ case TypeRef(_, ByNameParamClass, List(res)) if !isByNameParamType(tp) => isCompatible(tp, res)
+ case _ => false
+ }
val tp1 = normalize(tp)
- (tp1 weak_<:< pt) || isCoercible(tp1, pt)
+ (tp1 weak_<:< pt) || isCoercible(tp1, pt) || isCompatibleByName(tp, pt)
}
def isCompatibleArgs(tps: List[Type], pts: List[Type]) =
(tps corresponds pts)(isCompatible)
@@ -662,7 +674,7 @@ trait Infer {
case ExistentialType(tparams, qtpe) =>
isApplicable(undetparams, qtpe, argtpes0, pt)
case MethodType(params, _) =>
- val formals = formalTypes(params map { _.tpe }, argtpes0.length)
+ val formals = formalTypes(params map { _.tpe }, argtpes0.length, removeByName = false)
def tryTupleApply: Boolean = {
// if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
diff --git a/test/files/run/t3761-overload-byname.check b/test/files/run/t3761-overload-byname.check
new file mode 100644
index 0000000000..3a0a273e64
--- /dev/null
+++ b/test/files/run/t3761-overload-byname.check
@@ -0,0 +1,6 @@
+hello!
+hello working world
+goodnight!
+goodnight moon, nobody, noises everywhere
+0
+1
diff --git a/test/files/run/t3761-overload-byname.scala b/test/files/run/t3761-overload-byname.scala
new file mode 100644
index 0000000000..b1656c97ba
--- /dev/null
+++ b/test/files/run/t3761-overload-byname.scala
@@ -0,0 +1,23 @@
+
+class OverTheTop {
+ def info0(m: String) = m + "!"
+ def info0(m: String, args: Any*) = m +" "+ args.mkString(" ")
+
+ // as reported
+ def info1(m: =>String) = m + "!"
+ def info1(m: =>String, args: Any*) = m +" "+ args.mkString(", ")
+
+ // @lrytz
+ def m[A](x: => Int) = 0; def m[A](x: => Int, xs: Int*) = 1
+}
+object Test {
+ def main(args: Array[String]) {
+ val top = new OverTheTop
+ println(top.info0("hello"))
+ println(top.info0("hello","working","world"))
+ println(top.info1("goodnight"))
+ println(top.info1("goodnight", "moon", "nobody", "noises everywhere"))
+ println(top.m(17))
+ println(top.m(17,19))
+ }
+}