summaryrefslogtreecommitdiff
path: root/src/reflect/scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala')
-rw-r--r--src/reflect/scala/reflect/internal/FreshNames.scala24
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala18
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala10
-rw-r--r--src/reflect/scala/reflect/internal/util/Collections.scala3
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala9
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)