diff options
Diffstat (limited to 'src/reflect')
17 files changed, 203 insertions, 72 deletions
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index d3294dad9b..2d5d1d5d6b 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -173,6 +173,7 @@ trait FlagSets { self: Universe => * - the enum's class * - enum constants **/ + @deprecated("Use `isJavaEnum` on the corresponding symbol instead.", since = "2.11.8") val ENUM: FlagSet /** Flag indicating that tree represents a parameter of the primary constructor of some class diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index c01029d067..9e9fe5d67b 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -228,7 +228,7 @@ trait Symbols { self: Universe => throw new ScalaReflectionException(s"$this $msg") } - /** Used to provide a better error message for `asMethod` + /** Used to provide a better error message for `asMethod`. * * @group Tests */ @@ -257,7 +257,7 @@ trait Symbols { self: Universe => def isClass: Boolean = false /** Does this symbol represent the definition of a class implicitly associated - * with an object definition (module class in scala compiler parlance). + * with an object definition (module class in scala compiler parlance)? * If yes, `isType` is also guaranteed to be true. * * Note to compiler developers: During the "mixin" phase, trait implementation class symbols @@ -294,7 +294,7 @@ trait Symbols { self: Universe => /** For a class: the module or case class factory with the same name in the same package. * For a module: the class with the same name in the same package. - * For all others: NoSymbol + * For all others: NoSymbol. * * This API may return unexpected results for module classes, packages and package classes. * Use `companion` instead in order to get predictable results. @@ -345,7 +345,7 @@ trait Symbols { self: Universe => */ def overrides: List[Symbol] - /** The overloaded alternatives of this symbol + /** The overloaded alternatives of this symbol. * * @group Basics */ @@ -370,7 +370,7 @@ trait Symbols { self: Universe => /** Does this symbol represent a declaration or definition written in a source file as `private[this]` * or generated in tree/symbol form with the combination of flags LOCAL and PRIVATE? - * If yes, `isPrivate` is guaranteed to be true, + * If yes, `isPrivate` is guaranteed to be true. * * @group Tests */ @@ -504,6 +504,18 @@ trait Symbols { self: Universe => */ def isImplicit: Boolean + /** Does this symbol represent a java enum class or a java enum value? + * + * @group Tests + */ + def isJavaEnum: Boolean + + /** Does this symbol represent a java annotation interface? + * + * @group Tests + */ + def isJavaAnnotation: Boolean + /******************* helpers *******************/ /** Provides an alternate if symbol is a NoSymbol. @@ -678,7 +690,7 @@ trait Symbols { self: Universe => */ def toTypeIn(site: Type): Type - /** A type reference that refers to this type symbol + /** A type reference that refers to this type symbol. * Note if symbol is a member of a class, one almost always is interested * in `asTypeIn` with a site type instead. * @@ -727,7 +739,7 @@ trait Symbols { self: Universe => */ def isExistential : Boolean - /** For a polymorphic type, its type parameters, the empty list for all other types + /** For a polymorphic type, its type parameters, the empty list for all other types. * * @group Type */ @@ -756,12 +768,13 @@ trait Symbols { self: Universe => */ def typeParams: List[Symbol] - /** @see [[paramLists]] */ + /** @see [[paramLists]] + * + * The name ending with "ss" indicates that the result type is a list of lists. */ @deprecated("Use `paramLists` instead", "2.11.0") def paramss: List[List[Symbol]] /** All parameter lists of the method. - * The name ending with "ss" indicates that the result type is a list of lists. * * Can be used to distinguish nullary methods and methods with empty parameter lists. * For a nullary method, returns the empty list (i.e. `List()`). @@ -777,7 +790,7 @@ trait Symbols { self: Universe => */ def isVarargs: Boolean - /** The return type of the method + /** The return type of the method. * * @group Method */ @@ -911,7 +924,7 @@ trait Symbols { self: Universe => */ def superPrefix(supertpe: Type): Type - /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait + /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait. * * @group Class */ diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 0bdf5b4647..5ce5c39145 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -233,6 +233,8 @@ trait Definitions extends api.StandardDefinitions { || tp =:= AnyRefTpe ) + def isUnitType(tp: Type) = tp.typeSymbol == UnitClass && tp.annotations.isEmpty + def hasMultipleNonImplicitParamLists(member: Symbol): Boolean = hasMultipleNonImplicitParamLists(member.info) def hasMultipleNonImplicitParamLists(info: Type): Boolean = info match { case PolyType(_, restpe) => hasMultipleNonImplicitParamLists(restpe) @@ -795,7 +797,9 @@ trait Definitions extends api.StandardDefinitions { * The class defining the method is a supertype of `tp` that * has a public no-arg primary constructor. */ - def samOf(tp: Type): Symbol = if (!settings.Xexperimental) NoSymbol else { + def samOf(tp: Type): Symbol = if (!settings.Xexperimental) NoSymbol else findSam(tp) + + def findSam(tp: Type): Symbol = { // if tp has a constructor, it must be public and must not take any arguments // (not even an implicit argument list -- to keep it simple for now) val tpSym = tp.typeSymbol @@ -1103,6 +1107,7 @@ trait Definitions extends api.StandardDefinitions { lazy val BridgeClass = requiredClass[scala.annotation.bridge] lazy val ElidableMethodClass = requiredClass[scala.annotation.elidable] lazy val ImplicitNotFoundClass = requiredClass[scala.annotation.implicitNotFound] + lazy val ImplicitAmbiguousClass = getClassIfDefined("scala.annotation.implicitAmbiguous") lazy val MigrationAnnotationClass = requiredClass[scala.annotation.migration] lazy val ScalaStrictFPAttr = requiredClass[scala.annotation.strictfp] lazy val SwitchClass = requiredClass[scala.annotation.switch] @@ -1517,7 +1522,7 @@ trait Definitions extends api.StandardDefinitions { def isPolymorphicSignature(sym: Symbol) = PolySigMethods(sym) private lazy val PolySigMethods: Set[Symbol] = Set[Symbol](MethodHandle.info.decl(sn.Invoke), MethodHandle.info.decl(sn.InvokeExact)).filter(_.exists) - lazy val Scala_Java8_CompatPackage = rootMirror.getPackageIfDefined("scala.compat.java8") + lazy val Scala_Java8_CompatPackage = rootMirror.getPackageIfDefined("scala.runtime.java8") lazy val Scala_Java8_CompatPackage_JFunction = (0 to MaxFunctionArity).toArray map (i => getMemberIfDefined(Scala_Java8_CompatPackage.moduleClass, TypeName("JFunction" + i))) } } diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 0cbb976a98..0f0f16574e 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -180,7 +180,7 @@ trait Mirrors extends api.Mirrors { def getPackageObject(fullname: String): ModuleSymbol = getPackageObject(newTermName(fullname)) def getPackageObject(fullname: TermName): ModuleSymbol = - (getPackage(fullname).info member nme.PACKAGE) match { + (getPackage(fullname).packageObject) match { case x: ModuleSymbol => x case _ => MissingRequirementError.notFound("package object " + fullname) } @@ -191,15 +191,6 @@ trait Mirrors extends api.Mirrors { def getPackageObjectIfDefined(fullname: TermName): Symbol = wrapMissing(getPackageObject(fullname)) - final def getPackageObjectWithMember(pre: Type, sym: Symbol): Symbol = { - // The owner of a symbol which requires package qualification may be the - // package object iself, but it also could be any superclass of the package - // object. In the latter case, we must go through the qualifier's info - // to obtain the right symbol. - if (sym.owner.isModuleClass) sym.owner.sourceModule // fast path, if the member is owned by a module class, that must be linked to the package object - else pre member nme.PACKAGE // otherwise we have to findMember - } - override def staticPackage(fullname: String): ModuleSymbol = try ensurePackageSymbol(fullname.toString, getModuleOrClass(newTermNameCached(fullname)), allowModules = false) catch { case mre: MissingRequirementError => throw new ScalaReflectionException(mre.msg) } diff --git a/src/reflect/scala/reflect/internal/Reporting.scala b/src/reflect/scala/reflect/internal/Reporting.scala index f2de83bc5d..2534f59c97 100644 --- a/src/reflect/scala/reflect/internal/Reporting.scala +++ b/src/reflect/scala/reflect/internal/Reporting.scala @@ -8,11 +8,11 @@ package reflect package internal /** Provides delegates to the reporter doing the actual work. - * All forwarding methods should be marked final, - * but some subclasses out of our reach stil override them. + * All forwarding methods should be marked final, + * but some subclasses out of our reach stil override them. * - * Eventually, this interface should be reduced to one method: `reporter`, - * and clients should indirect themselves (reduce duplication of forwarders). + * Eventually, this interface should be reduced to one method: `reporter`, + * and clients should indirect themselves (reduce duplication of forwarders). */ trait Reporting { self : Positions => def reporter: Reporter @@ -71,8 +71,8 @@ import util.Position /** Report information, warnings and errors. * - * This describes the (future) external interface for issuing information, warnings and errors. - * Currently, scala.tools.nsc.Reporter is used by sbt/ide/partest. + * This describes the (future) external interface for issuing information, warnings and errors. + * Currently, scala.tools.nsc.Reporter is used by sbt/ide/partest. */ abstract class Reporter { protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit @@ -101,7 +101,10 @@ abstract class Reporter { resetCount(ERROR) } - def flush(): Unit = { } + def flush(): Unit = () + + /** Finish reporting: print summaries, release resources. */ + def finish(): Unit = () } // TODO: move into superclass once partest cuts tie on Severity diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 52558d9395..f1016e1b76 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -111,6 +111,7 @@ trait StdNames { val PACKAGE: NameType = "package" val ROOT: NameType = "<root>" val SPECIALIZED_SUFFIX: NameType = "$sp" + val CASE_ACCESSOR: NameType = "$access" val NESTED_IN: String = "$nestedIn" val NESTED_IN_ANON_CLASS: String = NESTED_IN + ANON_CLASS_NAME.toString.replace("$", "") diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index ef63078f90..b0145f8a89 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -332,7 +332,7 @@ abstract class SymbolTable extends macros.Universe /** if there's a `package` member object in `pkgClass`, enter its members into it. */ def openPackageModule(pkgClass: Symbol) { - val pkgModule = pkgClass.info.decl(nme.PACKAGEkw) + val pkgModule = pkgClass.packageObject def fromSource = pkgModule.rawInfo match { case ltp: SymLoader => ltp.fromSource case _ => false diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 4bdb8e6da8..c3b2a8da08 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -102,6 +102,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isPrivateThis = (this hasFlag PRIVATE) && (this hasFlag LOCAL) def isProtectedThis = (this hasFlag PROTECTED) && (this hasFlag LOCAL) + def isJavaEnum: Boolean = hasJavaEnumFlag + def isJavaAnnotation: Boolean = hasJavaAnnotationFlag + def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match { case n: TermName => newTermSymbol(n, pos, newFlags) case n: TypeName => if (isClass) newClassSymbol(n, pos, newFlags) else newNonClassSymbol(n, pos, newFlags) @@ -832,6 +835,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def skipPackageObject: Symbol = this + /** The package object symbol corresponding to this package or package class symbol, or NoSymbol otherwise */ + def packageObject: Symbol = + if (isPackageClass) tpe.packageObject + else if (isPackage) moduleClass.packageObject + else NoSymbol + /** If this is a constructor, its owner: otherwise this. */ final def skipConstructor: Symbol = if (isConstructor) owner else this @@ -871,7 +880,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isDeprecated = hasAnnotation(DeprecatedAttr) def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0) def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1) - def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0) + def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0 orElse Some(nme.NO_NAME)) def hasDeprecatedInheritanceAnnotation = hasAnnotation(DeprecatedInheritanceAttr) def deprecatedInheritanceMessage @@ -888,10 +897,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => // string. So this needs attention. For now the fact that migration is // private[scala] ought to provide enough protection. def hasMigrationAnnotation = hasAnnotation(MigrationAnnotationClass) - def migrationMessage = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(0) } - def migrationVersion = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(1) } - def elisionLevel = getAnnotation(ElidableMethodClass) flatMap { _.intArg(0) } - def implicitNotFoundMsg = getAnnotation(ImplicitNotFoundClass) flatMap { _.stringArg(0) } + def migrationMessage = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(0) } + def migrationVersion = getAnnotation(MigrationAnnotationClass) flatMap { _.stringArg(1) } + def elisionLevel = getAnnotation(ElidableMethodClass) flatMap { _.intArg(0) } + def implicitNotFoundMsg = getAnnotation(ImplicitNotFoundClass) flatMap { _.stringArg(0) } + def implicitAmbiguousMsg = getAnnotation(ImplicitAmbiguousClass) flatMap { _.stringArg(0) } def isCompileTimeOnly = hasAnnotation(CompileTimeOnlyAttr) def compileTimeOnlyMessage = getAnnotation(CompileTimeOnlyAttr) flatMap (_ stringArg 0) @@ -987,7 +997,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def isNotOverridden = ( owner.isClass && ( owner.isEffectivelyFinal - || owner.isSealed && owner.children.forall(c => c.isEffectivelyFinal && (overridingSymbol(c) == NoSymbol)) + || (owner.isSealed && owner.sealedChildren.forall(c => c.isEffectivelyFinal && (overridingSymbol(c) == NoSymbol))) ) ) @@ -999,6 +1009,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => isPrivate || isLocalToBlock ) + || isClass && originalOwner.isTerm && children.isEmpty // we track known subclasses of term-owned classes, use that infer finality ) /** Is this symbol effectively final or a concrete term member of sealed class whose children do not override it */ final def isEffectivelyFinalOrNotOverridden: Boolean = isEffectivelyFinal || (isTerm && !isDeferred && isNotOverridden) @@ -2502,14 +2513,15 @@ trait Symbols extends api.Symbols { self: SymbolTable => def associatedFile: AbstractFile = enclosingTopLevelClass.associatedFile def associatedFile_=(f: AbstractFile) { abort("associatedFile_= inapplicable for " + this) } - /** If this is a sealed class, its known direct subclasses. + /** If this is a sealed or local class, its known direct subclasses. * Otherwise, the empty set. */ def children: Set[Symbol] = Set() + final def sealedChildren: Set[Symbol] = if (!isSealed) Set.empty else children /** Recursively assemble all children of this symbol. */ - def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this + final def sealedDescendants: Set[Symbol] = if (!isSealed) Set(this) else children.flatMap(_.sealedDescendants) + this @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt @inline final def andAlso(f: Symbol => Unit): Symbol = { if (this ne NoSymbol) f(this) ; this } @@ -3391,13 +3403,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def implicitMembers: Scope = { val tp = info if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) { - // Skip a package object class, because the members are also in - // the package and we wish to avoid spurious ambiguities as in pos/t3999. - if (!isPackageObjectClass) { - implicitMembersCacheValue = tp.implicitMembers - implicitMembersCacheKey1 = tp - implicitMembersCacheKey2 = tp.decls.elems - } + implicitMembersCacheValue = tp.membersBasedOnFlags(BridgeFlags, IMPLICIT) + implicitMembersCacheKey1 = tp + implicitMembersCacheKey2 = tp.decls.elems } implicitMembersCacheValue } diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 201b727ed6..2933aa3892 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -129,7 +129,16 @@ abstract class TreeGen { /** Builds a reference to given symbol. */ def mkAttributedRef(sym: Symbol): RefTree = - if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym) + if (sym.owner.isStaticOwner) { + if (sym.owner.isRoot) + mkAttributedIdent(sym) + else { + val ownerModule = sym.owner.sourceModule + assert(ownerModule != NoSymbol, sym.owner) + mkAttributedSelect(mkAttributedRef(sym.owner.sourceModule), sym) + } + } + else if (sym.owner.isClass) mkAttributedRef(sym.owner.thisType, sym) else mkAttributedIdent(sym) def mkUnattributedRef(sym: Symbol): RefTree = mkUnattributedRef(sym.fullNameAsName('.')) @@ -191,8 +200,8 @@ abstract class TreeGen { ) val pkgQualifier = if (needsPackageQualifier) { - val packageObject = rootMirror.getPackageObjectWithMember(qual.tpe, sym) - Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject) + val packageObject = qualsym.packageObject + Select(qual, nme.PACKAGE) setSymbol packageObject setType packageObject.typeOfThis } else qual diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 4657fa0000..7ad5fdf096 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -128,6 +128,7 @@ abstract class TreeInfo { symOk(tree.symbol) && tree.symbol.isStable && !definitions.isByNameParamType(tree.tpe) + && !definitions.isByName(tree.symbol) && (allowVolatile || !tree.symbol.hasVolatileType) // TODO SPEC: not required by spec ) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index bbd9df05d2..49554d6d0f 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1617,21 +1617,9 @@ trait Trees extends api.Trees { } def apply[T <: Tree](tree: T): T = { val tree1 = transform(tree) - invalidateSingleTypeCaches(tree1) + invalidateTreeTpeCaches(tree1, mutatedSymbols) tree1.asInstanceOf[T] } - private def invalidateSingleTypeCaches(tree: Tree): Unit = { - if (mutatedSymbols.nonEmpty) - for (t <- tree if t.tpe != null) - for (tp <- t.tpe) { - tp match { - case s: SingleType if mutatedSymbols contains s.sym => - s.underlyingPeriod = NoPeriod - s.underlyingCache = NoType - case _ => - } - } - } override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to) } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 9697e16da7..33592bbd86 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -589,7 +589,12 @@ trait Types def nonPrivateMembersAdmitting(admit: Long): Scope = membersBasedOnFlags(BridgeAndPrivateFlags & ~admit, 0) /** A list of all implicit symbols of this type (defined or inherited) */ - def implicitMembers: Scope = membersBasedOnFlags(BridgeFlags, IMPLICIT) + def implicitMembers: Scope = { + typeSymbolDirect match { + case sym: ModuleClassSymbol => sym.implicitMembers + case _ => membersBasedOnFlags(BridgeFlags, IMPLICIT) + } + } /** A list of all deferred symbols of this type (defined or inherited) */ def deferredMembers: Scope = membersBasedOnFlags(BridgeFlags, DEFERRED) @@ -606,6 +611,8 @@ trait Types def nonPrivateMember(name: Name): Symbol = memberBasedOnName(name, BridgeAndPrivateFlags) + def packageObject: Symbol = member(nme.PACKAGE) + /** The non-private member with given name, admitting members with given flags `admit`. * "Admitting" refers to the fact that members with a PRIVATE, BRIDGE, or VBRIDGE * flag are usually excluded from findMember results, but supplying any of those flags @@ -659,7 +666,7 @@ trait Types ) if (trivial) this else { - val m = newAsSeenFromMap(pre.normalize, clazz) + val m = new AsSeenFromMap(pre.normalize, clazz) val tp = m(this) val tp1 = existentialAbstraction(m.capturedParams, tp) @@ -1207,6 +1214,10 @@ trait Types private[reflect] var underlyingCache: Type = NoType private[reflect] var underlyingPeriod = NoPeriod + private[Types] def invalidateSingleTypeCaches(): Unit = { + underlyingCache = NoType + underlyingPeriod = NoPeriod + } override def underlying: Type = { val cache = underlyingCache if (underlyingPeriod == currentPeriod && cache != null) cache @@ -1347,6 +1358,12 @@ trait Types private[reflect] var baseTypeSeqPeriod = NoPeriod private[reflect] var baseClassesCache: List[Symbol] = _ private[reflect] var baseClassesPeriod = NoPeriod + private[Types] def invalidatedCompoundTypeCaches() { + baseTypeSeqCache = null + baseTypeSeqPeriod = NoPeriod + baseClassesCache = null + baseClassesPeriod = NoPeriod + } override def baseTypeSeq: BaseTypeSeq = { val cached = baseTypeSeqCache @@ -1600,7 +1617,14 @@ trait Types private var normalized: Type = _ private def normalizeImpl = { // TODO see comments around def intersectionType and def merge - def flatten(tps: List[Type]): List[Type] = tps flatMap { case RefinedType(parents, ds) if ds.isEmpty => flatten(parents) case tp => List(tp) } + // SI-8575 The dealias is needed here to keep subtyping transitive, example in run/t8575b.scala + def flatten(tps: List[Type]): List[Type] = { + def dealiasRefinement(tp: Type) = if (tp.dealias.isInstanceOf[RefinedType]) tp.dealias else tp + tps map dealiasRefinement flatMap { + case RefinedType(parents, ds) if ds.isEmpty => flatten(parents) + case tp => List(tp) + } + } val flattened = flatten(parents).distinct if (decls.isEmpty && hasLength(flattened, 1)) { flattened.head @@ -1898,6 +1922,9 @@ trait Types narrowedCache } + private[Types] def invalidateModuleTypeRefCaches(): Unit = { + narrowedCache = null + } override protected def finishPrefix(rest: String) = objectPrefix + rest override def directObjectString = super.safeToString override def toLongString = toString @@ -1977,6 +2004,10 @@ trait Types */ private var relativeInfoCache: Type = _ private var relativeInfoPeriod: Period = NoPeriod + private[Types] def invalidateNonClassTypeRefCaches(): Unit = { + relativeInfoCache = NoType + relativeInfoPeriod = NoPeriod + } private[Types] def relativeInfo = /*trace(s"relativeInfo(${safeToString}})")*/{ if (relativeInfoPeriod != currentPeriod) { @@ -2109,6 +2140,10 @@ trait Types } thisInfoCache } + private[Types] def invalidateAbstractTypeRefCaches(): Unit = { + symInfoCache = null + thisInfoCache = null + } override def bounds = thisInfo.bounds override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this override def kind = "AbstractTypeRef" @@ -2128,9 +2163,12 @@ trait Types trivial = fromBoolean(!sym.isTypeParameter && pre.isTrivial && areTrivialTypes(args)) toBoolean(trivial) } - private[scala] def invalidateCaches(): Unit = { + private[Types] def invalidateTypeRefCaches(): Unit = { + parentsCache = null parentsPeriod = NoPeriod + baseTypeSeqCache = null baseTypeSeqPeriod = NoPeriod + normalized = null } private[reflect] var parentsCache: List[Type] = _ private[reflect] var parentsPeriod = NoPeriod @@ -4555,6 +4593,39 @@ trait Types if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyTpe else tp + def invalidateTreeTpeCaches(tree: Tree, updatedSyms: List[Symbol]) = if (updatedSyms.nonEmpty) + for (t <- tree if t.tpe != null) + for (tp <- t.tpe) { + invalidateCaches(tp, updatedSyms) + } + + def invalidateCaches(t: Type, updatedSyms: List[Symbol]) = { + t match { + case st: SingleType if updatedSyms.contains(st.sym) => st.invalidateSingleTypeCaches() + case _ => + } + t match { + case tr: NonClassTypeRef if updatedSyms.contains(tr.sym) => tr.invalidateNonClassTypeRefCaches() + case _ => + } + t match { + case tr: AbstractTypeRef if updatedSyms.contains(tr.sym) => tr.invalidateAbstractTypeRefCaches() + case _ => + } + t match { + case tr: TypeRef if updatedSyms.contains(tr.sym) => tr.invalidateTypeRefCaches() + case _ => + } + t match { + case tr: ModuleTypeRef if updatedSyms.contains(tr.sym) => tr.invalidateModuleTypeRefCaches() + case _ => + } + t match { + case ct: CompoundType if ct.baseClasses.exists(updatedSyms.contains) => ct.invalidatedCompoundTypeCaches() + case _ => + } + } + val shorthands = Set( "scala.collection.immutable.List", "scala.collection.immutable.Nil", diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index a9020a3d4c..277e89d656 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -239,7 +239,6 @@ abstract class UnPickler { if (missing.startsWith("scala.xml")) Some(("org.scala-lang.modules", "scala-xml")) else if (missing.startsWith("scala.util.parsing")) Some(("org.scala-lang.modules", "scala-parser-combinators")) else if (missing.startsWith("scala.swing")) Some(("org.scala-lang.modules", "scala-swing")) - else if (missing.startsWith("scala.util.continuations")) Some(("org.scala-lang.plugins", "scala-continuations-library")) else None (module map { case (group, art) => diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index b8d4050d7d..28a7fb37a6 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -449,12 +449,15 @@ private[internal] trait TypeMaps { (pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz) ) - def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap = - new AsSeenFromMap(pre, clazz) + @deprecated("Use new AsSeenFromMap instead", "2.12.0") + final def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap = new AsSeenFromMap(pre, clazz) /** A map to compute the asSeenFrom method. */ - class AsSeenFromMap(seenFromPrefix: Type, seenFromClass: Symbol) extends TypeMap with KeepOnlyTypeConstraints { + class AsSeenFromMap(seenFromPrefix0: Type, seenFromClass: Symbol) extends TypeMap with KeepOnlyTypeConstraints { + private val seenFromPrefix: Type = if (seenFromPrefix0.typeSymbolDirect.hasPackageFlag && !seenFromClass.hasPackageFlag) + seenFromPrefix0.packageObject.typeOfThis + else seenFromPrefix0 // Some example source constructs relevant in asSeenFrom: // // object CaptureThis { diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 01e28e5642..9853a0fa0c 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -282,8 +282,17 @@ trait Erasure { } object boxingErasure extends ScalaErasureMap { + private var boxPrimitives = true + + override def applyInArray(tp: Type): Type = { + val saved = boxPrimitives + boxPrimitives = false + try super.applyInArray(tp) + finally boxPrimitives = saved + } + override def eraseNormalClassRef(tref: TypeRef) = - if (isPrimitiveValueClass(tref.sym)) boxedClass(tref.sym).tpe + if (boxPrimitives && isPrimitiveValueClass(tref.sym)) boxedClass(tref.sym).tpe else super.eraseNormalClassRef(tref) override def eraseDerivedValueClassRef(tref: TypeRef) = super.eraseNormalClassRef(tref) diff --git a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala index 41011f6c6b..296934e253 100644 --- a/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala +++ b/src/reflect/scala/reflect/internal/util/ScalaClassLoader.scala @@ -11,7 +11,8 @@ import java.lang.reflect.{ Constructor, Modifier, Method } import java.io.{ File => JFile } import java.net.{ URLClassLoader => JURLClassLoader } import java.net.URL -import scala.reflect.runtime.ReflectionUtils.unwrapHandler +import scala.reflect.internal.FatalError +import scala.reflect.runtime.ReflectionUtils.{ show, unwrapHandler } import ScalaClassLoader._ import scala.util.control.Exception.{ catching } import scala.language.implicitConversions @@ -46,6 +47,33 @@ trait ScalaClassLoader extends JClassLoader { def create(path: String): AnyRef = tryToInitializeClass[AnyRef](path).map(_.newInstance()).orNull + /** Create an instance with ctor args, or invoke errorFn before throwing. */ + def create[T <: AnyRef : ClassTag](path: String, errorFn: String => Unit)(args: AnyRef*): T = { + def fail(msg: String) = error(msg, new IllegalArgumentException(msg)) + def error(msg: String, e: Throwable) = { errorFn(msg) ; throw e } + try { + val clazz = Class.forName(path, /*initialize =*/ true, /*loader =*/ this) + if (classTag[T].runtimeClass isAssignableFrom clazz) { + val ctor = { + val maybes = clazz.getConstructors filter (c => c.getParameterCount == args.size && + (c.getParameterTypes zip args).forall { case (k, a) => k isAssignableFrom a.getClass }) + if (maybes.size == 1) maybes.head + else fail(s"Constructor must accept arg list (${args map (_.getClass.getName) mkString ", "}): ${path}") + } + (ctor.newInstance(args: _*)).asInstanceOf[T] + } else { + errorFn(s"""Loader for ${classTag[T]}: [${show(classTag[T].runtimeClass.getClassLoader)}] + |Loader for ${clazz.getName}: [${show(clazz.getClassLoader)}]""".stripMargin) + fail(s"Not a ${classTag[T]}: ${path}") + } + } catch { + case e: ClassNotFoundException => + error(s"Class not found: ${path}", e) + case e @ (_: LinkageError | _: ReflectiveOperationException) => + error(s"Unable to create instance: ${path}: ${e.toString}", e) + } + } + /** The actual bytes for a class file, or an empty array if it can't be found. */ def classBytes(className: String): Array[Byte] = classAsStream(className) match { case null => Array() diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 7725e4a2f0..1e9a4fe8a5 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -369,6 +369,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.BridgeClass definitions.ElidableMethodClass definitions.ImplicitNotFoundClass + definitions.ImplicitAmbiguousClass definitions.MigrationAnnotationClass definitions.ScalaStrictFPAttr definitions.SwitchClass |