summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-04-12 11:52:39 +0000
committerMartin Odersky <odersky@gmail.com>2010-04-12 11:52:39 +0000
commitcfe47e4b74cc166af31cc130b0830112c46bdc61 (patch)
tree7716cb0c8cb0179f0b09328779e0c2ac06621025
parentbed1ffb1c357e09c05ea6a58bd19a75510f1822e (diff)
downloadscala-cfe47e4b74cc166af31cc130b0830112c46bdc61.tar.gz
scala-cfe47e4b74cc166af31cc130b0830112c46bdc61.tar.bz2
scala-cfe47e4b74cc166af31cc130b0830112c46bdc61.zip
Closes #3224. Review by retronym.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--test/files/neg/t3224.check6
-rwxr-xr-xtest/files/neg/t3224.scala30
4 files changed, 52 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index c0b54cb4f0..c8d3308077 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -802,6 +802,14 @@ trait Infer {
(argtpes1, argPos, namesOK)
}
+ /** don't do a () to (()) conversion for methods whose second parameter
+ * is a varargs. This is a fairly kludgey way to address #3224.
+ * We'll probably find a better way to do this by identifying
+ * tupled and n-ary methods, but thiws is something for a future major revision.
+ */
+ def isUnitForVarArgs(args: List[AnyRef], params: List[Symbol]): Boolean =
+ args.length == 0 && params.length == 2 && isVarArgs(params)
+
/** Is there an instantiation of free type variables <code>undetparams</code>
* such that function type <code>ftpe</code> is applicable to
* <code>argtpes</code> and its result conform to <code>pt</code>?
@@ -833,14 +841,15 @@ trait Infer {
def tryTupleApply: Boolean = {
// if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
- val tupleArgTpe = actualTypes(argtpes0 map {
+ val tupleArgTpes = actualTypes(argtpes0 map {
// no assignment is treated as named argument here
case NamedType(name, tp) => UnitClass.tpe
case tp => tp
}, formals.length)
- argtpes0.length != tupleArgTpe.length &&
- isApplicable(undetparams, ftpe, tupleArgTpe, pt)
+ argtpes0.length != tupleArgTpes.length &&
+ !isUnitForVarArgs(argtpes0, params) &&
+ isApplicable(undetparams, ftpe, tupleArgTpes, pt)
}
def typesCompatible(argtpes: List[Type]) = {
val restpe = ftpe.resultType(argtpes)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 284b12e501..3fe937f241 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2327,12 +2327,14 @@ trait Typers { self: Analyzer =>
// if 1 formal, 1 arg (a tuple), otherwise unmodified args
val tupleArgs = actualArgs(tree.pos.makeTransparent, args, formals.length)
- if (tupleArgs.length != args.length) {
+ if (tupleArgs.length != args.length && !isUnitForVarArgs(args, params)) {
// expected one argument, but got 0 or >1 ==> try applying to tuple
// the inner "doTypedApply" does "extractUndetparams" => restore when it fails
val savedUndetparams = context.undetparams
silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) match {
- case t: Tree => Some(t)
+ case t: Tree =>
+// println("tuple conversion to "+t+" for "+mt)//DEBUG
+ Some(t)
case ex =>
context.undetparams = savedUndetparams
None
diff --git a/test/files/neg/t3224.check b/test/files/neg/t3224.check
new file mode 100644
index 0000000000..de196f15be
--- /dev/null
+++ b/test/files/neg/t3224.check
@@ -0,0 +1,6 @@
+/home/odersky/workspace/scala/test/files/neg/t3224.scala:29: error: polymorphic expression cannot be instantiated to expected type;
+ found : [T]Array[T]
+ required: List[?]
+ println(Texts textL Array()); println(Texts textL Array(1)); println(Texts textL Array(1, 1))
+ ^
+one error found
diff --git a/test/files/neg/t3224.scala b/test/files/neg/t3224.scala
new file mode 100755
index 0000000000..0e24baf28a
--- /dev/null
+++ b/test/files/neg/t3224.scala
@@ -0,0 +1,30 @@
+object Texts{
+ def textL[T](list: List[T]) = {
+ list match{
+ case List() => "Empty"
+ case List(_) => "One"
+ case List(_*) => "Many"
+ }
+ }
+
+ def textA[T](array: Array[T]) = {
+ array match{
+ case Array() => "Empty"
+ case Array(_) => "One"
+ case Array(_*) => "Many"
+ }
+ }
+}
+
+object Test extends Application {
+
+ implicit def array2list[T](array: Array[T]) = {
+ println(array.toList.size)
+ array.toList
+ }
+
+
+ println(Texts textL List()); println(Texts textL List(1)); println(Texts textL List(1, 1));
+
+ println(Texts textL Array()); println(Texts textL Array(1)); println(Texts textL Array(1, 1))
+}