diff options
author | Paul Phillips <paulp@improving.org> | 2012-04-06 11:58:05 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-06 11:58:05 -0700 |
commit | 8e179506e7c230a9ff01cda9584ce2a73953e446 (patch) | |
tree | 0bbcf7f956784646fb996b8c6a944a3d8155e80c /src/compiler | |
parent | 22c229e4ed2100d662fe05f9a610186ce1ebbb5a (diff) | |
parent | 115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b (diff) | |
download | scala-8e179506e7c230a9ff01cda9584ce2a73953e446.tar.gz scala-8e179506e7c230a9ff01cda9584ce2a73953e446.tar.bz2 scala-8e179506e7c230a9ff01cda9584ce2a73953e446.zip |
Merge commit 'pull/358/head' into develop
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/reflect/internal/Definitions.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/Symbols.scala | 67 |
2 files changed, 71 insertions, 4 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index e1740b621e..0fa2762c0f 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -386,10 +386,10 @@ trait Definitions extends reflect.api.StandardDefinitions { def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params) - def isJavaVarArgs(params: List[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe) - def isScalaVarArgs(params: List[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe) - def isVarArgsList(params: List[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe) - def isVarArgTypes(formals: List[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last) + def isJavaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe) + def isScalaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe) + def isVarArgsList(params: Seq[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe) + def isVarArgTypes(formals: Seq[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last) def hasRepeatedParam(tp: Type): Boolean = tp match { case MethodType(formals, restpe) => isScalaVarArgs(formals) || hasRepeatedParam(restpe) diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index cfab069588..dc72ac2338 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -76,6 +76,73 @@ trait Symbols extends api.Symbols { self: SymbolTable => def setInternalFlags(flag: Long): this.type = { setFlag(flag); this } def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this } def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this } + + private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head + + private def formalTypes(formals: List[Type], nargs: Int): List[Type] = { + val formals1 = formals mapConserve { + case TypeRef(_, ByNameParamClass, List(arg)) => arg + case formal => formal + } + 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 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) + } + } + 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) + } + } + 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 + } } /** The class for all symbols */ |