summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-09-29 18:00:57 -0700
committerPaul Phillips <paulp@improving.org>2012-09-29 18:05:11 -0700
commit8886d22cd64e2bf861079873751455aeef9ee7a1 (patch)
treee0287151d61f392088fc93ed739df3b9aa7b9ccd
parent2e14b0771569b4fb6cd0273e1480f69c18743832 (diff)
downloadscala-8886d22cd64e2bf861079873751455aeef9ee7a1.tar.gz
scala-8886d22cd64e2bf861079873751455aeef9ee7a1.tar.bz2
scala-8886d22cd64e2bf861079873751455aeef9ee7a1.zip
Fix for SI-5859, inapplicable varargs.
And other polishing related to varargs handling.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala14
-rw-r--r--test/files/pos/t5859.scala15
7 files changed, 50 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index b04a736fd3..059d32fcb5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -118,7 +118,7 @@ trait EtaExpansion { self: Analyzer =>
val origTpe = sym.tpe
val isRepeated = definitions.isRepeatedParamType(origTpe)
// SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala
- val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropRepeatedParamType(origTpe)
+ val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropIllegalStarTypes(origTpe)
val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree)
(valDef, isRepeated)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 48abfd7a2c..6558379c51 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1593,10 +1593,10 @@ trait Infer extends Checkable {
}
// Drop those that use a default; keep those that use vararg/tupling conversion.
mtypes exists (t =>
- !t.typeSymbol.hasDefaultFlag && {
- compareLengths(t.params, argtpes) < 0 || // tupling (*)
- hasExactlyNumParams(t, argtpes.length) // same nb or vararg
- }
+ !t.typeSymbol.hasDefaultFlag && (
+ compareLengths(t.params, argtpes) < 0 // tupling (*)
+ || hasExactlyNumParams(t, argtpes.length) // same nb or vararg
+ )
)
// (*) more arguments than parameters, but still applicable: tupling conversion works.
// todo: should not return "false" when paramTypes = (Unit) no argument is given
@@ -1623,15 +1623,18 @@ trait Infer extends Checkable {
case OverloadedType(pre, alts) =>
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
tryTwice { isSecondTry =>
- debuglog("infer method alt "+ tree.symbol +" with alternatives "+
- (alts map pre.memberType) +", argtpes = "+ argtpes +", pt = "+ pt)
+ debuglog(s"infer method alt ${tree.symbol} with alternatives ${alts map pre.memberType} argtpes=$argtpes pt=$pt")
- val applicable = resolveOverloadedMethod(argtpes, {
- alts filter { alt =>
- inSilentMode(context)(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
- (!varArgsOnly || isVarArgsList(alt.tpe.params))
- }
- })
+ def varargsApplicableCheck(alt: Symbol) = !varArgsOnly || (
+ isVarArgsList(alt.tpe.params)
+ && (argtpes.size >= alt.tpe.params.size) // must be checked now due to SI-5859
+ )
+ val applicable = resolveOverloadedMethod(argtpes,
+ alts filter (alt =>
+ varargsApplicableCheck(alt)
+ && inSilentMode(context)(isApplicable(undetparams, followApply(pre memberType alt), argtpes, pt))
+ )
+ )
def improves(sym1: Symbol, sym2: Symbol) = {
// util.trace("improve "+sym1+sym1.locationString+" on "+sym2+sym2.locationString)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index abd433b929..f562a251e3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -800,7 +800,7 @@ trait Namers extends MethodSynthesis {
false
}
- val tpe1 = dropRepeatedParamType(tpe.deconst)
+ val tpe1 = dropIllegalStarTypes(tpe.deconst)
val tpe2 = tpe1.widen
// This infers Foo.type instead of "object Foo"
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 5e1f52830c..4b08f3ee80 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -60,23 +60,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
super.transformInfo(sym, tp)
}
- val toJavaRepeatedParam = new TypeMap {
- def apply(tp: Type) = tp match {
- case TypeRef(pre, RepeatedParamClass, args) =>
- typeRef(pre, JavaRepeatedParamClass, args)
- case _ =>
- mapOver(tp)
- }
- }
-
- val toScalaRepeatedParam = new TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, JavaRepeatedParamClass, args) =>
- typeRef(pre, RepeatedParamClass, args)
- case _ =>
- mapOver(tp)
- }
- }
+ val toJavaRepeatedParam = new SubstSymMap(RepeatedParamClass -> JavaRepeatedParamClass)
+ val toScalaRepeatedParam = new SubstSymMap(JavaRepeatedParamClass -> RepeatedParamClass)
def accessFlagsToString(sym: Symbol) = flagsToString(
sym getFlag (PRIVATE | PROTECTED),
@@ -1483,8 +1468,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
private def isRepeatedParamArg(tree: Tree) = currentApplication match {
case Apply(fn, args) =>
- !args.isEmpty && (args.last eq tree) &&
- fn.tpe.params.length == args.length && isRepeatedParamType(fn.tpe.params.last.tpe)
+ ( args.nonEmpty
+ && (args.last eq tree)
+ && (fn.tpe.params.length == args.length)
+ && isRepeatedParamType(fn.tpe.params.last.tpe)
+ )
case _ =>
false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3a443ea2c0..dc6beaf5c6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4988,7 +4988,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tree3 = stabilize(tree2, pre2, mode, pt)
// SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
// inference errors in pattern matching.
- tree3 setType dropRepeatedParamType(tree3.tpe)
+ tree3 setType dropIllegalStarTypes(tree3.tpe)
}
}
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 2c036b3308..97ad02c8a9 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3800,12 +3800,16 @@ trait Types extends api.Types { self: SymbolTable =>
// This is the specified behavior.
protected def etaExpandKeepsStar = false
- object dropRepeatedParamType extends TypeMap {
+ /** Turn any T* types into Seq[T] except when
+ * in method parameter position.
+ */
+ object dropIllegalStarTypes extends TypeMap {
def apply(tp: Type): Type = tp match {
case MethodType(params, restpe) =>
- MethodType(params, apply(restpe))
- case PolyType(tparams, restpe) =>
- PolyType(tparams, apply(restpe))
+ // Not mapping over params
+ val restpe1 = apply(restpe)
+ if (restpe eq restpe1) tp
+ else MethodType(params, restpe1)
case TypeRef(_, RepeatedParamClass, arg :: Nil) =>
seqType(arg)
case _ =>
@@ -4618,6 +4622,8 @@ trait Types extends api.Types { self: SymbolTable =>
/** A map to implement the `substSym` method. */
class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) {
+ def this(pairs: (Symbol, Symbol)*) = this(pairs.toList.map(_._1), pairs.toList.map(_._2))
+
protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
case TypeRef(pre, _, args) => copyTypeRef(fromtp, pre, sym, args)
case SingleType(pre, _) => singleType(pre, sym)
diff --git a/test/files/pos/t5859.scala b/test/files/pos/t5859.scala
new file mode 100644
index 0000000000..2a31e68ee5
--- /dev/null
+++ b/test/files/pos/t5859.scala
@@ -0,0 +1,15 @@
+
+class A {
+ def f(xs: List[Int], ys: AnyRef*) = ()
+ def f(xs: AnyRef*) = ()
+
+ f()
+ f(List[AnyRef](): _*)
+ f(List(): _*)
+ f(Nil: _*)
+ f(Array(): _*)
+ f(Array[AnyRef](): _*)
+ f(List(1))
+ f(List(1), Nil: _*)
+ f(List(1), Array(): _*)
+}