summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala323
-rw-r--r--test/files/run/reflect-resolveoverload-bynameparam.scala32
-rw-r--r--test/files/run/reflect-resolveoverload-expected.scala43
-rw-r--r--test/files/run/reflect-resolveoverload-invalid.scala43
-rw-r--r--test/files/run/reflect-resolveoverload-named.scala26
-rw-r--r--test/files/run/reflect-resolveoverload-targs.scala29
-rw-r--r--test/files/run/reflect-resolveoverload-tparm-substitute.scala77
-rw-r--r--test/files/run/reflect-resolveoverload-variadic.scala27
-rw-r--r--test/files/run/reflect-resolveoverload1.scala (renamed from test/files/run/reflect-overload.scala)4
-rw-r--r--test/files/run/reflect-resolveoverload2.scala40
11 files changed, 592 insertions, 60 deletions
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index eb9921a31a..11c7a38498 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -232,7 +232,13 @@ trait Symbols extends base.Symbols { self: Universe =>
/** The overloaded alternatives of this symbol */
def alternatives: List[Symbol]
- def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol
+ def resolveOverloaded(
+ pre: Type = NoPrefix,
+ targs: Seq[Type] = List(),
+ posVargs: Seq[Type] = List(),
+ nameVargs: Seq[(TermName, Type)] = List(),
+ expected: Type = NoType
+ ): Symbol
}
/** The API of type symbols */
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 119c3d42fd..3cb9f6ff37 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -82,71 +82,280 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def getAnnotations: List[AnnotationInfo] = { initialize; annotations }
def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
- private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head
+ def resolveOverloaded(
+ pre: Type,
+ targs: Seq[Type],
+ posVargTypes: Seq[Type],
+ nameVargTypes: Seq[(TermName, Type)],
+ expected: Type
+ ): Symbol = {
+
+ // Begin Correlation Helpers
+
+ def isCompatible(tp: Type, pt: Type): Boolean = {
+ def isCompatibleByName(tp: Type, pt: Type): Boolean = pt match {
+ case TypeRef(_, ByNameParamClass, List(res)) if !definitions.isByNameParamType(tp) =>
+ isCompatible(tp, res)
+ case _ =>
+ false
+ }
+ (tp <:< pt) || isCompatibleByName(tp, pt)
+ }
- private def formalTypes(formals: List[Type], nargs: Int): List[Type] = {
- val formals1 = formals mapConserve {
- case TypeRef(_, ByNameParamClass, List(arg)) => arg
- case formal => formal
+ def signatureAsSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = {
+ (substituteTypeParams(method1), substituteTypeParams(method2)) match {
+ case (NullaryMethodType(r1), NullaryMethodType(r2)) =>
+ r1 <:< r2
+ case (NullaryMethodType(_), MethodType(_, _)) =>
+ true
+ case (MethodType(_, _), NullaryMethodType(_)) =>
+ false
+ case (MethodType(p1, _), MethodType(p2, _)) =>
+ val len = p1.length max p2.length
+ val sub = extend(p1 map (_.typeSignature), len)
+ val sup = extend(p2 map (_.typeSignature), len)
+ (sub corresponds sup)(isCompatible)
+ }
}
- if (isVarArgTypes(formals1)) {
- val ft = lastElemType(formals)
- formals1.init ::: List.fill(nargs - (formals1.length - 1))(ft)
- } else formals1
- }
-
- def resolveOverloaded(pre: Type, targs: Seq[Type], actuals: Seq[Type]): Symbol = {
- def firstParams(tpe: Type): (List[Symbol], List[Type]) = tpe match {
- case PolyType(tparams, restpe) =>
- val (Nil, formals) = firstParams(restpe)
- (tparams, formals)
- case MethodType(params, _) =>
- (Nil, params map (_.tpe))
- case _ =>
- (Nil, Nil)
+
+ def scopeMoreSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = {
+ val o1 = method1.owner.asClassSymbol
+ val o2 = method2.owner.asClassSymbol
+ val c1 = if (o1.hasFlag(Flag.MODULE)) o1.companionSymbol else o1
+ val c2 = if (o2.hasFlag(Flag.MODULE)) o2.companionSymbol else o2
+ c1.typeSignature <:< c2.typeSignature
}
- def isApplicable(alt: Symbol, targs: List[Type], actuals: Seq[Type]) = {
- def isApplicableType(tparams: List[Symbol], tpe: Type): Boolean = {
- val (tparams, formals) = firstParams(pre memberType alt)
- val formals1 = formalTypes(formals, actuals.length)
- val actuals1 =
- if (isVarArgTypes(actuals)) {
- if (!isVarArgTypes(formals)) return false
- actuals.init :+ lastElemType(actuals)
- } else actuals
- if (formals1.length != actuals1.length) return false
-
- if (tparams.isEmpty) return (actuals1 corresponds formals1)(_ <:< _)
-
- if (targs.length == tparams.length)
- isApplicableType(List(), tpe.instantiateTypeParams(tparams, targs))
- else if (targs.nonEmpty)
- false
- else {
- val tvars = tparams map (TypeVar(_))
- (actuals1 corresponds formals1) { (actual, formal) =>
- val tp1 = actual.deconst.instantiateTypeParams(tparams, tvars)
- val pt1 = actual.instantiateTypeParams(tparams, tvars)
- tp1 <:< pt1
- } &&
- solve(tvars, tparams, List.fill(tparams.length)(COVARIANT), upper = false)
+
+ def moreSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = {
+ def points(m1: MethodSymbol, m2: MethodSymbol) = {
+ val p1 = if (signatureAsSpecific(m1, m2)) 1 else 0
+ val p2 = if (scopeMoreSpecific(m1, m2)) 1 else 0
+ p1 + p2
+ }
+ points(method1, method2) > points(method2, method1)
+ }
+
+ def combineInto (
+ variadic: Boolean
+ )(
+ positional: Seq[Type],
+ named: Seq[(TermName, Type)]
+ )(
+ target: Seq[TermName],
+ defaults: Map[Int, Type]
+ ): Option[Seq[Type]] = {
+
+ val offset = positional.length
+ val unfilled = target.zipWithIndex drop offset
+ val canAcceptAllNameVargs = named forall { case (argName, _) =>
+ unfilled exists (_._1 == argName)
+ }
+
+ val paramNamesUnique = {
+ named.length == named.map(_._1).distinct.length
+ }
+
+ if (canAcceptAllNameVargs && paramNamesUnique) {
+
+ val rest = unfilled map { case (paramName, paramIndex) =>
+ val passedIn = named.collect {
+ case (argName, argType) if argName == paramName => argType
+ }.headOption
+ if (passedIn isDefined) passedIn
+ else defaults.get(paramIndex).map(_.asInstanceOf[Type])
+ }
+
+ val rest1 = {
+ if (variadic && !rest.isEmpty && !rest.last.isDefined) rest.init
+ else rest
}
+
+
+ if (rest1 forall (_.isDefined)) {
+ val joined = positional ++ rest1.map(_.get)
+ val repeatedCollapsed = {
+ if (variadic) {
+ val (normal, repeated) = joined.splitAt(target.length - 1)
+ if (repeated.forall(_ =:= repeated.head)) Some(normal ++ repeated.headOption)
+ else None
+ }
+ else Some(joined)
+ }
+ if (repeatedCollapsed.exists(_.length == target.length))
+ repeatedCollapsed
+ else if (variadic && repeatedCollapsed.exists(_.length == target.length - 1))
+ repeatedCollapsed
+ else None
+ } else None
+
+ } else None
+ }
+
+ // Begin Reflection Helpers
+
+ // Replaces a repeated parameter type at the end of the parameter list
+ // with a number of non-repeated parameter types in order to pad the
+ // list to be nargs in length
+ def extend(types: Seq[Type], nargs: Int): Seq[Type] = {
+ if (isVarArgTypes(types)) {
+ val repeatedType = types.last.normalize.typeArgs.head
+ types.init ++ Seq.fill(nargs - (types.length - 1))(repeatedType)
+ } else types
+ }
+
+ // Replaces by-name parameters with their result type and
+ // TypeRefs with the thing they reference
+ def unwrap(paramType: Type): Type = paramType match {
+ case TypeRef(_, IntClass, _) => typeOf[Int]
+ case TypeRef(_, LongClass, _) => typeOf[Long]
+ case TypeRef(_, ShortClass, _) => typeOf[Short]
+ case TypeRef(_, ByteClass, _) => typeOf[Byte]
+ case TypeRef(_, CharClass, _) => typeOf[Char]
+ case TypeRef(_, FloatClass, _) => typeOf[Float]
+ case TypeRef(_, DoubleClass, _) => typeOf[Double]
+ case TypeRef(_, BooleanClass, _) => typeOf[Boolean]
+ case TypeRef(_, UnitClass, _) => typeOf[Unit]
+ case TypeRef(_, NullClass, _) => typeOf[Null]
+ case TypeRef(_, AnyClass, _) => typeOf[Any]
+ case TypeRef(_, NothingClass, _) => typeOf[Nothing]
+ case TypeRef(_, AnyRefClass, _) => typeOf[AnyRef]
+ case TypeRef(_, ByNameParamClass, List(resultType)) => unwrap(resultType)
+ case t: Type => t
+ }
+
+ // Gives the names of the parameters to a method
+ def paramNames(signature: Type): Seq[TermName] = signature match {
+ case PolyType(_, resultType) => paramNames(resultType)
+ case MethodType(params, _) => params.map(_.name.asInstanceOf[TermName])
+ case NullaryMethodType(_) => Seq.empty
+ }
+
+ def valParams(signature: Type): Seq[TermSymbol] = signature match {
+ case PolyType(_, resultType) => valParams(resultType)
+ case MethodType(params, _) => params.map(_.asTermSymbol)
+ case NullaryMethodType(_) => Seq.empty
+ }
+
+ // Returns a map from parameter index to default argument type
+ def defaultTypes(method: MethodSymbol): Map[Int, Type] = {
+ val typeSig = substituteTypeParams(method)
+ val owner = method.owner
+ valParams(typeSig).zipWithIndex.filter(_._1.hasFlag(Flag.DEFAULTPARAM)).map { case(_, index) =>
+ val name = nme.defaultGetterName(method.name.decodedName, index + 1)
+ val default = owner.asType member name
+ index -> default.typeSignature.asInstanceOf[NullaryMethodType].resultType
+ }.toMap
+ }
+
+ // True if any of method's parameters have default values. False otherwise.
+ def usesDefault(method: MethodSymbol): Boolean = valParams(method.typeSignature) drop(posVargTypes).length exists { param =>
+ (param hasFlag Flag.DEFAULTPARAM) && nameVargTypes.forall { case (argName, _) =>
+ param.name != argName
+ }
+ }
+
+ // The number of type parameters that the method takes
+ def numTypeParams(x: MethodSymbol): Int = {
+ x.typeSignature.typeParams.length
+ }
+
+ def substituteTypeParams(m: MethodSymbol): Type = {
+ (pre memberType m) match {
+ case m: MethodType => m
+ case n: NullaryMethodType => n
+ case PolyType(tparams, rest) => rest.substituteTypes(tparams, targs.toList)
}
- isApplicableType(List(), pre.memberType(alt))
}
- def isAsGood(alt1: Symbol, alt2: Symbol): Boolean = {
- alt1 == alt2 ||
- alt2 == NoSymbol || {
- val (tparams, formals) = firstParams(pre memberType alt1)
- isApplicable(alt2, tparams map (_.tpe), formals)
+
+ // Begin Selection Helpers
+
+ def select(
+ alternatives: Seq[MethodSymbol],
+ filters: Seq[Seq[MethodSymbol] => Seq[MethodSymbol]]
+ ): Seq[MethodSymbol] =
+ filters.foldLeft(alternatives)((a, f) => {
+ if (a.size > 1) f(a) else a
+ })
+
+ // Drop arguments that take the wrong number of type
+ // arguments.
+ val posTargLength: Seq[MethodSymbol] => Seq[MethodSymbol] = _.filter { alt =>
+ numTypeParams(alt) == targs.length
+ }
+
+ // Drop methods that are not applicable to the arguments
+ val applicable: Seq[MethodSymbol] => Seq[MethodSymbol] = _.filter { alt =>
+ // Note: combine returns None if a is not applicable and
+ // None.exists(_ => true) == false
+ val paramTypes =
+ valParams(substituteTypeParams(alt)).map(p => unwrap(p.typeSignature))
+ val variadic = isVarArgTypes(paramTypes)
+ val maybeArgTypes =
+ combineInto(variadic)(posVargTypes, nameVargTypes)(paramNames(alt.typeSignature), defaultTypes(alt))
+ maybeArgTypes exists { argTypes =>
+ if (isVarArgTypes(argTypes) && !isVarArgTypes(paramTypes)) false
+ else {
+ val a = argTypes
+ val p = extend(paramTypes, argTypes.length)
+ (a corresponds p)(_ <:< _)
}
+ }
}
- assert(isOverloaded)
- val applicables = alternatives filter (isApplicable(_, targs.toList, actuals))
- def winner(alts: List[Symbol]) =
- ((NoSymbol: Symbol) /: alts)((best, alt) => if (isAsGood(alt, best)) alt else best)
- val best = winner(applicables)
- if (best == winner(applicables.reverse)) best else NoSymbol
+
+ // Always prefer methods that don't need to use default
+ // arguments over those that do.
+ // e.g. when resolving foo(1), prefer def foo(x: Int) over
+ // def foo(x: Int, y: Int = 4)
+ val noDefaults: Seq[MethodSymbol] => Seq[MethodSymbol] =
+ _ filterNot usesDefault
+
+ // Try to select the most specific method. If that's not possible,
+ // return all of the candidates (this will likely cause an error
+ // higher up in the call stack)
+ val mostSpecific: Seq[MethodSymbol] => Seq[MethodSymbol] = { alts =>
+ val sorted = alts.sortWith(moreSpecific)
+ val mostSpecific = sorted.head
+ val agreeTest: MethodSymbol => Boolean =
+ moreSpecific(mostSpecific, _)
+ val disagreeTest: MethodSymbol => Boolean =
+ moreSpecific(_, mostSpecific)
+ if (!sorted.tail.forall(agreeTest)) {
+ mostSpecific +: sorted.tail.filterNot(agreeTest)
+ } else if (sorted.tail.exists(disagreeTest)) {
+ mostSpecific +: sorted.tail.filter(disagreeTest)
+ } else {
+ Seq(mostSpecific)
+ }
+ }
+
+ def finalResult(t: Type): Type = t match {
+ case PolyType(_, rest) => finalResult(rest)
+ case MethodType(_, result) => finalResult(result)
+ case NullaryMethodType(result) => finalResult(result)
+ case t: Type => t
+ }
+
+ // If a result type is given, drop alternatives that don't meet it
+ val resultType: Seq[MethodSymbol] => Seq[MethodSymbol] =
+ if (expected == NoType) identity
+ else _.filter { alt =>
+ finalResult(substituteTypeParams(alt)) <:< expected
+ }
+
+ def defaultFilteringOps =
+ Seq(posTargLength, resultType, applicable, noDefaults, mostSpecific)
+
+ // Begin Method Proper
+
+
+ val alts = alternatives.map(_.asMethodSymbol)
+
+ val selection = select(alts, defaultFilteringOps)
+
+ val knownApplicable = applicable(selection)
+
+ if (knownApplicable.size == 1) knownApplicable.head
+ else NoSymbol
}
}
diff --git a/test/files/run/reflect-resolveoverload-bynameparam.scala b/test/files/run/reflect-resolveoverload-bynameparam.scala
new file mode 100644
index 0000000000..7fb8c82ab8
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-bynameparam.scala
@@ -0,0 +1,32 @@
+
+class A
+class B extends A
+
+class C {
+ def foo(x: => Int)(y: String) = x
+ def foo(x: String)(y: List[_]) = x
+ def foo(x: => A)(y: Array[_]) = 1
+ def foo(x: A)(y: Seq[_]) = 2
+ def foo(x: B)(y: Map[_, _]) = 4
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val c = new C
+ val im = cm.reflect(c)
+ val t = u.typeOf[C] member u.newTermName("foo") asTermSymbol
+ val f1 = t.resolveOverloaded(posVargs = List(u.typeOf[Int])) asMethodSymbol
+ val f2 = t.resolveOverloaded(posVargs = List(u.typeOf[String])) asMethodSymbol
+ val f3 = t.resolveOverloaded(posVargs = List(u.typeOf[A])) asMethodSymbol
+ val f4 = t.resolveOverloaded(posVargs = List(u.typeOf[B])) asMethodSymbol
+ val m1 = im.reflectMethod(f1)
+ val m2 = im.reflectMethod(f2)
+ val m3 = im.reflectMethod(f3)
+ val m4 = im.reflectMethod(f4)
+ assert(m1(() => 1, null) == c.foo(1)(null))
+ assert(m2("a", null) == c.foo("a")(null))
+ assert(m3(new A, null) == c.foo(new A)(null))
+ assert(m4(new B, null) == c.foo(new B)(null))
+}
+
diff --git a/test/files/run/reflect-resolveoverload-expected.scala b/test/files/run/reflect-resolveoverload-expected.scala
new file mode 100644
index 0000000000..1378090309
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-expected.scala
@@ -0,0 +1,43 @@
+
+class A {
+ override def equals(x: Any) = {
+ x.isInstanceOf[A] && !x.isInstanceOf[B]
+ }
+}
+class B extends A {
+ override def equals(x: Any) = {
+ x.isInstanceOf[B]
+ }
+}
+
+class C {
+ def a(x: String) = 1
+ def a(x: Array[_]) = "a"
+ def b(x: String) = new A
+ def b(x: Array[_]) = new B
+ def c(x: String) = new B
+ def c(x: Array[_]) = "a"
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val c = new C
+ val im = cm.reflect(c)
+ def invoke(s: String, expectedType: u.Type, expectedResult: Any) {
+ val ol = (u.typeOf[C] member u.newTermName(s)).asTermSymbol
+ val methodSym = ol.resolveOverloaded(posVargs = List(u.typeOf[Null]), expected = expectedType).asMethodSymbol
+ val sig = methodSym.typeSignature.asInstanceOf[u.MethodType]
+ val method = im.reflectMethod(methodSym)
+ assert(method(null) == expectedResult)
+ }
+
+ invoke("a", u.typeOf[Int], c.a(null): Int)
+ invoke("a", u.typeOf[String], c.a(null): String)
+ invoke("b", u.typeOf[B], c.b(null): B)
+ invoke("c", u.typeOf[A], c.c(null): A)
+ invoke("c", u.typeOf[A], c.c(null): A)
+ invoke("c", u.typeOf[B], c.c(null): B)
+ invoke("c", u.typeOf[String], c.c(null): String)
+
+}
diff --git a/test/files/run/reflect-resolveoverload-invalid.scala b/test/files/run/reflect-resolveoverload-invalid.scala
new file mode 100644
index 0000000000..def28ccbb4
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-invalid.scala
@@ -0,0 +1,43 @@
+
+class A
+class B extends A
+
+class C {
+ def a(x: Int) = 1
+ def a(x: String) = 2
+ def b(x: B) = 3
+ def c(x: A, y: B) = 4
+ def c(x: B, y: A) = 5
+ def d[T](x: Int) = 6
+ def d(x: String) = 7
+ def e(x: A) = 8
+ def e(x: =>B) = 9
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+
+ val x = new C
+ val t = u.typeOf[C]
+
+ val a = t member u.newTermName("a") asTermSymbol
+ val b = t member u.newTermName("b") asTermSymbol
+ val c = t member u.newTermName("c") asTermSymbol
+ val d = t member u.newTermName("d") asTermSymbol
+ val e = t member u.newTermName("e") asTermSymbol
+
+ val n1 = a.resolveOverloaded(posVargs = List(u.typeOf[Char]))
+ val n2 = b.resolveOverloaded(posVargs = List(u.typeOf[A]))
+ val n3 = c.resolveOverloaded(posVargs = List(u.typeOf[B], u.typeOf[B]))
+ val n4 = d.resolveOverloaded(targs = List(u.typeOf[Int]))
+ val n5 = d.resolveOverloaded()
+ val n6 = e.resolveOverloaded(posVargs = List(u.typeOf[B]))
+
+ assert(n1 == u.NoSymbol)
+ assert(n2 == u.NoSymbol)
+ assert(n3 == u.NoSymbol)
+ assert(n4 == u.NoSymbol)
+ assert(n5 == u.NoSymbol)
+ assert(n6 == u.NoSymbol)
+}
diff --git a/test/files/run/reflect-resolveoverload-named.scala b/test/files/run/reflect-resolveoverload-named.scala
new file mode 100644
index 0000000000..017ec85c0d
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-named.scala
@@ -0,0 +1,26 @@
+
+class A {
+ def foo(x: String, y: Int) = 1
+ def foo(x: Int, y: String) = 2
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val a = new A
+ val im = cm.reflect(a)
+ val tpe = u.typeOf[A]
+ val overloaded = tpe member u.newTermName("foo") asTermSymbol
+ val ms1 =
+ overloaded resolveOverloaded(nameVargs = Seq((u.newTermName("x"), u.typeOf[String]), (u.newTermName("y"), u.typeOf[Int])))
+ val ms2 =
+ overloaded resolveOverloaded(nameVargs = Seq((u.newTermName("y"), u.typeOf[Int]), (u.newTermName("x"), u.typeOf[String])))
+ val ms3 =
+ overloaded resolveOverloaded(nameVargs = Seq((u.newTermName("x"), u.typeOf[Int]), (u.newTermName("y"), u.typeOf[String])))
+ val ms4 =
+ overloaded resolveOverloaded(nameVargs = Seq((u.newTermName("y"), u.typeOf[String]), (u.newTermName("x"), u.typeOf[Int])))
+ assert(im.reflectMethod(ms1 asMethodSymbol)("A", 1) == 1)
+ assert(im.reflectMethod(ms2 asMethodSymbol)("A", 1) == 1)
+ assert(im.reflectMethod(ms3 asMethodSymbol)(1, "A") == 2)
+ assert(im.reflectMethod(ms4 asMethodSymbol)(1, "A") == 2)
+}
diff --git a/test/files/run/reflect-resolveoverload-targs.scala b/test/files/run/reflect-resolveoverload-targs.scala
new file mode 100644
index 0000000000..888b2f0c15
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-targs.scala
@@ -0,0 +1,29 @@
+
+import reflect.runtime.{universe=>u}
+import scala.reflect.runtime.{currentMirror => cm}
+
+class C {
+ def foo[T: u.TypeTag](x: String) = 1
+ def foo[T: u.TypeTag, S: u.TypeTag](x: String) = 2
+}
+
+object Test extends App {
+ val c = new C
+ val im = cm.reflect(c)
+ val foo = u.typeOf[C] member u.newTermName("foo") asTermSymbol
+ val f1 = foo.resolveOverloaded(
+ targs = Seq(u.typeOf[Int]),
+ posVargs = Seq(u.typeOf[String])
+ )
+
+ val f2 = foo.resolveOverloaded(
+ targs = Seq(u.typeOf[Int],
+ u.typeOf[Int]), posVargs = Seq(u.typeOf[String])
+ )
+
+ val m1 = im.reflectMethod(f1 asMethodSymbol)
+ val m2 = im.reflectMethod(f2 asMethodSymbol)
+
+ assert(m1("a", u.typeTag[Int]) == c.foo[Int]("a"))
+ assert(m2("a", u.typeTag[Int], u.typeTag[Int]) == c.foo[Int, Int]("a"))
+}
diff --git a/test/files/run/reflect-resolveoverload-tparm-substitute.scala b/test/files/run/reflect-resolveoverload-tparm-substitute.scala
new file mode 100644
index 0000000000..22e7bcd40a
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-tparm-substitute.scala
@@ -0,0 +1,77 @@
+
+class A
+class B extends A
+
+class C {
+ def foo[T](x: T) = x
+ def foo(x: Int) = "a"
+ def foo(x: A) = x
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val c = new C
+ val im = cm.reflect(c)
+ val term = u.typeOf[C] member u.newTermName("foo") asTermSymbol
+
+ val f1 = term.resolveOverloaded(
+ posVargs = List(u.typeOf[Int]),
+ expected = u.typeOf[String]
+ )
+
+ val f2 = term.resolveOverloaded(
+ targs = List(u.typeOf[String]),
+ posVargs = List(u.typeOf[String]),
+ expected = u.typeOf[String]
+ )
+
+ val f3 = term.resolveOverloaded(
+ posVargs = List(u.typeOf[A]),
+ expected = u.typeOf[A]
+ )
+
+ val f4 = term.resolveOverloaded(
+ targs = List(u.typeOf[A]),
+ posVargs = List(u.typeOf[A]),
+ expected = u.typeOf[A]
+ )
+
+ val f5 = term.resolveOverloaded(
+ targs = List(u.typeOf[B]),
+ posVargs = List(u.typeOf[B]),
+ expected = u.typeOf[B]
+ )
+
+ val f6 = term.resolveOverloaded(
+ targs = List(u.typeOf[B]),
+ posVargs = List(u.typeOf[B]),
+ expected = u.typeOf[A]
+ )
+
+ val f7 = term.resolveOverloaded(
+ targs = List(u.typeOf[A]),
+ posVargs = List(u.typeOf[B]),
+ expected = u.typeOf[A]
+ )
+
+ val m1 = im.reflectMethod(f1 asMethodSymbol)
+ val m2 = im.reflectMethod(f2 asMethodSymbol)
+ val m3 = im.reflectMethod(f3 asMethodSymbol)
+ val m4 = im.reflectMethod(f4 asMethodSymbol)
+ val m5 = im.reflectMethod(f5 asMethodSymbol)
+ val m6 = im.reflectMethod(f6 asMethodSymbol)
+ val m7 = im.reflectMethod(f7 asMethodSymbol)
+
+ val a = new A
+ val b = new B
+ assert(m1(2) == (c.foo(2): String))
+ assert(m2("xyz") == (c.foo[String]("xyz"): String))
+ assert(m3(a) == (c.foo(a): A))
+ assert(m4(a) == (c.foo[A](a): A))
+ assert(m5(b) == (c.foo[B](b): B))
+ assert(m6(b) == (c.foo[B](b): A))
+ assert(m7(b) == (c.foo[A](b): A))
+
+
+}
diff --git a/test/files/run/reflect-resolveoverload-variadic.scala b/test/files/run/reflect-resolveoverload-variadic.scala
new file mode 100644
index 0000000000..8e2e15600f
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload-variadic.scala
@@ -0,0 +1,27 @@
+
+class C {
+ def foo(x: Int*) = 1 + x.sum
+ def foo(x: String) = 2
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val c = new C
+ val im = cm.reflect(c)
+ val foo = u.typeOf[C] member u.newTermName("foo") asTermSymbol
+ val f0 = foo.resolveOverloaded()
+ val f1 = foo.resolveOverloaded(posVargs = Seq(u.typeOf[Int]))
+ val f2 = foo.resolveOverloaded(posVargs = Seq(u.typeOf[Int], u.typeOf[Int]))
+ val f3 = foo.resolveOverloaded(posVargs = Seq(u.typeOf[String]))
+
+ val m0 = im.reflectMethod(f0 asMethodSymbol)
+ val m1 = im.reflectMethod(f1 asMethodSymbol)
+ val m2 = im.reflectMethod(f2 asMethodSymbol)
+ val m3 = im.reflectMethod(f3 asMethodSymbol)
+
+ assert(m0(Seq()) == c.foo())
+ assert(m1(Seq(1)) == c.foo(1))
+ assert(m2(Seq(4, 9)) == c.foo(4, 9))
+ assert(m3("abc") == c.foo("abc"))
+}
diff --git a/test/files/run/reflect-overload.scala b/test/files/run/reflect-resolveoverload1.scala
index 870a200813..a859a0ec4e 100644
--- a/test/files/run/reflect-overload.scala
+++ b/test/files/run/reflect-resolveoverload1.scala
@@ -9,11 +9,11 @@ object Test extends App {
val st = sc.asType
val meth = (st member newTermName("indexOf")).asTermSymbol
val IntType = definitions.IntClass.asType
- val indexOf = (meth resolveOverloaded(actuals = List(IntType))).asMethodSymbol
+ val indexOf = (meth resolveOverloaded(posVargs = List(IntType))).asMethodSymbol
assert(m.reflectMethod(indexOf)('w') == 6)
assert((m.reflectMethod(indexOf)('w') match { case x: Int => x }) == 6)
val meth2 = (st member newTermName("substring")).asTermSymbol
- val substring = (meth2 resolveOverloaded(actuals = List(IntType, IntType))).asMethodSymbol
+ val substring = (meth2 resolveOverloaded(posVargs = List(IntType, IntType))).asMethodSymbol
assert(m.reflectMethod(substring)(2, 6) == "llo ")
}
diff --git a/test/files/run/reflect-resolveoverload2.scala b/test/files/run/reflect-resolveoverload2.scala
new file mode 100644
index 0000000000..b5f719814b
--- /dev/null
+++ b/test/files/run/reflect-resolveoverload2.scala
@@ -0,0 +1,40 @@
+class A
+class B extends A
+
+class C {
+ def a(x: Int) = 1
+ def a(x: String) = 2
+ //def b(x: => Int)(s: String) = 1
+ //def b(x: => String)(a: Array[_]) = 2
+ def c(x: A) = 1
+ def c(x: B) = 2
+ //def d(x: => A)(s: String) = 1
+ //def d(x: => B)(a: Array[_]) = 2
+ def e(x: A) = 1
+ def e(x: B = new B) = 2
+}
+
+object Test extends App {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val c = new C
+ val im = cm.reflect(c)
+ def invoke(s: String, arg: Any, argType: u.Type): Int = {
+ val ol = u.typeOf[C] member u.newTermName(s) asTermSymbol
+ val methodSym = ol.resolveOverloaded(posVargs = List(argType)) asMethodSymbol
+ val sig = methodSym.typeSignature.asInstanceOf[u.MethodType]
+ val method = im.reflectMethod(methodSym)
+ if (sig.resultType.kind == "MethodType") method(arg, null).asInstanceOf[Int]
+ else method(arg).asInstanceOf[Int]
+ }
+ assert(c.a(1) == invoke("a", 1, u.typeOf[Int]))
+ assert(c.a("a") == invoke("a", "a", u.typeOf[String]))
+ //assert(c.b(1)(null) == invoke("b", 1, u.typeOf[Int]))
+ //assert(c.b("a")(null) == invoke("b", "a", u.typeOf[String]))
+ assert(c.c(new A) == invoke("c", new A, u.typeOf[A]))
+ assert(c.c(new B) == invoke("c", new B, u.typeOf[B]))
+ //assert(c.d(new A)(null) == invoke("d", new A, u.typeOf[A]))
+ //assert(c.d(new B)(null) == invoke("d", new B, u.typeOf[B]))
+ assert(c.e(new A) == invoke("e", new A, u.typeOf[A]))
+ assert(c.e(new B) == invoke("e", new B, u.typeOf[B]))
+}