diff options
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/api/Symbols.scala | 26 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/BuildUtils.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 72 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Flags.scala | 3 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/HasFlags.scala | 1 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Mirrors.scala | 4 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdAttachments.scala | 17 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 1 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 336 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 11 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 16 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/pickling/UnPickler.scala | 6 | ||||
-rw-r--r-- | src/reflect/scala/reflect/makro/Universe.scala | 24 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaMirrors.scala | 21 |
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) |