diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-04-01 16:47:22 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-04-01 16:47:22 +0200 |
commit | dcd9a83916f9e0128ef6869def82d4f23bdea0e0 (patch) | |
tree | e58331aebe8ba06fd1c15faf36fdbb3f77b489b9 /src/reflect | |
parent | ebf0976c363c67e6a46c66d70b39704f1ce5e74a (diff) | |
parent | fcc20fe4d3ac5caceb50965bc202b880e61f984c (diff) | |
download | scala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.tar.gz scala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.tar.bz2 scala-dcd9a83916f9e0128ef6869def82d4f23bdea0e0.zip |
Merge commit 'fcc20fe' into merge/2.11-to-2.12-apr-1
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/FreshNames.scala | 24 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 18 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/SymbolTable.scala | 8 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 20 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 10 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/util/Collections.scala | 3 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaMirrors.scala | 9 |
8 files changed, 84 insertions, 21 deletions
diff --git a/src/reflect/scala/reflect/internal/FreshNames.scala b/src/reflect/scala/reflect/internal/FreshNames.scala index 7e9a568266..17883d12ad 100644 --- a/src/reflect/scala/reflect/internal/FreshNames.scala +++ b/src/reflect/scala/reflect/internal/FreshNames.scala @@ -7,6 +7,7 @@ package reflect package internal import scala.reflect.internal.util.FreshNameCreator +import scala.util.matching.Regex trait FreshNames { self: Names with StdNames => // SI-6879 Keeps track of counters that are supposed to be globally unique @@ -23,17 +24,20 @@ trait FreshNames { self: Names with StdNames => // Extractor that matches names which were generated by some // FreshNameCreator with known prefix. Extracts user-specified // prefix that was used as a parameter to newName by stripping - // global creator prefix and unique number in the end of the name. + // global creator prefix and unique numerical suffix. + // The creator prefix and numerical suffix may both be empty. class FreshNameExtractor(creatorPrefix: String = "") { - // quote prefix so that it can be used with replaceFirst - // which expects regExp rather than simple string - val quotedCreatorPrefix = java.util.regex.Pattern.quote(creatorPrefix) - - def unapply(name: Name): Option[String] = { - val sname = name.toString - // name should start with creatorPrefix and end with number - if (!sname.startsWith(creatorPrefix) || !sname.matches("^.*\\d*$")) None - else Some(NameTransformer.decode(sname.replaceFirst(quotedCreatorPrefix, "").replaceAll("\\d*$", ""))) + + // name should start with creatorPrefix and end with number + val freshlyNamed = { + val pre = if (!creatorPrefix.isEmpty) Regex quote creatorPrefix else "" + s"""$pre(.*?)\\d*""".r } + + def unapply(name: Name): Option[String] = + name.toString match { + case freshlyNamed(prefix) => Some(prefix) + case _ => None + } } } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index ea07fb2a74..15584c382c 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -113,6 +113,23 @@ trait StdNames { 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("$", "") + val NESTED_IN_ANON_FUN: String = NESTED_IN + ANON_FUN_NAME.toString.replace("$", "") + val NESTED_IN_LAMBDA: String = NESTED_IN + DELAMBDAFY_LAMBDA_CLASS_NAME.toString.replace("$", "") + + /** + * Ensures that name mangling does not accidentally make a class respond `true` to any of + * isAnonymousClass, isAnonymousFunction, isDelambdafyFunction, e.g. by introducing "$anon". + */ + def ensureNonAnon(name: String) = { + name + .replace(nme.ANON_CLASS_NAME.toString, NESTED_IN_ANON_CLASS) + .replace(nme.ANON_FUN_NAME.toString, NESTED_IN_ANON_FUN) + .replace(nme.DELAMBDAFY_LAMBDA_CLASS_NAME.toString, NESTED_IN_LAMBDA) + } + + // value types (and AnyRef) are all used as terms as well // as (at least) arguments to the @specialize annotation. final val Boolean: NameType = "Boolean" @@ -1062,6 +1079,7 @@ trait StdNames { val reflPolyCacheName: NameType = "reflPoly$Cache" val reflParamsCacheName: NameType = "reflParams$Cache" val reflMethodName: NameType = "reflMethod$Method" + val argument: NameType = "<argument>" } diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index bea6979431..b0145f8a89 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -355,6 +355,14 @@ abstract class SymbolTable extends macros.Universe cache } + /** + * Removes a cache from the per-run caches. This is useful for testing: it allows running the + * compiler and then inspect the state of a cache. + */ + def unrecordCache[T <: Clearable](cache: T): Unit = { + caches = caches.filterNot(_.get eq cache) + } + def clearAll() = { debuglog("Clearing " + caches.size + " caches.") caches foreach (ref => Option(ref.get).foreach(_.clear)) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 293af68c5f..00067daa7f 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -66,14 +66,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => // when under some flag. Define per-phase invariants for owner/owned relationships, // e.g. after flatten all classes are owned by package classes, there are lots and // lots of these to be declared (or more realistically, discovered.) + // could be private since 2.11.6, but left protected to avoid potential breakages (eg ensime) protected def saveOriginalOwner(sym: Symbol): Unit = { // some synthetic symbols have NoSymbol as owner initially if (sym.owner != NoSymbol) { if (originalOwnerMap contains sym) () - else originalOwnerMap(sym) = sym.rawowner + else defineOriginalOwner(sym, sym.rawowner) } } + def defineOriginalOwner(sym: Symbol, owner: Symbol): Unit = { + originalOwnerMap(sym) = owner + } + def symbolOf[T: WeakTypeTag]: TypeSymbol = weakTypeOf[T].typeSymbolDirect.asType abstract class SymbolContextApiImpl extends SymbolApi { @@ -2060,7 +2065,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => * where it is the outer class of the enclosing class. */ final def outerClass: Symbol = - if (owner.isClass) owner + if (this == NoSymbol) { + // ideally we shouldn't get here, but its better to harden against this than suffer the infinite loop in SI-9133 + devWarningDumpStack("NoSymbol.outerClass", 15) + NoSymbol + } else if (owner.isClass) owner else if (isClassLocalToConstructor) owner.enclClass.outerClass else owner.outerClass diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 35de3adff6..fd918b8595 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1576,6 +1576,7 @@ trait Trees extends api.Trees { */ class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer { val symSubst = new SubstSymMap(from, to) + private var mutatedSymbols: List[Symbol] = Nil override def transform(tree: Tree): Tree = { def subst(from: List[Symbol], to: List[Symbol]) { if (!from.isEmpty) @@ -1594,6 +1595,7 @@ trait Trees extends api.Trees { |TreeSymSubstituter: updated info of symbol ${tree.symbol} | Old: ${showRaw(tree.symbol.info, printTypes = true, printIds = true)} | New: ${showRaw(newInfo, printTypes = true, printIds = true)}""") + mutatedSymbols ::= tree.symbol tree.symbol updateInfo newInfo } case _ => @@ -1613,7 +1615,23 @@ trait Trees extends api.Trees { } else super.transform(tree) } - def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T] + def apply[T <: Tree](tree: T): T = { + val tree1 = transform(tree) + invalidateSingleTypeCaches(tree1) + 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 a4269fcbc5..b65063d9d4 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1990,13 +1990,13 @@ trait Types * usage scenario. */ private var relativeInfoCache: Type = _ - private var memberInfoCache: Type = _ + private var relativeInfoPeriod: Period = NoPeriod - private[Types] def relativeInfo = { - val memberInfo = pre.memberInfo(sym) - if (relativeInfoCache == null || (memberInfo ne memberInfoCache)) { - memberInfoCache = memberInfo + private[Types] def relativeInfo = /*trace(s"relativeInfo(${safeToString}})")*/{ + if (relativeInfoPeriod != currentPeriod) { + val memberInfo = pre.memberInfo(sym) relativeInfoCache = transformInfo(memberInfo) + relativeInfoPeriod = currentPeriod } relativeInfoCache } diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index d128521be8..a743d8962a 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -181,6 +181,9 @@ trait Collections { final def mapFrom[A, A1 >: A, B](xs: List[A])(f: A => B): Map[A1, B] = { Map[A1, B](xs map (x => (x, f(x))): _*) } + final def linkedMapFrom[A, A1 >: A, B](xs: List[A])(f: A => B): mutable.LinkedHashMap[A1, B] = { + mutable.LinkedHashMap[A1, B](xs map (x => (x, f(x))): _*) + } final def mapWithIndex[A, B](xs: List[A])(f: (A, Int) => B): List[B] = { val lb = new ListBuffer[B] diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 1c751fb93b..3b497227e7 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -428,9 +428,12 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive var i = 0 while (i < args1.length) { val arg = args(i) - if (i >= paramCount) args1(i) = arg // don't transform varargs - else if (isByName(i)) args1(i) = () => arg // don't transform by-name value class params - else if (isDerivedValueClass(i)) args1(i) = paramUnboxers(i).invoke(arg) + args1(i) = ( + if (i >= paramCount) arg // don't transform varargs + else if (isByName(i)) () => arg // don't transform by-name value class params + else if (isDerivedValueClass(i)) paramUnboxers(i).invoke(arg) // do get the underlying value + else arg // don't molest anything else + ) i += 1 } jinvoke(args1) |