summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-08-11 16:59:19 -0700
committerGitHub <noreply@github.com>2016-08-11 16:59:19 -0700
commitfdb3105228db20e347a61e61e2e1d86b27683d0d (patch)
tree3acf954c38584c945cefcf63292e07a2b864f2bc /src/reflect
parent19aea1a52e941977691892e0ebd52e078fe5f9cc (diff)
parentaf02e291b6baf4f673a79f4c32e6da67d31bdd75 (diff)
downloadscala-fdb3105228db20e347a61e61e2e1d86b27683d0d.tar.gz
scala-fdb3105228db20e347a61e61e2e1d86b27683d0d.tar.bz2
scala-fdb3105228db20e347a61e61e2e1d86b27683d0d.zip
Merge pull request #5141 from adriaanm/fields
Introducing: the fields phase [ci: last-only]
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala52
-rw-r--r--src/reflect/scala/reflect/internal/Phase.scala4
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala1
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala3
-rw-r--r--src/reflect/scala/reflect/internal/SymbolPairs.scala28
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala178
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala28
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala4
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala14
-rw-r--r--src/reflect/scala/reflect/internal/transform/RefChecks.scala14
-rw-r--r--src/reflect/scala/reflect/internal/transform/Transforms.scala5
-rw-r--r--src/reflect/scala/reflect/internal/transform/UnCurry.scala7
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala7
16 files changed, 170 insertions, 216 deletions
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index fa19103d0c..cfde164754 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -175,15 +175,6 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
case (Nil, defaults) => defaults contains category
case (metas, _) => metas exists (_ matches category)
}
-
- def mkFilter(categories: List[Symbol], defaultRetention: Boolean)(ann: AnnotationInfo) =
- (ann.metaAnnotations, ann.defaultTargets) match {
- case (Nil, Nil) => defaultRetention
- case (Nil, defaults) => categories exists defaults.contains
- case (metas, _) =>
- val metaSyms = metas collect { case ann if !ann.symbol.isInstanceOf[StubSymbol] => ann.symbol }
- categories exists (category => metaSyms exists (_ isNonBottomSubClass category))
- }
}
class CompleteAnnotationInfo(
@@ -305,10 +296,13 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
}
/** The default kind of members to which this annotation is attached.
- * For instance, for scala.deprecated defaultTargets =
- * List(getter, setter, beanGetter, beanSetter).
- */
- def defaultTargets = symbol.annotations map (_.symbol) filter isMetaAnnotation
+ * For instance, for scala.deprecated defaultTargets =
+ * List(getter, setter, beanGetter, beanSetter).
+ *
+ * NOTE: have to call symbol.initialize, since we won't get any annotations if the symbol hasn't yet been completed
+ */
+ def defaultTargets = symbol.initialize.annotations map (_.symbol) filter isMetaAnnotation
+
// Test whether the typeSymbol of atp conforms to the given class.
def matches(clazz: Symbol) = !symbol.isInstanceOf[StubSymbol] && (symbol isNonBottomSubClass clazz)
// All subtrees of all args are considered.
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 0342daf113..eca1bbea5a 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -362,7 +362,6 @@ trait Definitions extends api.StandardDefinitions {
// classes with special meanings
lazy val StringAddClass = requiredClass[scala.runtime.StringAdd]
lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber]
- lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter]
lazy val DelayedInitClass = requiredClass[scala.DelayedInit]
def delayedInitMethod = getMemberMethod(DelayedInitClass, nme.delayedInit)
@@ -675,8 +674,10 @@ trait Definitions extends api.StandardDefinitions {
// Note that these call .dealiasWiden and not .normalize, the latter of which
// tends to change the course of events by forcing types.
def isFunctionType(tp: Type) = isFunctionTypeDirect(tp.dealiasWiden)
+
// the number of arguments expected by the function described by `tp` (a FunctionN or SAM type),
// or `-1` if `tp` does not represent a function type or SAM
+ // for use during typers (after fields, samOf will be confused by abstract accessors for trait fields)
def functionArityFromType(tp: Type) = {
val dealiased = tp.dealiasWiden
if (isFunctionTypeDirect(dealiased)) dealiased.typeArgs.length - 1
@@ -686,16 +687,6 @@ trait Definitions extends api.StandardDefinitions {
}
}
- // the result type of a function or corresponding SAM type
- def functionResultType(tp: Type): Type = {
- val dealiased = tp.dealiasWiden
- if (isFunctionTypeDirect(dealiased)) dealiased.typeArgs.last
- else samOf(tp) match {
- case samSym if samSym.exists => tp.memberInfo(samSym).resultType.deconst
- case _ => NoType
- }
- }
-
// the SAM's parameters and the Function's formals must have the same length
// (varargs etc don't come into play, as we're comparing signatures, not checking an application)
def samMatchesFunctionBasedOnArity(sam: Symbol, formals: List[Any]): Boolean =
@@ -1049,11 +1040,7 @@ trait Definitions extends api.StandardDefinitions {
}
}
- /** Remove references to class Object (other than the head) in a list of parents */
- def removeLaterObjects(tps: List[Type]): List[Type] = tps match {
- case Nil => Nil
- case x :: xs => x :: xs.filterNot(_.typeSymbol == ObjectClass)
- }
+
/** Remove all but one reference to class Object from a list of parents. */
def removeRedundantObjects(tps: List[Type]): List[Type] = tps match {
case Nil => Nil
@@ -1470,6 +1457,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val StringAdd_+ = getMemberMethod(StringAddClass, nme.PLUS)
// The given symbol represents either String.+ or StringAdd.+
+ // TODO: this misses Predef.any2stringadd
def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+
lazy val StringContext_f = getMemberMethod(StringContextClass, nme.f)
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index e06decea6d..a146f9aea5 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -169,17 +169,23 @@ class Flags extends ModifierFlags {
final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED
+ final val SYNTHESIZE_IMPL_IN_SUBCLASS = 1L << 50 // used in fields phase to indicate this accessor should receive an implementation in a subclass
+
+ // flags used strictly internally in the Fields phase (info/tree transform):
+ final val NEEDS_TREES = 1L << 59 // this symbol needs a tree. (distinct from SYNTHESIZE_IMPL_IN_SUBCLASS)
+
// ------- shift definitions -------------------------------------------------------
//
// Flags from 1L to (1L << 50) are normal flags.
//
- // The flags DEFERRED (1L << 4) to MODULE (1L << 8) have a `late` counterpart. Late flags change
- // their counterpart from 0 to 1 after a specific phase (see below). The first late flag
- // (lateDEFERRED) is at (1L << 51), i.e., late flags are shifted by 47. The last one is (1L << 55).
+ // The "late" counterpart to flags DEFERRED (1L << 4) to MODULE (1L << 8)
+ // show up in `sym.flags` as their regular counterpart once the phase mask admits them (see below).
+ // The first late flag (lateDEFERRED) is at (1L << 51), i.e., late flags are shifted by 47. The last one is (1L << 55).
+ // Think of it as a poor man's flag history akin to the type history for a symbol's info.
//
- // The flags PROTECTED (1L) to PRIVATE (1L << 2) have a `not` counterpart. Negated flags change
- // their counterpart from 1 to 0 after a specific phase (see below). They are shifted by 56, i.e.,
- // the first negated flag (notPROTECTED) is at (1L << 56), the last at (1L << 58).
+ // The "not" counterpart to flags PROTECTED (1L) to PRIVATE (1L << 2)
+ // are negated flags that suppress their counterpart after a specific phase (see below).
+ // They are shifted by 56, i.e., the first negated flag (notPROTECTED) is at (1L << 56), the last at (1L << 58).
//
// Late and negative flags are only enabled after certain phases, implemented by the phaseNewFlags
// method of the SubComponent, so they implement a bit of a flag history.
@@ -211,20 +217,15 @@ class Flags extends ModifierFlags {
// erasure 15 [START] <latedeferred>
// mixin 20 [START] <latemodule> <notoverride>
//
- // lateMETHOD set in RefChecks#transformInfo.
- // lateFINAL set in Symbols#makeNotPrivate.
// notPRIVATE set in Symbols#makeNotPrivate, IExplicitOuter#transform, Inliners.
// notPROTECTED set in ExplicitOuter#transform.
- // lateDEFERRED set in AddInterfaces, Mixin, etc.
- // lateMODULE set in Mixin#transformInfo.
- // notOVERRIDE set in Mixin#preTransform.
- final val lateDEFERRED = (DEFERRED: Long) << LateShift
- final val lateFINAL = (FINAL: Long) << LateShift
- final val lateMETHOD = (METHOD: Long) << LateShift
- final val lateMODULE = (MODULE: Long) << LateShift
+// final val lateDEFERRED = (DEFERRED: Long) << LateShift // unused
+// final val lateFINAL = (FINAL: Long) << LateShift // only used for inliner -- could be subsumed by notPRIVATE?
+// final val lateMETHOD = (METHOD: Long) << LateShift // unused
+// final val lateMODULE = (MODULE: Long) << LateShift // unused
- final val notOVERRIDE = (OVERRIDE: Long) << AntiShift
+// final val notOVERRIDE = (OVERRIDE: Long) << AntiShift // unused
final val notPRIVATE = (PRIVATE: Long) << AntiShift
final val notPROTECTED = (PROTECTED: Long) << AntiShift
@@ -257,7 +258,8 @@ class Flags extends ModifierFlags {
/** These modifiers appear in TreePrinter output. */
final val PrintableFlags =
ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
- ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | ARTIFACT
+ ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | ARTIFACT |
+ SYNTHESIZE_IMPL_IN_SUBCLASS | NEEDS_TREES
/** When a symbol for a field is created, only these flags survive
* from Modifiers. Others which may be applied at creation time are:
@@ -442,16 +444,16 @@ class Flags extends ModifierFlags {
case JAVA_DEFAULTMETHOD => "<defaultmethod>" // (1L << 47)
case JAVA_ENUM => "<enum>" // (1L << 48)
case JAVA_ANNOTATION => "<annotation>" // (1L << 49)
- case 0x4000000000000L => "" // (1L << 50)
- case `lateDEFERRED` => "<latedeferred>" // (1L << 51)
- case `lateFINAL` => "<latefinal>" // (1L << 52)
- case `lateMETHOD` => "<latemethod>" // (1L << 53)
- case 0x80000000000000L => "" // (1L << 54)
- case `lateMODULE` => "<latemodule>" // (1L << 55)
+ case SYNTHESIZE_IMPL_IN_SUBCLASS => "<sub_synth>" // (1L << 50)
+ case 0x08000000000000L => "<latedeferred>" // (1L << 51)
+ case 0x10000000000000L => "<latefinal>" // (1L << 52)
+ case 0x20000000000000L => "<latemethod>" // (1L << 53)
+ case 0x40000000000000L => "" // (1L << 54)
+ case 0x80000000000000L => "<latemodule>" // (1L << 55)
case `notPROTECTED` => "<notprotected>" // (1L << 56)
- case `notOVERRIDE` => "<notoverride>" // (1L << 57)
+ case 0x200000000000000L => "<notoverride>" // (1L << 57)
case `notPRIVATE` => "<notprivate>" // (1L << 58)
- case 0x800000000000000L => "" // (1L << 59)
+ case NEEDS_TREES => "<needs_trees>" // (1L << 59)
case 0x1000000000000000L => "" // (1L << 60)
case 0x2000000000000000L => "" // (1L << 61)
case 0x4000000000000000L => "" // (1L << 62)
diff --git a/src/reflect/scala/reflect/internal/Phase.scala b/src/reflect/scala/reflect/internal/Phase.scala
index a761f686e6..eb193adbf2 100644
--- a/src/reflect/scala/reflect/internal/Phase.scala
+++ b/src/reflect/scala/reflect/internal/Phase.scala
@@ -47,6 +47,10 @@ abstract class Phase(val prev: Phase) {
final val specialized: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "specialize" || prev.specialized)
final val refChecked: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "refchecks" || prev.refChecked)
+ // are we past the fields phase, so that:
+ // - we should allow writing to vals (as part of type checking trait setters)
+ // - modules have module accessors
+ final val assignsFields: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "fields" || prev.assignsFields)
/** This is used only in unsafeTypeParams, and at this writing is
* overridden to false in parser, namer, typer, and erasure. (And NoPhase.)
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 30f2efd7e3..33ca78b439 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -285,6 +285,7 @@ trait ReificationSupport { self: SymbolTable =>
val (gvdefs, etdefs) = rawEdefs.partition(treeInfo.isEarlyValDef)
val (fieldDefs, UnCtor(ctorMods, ctorVparamss, lvdefs) :: body) = rest.splitAt(indexOfCtor(rest))
val evdefs = gvdefs.zip(lvdefs).map {
+ // TODO: in traits, early val defs are defdefs
case (gvdef @ ValDef(_, _, tpt: TypeTree, _), ValDef(_, _, _, rhs)) =>
copyValDef(gvdef)(tpt = tpt.original, rhs = rhs)
case (tr1, tr2) =>
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 11b5db9793..925018d3a6 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -95,6 +95,8 @@ trait StdNames {
val NAME_JOIN_STRING: String = NameTransformer.NAME_JOIN_STRING
val MODULE_SUFFIX_STRING: String = NameTransformer.MODULE_SUFFIX_STRING
val LOCAL_SUFFIX_STRING: String = NameTransformer.LOCAL_SUFFIX_STRING
+ val LAZY_LOCAL_SUFFIX_STRING: String = NameTransformer.LAZY_LOCAL_SUFFIX_STRING
+
val TRAIT_SETTER_SEPARATOR_STRING: String = NameTransformer.TRAIT_SETTER_SEPARATOR_STRING
val SINGLETON_SUFFIX: String = ".type"
@@ -337,7 +339,6 @@ trait StdNames {
val DEFAULT_CASE: NameType = "defaultCase$"
val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$"
val FAKE_LOCAL_THIS: NameType = "this$"
- val LAZY_LOCAL: NameType = "$lzy"
val LAZY_SLOW_SUFFIX: NameType = "$lzycompute"
val UNIVERSE_BUILD_PREFIX: NameType = "$u.internal.reificationSupport."
val UNIVERSE_PREFIX: NameType = "$u."
diff --git a/src/reflect/scala/reflect/internal/SymbolPairs.scala b/src/reflect/scala/reflect/internal/SymbolPairs.scala
index a52d2d8510..320c814696 100644
--- a/src/reflect/scala/reflect/internal/SymbolPairs.scala
+++ b/src/reflect/scala/reflect/internal/SymbolPairs.scala
@@ -30,27 +30,6 @@ abstract class SymbolPairs {
val global: SymbolTable
import global._
- /** Type operations relative to a prefix. All operations work on Symbols,
- * and the types are the member types of those symbols in the prefix.
- */
- class RelativeTo(val prefix: Type) {
- def this(clazz: Symbol) = this(clazz.thisType)
- import scala.language.implicitConversions // geez, it even has to hassle me when it's private
- private implicit def symbolToType(sym: Symbol): Type = prefix memberType sym
-
- def erasureOf(sym: Symbol): Type = erasure.erasure(sym)(sym: Type)
- def signature(sym: Symbol): String = sym defStringSeenAs (sym: Type)
- def erasedSignature(sym: Symbol): String = sym defStringSeenAs erasureOf(sym)
-
- def isSameType(sym1: Symbol, sym2: Symbol): Boolean = sym1 =:= sym2
- def isSubType(sym1: Symbol, sym2: Symbol): Boolean = sym1 <:< sym2
- def isSuperType(sym1: Symbol, sym2: Symbol): Boolean = sym2 <:< sym1
- def isSameErasure(sym1: Symbol, sym2: Symbol): Boolean = erasureOf(sym1) =:= erasureOf(sym2)
- def matches(sym1: Symbol, sym2: Symbol): Boolean = (sym1: Type) matches (sym2: Type)
-
- override def toString = s"RelativeTo($prefix)"
- }
-
/** Are types tp1 and tp2 equivalent seen from the perspective
* of `baseClass`? For instance List[Int] and Seq[Int] are =:=
* when viewed from IterableClass.
@@ -58,10 +37,11 @@ abstract class SymbolPairs {
def sameInBaseClass(baseClass: Symbol)(tp1: Type, tp2: Type) =
(tp1 baseType baseClass) =:= (tp2 baseType baseClass)
- case class SymbolPair(base: Symbol, low: Symbol, high: Symbol) {
+ final case class SymbolPair(base: Symbol, low: Symbol, high: Symbol) {
+ private[this] val self = base.thisType
+
def pos = if (low.owner == base) low.pos else if (high.owner == base) high.pos else base.pos
- def self: Type = base.thisType
- def rootType: Type = base.thisType
+ def rootType: Type = self
def lowType: Type = self memberType low
def lowErased: Type = erasure.specialErasure(base)(low.tpe)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index ab52a875f8..487aadf5e5 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -96,8 +96,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isByNameParam: Boolean = this.isValueParameter && (this hasFlag BYNAMEPARAM)
def isImplementationArtifact: Boolean = (this hasFlag BRIDGE) || (this hasFlag VBRIDGE) || (this hasFlag ARTIFACT)
def isJava: Boolean = isJavaDefined
- def isVal: Boolean = isTerm && !isModule && !isMethod && !isMutable
- def isVar: Boolean = isTerm && !isModule && !isMethod && !isLazy && isMutable
+
+ def isField: Boolean = isTerm && !isModule && (!isMethod || owner.isTrait && isAccessor)
+ def isMutableVal = if (owner.isTrait) !hasFlag(STABLE) else isMutable
+ def isVal: Boolean = isField && !isMutableVal
+ def isVar: Boolean = isField && !isLazy && isMutableVal
+
def isAbstract: Boolean = isAbstractClass || isDeferred || isAbstractType
def isPrivateThis = (this hasFlag PRIVATE) && (this hasFlag LOCAL)
def isProtectedThis = (this hasFlag PROTECTED) && (this hasFlag LOCAL)
@@ -320,17 +324,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def newImport(pos: Position): TermSymbol =
newTermSymbol(nme.IMPORT, pos)
- def newModuleVarSymbol(accessor: Symbol): TermSymbol = {
- val newName = nme.moduleVarName(accessor.name.toTermName)
- val newFlags = MODULEVAR | ( if (this.isClass) PrivateLocal | SYNTHETIC else 0 )
- val newInfo = thisType.memberType(accessor).finalResultType
- val mval = newVariable(newName, accessor.pos.focus, newFlags.toLong) addAnnotation VolatileAttr
-
- if (this.isClass)
- mval setInfoAndEnter newInfo
- else
- mval setInfo newInfo
- }
final def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol]
@@ -753,10 +746,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def hasGetter = isTerm && nme.isLocalName(name)
/**
- * Nested modules which have no static owner when ModuleDefs are eliminated (refchecks) are
- * given the lateMETHOD flag, which makes them appear as methods after refchecks.
+ * Nested modules with a non-static owner receive the METHOD flag during UnCurry's info transform.
+ * (They are replaced by a ClassDef and DefDef for the module accessor during the fields phase.)
*
- * Note: the lateMETHOD flag is added lazily in the info transformer of the RefChecks phase.
+ * Note: the METHOD flag is added lazily in the info transformer of the UnCurry phase.
* This means that forcing the `sym.info` may change the value of `sym.isMethod`. Forcing the
* info is in the responsibility of the caller. Doing it eagerly here was tried (0ccdb151f) but
* has proven to lead to bugs (SI-8907).
@@ -992,10 +985,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
|| isModuleOrModuleClass && (isTopLevel || !settings.overrideObjects)
- || isTerm && (
- isPrivate
- || isLocalToBlock
- )
+ || isTerm && (isPrivate || isLocalToBlock || (hasAllFlags(notPRIVATE | METHOD) && !hasFlag(DEFERRED)))
|| 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 */
@@ -1532,7 +1522,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def setInfo(info: Type): this.type = { info_=(info); this }
/** Modifies this symbol's info in place. */
def modifyInfo(f: Type => Type): this.type = setInfo(f(info))
- /** Substitute second list of symbols for first in current info. */
+ /** Substitute second list of symbols for first in current info.
+ *
+ * NOTE: this discards the type history (uses setInfo)
+ */
def substInfo(syms0: List[Symbol], syms1: List[Symbol]): this.type =
if (syms0.isEmpty) this
else modifyInfo(_.substSym(syms0, syms1))
@@ -2048,7 +2041,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
assert(hasAccessorFlag, this)
val localField = owner.info decl localName
- if (localField == NoSymbol && this.hasFlag(MIXEDIN)) {
+ if (localField == NoSymbol && this.hasFlag(MIXEDIN)) { // TODO: fields phase does not (yet?) add MIXEDIN in setMixedinAccessorFlags
// SI-8087: private[this] fields don't have a `localName`. When searching the accessed field
// for a mixin accessor of such a field, we need to look for `name` instead.
// The phase travel ensures that the field is found (`owner` is the trait class symbol, the
@@ -2088,8 +2081,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** If this is a lazy value, the lazy accessor; otherwise this symbol. */
def lazyAccessorOrSelf: Symbol = if (isLazy) lazyAccessor else this
- /** If this is an accessor, the accessed symbol. Otherwise, this symbol. */
- def accessedOrSelf: Symbol = if (hasAccessorFlag) accessed else this
+ /** `accessed`, if this is an accessor that should have an underlying field. Otherwise, `this`.
+ * Note that a "regular" accessor in a trait does not have a field, as an interface cannot define a field.
+ * "non-regular" vals are: early initialized or lazy vals.
+ * Eventually, we should delay introducing symbols for all val/vars until the fields (or lazyvals) phase,
+ * as they are an implementation detail that's irrelevant to type checking.
+ */
+ def accessedOrSelf: Symbol =
+ if (hasAccessorFlag && (!owner.isTrait || hasFlag(PRESUPER | LAZY))) accessed
+ else this
/** For an outer accessor: The class from which the outer originates.
* For all other symbols: NoSymbol
@@ -2447,14 +2447,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
final def makeNotPrivate(base: Symbol) {
if (this.isPrivate) {
- setFlag(notPRIVATE)
- // Marking these methods final causes problems for proxies which use subclassing. If people
- // write their code with no usage of final, we probably shouldn't introduce it ourselves
- // unless we know it is safe. ... Unfortunately if they aren't marked final the inliner
- // thinks it can't inline them. So once again marking lateFINAL, and in genjvm we no longer
- // generate ACC_FINAL on "final" methods which are actually lateFINAL.
- if (isMethod && !isDeferred)
- setFlag(lateFINAL)
+ setFlag(notPRIVATE) // this makes it effectively final (isEffectivelyFinal)
+ // don't set FINAL -- methods not marked final by user should not end up final in bytecode
+ // inliner will know it's effectively final (notPRIVATE non-deferred method)
if (!isStaticModule && !isClassConstructor) {
expandName(base)
if (isModule) moduleClass.makeNotPrivate(base)
@@ -2532,30 +2527,34 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private def symbolKind: SymbolKind = {
var kind =
- if (isTermMacro) ("term macro", "macro method", "MACM")
- else if (isInstanceOf[FreeTermSymbol]) ("free term", "free term", "FTE")
- else if (isInstanceOf[FreeTypeSymbol]) ("free type", "free type", "FTY")
- else if (isPackageClass) ("package class", "package", "PKC")
- else if (hasPackageFlag) ("package", "package", "PK")
- else if (isPackageObject) ("package object", "package", "PKO")
- else if (isPackageObjectClass) ("package object class", "package", "PKOC")
- else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC")
- else if (isRefinementClass) ("refinement class", "", "RC")
- else if (isModule) ("module", "object", "MOD")
- else if (isModuleClass) ("module class", "object", "MODC")
- else if (isGetter) ("getter", if (isSourceMethod) "method" else "value", "GET")
- else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET")
- else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ")
- else if (isVariable) ("field", "variable", "VAR")
- else if (isTrait) ("trait", "trait", "TRT")
- else if (isClass) ("class", "class", "CLS")
- else if (isType) ("type", "type", "TPE")
- else if (isClassConstructor && (owner.hasCompleteInfo && isPrimaryConstructor)) ("primary constructor", "constructor", "PCTOR")
- else if (isClassConstructor) ("constructor", "constructor", "CTOR")
- else if (isSourceMethod) ("method", "method", "METH")
- else if (isTerm) ("value", "value", "VAL")
- else ("", "", "???")
+ if (isTermMacro) ("term macro", "macro method", "MACM")
+ else if (isInstanceOf[FreeTermSymbol]) ("free term", "free term", "FTE")
+ else if (isInstanceOf[FreeTypeSymbol]) ("free type", "free type", "FTY")
+ else if (isPackageClass) ("package class", "package", "PKC")
+ else if (hasPackageFlag) ("package", "package", "PK")
+ else if (isPackageObject) ("package object", "package", "PKO")
+ else if (isPackageObjectClass) ("package object class", "package", "PKOC")
+ else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC")
+ else if (isRefinementClass) ("refinement class", "", "RC")
+ else if (isModule) ("module", "object", "MOD")
+ else if (isModuleClass) ("module class", "object", "MODC")
+ else if (isAccessor &&
+ !hasFlag(STABLE | LAZY)) ("setter", "variable", "SET")
+ else if (isAccessor && !hasFlag(LAZY)) ("getter", "value", "GET")
+ else if (isTerm && hasFlag(LAZY)) ("lazy value", "lazy value", "LAZ")
+ else if (isVariable) ("field", "variable", "VAR")
+ else if (isTrait) ("trait", "trait", "TRT")
+ else if (isClass) ("class", "class", "CLS")
+ else if (isType) ("type", "type", "TPE")
+ else if (isClassConstructor && (owner.hasCompleteInfo &&
+ isPrimaryConstructor)) ("primary constructor", "constructor", "PCTOR")
+ else if (isClassConstructor) ("constructor", "constructor", "CTOR")
+ else if (isMethod) ("method", "method", "METH")
+ else if (isTerm) ("value", "value", "VAL")
+ else ("", "", "???")
+
if (isSkolem) kind = (kind._1, kind._2, kind._3 + "#SKO")
+
SymbolKind(kind._1, kind._2, kind._3)
}
@@ -2623,12 +2622,17 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
*/
override def toString: String = {
- if (isPackageObjectOrClass && !settings.debug)
- s"package object ${owner.decodedName}"
- else compose(
- kindString,
- if (hasMeaninglessName) owner.decodedName + idString else nameString
- )
+ val simplifyNames = !settings.debug
+ if (isPackageObjectOrClass && simplifyNames) s"package object ${owner.decodedName}"
+ else {
+ val kind = kindString
+ val _name: String =
+ if (hasMeaninglessName) owner.decodedName + idString
+ else if (simplifyNames && (kind == "variable" || kind == "value")) unexpandedName.getterName.decode.toString // TODO: make condition less gross?
+ else nameString
+
+ compose(kind, _name)
+ }
}
/** String representation of location.
@@ -2764,18 +2768,21 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
)
***/
override def isValueParameter = this hasFlag PARAM
-
override def isSetterParameter = isValueParameter && owner.isSetter
- override def isAccessor = this hasFlag ACCESSOR
- override def isGetter = isAccessor && !isSetter
+
override def isDefaultGetter = name containsName nme.DEFAULT_GETTER_STRING
- override def isSetter = isAccessor && nme.isSetterName(name) // todo: make independent of name, as this can be forged.
+
+ override def isAccessor = this hasFlag ACCESSOR
+ override def isGetter = isAccessor && !nme.isSetterName(name) // TODO: make independent of name, as this can be forged.
+ override def isSetter = isAccessor && nme.isSetterName(name) // TODO: make independent of name, as this can be forged.
+
override def isLocalDummy = nme.isLocalDummyName(name)
+
override def isClassConstructor = name == nme.CONSTRUCTOR
override def isMixinConstructor = name == nme.MIXIN_CONSTRUCTOR
- override def isConstructor = nme.isConstructorName(name)
+ override def isConstructor = isClassConstructor || isMixinConstructor
- override def isPackageObject = isModule && (name == nme.PACKAGE)
+ override def isPackageObject = isModule && (name == nme.PACKAGE)
// The name in comments is what it is being disambiguated from.
// TODO - rescue CAPTURED from BYNAMEPARAM so we can see all the names.
@@ -2871,7 +2878,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def owner = {
if (Statistics.hotEnabled) Statistics.incCounter(ownerCount)
- // a module symbol may have the lateMETHOD flag after refchecks, see isModuleNotMethod
+ // a non-static module symbol gets the METHOD flag in uncurry's info transform -- see isModuleNotMethod
if (!isMethod && needsFlatClasses) rawowner.owner
else rawowner
}
@@ -2891,38 +2898,23 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** A class for method symbols */
class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
extends TermSymbol(initOwner, initPos, initName) with MethodSymbolApi {
- private[this] var mtpePeriod = NoPeriod
- private[this] var mtpePre: Type = _
- private[this] var mtpeResult: Type = _
- private[this] var mtpeInfo: Type = _
-
override def isLabel = this hasFlag LABEL
override def isVarargsMethod = this hasFlag VARARGS
override def isLiftedMethod = this hasFlag LIFTED
- // TODO - this seems a strange definition for "isSourceMethod", given that
- // it does not make any specific effort to exclude synthetics. Figure out what
- // this method is really for and what logic makes sense.
- override def isSourceMethod = !(this hasFlag STABLE) // exclude all accessors
+ // TODO: this definition of isSourceMethod makes no sense -- inline it and re-evaluate at each call site.
+ // I'm guessing it meant "method written by user, and not generated by the compiler"
+ // (And then assuming those generated by the compiler don't require certain transformations?)
+ // Use SYNTHETIC/ARTIFACT instead as an indicator? I don't see how it makes sense to only exclude getters.
+ // Note also that trait vals are modelled as getters, and thus that user-supplied code appears in their rhs.
+ // Originally, it may have been an optimization to skip methods that were not user-defined (getters),
+ // but it doesn't even exclude setters, contrary to its original comment (// exclude all accessors)
+ override def isSourceMethod = !(this hasFlag STABLE)
+
// unfortunately having the CASEACCESSOR flag does not actually mean you
// are a case accessor (you can also be a field.)
override def isCaseAccessorMethod = isCaseAccessor
- def typeAsMemberOf(pre: Type): Type = {
- if (mtpePeriod == currentPeriod) {
- if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
- } else if (isValid(mtpePeriod)) {
- mtpePeriod = currentPeriod
- if ((mtpePre eq pre) && (mtpeInfo eq info)) return mtpeResult
- }
- val res = pre.computeMemberType(this)
- mtpePeriod = currentPeriod
- mtpePre = pre
- mtpeInfo = info
- mtpeResult = res
- res
- }
-
override def isVarargs: Boolean = definitions.isVarArgsList(paramss.flatten)
override def returnType: Type = {
@@ -3231,7 +3223,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* returned, otherwise, `NoSymbol` is returned.
*/
protected final def companionModule0: Symbol =
- flatOwnerInfo.decl(name.toTermName).suchThat(sym => sym.isModuleNotMethod && (sym isCoDefinedWith this))
+ flatOwnerInfo.decl(name.toTermName).suchThat(sym => sym.isModule && (sym isCoDefinedWith this))
override def companionModule = companionModule0
override def companionSymbol = companionModule0
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 895bb60a08..7dda805378 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -686,23 +686,21 @@ trait Types
* }}}
*/
def memberInfo(sym: Symbol): Type = {
- require(sym ne NoSymbol, this)
+// assert(sym ne NoSymbol, this)
sym.info.asSeenFrom(this, sym.owner)
}
/** The type of `sym`, seen as a member of this type. */
- def memberType(sym: Symbol): Type = sym match {
- case meth: MethodSymbol =>
- meth.typeAsMemberOf(this)
- case _ =>
- computeMemberType(sym)
- }
-
- def computeMemberType(sym: Symbol): Type = sym.tpeHK match { //@M don't prematurely instantiate higher-kinded types, they will be instantiated by transform, typedTypeApply, etc. when really necessary
- case OverloadedType(_, alts) =>
- OverloadedType(this, alts)
+ def memberType(sym: Symbol): Type = sym.tpeHK match {
+ case OverloadedType(_, alts) => OverloadedType(this, alts)
case tp =>
- if (sym eq NoSymbol) NoType else tp.asSeenFrom(this, sym.owner)
+ // Correct caching is nearly impossible because `sym.tpeHK.asSeenFrom(pre, sym.owner)`
+ // may have different results even for reference-identical `sym.tpeHK` and `pre` (even in the same period).
+ // For example, `pre` could be a `ThisType`. For such a type, `tpThen eq tpNow` does not imply
+ // `tpThen` and `tpNow` mean the same thing, because `tpThen.typeSymbol.info` could have been different
+ // from what it is now, and the cache won't know simply by looking at `pre`.
+ if (sym eq NoSymbol) NoType
+ else tp.asSeenFrom(this, sym.owner)
}
/** Substitute types `to` for occurrences of references to
@@ -3471,10 +3469,10 @@ trait Types
if (!sym.isOverridableMember || sym.owner == pre.typeSymbol) sym
else pre.nonPrivateMember(sym.name).suchThat { sym =>
// SI-7928 `isModuleNotMethod` is here to avoid crashing with spuriously "overloaded" module accessor and module symbols.
- // These appear after refchecks eliminates ModuleDefs that implement an interface.
+ // These appear after the fields phase eliminates ModuleDefs that implement an interface.
// Here, we exclude the module symbol, which allows us to bind to the accessor.
- // SI-8054 We must only do this after refchecks, otherwise we exclude the module symbol which does not yet have an accessor!
- val isModuleWithAccessor = phase.refChecked && sym.isModuleNotMethod
+ // SI-8054 We must only do this after fields, otherwise we exclude the module symbol which does not yet have an accessor!
+ val isModuleWithAccessor = phase.assignsFields && sym.isModuleNotMethod
sym.isType || (!isModuleWithAccessor && sym.isStable && !sym.hasVolatileType)
} orElse sym
}
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 69bade55f1..bc8a5de119 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -167,7 +167,9 @@ trait Variances {
case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(sym)
super.traverse(tree)
- // ModuleDefs need not be considered because they have been eliminated already
+ case ModuleDef(_, _, _) =>
+ validateVariance(sym.moduleClass)
+ super.traverse(tree)
case ValDef(_, _, _, _) =>
validateVariance(sym)
case DefDef(_, _, tparams, vparamss, _, _) =>
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index 412c49f571..62ca50d035 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -148,9 +148,19 @@ trait Erasure {
apply(atp)
case ClassInfoType(parents, decls, clazz) =>
ClassInfoType(
- if (clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil
+ if (clazz == ObjectClass || isPrimitiveValueClass(clazz) || parents.isEmpty) Nil
else if (clazz == ArrayClass) ObjectTpe :: Nil
- else removeLaterObjects(parents map this),
+ else {
+ val erasedParents = parents map this
+
+ // drop first parent for traits -- it has been normalized to a class by now,
+ // but we should drop that in bytecode
+ val firstParent =
+ if (clazz.hasFlag(Flags.TRAIT) && !clazz.hasFlag(Flags.JAVA)) ObjectTpe
+ else erasedParents.head
+
+ firstParent :: erasedParents.tail.filter(_.typeSymbol != ObjectClass)
+ },
decls, clazz)
case _ =>
mapOver(tp)
diff --git a/src/reflect/scala/reflect/internal/transform/RefChecks.scala b/src/reflect/scala/reflect/internal/transform/RefChecks.scala
index 4ca114e781..e69de29bb2 100644
--- a/src/reflect/scala/reflect/internal/transform/RefChecks.scala
+++ b/src/reflect/scala/reflect/internal/transform/RefChecks.scala
@@ -1,14 +0,0 @@
-package scala
-package reflect
-package internal
-package transform
-
-trait RefChecks {
-
- val global: SymbolTable
- import global._
-
- def transformInfo(sym: Symbol, tp: Type): Type =
- if (sym.isModule && !sym.isStatic) NullaryMethodType(tp)
- else tp
-}
diff --git a/src/reflect/scala/reflect/internal/transform/Transforms.scala b/src/reflect/scala/reflect/internal/transform/Transforms.scala
index 0d2f355aa5..de5bfbd39a 100644
--- a/src/reflect/scala/reflect/internal/transform/Transforms.scala
+++ b/src/reflect/scala/reflect/internal/transform/Transforms.scala
@@ -23,12 +23,10 @@ trait Transforms { self: SymbolTable =>
}
}
- private val refChecksLazy = new Lazy(new { val global: Transforms.this.type = self } with RefChecks)
private val uncurryLazy = new Lazy(new { val global: Transforms.this.type = self } with UnCurry)
private val erasureLazy = new Lazy(new { val global: Transforms.this.type = self } with Erasure)
private val postErasureLazy = new Lazy(new { val global: Transforms.this.type = self } with PostErasure)
- def refChecks = refChecksLazy.force
def uncurry = uncurryLazy.force
def erasure = erasureLazy.force
def postErasure = postErasureLazy.force
@@ -36,8 +34,7 @@ trait Transforms { self: SymbolTable =>
def transformedType(sym: Symbol) =
postErasure.transformInfo(sym,
erasure.transformInfo(sym,
- uncurry.transformInfo(sym,
- refChecks.transformInfo(sym, sym.info))))
+ uncurry.transformInfo(sym, sym.info)))
def transformedType(tpe: Type) =
postErasure.elimErasedValueType(erasure.scalaErasure(uncurry.uncurry(tpe)))
diff --git a/src/reflect/scala/reflect/internal/transform/UnCurry.scala b/src/reflect/scala/reflect/internal/transform/UnCurry.scala
index 85e3ac60e8..a50084f40d 100644
--- a/src/reflect/scala/reflect/internal/transform/UnCurry.scala
+++ b/src/reflect/scala/reflect/internal/transform/UnCurry.scala
@@ -83,5 +83,10 @@ trait UnCurry {
* @MAT: starting with this phase, the info of every symbol will be normalized
*/
def transformInfo(sym: Symbol, tp: Type): Type =
- if (sym.isType) uncurryType(tp) else uncurry(tp)
+ if (sym.isType) uncurryType(tp)
+ else if ((sym hasFlag MODULE) && !sym.isStatic) { // see Fields::nonStaticModuleToMethod
+ sym setFlag METHOD | STABLE
+ MethodType(Nil, uncurry(tp))
+ }
+ else uncurry(tp)
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 0a90a141d3..caef5535b4 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -247,7 +247,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.SymbolModule
definitions.StringAddClass
definitions.ScalaNumberClass
- definitions.TraitSetterAnnotationClass
definitions.DelayedInitClass
definitions.TypeConstraintClass
definitions.SingletonClass
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 313ec89311..237afa082b 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -199,12 +199,7 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb
trait SynchronizedTermSymbol extends SynchronizedSymbol
- trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol {
- // we can keep this lock fine-grained, because it's just a cache over asSeenFrom, which makes deadlocks impossible
- // unfortunately we cannot elide this lock, because the cache depends on `pre`
- private lazy val typeAsMemberOfLock = new Object
- override def typeAsMemberOf(pre: Type): Type = gilSynchronizedIfNotThreadsafe { typeAsMemberOfLock.synchronized { super.typeAsMemberOf(pre) } }
- }
+ trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol
trait SynchronizedModuleSymbol extends ModuleSymbol with SynchronizedTermSymbol