summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-07-13 12:08:20 -0700
committerPaul Phillips <paulp@improving.org>2012-07-13 12:08:20 -0700
commit453b7068ed4294eef18bf10a321a5b63497c7466 (patch)
tree8cfc64ec934fdf15d7665208a366611ce9474855 /src/reflect
parent724b0dc71f1f8f91b995d01e9e027789f54ecdfe (diff)
parent3d0099dbc990ab914de5b9deb5087d9d3fb6220c (diff)
downloadscala-453b7068ed4294eef18bf10a321a5b63497c7466.tar.gz
scala-453b7068ed4294eef18bf10a321a5b63497c7466.tar.bz2
scala-453b7068ed4294eef18bf10a321a5b63497c7466.zip
Merge branch '2.10.x' into topic/name-implicits
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala26
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala72
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala3
-rw-r--r--src/reflect/scala/reflect/internal/HasFlags.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala4
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala17
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala336
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala16
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala6
-rw-r--r--src/reflect/scala/reflect/makro/Universe.scala24
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala21
14 files changed, 389 insertions, 151 deletions
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index eb9921a31a..1d2888961b 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -232,7 +232,31 @@ 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
+ /** Performs method overloading resolution. More precisely, resolves an overloaded TermSymbol
+ * to a single, non-overloaded TermSymbol that accepts the specified argument types.
+ * @param pre The prefix type, i.e. the type of the value the method is dispatched on.
+ * This is required when resolving references to type parameters of the type
+ * the method is declared in. For example if the method is declared in class `List[A]`,
+ * providing the prefix as `List[Int]` allows the overloading resolution to use
+ * `Int` instead of `A`.
+ * @param targs Type arguments that a candidate alternative must be able to accept. Candidates
+ * will be considered with these arguments substituted for their corresponding
+ * type parameters.
+ * @param posVargs Positional argument types that a candidate alternative must be able to accept.
+ * @param nameVargs Named argument types that a candidate alternative must be able to accept.
+ * Each element in the sequence should be a pair of a parameter name and an
+ * argument type.
+ * @param expected Return type that a candidate alternative has to be compatible with.
+ * @return Either a single, non-overloaded Symbol referring to the selected alternative
+ * or NoSymbol if no single member could be selected given the passed arguments.
+ */
+ 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/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 0bf5aa4b69..ad59605760 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -20,7 +20,7 @@ trait BuildUtils extends base.BuildUtils { self: SymbolTable =>
val result = owner.info decl name
if (result ne NoSymbol) result
else
- mirrorThatLoaded(owner).tryMissingHooks(owner, name) orElse
+ mirrorThatLoaded(owner).missingHook(owner, name) orElse
MissingRequirementError.notFound("%s %s in %s".format(if (name.isTermName) "term" else "type", name, owner.fullName))
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 7891433b4f..60689d70fe 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -496,6 +496,9 @@ trait Definitions extends api.StandardDefinitions {
def MacroInternal_materializeAbsTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeAbsTypeTag)
def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag)
+ lazy val StringContextClass = requiredClass[scala.StringContext]
+ def StringContext_f = getMemberMethod(StringContextClass, nme.f)
+
lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
@@ -1125,6 +1128,39 @@ trait Definitions extends api.StandardDefinitions {
/** Is symbol a phantom class for which no runtime representation exists? */
lazy val isPhantomClass = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
+ lazy val magicSymbols = List(
+ AnnotationDefaultAttr, // #2264
+ RepeatedParamClass,
+ JavaRepeatedParamClass,
+ ByNameParamClass,
+ AnyClass,
+ AnyRefClass,
+ AnyValClass,
+ NullClass,
+ NothingClass,
+ SingletonClass,
+ EqualsPatternClass,
+ Any_==,
+ Any_!=,
+ Any_equals,
+ Any_hashCode,
+ Any_toString,
+ Any_getClass,
+ Any_isInstanceOf,
+ Any_asInstanceOf,
+ Any_##,
+ Object_eq,
+ Object_ne,
+ Object_==,
+ Object_!=,
+ Object_##,
+ Object_synchronized,
+ Object_isInstanceOf,
+ Object_asInstanceOf,
+ String_+,
+ ComparableClass,
+ JavaSerializableClass
+ )
/** Is the symbol that of a parent which is added during parsing? */
lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass
@@ -1188,41 +1224,7 @@ trait Definitions extends api.StandardDefinitions {
def init() {
if (isInitialized) return
-
- val forced = List( // force initialization of every symbol that is entered as a side effect
- AnnotationDefaultAttr, // #2264
- RepeatedParamClass,
- JavaRepeatedParamClass,
- ByNameParamClass,
- AnyClass,
- AnyRefClass,
- AnyValClass,
- NullClass,
- NothingClass,
- SingletonClass,
- EqualsPatternClass,
- Any_==,
- Any_!=,
- Any_equals,
- Any_hashCode,
- Any_toString,
- Any_getClass,
- Any_isInstanceOf,
- Any_asInstanceOf,
- Any_##,
- Object_eq,
- Object_ne,
- Object_==,
- Object_!=,
- Object_##,
- Object_synchronized,
- Object_isInstanceOf,
- Object_asInstanceOf,
- String_+,
- ComparableClass,
- JavaSerializableClass
- )
-
+ val forced = magicSymbols // force initialization of every symbol that is entered as a side effect
isInitialized = true
} //init
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 37e5a23819..352196fc69 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -135,7 +135,7 @@ class Flags extends ModifierFlags {
final val CAPTURED = 1 << 16 // variable is accessed from nested function. Set by LambdaLift.
final val LABEL = 1 << 17 // method symbol is a label. Set by TailCall
final val INCONSTRUCTOR = 1 << 17 // class symbol is defined in this/superclass constructor.
- final val SYNTHETIC = 1 << 21 // symbol is compiler-generated
+ final val SYNTHETIC = 1 << 21 // symbol is compiler-generated (compare with HIDDEN)
final val STABLE = 1 << 22 // functions that are assumed to be stable
// (typically, access methods for valdefs)
// or classes that do not contain abstract types.
@@ -165,6 +165,7 @@ class Flags extends ModifierFlags {
// A Java method's type is ``cooked'' by transforming raw types to existentials
final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED
+ final val HIDDEN = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode
// ------- shift definitions -------------------------------------------------------
final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1.
diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala
index c7c0882209..7ead9d6a1b 100644
--- a/src/reflect/scala/reflect/internal/HasFlags.scala
+++ b/src/reflect/scala/reflect/internal/HasFlags.scala
@@ -92,6 +92,7 @@ trait HasFlags {
def isCaseAccessor = hasFlag(CASEACCESSOR)
def isDeferred = hasFlag(DEFERRED)
def isFinal = hasFlag(FINAL)
+ def isHidden = hasFlag(HIDDEN)
def isImplicit = hasFlag(IMPLICIT)
def isInterface = hasFlag(INTERFACE)
def isJavaDefined = hasFlag(JAVA)
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index dedfd41e83..210af661ee 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -41,7 +41,7 @@ trait Mirrors extends api.Mirrors {
if (result != NoSymbol) result
else {
if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug
- tryMissingHooks(owner, name) orElse {
+ thisMirror.missingHook(owner, name) orElse {
MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path+" in "+thisMirror)
}
}
@@ -51,7 +51,7 @@ trait Mirrors extends api.Mirrors {
protected def symbolTableMissingHook(owner: Symbol, name: Name): Symbol = self.missingHook(owner, name)
- private[reflect] def tryMissingHooks(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse symbolTableMissingHook(owner, name)
+ private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse symbolTableMissingHook(owner, name)
/** If you're looking for a class, pass a type name.
* If a module, a term name.
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 4ea9b27da9..60b3a6f436 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -4,9 +4,24 @@ package internal
trait StdAttachments {
self: SymbolTable =>
+ /**
+ * Common code between reflect-internal Symbol and Tree related to Attachments.
+ */
+ trait Attachable {
+ protected var rawatt: base.Attachments { type Pos = Position } = NoPosition
+ def attachments = rawatt
+ def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this }
+ def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this }
+
+ // cannot be final due to SynchronizedSymbols
+ def pos: Position = rawatt.pos
+ def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos)
+ def setPos(newpos: Position): this.type = { pos = newpos; this }
+ }
+
case object BackquotedIdentifierAttachment
case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree])
case class MacroExpansionAttachment(original: Tree)
-} \ No newline at end of file
+}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 4070ad83c6..51dd309a61 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -665,6 +665,7 @@ trait StdNames {
val eval: NameType = "eval"
val ex: NameType = "ex"
val experimental: NameType = "experimental"
+ val f: NameType = "f"
val false_ : NameType = "false"
val filter: NameType = "filter"
val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 119c3d42fd..957202e448 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -10,6 +10,7 @@ import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
import util.Statistics
import Flags._
+import base.Attachments
trait Symbols extends api.Symbols { self: SymbolTable =>
import definitions._
@@ -82,71 +83,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
}
}
@@ -154,7 +364,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name)
extends SymbolContextApiImpl
with HasFlags
- with Annotatable[Symbol] {
+ with Annotatable[Symbol]
+ with Attachable {
type AccessBoundaryType = Symbol
type AnnotationType = AnnotationInfo
@@ -176,7 +387,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def rawowner = _rawowner
def rawflags = _rawflags
- private var rawpos = initPos
+ rawatt = initPos
val id = nextId() // identity displayed when -uniqid
//assert(id != 3390, initName)
@@ -189,8 +400,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def validTo = _validTo
def validTo_=(x: Period) { _validTo = x}
- def pos = rawpos
- def setPos(pos: Position): this.type = { this.rawpos = pos; this }
def setName(name: Name): this.type = { this.name = asNameType(name) ; this }
// Update the surrounding scopes
@@ -748,13 +957,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this symbol an accessor method for outer? */
final def isOuterAccessor = {
- hasFlag(STABLE | SYNTHETIC) &&
+ hasFlag(STABLE | HIDDEN) &&
originalName == nme.OUTER
}
/** Is this symbol an accessor method for outer? */
final def isOuterField = {
- hasFlag(SYNTHETIC) &&
+ hasFlag(HIDDEN) &&
originalName == nme.OUTER_LOCAL
}
@@ -1612,6 +1821,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
setInfo (this.info cloneInfo clone)
setAnnotations this.annotations
)
+ this.attachments.all.foreach(clone.addAttachment)
if (clone.thisSym != clone)
clone.typeOfThis = (clone.typeOfThis cloneInfo clone)
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index dd13dd4c4c..e92d644f4a 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -15,20 +15,13 @@ trait Trees extends api.Trees { self: SymbolTable =>
private[scala] var nodeCount = 0
- abstract class Tree extends TreeContextApiImpl with Product {
+ abstract class Tree extends TreeContextApiImpl with Attachable with Product {
val id = nodeCount // TODO: add to attachment?
nodeCount += 1
Statistics.incCounter(TreesStats.nodeByType, getClass)
- @inline final def pos: Position = rawatt.pos
- def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos)
- def setPos(newpos: Position): this.type = { pos = newpos; this }
-
- private var rawatt: Attachments { type Pos = Position } = NoPosition
- def attachments = rawatt
- def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this }
- def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this }
+ @inline final override def pos: Position = rawatt.pos
private[this] var rawtpe: Type = _
@inline final def tpe = rawtpe
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 96a6d4bba0..56cc265e48 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -4293,18 +4293,6 @@ trait Types extends api.Types { self: SymbolTable =>
qvar
}).tpe
- /** Return `pre.baseType(clazz)`, or if that's `NoType` and `clazz` is a refinement, `pre` itself.
- * See bug397.scala for an example where the second alternative is needed.
- * The problem is that when forming the base type sequence of an abstract type,
- * any refinements in the base type list might be regenerated, and thus acquire
- * new class symbols. However, since refinements always have non-interesting prefixes
- * it looks OK to me to just take the prefix directly. */
- def base(pre: Type, clazz: Symbol) = {
- val b = pre.baseType(clazz)
- if (b == NoType && clazz.isRefinementClass) pre
- else b
- }
-
def apply(tp: Type): Type =
if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
else tp match {
@@ -4325,7 +4313,7 @@ trait Types extends api.Types { self: SymbolTable =>
pre1
}
} else {
- toPrefix(base(pre, clazz).prefix, clazz.owner)
+ toPrefix(pre.baseType(clazz).prefix, clazz.owner)
}
toPrefix(pre, clazz)
case SingleType(pre, sym) =>
@@ -4405,7 +4393,7 @@ trait Types extends api.Types { self: SymbolTable =>
case t =>
throwError
}
- } else toInstance(base(pre, clazz).prefix, clazz.owner)
+ } else toInstance(pre.baseType(clazz).prefix, clazz.owner)
}
toInstance(pre, clazz)
case _ =>
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index 757163a074..4d8e932862 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -818,7 +818,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol =
- missingHook(owner, name) orElse MissingRequirementError.signal(
+ mirrorThatLoaded(owner).missingHook(owner, name) orElse MissingRequirementError.signal(
s"bad reference while unpickling $filename: ${name.longString} not found in ${owner.tpe.widen}"
)
@@ -832,8 +832,10 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
* Similar in intent to what SymbolLoader does (but here we don't have access to
* error reporting, so we rely on the typechecker to report the error).
*/
- def toTypeError(e: MissingRequirementError) =
+ def toTypeError(e: MissingRequirementError) = {
+ // e.printStackTrace()
new TypeError(e.msg)
+ }
/** A lazy type which when completed returns type at index `i`. */
private class LazyTypeRef(i: Int) extends LazyType {
diff --git a/src/reflect/scala/reflect/makro/Universe.scala b/src/reflect/scala/reflect/makro/Universe.scala
index 98046be555..a676f7f1de 100644
--- a/src/reflect/scala/reflect/makro/Universe.scala
+++ b/src/reflect/scala/reflect/makro/Universe.scala
@@ -5,13 +5,24 @@ abstract class Universe extends scala.reflect.api.Universe {
val treeBuild: TreeBuilder { val global: Universe.this.type }
+ trait AttachableApi {
+ /** ... */
+ def attachments: base.Attachments { type Pos = Position }
+
+ /** ... */
+ def addAttachment(attachment: Any): AttachableApi.this.type
+
+ /** ... */
+ def removeAttachment[T: ClassTag]: AttachableApi.this.type
+ }
+
// Symbol extensions ---------------------------------------------------------------
override type Symbol >: Null <: SymbolContextApi
/** The extended API of symbols that's supported in macro context universes
*/
- trait SymbolContextApi extends SymbolApi { this: Symbol =>
+ trait SymbolContextApi extends SymbolApi with AttachableApi { this: Symbol =>
// [Eugene++ to Martin] should we also add mutability methods here (similarly to what's done below for trees)?
// I'm talking about `setAnnotations` and friends
@@ -23,7 +34,7 @@ abstract class Universe extends scala.reflect.api.Universe {
/** The extended API of trees that's supported in macro context universes
*/
- trait TreeContextApi extends TreeApi { this: Tree =>
+ trait TreeContextApi extends TreeApi with AttachableApi { this: Tree =>
/** ... */
def pos_=(pos: Position): Unit
@@ -62,15 +73,6 @@ abstract class Universe extends scala.reflect.api.Universe {
/** ... */
def setSymbol(sym: Symbol): this.type
-
- /** ... */
- def attachments: base.Attachments { type Pos = Position }
-
- /** ... */
- def addAttachment(attachment: Any): this.type
-
- /** ... */
- def removeAttachment[T: ClassTag]: this.type
}
override type SymTree >: Null <: Tree with SymTreeContextApi
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index e147046410..185621efa4 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -999,10 +999,10 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
mirrors(rootToLoader getOrElseUpdate(root, findLoader)).get.get
}
- private def byName(sym: Symbol): (Name, Symbol) = sym.name -> sym
-
- private lazy val phantomTypes: Map[Name, Symbol] =
- Map(byName(definitions.AnyRefClass)) ++ (definitions.isPhantomClass map byName)
+ private lazy val magicSymbols: Map[(String, Name), Symbol] = {
+ def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym
+ Map() ++ (definitions.magicSymbols filter (_.isClass) map mapEntry)
+ }
/** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
* <owner>.<name>, otherwise return NoSymbol.
@@ -1020,13 +1020,12 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
if (name.isTermName && !owner.isEmptyPackageClass)
return mirror.makeScalaPackage(
if (owner.isRootSymbol) name.toString else owner.fullName+"."+name)
- if (owner.name.toTermName == nme.scala_ && owner.owner.isRoot)
- phantomTypes get name match {
- case Some(tsym) =>
- owner.info.decls enter tsym
- return tsym
- case None =>
- }
+ magicSymbols get (owner.fullName, name) match {
+ case Some(tsym) =>
+ owner.info.decls enter tsym
+ return tsym
+ case None =>
+ }
}
info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
super.missingHook(owner, name)