aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Contexts.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala57
-rw-r--r--compiler/src/dotty/tools/dotc/core/Denotations.scala46
-rw-r--r--compiler/src/dotty/tools/dotc/core/Flags.scala29
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameKinds.scala317
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala409
-rw-r--r--compiler/src/dotty/tools/dotc/core/Names.scala455
-rw-r--r--compiler/src/dotty/tools/dotc/core/Scopes.scala73
-rw-r--r--compiler/src/dotty/tools/dotc/core/Signature.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala101
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymDenotations.scala182
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala111
-rw-r--r--compiler/src/dotty/tools/dotc/core/Symbols.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeApplications.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala41
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala46
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala115
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyBuffer.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala35
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala30
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyReader.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala72
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala46
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala59
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala41
30 files changed, 1360 insertions, 984 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala
index 8707b66f9..b299de434 100644
--- a/compiler/src/dotty/tools/dotc/core/Contexts.scala
+++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala
@@ -174,9 +174,6 @@ object Contexts {
protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames
def freshNames: FreshNameCreator = _freshNames
- def freshName(prefix: String = ""): String = freshNames.newName(prefix)
- def freshName(prefix: Name): String = freshName(prefix.toString)
-
/** A map in which more contextual properties can be stored */
private var _moreProperties: Map[Key[Any], Any] = _
protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties
@@ -297,7 +294,7 @@ object Contexts {
/** Is this a context that introduces a non-empty scope? */
def isNonEmptyScopeContext: Boolean =
- (this.scope ne outer.scope) && this.scope.nonEmpty
+ (this.scope ne outer.scope) && !this.scope.isEmpty
/** Leave message in diagnostics buffer if it exists */
def diagnose(str: => String) =
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index b70fcb093..a97589d73 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -10,6 +10,7 @@ import scala.collection.{ mutable, immutable }
import PartialFunction._
import collection.mutable
import util.common.alwaysZero
+import typer.Applications
object Definitions {
@@ -67,7 +68,7 @@ class Definitions {
enterTypeField(cls, name, flags | ClassTypeParamCreationFlags, scope)
private def enterSyntheticTypeParam(cls: ClassSymbol, paramFlags: FlagSet, scope: MutableScope, suffix: String = "T0") =
- enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope)
+ enterTypeParam(cls, suffix.toTypeName.expandedName(cls), paramFlags, scope)
// NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
// implemented in Dotty and not in Scala 2.
@@ -108,7 +109,7 @@ class Definitions {
* def apply(implicit $x0: T0, ..., $x{N_1}: T{N-1}): R
* }
*/
- private def newFunctionNTrait(name: TypeName) = {
+ def newFunctionNTrait(name: TypeName) = {
val completer = new LazyType {
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
val cls = denot.asClass.classSymbol
@@ -119,7 +120,7 @@ class Definitions {
enterTypeParam(cls, name ++ "$T" ++ i.toString, Contravariant, decls)
val resParam = enterTypeParam(cls, name ++ "$R", Covariant, decls)
val (methodType, parentTraits) =
- if (name.startsWith(tpnme.ImplicitFunction)) {
+ if (name.firstPart.startsWith(str.ImplicitFunction)) {
val superTrait =
FunctionType(arity).appliedTo(argParams.map(_.typeRef) ::: resParam.typeRef :: Nil)
(ImplicitMethodType, ctx.normalizeToClassRefs(superTrait :: Nil, cls, decls))
@@ -477,6 +478,7 @@ class Definitions {
lazy val JavaCloneableClass = ctx.requiredClass("java.lang.Cloneable")
lazy val NullPointerExceptionClass = ctx.requiredClass("java.lang.NullPointerException")
+ lazy val IndexOutOfBoundsException = ctx.requiredClass("java.lang.IndexOutOfBoundsException")
lazy val ClassClass = ctx.requiredClass("java.lang.Class")
lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number")
lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable")
@@ -723,12 +725,11 @@ class Definitions {
/** If type `ref` refers to a class in the scala package, its name, otherwise EmptyTypeName */
def scalaClassName(ref: Type)(implicit ctx: Context): TypeName = scalaClassName(ref.classSymbol)
- private def isVarArityClass(cls: Symbol, prefix: Name) = {
- val name = scalaClassName(cls)
- name.startsWith(prefix) &&
- name.length > prefix.length &&
- name.drop(prefix.length).forall(_.isDigit)
- }
+ private def isVarArityClass(cls: Symbol, prefix: String) =
+ scalaClassName(cls).testSimple(name =>
+ name.startsWith(prefix) &&
+ name.length > prefix.length &&
+ name.drop(prefix.length).forall(_.isDigit))
def isBottomClass(cls: Symbol) =
cls == NothingClass || cls == NullClass
@@ -758,9 +759,9 @@ class Definitions {
*/
def isSyntheticFunctionClass(cls: Symbol) = scalaClassName(cls).isSyntheticFunction
- def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.AbstractFunction)
- def isTupleClass(cls: Symbol) = isVarArityClass(cls, tpnme.Tuple)
- def isProductClass(cls: Symbol) = isVarArityClass(cls, tpnme.Product)
+ def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, str.AbstractFunction)
+ def isTupleClass(cls: Symbol) = isVarArityClass(cls, str.Tuple)
+ def isProductClass(cls: Symbol) = isVarArityClass(cls, str.Product)
/** Returns the erased class of the function class `cls`
* - FunctionN for N > 22 becomes FunctionXXL
@@ -845,18 +846,7 @@ class Definitions {
TupleType(elems.size).appliedTo(elems)
}
- def isProductSubType(tp: Type)(implicit ctx: Context) =
- (tp derivesFrom ProductType.symbol) && tp.baseClasses.exists(isProductClass)
-
- def productArity(tp: Type)(implicit ctx: Context) =
- if (tp derivesFrom ProductType.symbol)
- tp.baseClasses.find(isProductClass) match {
- case Some(prod) => prod.typeParams.length
- case None => -1
- }
- else -1
-
- /** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN ? */
+ /** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN? */
def isFunctionType(tp: Type)(implicit ctx: Context) = {
val arity = functionArity(tp)
val sym = tp.dealias.typeSymbol
@@ -933,23 +923,6 @@ class Definitions {
// ----- Initialization ---------------------------------------------------
- /** Give the scala package a scope where a FunctionN trait is automatically
- * added when someone looks for it.
- */
- private def makeScalaSpecial()(implicit ctx: Context) = {
- val oldInfo = ScalaPackageClass.classInfo
- val oldDecls = oldInfo.decls
- val newDecls = new MutableScope(oldDecls) {
- override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
- val res = super.lookupEntry(name)
- if (res == null && name.isTypeName && name.isSyntheticFunction)
- newScopeEntry(newFunctionNTrait(name.asTypeName))
- else res
- }
- }
- ScalaPackageClass.info = oldInfo.derivedClassInfo(decls = newDecls)
- }
-
/** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
lazy val syntheticScalaClasses = List(
AnyClass,
@@ -977,8 +950,6 @@ class Definitions {
def init()(implicit ctx: Context) = {
this.ctx = ctx
if (!_isInitialized) {
- makeScalaSpecial()
-
// force initialization of every symbol that is synthesized or hijacked by the compiler
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses()
diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala
index 7341b96af..fd42bde36 100644
--- a/compiler/src/dotty/tools/dotc/core/Denotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala
@@ -4,8 +4,9 @@ package core
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation }
import Contexts.{Context, ContextBase}
-import Names.{Name, PreName}
-import Names.TypeName
+import Names._
+import NameOps._
+import NameKinds._
import StdNames._
import Symbols.NoSymbol
import Symbols._
@@ -1171,27 +1172,42 @@ object Denotations {
* if generateStubs is set, generates stubs for missing top-level symbols
*/
def staticRef(path: Name, generateStubs: Boolean = true)(implicit ctx: Context): Denotation = {
- def recur(path: Name, len: Int): Denotation = {
- val point = path.lastIndexOf('.', len - 1)
- val owner =
- if (point > 0) recur(path.toTermName, point).disambiguate(_.info.isParameterless)
- else if (path.isTermName) defn.RootClass.denot
- else defn.EmptyPackageClass.denot
+ def select(prefix: Denotation, selector: Name): Denotation = {
+ val owner = prefix.disambiguate(_.info.isParameterless)
if (owner.exists) {
- val name = path slice (point + 1, len)
- val result = owner.info.member(name)
- if (result ne NoDenotation) result
+ val result = owner.info.member(selector)
+ if (result.exists) result
else {
val alt =
- if (generateStubs) missingHook(owner.symbol.moduleClass, name)
+ if (generateStubs) missingHook(owner.symbol.moduleClass, selector)
else NoSymbol
- if (alt.exists) alt.denot
- else MissingRef(owner, name)
+ if (alt.exists) alt.denot else MissingRef(owner, selector)
}
}
else owner
}
- recur(path, path.length)
+ def recur(path: Name, wrap: TermName => Name = identity): Denotation = path match {
+ case path: TypeName =>
+ recur(path.toTermName, n => n.toTypeName)
+ case ModuleClassName(underlying) =>
+ recur(underlying, n => wrap(ModuleClassName(n)))
+ case QualifiedName(prefix, selector) =>
+ select(recur(prefix), wrap(selector))
+ case qn @ AnyQualifiedName(prefix, _) =>
+ recur(prefix, n => wrap(qn.info.mkString(n).toTermName))
+ case path: SimpleTermName =>
+ def recurSimple(len: Int, wrap: TermName => Name): Denotation = {
+ val point = path.lastIndexOf('.', len - 1)
+ val selector = wrap(path.slice(point + 1, len).asTermName)
+ val prefix =
+ if (point > 0) recurSimple(point, identity)
+ else if (selector.isTermName) defn.RootClass.denot
+ else defn.EmptyPackageClass.denot
+ select(prefix, selector)
+ }
+ recurSimple(path.length, wrap)
+ }
+ recur(path)
}
/** If we are looking for a non-existing term name in a package,
diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala
index 29f1078a2..84072cd50 100644
--- a/compiler/src/dotty/tools/dotc/core/Flags.scala
+++ b/compiler/src/dotty/tools/dotc/core/Flags.scala
@@ -272,9 +272,6 @@ object Flags {
*/
final val Synthetic = commonFlag(18, "<synthetic>")
- /** Symbol's name is expanded */
- final val ExpandedName = commonFlag(19, "<expandedname>")
-
/** A covariant type variable / an outer accessor */
final val CovariantOrOuter = commonFlag(20, "")
final val Covariant = typeFlag(20, "<covariant>")
@@ -308,19 +305,18 @@ object Flags {
final val CaseAccessor = termFlag(25, "<caseaccessor>")
/** A binding for a type parameter of a base class or trait.
- * TODO: Replace with combination of isType, ExpandedName, and Override?
*/
final val BaseTypeArg = typeFlag(25, "<basetypearg>")
final val CaseAccessorOrBaseTypeArg = CaseAccessor.toCommonFlags
/** A super accessor */
- final val SuperAccessor = termFlag(26, "<superaccessor>")
+ final val Scala2SuperAccessor = termFlag(26, "<superaccessor>")
/** An unpickled Scala 2.x class */
final val Scala2x = typeFlag(26, "<scala-2.x>")
- final val SuperAccessorOrScala2x = SuperAccessor.toCommonFlags
+ final val SuperAccessorOrScala2x = Scala2x.toCommonFlags
/** A method that has default params */
final val DefaultParameterized = termFlag(27, "<defaultparam>")
@@ -409,9 +405,6 @@ object Flags {
final val Scala2ExistentialCommon = commonFlag(55, "<existential>")
final val Scala2Existential = Scala2ExistentialCommon.toTypeFlags
- /** An overloaded symbol (Scala 2.x only) */
- final val Scala2Overloaded = termFlag(56, "<overloaded>")
-
/** A module variable (Scala 2.x only) */
final val Scala2ModuleVar = termFlag(57, "<modulevar>")
@@ -424,6 +417,13 @@ object Flags {
/** A method that is known to have inherited default parameters */
final val InheritedDefaultParams = termFlag(60, "<inherited-default-param>")
+ /** Translation of Scala2's EXPANDEDNAME flag. This flag is never stored in
+ * symbols, is only used locally when reading the flags of a Scala2 symbol.
+ * It's therefore safe to share the code with `InheritedDefaultParams` because
+ * the latter is never present in Scala2 unpickle info.
+ */
+ final val Scala2ExpandedName = InheritedDefaultParams.toCommonFlags
+
/** A method that is known to have no default parameters */
final val NoDefaultParams = termFlag(61, "<no-default-param>")
@@ -452,7 +452,7 @@ object Flags {
final val FromStartFlags =
Module | Package | Deferred | MethodOrHKCommon | Param | ParamAccessor |
Scala2ExistentialCommon | Mutable.toCommonFlags | InSuperCall | Touched | JavaStatic |
- CovariantOrOuter | ContravariantOrLabel | ExpandedName | CaseAccessorOrBaseTypeArg |
+ CovariantOrOuter | ContravariantOrLabel | CaseAccessorOrBaseTypeArg |
Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic |
SuperAccessorOrScala2x | Inline
@@ -475,7 +475,7 @@ object Flags {
/** Flags that are passed from a type parameter of a class to a refinement symbol
* that sets the type parameter */
- final val RetainedTypeArgFlags = VarianceFlags | ExpandedName | Protected | Local
+ final val RetainedTypeArgFlags = VarianceFlags | Protected | Local
/** Modules always have these flags set */
final val ModuleCreationFlags = ModuleVal | Lazy | Final | Stable
@@ -502,7 +502,7 @@ object Flags {
*/
final val RetainedModuleValAndClassFlags: FlagSet =
AccessFlags | Package | Case |
- Synthetic | ExpandedName | JavaDefined | JavaStatic | Artifact |
+ Synthetic | JavaDefined | JavaStatic | Artifact |
Erroneous | Lifted | MixedIn | Specialized
/** Flags that can apply to a module val */
@@ -550,9 +550,6 @@ object Flags {
/** A private accessor */
final val PrivateAccessor = allOf(Private, Accessor)
- /** A type parameter with synthesized name */
- final val ExpandedTypeParam = allOf(ExpandedName, TypeParam)
-
/** An inline method */
final val InlineMethod = allOf(Inline, Method)
@@ -578,7 +575,7 @@ object Flags {
final val FinalOrInline = Final | Inline
/** If symbol of a type alias has these flags, prefer the alias */
- final val AliasPreferred = TypeParam | BaseTypeArg | ExpandedName
+ final val AliasPreferred = TypeParam | BaseTypeArg
/** A covariant type parameter instance */
final val LocalCovariant = allOf(Local, Covariant)
diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala
new file mode 100644
index 000000000..0f08e4701
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala
@@ -0,0 +1,317 @@
+package dotty.tools
+package dotc
+package core
+
+import Names._
+import NameOps._
+import StdNames._
+import util.DotClass
+import tasty.TastyFormat._
+import Decorators._
+import Contexts.Context
+import collection.mutable
+
+object NameKinds {
+
+ // These are sharable since all NameKinds are created eagerly at the start of the program
+ // before any concurrent threads are forked. for this to work, NameKinds should never
+ // be created lazily or in modules that start running after compilers are forked.
+ @sharable private val simpleNameKinds = new mutable.HashMap[Int, ClassifiedNameKind]
+ @sharable private val qualifiedNameKinds = new mutable.HashMap[Int, QualifiedNameKind]
+ @sharable private val uniqueNameKinds = new mutable.HashMap[String, UniqueNameKind]
+
+ abstract class NameInfo extends DotClass {
+ def kind: NameKind
+ def mkString(underlying: TermName): String
+ def map(f: SimpleTermName => SimpleTermName): NameInfo = this
+ }
+
+ abstract class NameKind(val tag: Int) extends DotClass { self =>
+ type ThisInfo <: Info
+ class Info extends NameInfo { this: ThisInfo =>
+ def kind = self
+ def mkString(underlying: TermName) = self.mkString(underlying, this)
+ override def toString = infoString
+ }
+ def definesNewName = false
+ def unmangle(name: SimpleTermName): TermName = name
+ def mkString(underlying: TermName, info: ThisInfo): String
+ def infoString: String
+ }
+
+ object SimpleTermNameKind extends NameKind(UTF8) { self =>
+ type ThisInfo = Info
+ val info = new Info
+ def mkString(underlying: TermName, info: ThisInfo) = unsupported("mkString")
+ def infoString = unsupported("infoString")
+ }
+
+ abstract class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) {
+ type ThisInfo = Info
+ val info = new Info
+ def apply(qual: TermName) =
+ qual.derived(info)
+ def unapply(name: DerivedTermName): Option[TermName] = name match {
+ case DerivedTermName(underlying, `info`) => Some(underlying)
+ case _ => None
+ }
+ simpleNameKinds(tag) = this
+ }
+
+ class PrefixNameKind(tag: Int, prefix: String, optInfoString: String = "")
+ extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Prefix $prefix" else optInfoString) {
+ def mkString(underlying: TermName, info: ThisInfo) =
+ underlying.mapLast(n => termName(prefix + n.toString)).toString
+ override def unmangle(name: SimpleTermName): TermName =
+ if (name.startsWith(prefix)) apply(name.drop(prefix.length).asSimpleName)
+ else name
+ }
+
+ class SuffixNameKind(tag: Int, suffix: String, optInfoString: String = "")
+ extends ClassifiedNameKind(tag, if (optInfoString.isEmpty) s"Suffix $suffix" else optInfoString) {
+ def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix
+ override def unmangle(name: SimpleTermName): TermName =
+ if (name.endsWith(suffix)) apply(name.take(name.length - suffix.length).asSimpleName)
+ else name
+ }
+
+ trait QualifiedInfo extends NameInfo {
+ val name: SimpleTermName
+ }
+
+ class QualifiedNameKind(tag: Int, val separator: String)
+ extends NameKind(tag) {
+ type ThisInfo = QualInfo
+ case class QualInfo(val name: SimpleTermName) extends Info with QualifiedInfo {
+ override def map(f: SimpleTermName => SimpleTermName): NameInfo = new QualInfo(f(name))
+ override def toString = s"$infoString $name"
+ }
+ def apply(qual: TermName, name: SimpleTermName): TermName =
+ qual.derived(new QualInfo(name))
+
+ /** Overloaded version used only for ExpandedName and TraitSetterName.
+ * Needed because the suffix of an expanded name may itself be expanded.
+ * For example, look at javap of scala.App.initCode
+ */
+ def apply(qual: TermName, name: TermName): TermName = name rewrite {
+ case name: SimpleTermName => apply(qual, name)
+ case AnyQualifiedName(_, _) => apply(qual, name.toSimpleName)
+ }
+
+ def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
+ case DerivedTermName(qual, info: this.QualInfo) => Some((qual, info.name))
+ case _ => None
+ }
+
+ override def definesNewName = true
+
+ def mkString(underlying: TermName, info: ThisInfo) =
+ s"$underlying$separator${info.name}"
+ def infoString = s"Qualified $separator"
+
+ qualifiedNameKinds(tag) = this
+ }
+
+ object AnyQualifiedName {
+ def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
+ case DerivedTermName(qual, info: QualifiedInfo) =>
+ Some((name.underlying, info.name))
+ case _ => None
+ }
+ }
+
+ trait NumberedInfo extends NameInfo {
+ def num: Int
+ }
+
+ abstract class NumberedNameKind(tag: Int, val infoString: String) extends NameKind(tag) { self =>
+ type ThisInfo = NumberedInfo
+ case class NumberedInfo(val num: Int) extends Info with NameKinds.NumberedInfo {
+ override def toString = s"$infoString $num"
+ }
+ def apply(qual: TermName, num: Int) =
+ qual.derived(new NumberedInfo(num))
+ def unapply(name: DerivedTermName): Option[(TermName, Int)] = name match {
+ case DerivedTermName(underlying, info: this.NumberedInfo) => Some((underlying, info.num))
+ case _ => None
+ }
+ protected def skipSeparatorAndNum(name: SimpleTermName, separator: String): Int = {
+ var i = name.length
+ while (i > 0 && name(i - 1).isDigit) i -= 1
+ if (i > separator.length && i < name.length &&
+ name.slice(i - separator.length, i).toString == separator) i
+ else -1
+ }
+ }
+
+ object AnyNumberedName {
+ def unapply(name: DerivedTermName): Option[(TermName, Int)] = name match {
+ case DerivedTermName(qual, info: NumberedInfo) => Some((qual, info.num))
+ case _ => None
+ }
+ }
+
+ case class UniqueNameKind(val separator: String)
+ extends NumberedNameKind(UNIQUE, s"Unique $separator") {
+ override def definesNewName = true
+ def mkString(underlying: TermName, info: ThisInfo) = {
+ val safePrefix = str.sanitize(underlying.toString + separator)
+ safePrefix + info.num
+ }
+
+ def fresh(prefix: TermName = EmptyTermName)(implicit ctx: Context): TermName =
+ ctx.freshNames.newName(prefix, this)
+
+ uniqueNameKinds(separator) = this
+ }
+
+ object AnyUniqueName {
+ def unapply(name: DerivedTermName): Option[(TermName, String, Int)] = name match {
+ case DerivedTermName(qual, info: NumberedInfo) =>
+ info.kind match {
+ case unique: UniqueNameKind => Some((qual, unique.separator, info.num))
+ case _ => None
+ }
+ case _ => None
+ }
+ }
+
+ val QualifiedName = new QualifiedNameKind(QUALIFIED, ".")
+ val FlatName = new QualifiedNameKind(FLATTENED, "$")
+ val ExpandPrefixName = new QualifiedNameKind(EXPANDPREFIX, "$")
+
+ val ExpandedName = new QualifiedNameKind(EXPANDED, str.EXPAND_SEPARATOR) {
+ private val FalseSuper = termName("$$super")
+ private val FalseSuperLength = FalseSuper.length
+
+ override def unmangle(name: SimpleTermName): TermName = {
+ var i = name.lastIndexOfSlice(str.EXPAND_SEPARATOR)
+ if (i < 0) name
+ else {
+ // Hack to make super accessors from traits work. They would otherwise fail because of #765
+ // The problem is that in `x$$super$$plus` the expansion prefix needs to be `x`
+ // instead of `x$$super`.
+ if (i > FalseSuperLength && name.slice(i - FalseSuperLength, i) == FalseSuper)
+ i -= FalseSuper.length
+
+ apply(name.take(i).asTermName, name.drop(i + str.EXPAND_SEPARATOR.length).asSimpleName)
+ }
+ }
+ }
+
+ val TraitSetterName = new QualifiedNameKind(TRAITSETTER, str.TRAIT_SETTER_SEPARATOR)
+
+ val UniqueName = new UniqueNameKind("$") {
+ override def mkString(underlying: TermName, info: ThisInfo) =
+ if (underlying.isEmpty) "$" + info.num + "$" else super.mkString(underlying, info)
+ }
+
+ val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$")
+ val TempResultName = new UniqueNameKind("ev$")
+ val EvidenceParamName = new UniqueNameKind("evidence$")
+ val DepParamName = new UniqueNameKind("<param>")
+ val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$")
+ val LazyLocalName = new UniqueNameKind("$lzy")
+ val LazyLocalInitName = new UniqueNameKind("$lzyINIT")
+ val LazyFieldOffsetName = new UniqueNameKind("$OFFSET")
+ val LazyBitMapName = new UniqueNameKind(nme.BITMAP_PREFIX.toString)
+ val NonLocalReturnKeyName = new UniqueNameKind("nonLocalReturnKey")
+ val WildcardParamName = new UniqueNameKind("_$")
+ val TailLabelName = new UniqueNameKind("tailLabel")
+ val ExceptionBinderName = new UniqueNameKind("ex")
+ val SkolemName = new UniqueNameKind("?")
+ val LiftedTreeName = new UniqueNameKind("liftedTree")
+
+ val UniqueExtMethName = new UniqueNameKind("$extension") {
+ override def unmangle(name: SimpleTermName): TermName = {
+ val i = skipSeparatorAndNum(name, separator)
+ if (i > 0) {
+ val index = name.drop(i).toString.toInt
+ var original = name.take(i - separator.length).asTermName
+ apply(original, index)
+ }
+ else name
+ }
+ }
+
+ val PatMatStdBinderName = new UniqueNameKind("x")
+ val PatMatPiName = new UniqueNameKind("pi") // FIXME: explain what this is
+ val PatMatPName = new UniqueNameKind("p") // FIXME: explain what this is
+ val PatMatOName = new UniqueNameKind("o") // FIXME: explain what this is
+ val PatMatCaseName = new UniqueNameKind("case")
+ val PatMatMatchFailName = new UniqueNameKind("matchFail")
+ val PatMatSelectorName = new UniqueNameKind("selector")
+
+ object DefaultGetterName extends NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
+ def mkString(underlying: TermName, info: ThisInfo) = {
+ val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying
+ prefix.toString + str.DEFAULT_GETTER + (info.num + 1)
+ }
+ // TODO: Reduce code duplication with UniqueExtMethName
+ override def unmangle(name: SimpleTermName): TermName = {
+ val i = skipSeparatorAndNum(name, str.DEFAULT_GETTER)
+ if (i > 0) {
+ val index = name.drop(i).toString.toInt - 1
+ var original = name.take(i - str.DEFAULT_GETTER.length).asTermName
+ if (original == nme.DEFAULT_GETTER_INIT) original = Names.CONSTRUCTOR
+ apply(original, index)
+ }
+ else name
+ }
+ }
+
+ object VariantName extends NumberedNameKind(VARIANT, "Variant") {
+ val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
+ def mkString(underlying: TermName, info: ThisInfo) = {
+ varianceToPrefix(info.num).toString + underlying
+ }
+ }
+
+ /** Names of the form N_<outer>. Emitted by inliner, replaced by outer path
+ * in ExplicitOuter.
+ */
+ object OuterSelectName extends NumberedNameKind(OUTERSELECT, "OuterSelect") {
+ def mkString(underlying: TermName, info: ThisInfo) = {
+ assert(underlying.isEmpty)
+ info.num + "_<outer>"
+ }
+ }
+
+ val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$")
+ val InitializerName = new PrefixNameKind(INITIALIZER, "initial$")
+ val ShadowedName = new PrefixNameKind(SHADOWED, "(shadowed)")
+ val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$")
+ val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected$set") // dubious encoding, kept for Scala2 compatibility
+ val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
+ val DirectName = new SuffixNameKind(DIRECT, "$direct")
+ val FieldName = new SuffixNameKind(FIELD, "$$local")
+ val ExtMethName = new SuffixNameKind(EXTMETH, "$extension")
+ val ModuleVarName = new SuffixNameKind(OBJECTVAR, "$module")
+ val ModuleClassName = new SuffixNameKind(OBJECTCLASS, "$", optInfoString = "ModuleClass")
+
+ object SignedName extends NameKind(63) {
+
+ /** @param parts resultSig followed by paramsSig */
+ case class SignedInfo(sig: Signature) extends Info {
+ override def toString = s"$infoString $sig"
+ }
+ type ThisInfo = SignedInfo
+
+ def apply(qual: TermName, sig: Signature) =
+ qual.derived(new SignedInfo(sig))
+ def unapply(name: DerivedTermName): Option[(TermName, Signature)] = name match {
+ case DerivedTermName(underlying, info: SignedInfo) => Some((underlying, info.sig))
+ case _ => None
+ }
+
+ def mkString(underlying: TermName, info: ThisInfo): String = unsupported("mkString")
+ def infoString: String = "Signed"
+ }
+
+ val Scala2MethodNameKinds: List[NameKind] =
+ List(DefaultGetterName, ExtMethName, UniqueExtMethName, ProtectedAccessorName, ProtectedSetterName)
+
+ def simpleNameKindOfTag : collection.Map[Int, ClassifiedNameKind] = simpleNameKinds
+ def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
+ def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
+} \ No newline at end of file
diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala
index 240ad359b..915bd52ab 100644
--- a/compiler/src/dotty/tools/dotc/core/NameOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala
@@ -4,11 +4,12 @@ package core
import java.security.MessageDigest
import scala.annotation.switch
import scala.io.Codec
-import Names._, StdNames._, Contexts._, Symbols._, Flags._
+import Names._, StdNames._, Contexts._, Symbols._, Flags._, NameKinds._
import Decorators.PreNamedString
import util.{Chars, NameTransformer}
import Chars.isOperatorPart
import Definitions._
+import config.Config
object NameOps {
@@ -48,212 +49,97 @@ object NameOps {
}
}
- class PrefixNameExtractor(pre: TermName) {
- def apply(name: TermName): TermName = pre ++ name
- def unapply(name: TermName): Option[TermName] =
- if (name startsWith pre) Some(name.drop(pre.length).asTermName) else None
- }
-
- object SuperAccessorName extends PrefixNameExtractor(nme.SUPER_PREFIX)
- object InitializerName extends PrefixNameExtractor(nme.INITIALIZER_PREFIX)
-
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
import nme._
- def likeTyped(n: PreName): N =
+ def testSimple(f: SimpleTermName => Boolean): Boolean = name match {
+ case name: SimpleTermName => f(name)
+ case name: TypeName => name.toTermName.testSimple(f)
+ case _ => false
+ }
+
+ def likeSpaced(n: PreName): N =
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
def isConstructorName = name == CONSTRUCTOR || name == TRAIT_CONSTRUCTOR
def isStaticConstructorName = name == STATIC_CONSTRUCTOR
- def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX
- def isImplClassName = name endsWith IMPL_CLASS_SUFFIX
- def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX
- def isLoopHeaderLabel = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
- def isProtectedAccessorName = name startsWith PROTECTED_PREFIX
- def isReplWrapperName = name containsSlice INTERPRETER_IMPORT_WRAPPER
- def isTraitSetterName = name containsSlice TRAIT_SETTER_SEPARATOR
- def isSetterName = name endsWith SETTER_SUFFIX
- def isSingletonName = name endsWith SINGLETON_SUFFIX
- def isModuleClassName = name endsWith MODULE_SUFFIX
- def isAvoidClashName = name endsWith AVOID_CLASH_SUFFIX
- def isImportName = name startsWith IMPORT
- def isFieldName = name endsWith LOCAL_SUFFIX
- def isShadowedName = name.length > 0 && name.head == '(' && name.startsWith(nme.SHADOWED)
- def isDefaultGetterName = name.isTermName && name.asTermName.defaultGetterIndex >= 0
- def isScala2LocalSuffix = name.endsWith(" ")
- def isModuleVarName(name: Name): Boolean =
- name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX
- def isSelectorName = name.startsWith(" ") && name.tail.forall(_.isDigit)
- def isLazyLocal = name.endsWith(nme.LAZY_LOCAL)
- def isOuterSelect = name.endsWith(nme.OUTER_SELECT)
- def isInlineAccessor = name.startsWith(nme.INLINE_ACCESSOR_PREFIX)
+ def isLocalDummyName = name startsWith str.LOCALDUMMY_PREFIX
+ def isReplWrapperName = name.toString contains str.INTERPRETER_IMPORT_WRAPPER
+ def isSetterName = name endsWith str.SETTER_SUFFIX
+ def isScala2LocalSuffix = testSimple(_.endsWith(" "))
+ def isSelectorName = testSimple(n => n.startsWith("_") && n.drop(1).forall(_.isDigit))
/** Is name a variable name? */
- def isVariableName: Boolean = name.length > 0 && {
- val first = name.head
- (((first.isLower && first.isLetter) || first == '_')
- && (name != false_)
- && (name != true_)
- && (name != null_))
+ def isVariableName: Boolean = testSimple { n =>
+ n.length > 0 && {
+ val first = n.head
+ (((first.isLower && first.isLetter) || first == '_')
+ && (n != false_)
+ && (n != true_)
+ && (n != null_))
+ }
}
def isOpAssignmentName: Boolean = name match {
case raw.NE | raw.LE | raw.GE | EMPTY =>
false
- case _ =>
+ case name: SimpleTermName =>
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head)
- }
-
- /** If the name ends with $nn where nn are
- * all digits, strip the $ and the digits.
- * Otherwise return the argument.
- */
- def stripAnonNumberSuffix: Name = {
- var pos = name.length
- while (pos > 0 && name(pos - 1).isDigit)
- pos -= 1
-
- if (pos > 0 && pos < name.length && name(pos - 1) == '$')
- name take (pos - 1)
- else
- name
+ case _ =>
+ false
}
/** Convert this module name to corresponding module class name */
- def moduleClassName: TypeName = (name ++ tpnme.MODULE_SUFFIX).toTypeName
+ def moduleClassName: TypeName = name.derived(ModuleClassName).toTypeName
/** Convert this module class name to corresponding source module name */
- def sourceModuleName: TermName = stripModuleClassSuffix.toTermName
-
- /** If name ends in module class suffix, drop it */
- def stripModuleClassSuffix: Name =
- if (isModuleClassName) name dropRight MODULE_SUFFIX.length else name
-
- /** Append a suffix so that this name does not clash with another name in the same scope */
- def avoidClashName: TermName = (name ++ AVOID_CLASH_SUFFIX).toTermName
+ def sourceModuleName: TermName = name.toTermName.exclude(ModuleClassName)
- /** If name ends in "avoid clash" suffix, drop it */
- def stripAvoidClashSuffix: Name =
- if (isAvoidClashName) name dropRight AVOID_CLASH_SUFFIX.length else name
+ /** If name ends in module class suffix, drop it. This
+ * method needs to work on mangled as well as unmangled names because
+ * it is also called from the backend.
+ */
+ def stripModuleClassSuffix: N = likeSpaced {
+ val semName =
+ if (name.isSimple && name.endsWith("$")) name.unmangleClassName else name
+ semName.exclude(ModuleClassName)
+ }
/** If flags is a ModuleClass but not a Package, add module class suffix */
- def adjustIfModuleClass(flags: Flags.FlagSet): N = {
+ def adjustIfModuleClass(flags: Flags.FlagSet): N = likeSpaced {
if (flags is (ModuleClass, butNot = Package)) name.asTypeName.moduleClassName
- else stripAvoidClashSuffix
- }.asInstanceOf[N]
-
- /** The superaccessor for method with given name */
- def superName: TermName = (nme.SUPER_PREFIX ++ name).toTermName
-
- /** The expanded name of `name` relative to given class `base`.
- */
- def expandedName(base: Symbol, separator: Name)(implicit ctx: Context): N =
- expandedName(if (base is Flags.ExpandedName) base.name else base.fullNameSeparated("$"), separator)
-
- def expandedName(base: Symbol)(implicit ctx: Context): N = expandedName(base, nme.EXPAND_SEPARATOR)
-
- /** The expanded name of `name` relative to `basename` with given `separator`
- */
- def expandedName(prefix: Name, separator: Name = nme.EXPAND_SEPARATOR): N =
- name.fromName(prefix ++ separator ++ name).asInstanceOf[N]
-
- def expandedName(prefix: Name): N = expandedName(prefix, nme.EXPAND_SEPARATOR)
-
- /** Revert the expanded name. Note: This currently gives incorrect results
- * if the normal name contains `nme.EXPAND_SEPARATOR`, i.e. two consecutive '$'
- * signs. This can happen for instance if a super accessor is paired with
- * an encoded name, e.g. super$$plus$eq. See #765.
- */
- def unexpandedName: N = {
- var idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
-
- // Hack to make super accessors from traits work. They would otherwise fail because of #765
- // TODO: drop this once we have more robust name handling
- if (idx > FalseSuperLength && name.slice(idx - FalseSuperLength, idx) == FalseSuper)
- idx -= FalseSuper.length
-
- if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
+ else name.toTermName.exclude(AvoidClashName)
}
- def expandedPrefix: N = {
- val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
- assert(idx >= 0)
- name.take(idx).asInstanceOf[N]
+ def expandedName(base: Symbol, kind: QualifiedNameKind = ExpandedName)(implicit ctx: Context): N = {
+ val prefix =
+ if (base.name.is(ExpandedName)) base.name else base.fullNameSeparated(ExpandPrefixName)
+ likeSpaced { kind(prefix.toTermName, name.toTermName) }
}
- def shadowedName: N = likeTyped(nme.SHADOWED ++ name)
-
- def revertShadowed: N = likeTyped(name.drop(nme.SHADOWED.length))
-
- def implClassName: N = likeTyped(name ++ tpnme.IMPL_CLASS_SUFFIX)
+ /** Revert the expanded name. */
+ def unexpandedName: N = likeSpaced {
+ name.rewrite { case ExpandedName(_, unexp) => unexp }
+ }
- def errorName: N = likeTyped(name ++ nme.ERROR)
+ def implClassName: N = likeSpaced(name ++ tpnme.IMPL_CLASS_SUFFIX)
- def directName: N = likeTyped(name ++ DIRECT_SUFFIX)
+ def errorName: N = likeSpaced(name ++ nme.ERROR)
- def freshened(implicit ctx: Context): N =
- likeTyped(
- if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName
- else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING)))
/** Name with variance prefix: `+` for covariant, `-` for contravariant */
def withVariance(v: Int): N =
- if (hasVariance) dropVariance.withVariance(v)
- else v match {
- case -1 => likeTyped('-' +: name)
- case 1 => likeTyped('+' +: name)
- case 0 => name
- }
-
- /** Does name have a `+`/`-` variance prefix? */
- def hasVariance: Boolean =
- name.nonEmpty && name.head == '+' || name.head == '-'
-
- /** Drop variance prefix if name has one */
- def dropVariance: N = if (hasVariance) likeTyped(name.tail) else name
+ likeSpaced { VariantName(name.exclude(VariantName).toTermName, v) }
/** The variance as implied by the variance prefix, or 0 if there is
* no variance prefix.
*/
- def variance = name.head match {
- case '-' => -1
- case '+' => 1
- case _ => 0
- }
+ def variance = name.collect { case VariantName(_, n) => n }.getOrElse(0)
- /** Translate a name into a list of simple TypeNames and TermNames.
- * In all segments before the last, type/term is determined by whether
- * the following separator char is '.' or '#'. The last segment
- * is of the same type as the original name.
- *
- * Examples:
- *
- * package foo {
- * object Lorax { object Wog ; class Wog }
- * class Lorax { object Zax ; class Zax }
- * }
- *
- * f("foo.Lorax".toTermName) == List("foo": Term, "Lorax": Term) // object Lorax
- * f("foo.Lorax".toTypeName) == List("foo": Term, "Lorax": Type) // class Lorax
- * f("Lorax.Wog".toTermName) == List("Lorax": Term, "Wog": Term) // object Wog
- * f("Lorax.Wog".toTypeName) == List("Lorax": Term, "Wog": Type) // class Wog
- * f("Lorax#Zax".toTermName) == List("Lorax": Type, "Zax": Term) // object Zax
- * f("Lorax#Zax".toTypeName) == List("Lorax": Type, "Zax": Type) // class Zax
- *
- * Note that in actual scala syntax you cannot refer to object Zax without an
- * instance of Lorax, so Lorax#Zax could only mean the type. One might think
- * that Lorax#Zax.type would work, but this is not accepted by the parser.
- * For the purposes of referencing that object, the syntax is allowed.
- */
- def segments: List[Name] = {
- def mkName(name: Name, follow: Char): Name =
- if (follow == '.') name.toTermName else name.toTypeName
-
- name.indexWhere(ch => ch == '.' || ch == '#') match {
- case -1 =>
- if (name.isEmpty) scala.Nil else name :: scala.Nil
- case idx =>
- mkName(name take idx, name(idx)) :: (name drop (idx + 1)).segments
+ def freshened(implicit ctx: Context): N = likeSpaced {
+ name.toTermName match {
+ case ModuleClassName(original) => ModuleClassName(original.freshened)
+ case name => UniqueName.fresh(name)
}
}
@@ -263,7 +149,7 @@ object NameOps {
* - (-1) otherwise
*/
def functionArity: Int =
- functionArityFor(tpnme.Function) max functionArityFor(tpnme.ImplicitFunction)
+ functionArityFor(str.Function) max functionArityFor(str.ImplicitFunction)
/** Is a function name
* - FunctionN for N >= 0
@@ -276,7 +162,7 @@ object NameOps {
* - ImplicitFunctionN for N >= 0
* - false otherwise
*/
- def isImplicitFunction: Boolean = functionArityFor(tpnme.ImplicitFunction) >= 0
+ def isImplicitFunction: Boolean = functionArityFor(str.ImplicitFunction) >= 0
/** Is a synthetic function name
* - FunctionN for N > 22
@@ -284,24 +170,18 @@ object NameOps {
* - false otherwise
*/
def isSyntheticFunction: Boolean = {
- functionArityFor(tpnme.Function) > MaxImplementedFunctionArity ||
- functionArityFor(tpnme.ImplicitFunction) >= 0
+ functionArityFor(str.Function) > MaxImplementedFunctionArity ||
+ functionArityFor(str.ImplicitFunction) >= 0
}
/** Parsed function arity for function with some specific prefix */
- private def functionArityFor(prefix: Name): Int = {
+ private def functionArityFor(prefix: String): Int = {
if (name.startsWith(prefix))
try name.toString.substring(prefix.length).toInt
catch { case _: NumberFormatException => -1 }
else -1
}
- /** The number of hops specified in an outer-select name */
- def outerSelectHops: Int = {
- require(isOuterSelect)
- name.dropRight(nme.OUTER_SELECT.length).toString.toInt
- }
-
/** The name of the generic runtime operation corresponding to an array operation */
def genericArrayOp: TermName = name match {
case nme.apply => nme.array_apply
@@ -338,100 +218,61 @@ object NameOps {
val methodTags: Seq[Name] = (methodTargs zip methodTarsNames).sortBy(_._2).map(x => typeToTag(x._1))
val classTags: Seq[Name] = (classTargs zip classTargsNames).sortBy(_._2).map(x => typeToTag(x._1))
- name.fromName(name ++ nme.specializedTypeNames.prefix ++
+ name.likeSpaced(name ++ nme.specializedTypeNames.prefix ++
methodTags.fold(nme.EMPTY)(_ ++ _) ++ nme.specializedTypeNames.separator ++
classTags.fold(nme.EMPTY)(_ ++ _) ++ nme.specializedTypeNames.suffix)
}
/** If name length exceeds allowable limit, replace part of it by hash */
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
- }
- // needed???
- private val Boxed = Map[TypeName, TypeName](
- tpnme.Boolean -> jtpnme.BoxedBoolean,
- tpnme.Byte -> jtpnme.BoxedByte,
- tpnme.Char -> jtpnme.BoxedCharacter,
- tpnme.Short -> jtpnme.BoxedShort,
- tpnme.Int -> jtpnme.BoxedInteger,
- tpnme.Long -> jtpnme.BoxedLong,
- tpnme.Float -> jtpnme.BoxedFloat,
- tpnme.Double -> jtpnme.BoxedDouble)
+ def unmangleClassName: N = name.toTermName match {
+ case name: SimpleTermName
+ if name.endsWith(str.MODULE_SUFFIX) && !nme.falseModuleClassNames.contains(name) =>
+ likeSpaced(name.dropRight(str.MODULE_SUFFIX.length).moduleClassName)
+ case _ => name
+ }
+
+ def unmangle(kind: NameKind): N = likeSpaced {
+ name rewrite {
+ case unmangled: SimpleTermName =>
+ kind.unmangle(unmangled)
+ case ExpandedName(prefix, last) =>
+ kind.unmangle(last) rewrite {
+ case kernel: SimpleTermName =>
+ ExpandedName(prefix, kernel)
+ }
+ }
+ }
+
+ def unmangle(kinds: List[NameKind]): N = {
+ val unmangled = (name /: kinds)(_.unmangle(_))
+ if (unmangled eq name) name else unmangled.unmangle(kinds)
+ }
+ }
implicit class TermNameDecorator(val name: TermName) extends AnyVal {
import nme._
- def setterName: TermName =
- if (name.isFieldName) name.fieldToGetter.setterName
- else name ++ SETTER_SUFFIX
+ def setterName: TermName = name.exclude(FieldName) ++ str.SETTER_SUFFIX
def getterName: TermName =
- if (name.isFieldName) fieldToGetter
- else setterToGetter
+ name.exclude(FieldName).mapLast(n =>
+ if (n.endsWith(str.SETTER_SUFFIX)) n.take(n.length - str.SETTER_SUFFIX.length).asSimpleName
+ else n)
def fieldName: TermName =
if (name.isSetterName) {
- if (name.isTraitSetterName) {
- // has form <$-separated-trait-name>$_setter_$ `name`_$eq
- val start = name.indexOfSlice(TRAIT_SETTER_SEPARATOR) + TRAIT_SETTER_SEPARATOR.length
- val end = name.indexOfSlice(SETTER_SUFFIX)
- name.slice(start, end) ++ LOCAL_SUFFIX
- } else getterName.fieldName
+ if (name.is(TraitSetterName)) {
+ val TraitSetterName(_, original) = name
+ original.fieldName
+ }
+ else getterName.fieldName
}
- else name ++ LOCAL_SUFFIX
-
- private def setterToGetter: TermName = {
- assert(name.endsWith(SETTER_SUFFIX), name + " is referenced as a setter but has wrong name format")
- name.take(name.length - SETTER_SUFFIX.length).asTermName
- }
-
- def fieldToGetter: TermName = {
- assert(name.isFieldName)
- name.take(name.length - LOCAL_SUFFIX.length).asTermName
- }
-
- /** Nominally, name$default$N, encoded for <init>
- * @param Post the parameters position.
- * @note Default getter name suffixes start at 1, so `pos` has to be adjusted by +1
- */
- def defaultGetterName(pos: Int): TermName = {
- val prefix = if (name.isConstructorName) DEFAULT_GETTER_INIT else name
- prefix ++ DEFAULT_GETTER ++ (pos + 1).toString
- }
-
- /** Nominally, name from name$default$N, CONSTRUCTOR for <init> */
- def defaultGetterToMethod: TermName = {
- val p = name.indexOfSlice(DEFAULT_GETTER)
- if (p >= 0) {
- val q = name.take(p).asTermName
- // i.e., if (q.decoded == CONSTRUCTOR.toString) CONSTRUCTOR else q
- if (q == DEFAULT_GETTER_INIT) CONSTRUCTOR else q
- } else name
- }
-
- /** If this is a default getter, its index (starting from 0), else -1 */
- def defaultGetterIndex: Int = {
- var i = name.length
- while (i > 0 && name(i - 1).isDigit) i -= 1
- if (i > 0 && i < name.length && name.take(i).endsWith(DEFAULT_GETTER))
- name.drop(i).toString.toInt - 1
- else
- -1
- }
+ else FieldName(name)
def stripScala2LocalSuffix: TermName =
- if (name.isScala2LocalSuffix) name.init.asTermName else name
-
- /** The name of an accessor for protected symbols. */
- def protectedAccessorName: TermName =
- PROTECTED_PREFIX ++ name.unexpandedName
-
- /** The name of a setter for protected symbols. Used for inherited Java fields. */
- def protectedSetterName: TermName =
- PROTECTED_SET_PREFIX ++ name.unexpandedName
-
- def moduleVarName: TermName =
- name ++ MODULE_VAR_SUFFIX
+ if (name.isScala2LocalSuffix) name.asSimpleName.dropRight(1) else name
/** The name unary_x for a prefix operator x */
def toUnaryName: TermName = name match {
@@ -441,65 +282,5 @@ object NameOps {
case raw.BANG => UNARY_!
case _ => name
}
-
- /** The name of a method which stands in for a primitive operation
- * during structural type dispatch.
- */
- def primitiveInfixMethodName: TermName = name match {
- case OR => takeOr
- case XOR => takeXor
- case AND => takeAnd
- case EQ => testEqual
- case NE => testNotEqual
- case ADD => add
- case SUB => subtract
- case MUL => multiply
- case DIV => divide
- case MOD => takeModulo
- case LSL => shiftSignedLeft
- case LSR => shiftLogicalRight
- case ASR => shiftSignedRight
- case LT => testLessThan
- case LE => testLessOrEqualThan
- case GE => testGreaterOrEqualThan
- case GT => testGreaterThan
- case ZOR => takeConditionalOr
- case ZAND => takeConditionalAnd
- case _ => NO_NAME
- }
-
- /** Postfix/prefix, really.
- */
- def primitivePostfixMethodName: TermName = name match {
- case UNARY_! => takeNot
- case UNARY_+ => positive
- case UNARY_- => negate
- case UNARY_~ => complement
- case `toByte` => toByte
- case `toShort` => toShort
- case `toChar` => toCharacter
- case `toInt` => toInteger
- case `toLong` => toLong
- case `toFloat` => toFloat
- case `toDouble` => toDouble
- case _ => NO_NAME
- }
-
- def primitiveMethodName: TermName =
- primitiveInfixMethodName match {
- case NO_NAME => primitivePostfixMethodName
- case name => name
- }
-
- def lazyLocalName = name ++ nme.LAZY_LOCAL
- def nonLazyName = {
- assert(name.isLazyLocal)
- name.dropRight(nme.LAZY_LOCAL.length)
- }
-
- def inlineAccessorName = nme.INLINE_ACCESSOR_PREFIX ++ name ++ "$"
}
-
- private final val FalseSuper = "$$super".toTermName
- private val FalseSuperLength = FalseSuper.length
}
diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala
index 11f0b55a8..a72a02844 100644
--- a/compiler/src/dotty/tools/dotc/core/Names.scala
+++ b/compiler/src/dotty/tools/dotc/core/Names.scala
@@ -10,13 +10,16 @@ import Decorators._
import Contexts.Context
import collection.IndexedSeqOptimized
import collection.generic.CanBuildFrom
-import collection.mutable.{ Builder, StringBuilder }
+import collection.mutable.{ Builder, StringBuilder, AnyRefMap }
import collection.immutable.WrappedString
import collection.generic.CanBuildFrom
-import util.DotClass
+import util.{DotClass, SimpleMap}
+import java.util.HashMap
+
//import annotation.volatile
object Names {
+ import NameKinds._
/** A common class for things that can be turned into names.
* Instances are both names and strings, the latter via a decorator.
@@ -37,20 +40,11 @@ object Names {
* 3. Names are intended to be encoded strings. @see dotc.util.NameTransformer.
* The encoding will be applied when converting a string to a name.
*/
- abstract class Name extends DotClass
- with PreName
- with collection.immutable.Seq[Char]
- with IndexedSeqOptimized[Char, Name] {
+ abstract class Name extends DotClass with PreName {
/** A type for names of the same kind as this name */
type ThisName <: Name
- /** The start index in the character array */
- val start: Int
-
- /** The length of the names */
- override val length: Int
-
/** Is this name a type name? */
def isTypeName: Boolean
@@ -69,120 +63,244 @@ object Names {
/** This name downcasted to a term name */
def asTermName: TermName
- /** Create a new name of same kind as this one, in the given
- * basis, with `len` characters taken from `cs` starting at `offset`.
- */
- def fromChars(cs: Array[Char], offset: Int, len: Int): ThisName
+ def isSimple: Boolean
+ def asSimpleName: SimpleTermName
+ def toSimpleName: SimpleTermName
+ def mangled: Name
- /** Create new name of same kind as this name and with same
- * characters as given `name`.
- */
- def fromName(name: Name): ThisName = fromChars(chrs, name.start, name.length)
+ def rewrite(f: PartialFunction[Name, Name]): ThisName
+ def collect[T](f: PartialFunction[Name, T]): Option[T]
+ def mapLast(f: SimpleTermName => SimpleTermName): ThisName
+ def mapParts(f: SimpleTermName => SimpleTermName): ThisName
- /** Create new name of same kind as this name with characters from
- * the given string
+ /** A name in the same (term or type) namespace as this name and
+ * with same characters as given `name`.
*/
- def fromString(str: String): ThisName = {
- val cs = str.toCharArray
- fromChars(cs, 0, cs.length)
- }
+ def likeSpaced(name: Name): ThisName
- override def toString =
- if (length == 0) "" else new String(chrs, start, length)
+ def derived(info: NameInfo): ThisName
+ def derived(kind: ClassifiedNameKind): ThisName = derived(kind.info)
+ def exclude(kind: NameKind): ThisName
+ def is(kind: NameKind): Boolean
+ def debugString: String
def toText(printer: Printer): Text = printer.toText(this)
- /** Write to UTF8 representation of this name to given character array.
- * Start copying to index `to`. Return index of next free byte in array.
- * Array must have enough remaining space for all bytes
- * (i.e. maximally 3*length bytes).
- */
- final def copyUTF8(bs: Array[Byte], offset: Int): Int = {
- val bytes = Codec.toUTF8(chrs, start, length)
- scala.compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length)
- offset + bytes.length
- }
-
/** Replace \$op_name's by corresponding operator symbols. */
- def decode: Name =
- if (contains('$')) fromString(NameTransformer.decode(toString))
- else this
+ def decode: Name
/** Replace operator symbols by corresponding \$op_name's. */
- def encode: Name =
- if (dontEncode(toTermName)) this else NameTransformer.encode(this)
+ def encode: Name
+
+ def firstPart: SimpleTermName
+ def lastPart: SimpleTermName
/** A more efficient version of concatenation */
def ++ (other: Name): ThisName = ++ (other.toString)
+ def ++ (other: String): ThisName = mapLast(n => termName(n.toString + other))
+ def replace(from: Char, to: Char): ThisName = mapParts(_.replace(from, to))
+
+ def isEmpty: Boolean
+
+ def startsWith(str: String): Boolean = firstPart.startsWith(str)
+ def endsWith(str: String): Boolean = lastPart.endsWith(str)
+
+ override def hashCode = System.identityHashCode(this)
+ override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+ }
- def ++ (other: String): ThisName = {
- val s = toString + other
- fromChars(s.toCharArray, 0, s.length)
+ abstract class TermName extends Name {
+ type ThisName = TermName
+ def isTypeName = false
+ def isTermName = true
+ def toTermName = this
+ def asTypeName = throw new ClassCastException(this + " is not a type name")
+ def asTermName = this
+
+ @sharable // because it is only modified in the synchronized block of toTypeName.
+ @volatile private[this] var _typeName: TypeName = null
+
+ def toTypeName: TypeName = {
+ if (_typeName == null)
+ synchronized {
+ if (_typeName == null)
+ _typeName = new TypeName(this)
+ }
+ _typeName
}
- def replace(from: Char, to: Char): ThisName = {
- val cs = new Array[Char](length)
- Array.copy(chrs, start, cs, 0, length)
- for (i <- 0 until length) {
- if (cs(i) == from) cs(i) = to
+ def likeSpaced(name: Name): TermName = name.toTermName
+
+ def info: NameInfo = SimpleTermNameKind.info
+ def underlying: TermName = unsupported("underlying")
+
+ @sharable // because of synchronized block in `and`
+ private var derivedNames: AnyRef /* SimpleMap | j.u.HashMap */ =
+ SimpleMap.Empty[NameInfo]
+
+ private def getDerived(info: NameInfo): DerivedTermName /* | Null */= derivedNames match {
+ case derivedNames: SimpleMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames(info)
+ case derivedNames: HashMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames.get(info)
+ }
+
+ private def putDerived(info: NameInfo, name: DerivedTermName): name.type = {
+ derivedNames match {
+ case derivedNames: SimpleMap[NameInfo, DerivedTermName] @unchecked =>
+ if (derivedNames.size < 4)
+ this.derivedNames = derivedNames.updated(info, name)
+ else {
+ val newMap = new HashMap[NameInfo, DerivedTermName]
+ derivedNames.foreachBinding(newMap.put(_, _))
+ newMap.put(info, name)
+ this.derivedNames = newMap
+ }
+ case derivedNames: HashMap[NameInfo, DerivedTermName] @unchecked =>
+ derivedNames.put(info, name)
+ }
+ name
+ }
+
+ private def add(info: NameInfo): TermName = synchronized {
+ getDerived(info) match {
+ case null => putDerived(info, new DerivedTermName(this, info))
+ case derivedName => derivedName
+ }
+ }
+
+ private def rewrap(underlying: TermName) =
+ if (underlying eq this.underlying) this else underlying.add(info)
+
+ /** Return derived name with given `info` and the current
+ * name as underlying name.
+ */
+ def derived(info: NameInfo): TermName = {
+ val thisKind = this.info.kind
+ val thatKind = info.kind
+ if (thisKind.tag < thatKind.tag || thatKind.definesNewName) add(info)
+ else if (thisKind.tag > thatKind.tag) rewrap(underlying.derived(info))
+ else {
+ assert(info == this.info)
+ this
}
- fromChars(cs, 0, length)
}
+ def exclude(kind: NameKind): TermName = {
+ val thisKind = this.info.kind
+ if (thisKind.tag < kind.tag || thisKind.definesNewName) this
+ else if (thisKind.tag > kind.tag) rewrap(underlying.exclude(kind))
+ else underlying
+ }
+
+ def is(kind: NameKind): Boolean = {
+ val thisKind = this.info.kind
+ thisKind == kind ||
+ !thisKind.definesNewName && thisKind.tag > kind.tag && underlying.is(kind)
+ }
+ }
+
+ class SimpleTermName(val start: Int, val length: Int, @sharable private[Names] var next: SimpleTermName) extends TermName {
+ // `next` is @sharable because it is only modified in the synchronized block of termName.
+
+ def apply(n: Int) = chrs(start + n)
+
+ def exists(p: Char => Boolean): Boolean = {
+ var i = 0
+ while (i < length && !p(chrs(start + i))) i += 1
+ i < length
+ }
+
+ def forall(p: Char => Boolean) = !exists(!p(_))
+
def contains(ch: Char): Boolean = {
var i = 0
while (i < length && chrs(start + i) != ch) i += 1
i < length
}
- def firstChar = chrs(start)
+ def isEmpty = length == 0
+
+ override def startsWith(str: String): Boolean = {
+ var i = 0
+ while (i < str.length && i < length && apply(i) == str(i)) i += 1
+ i == str.length
+ }
+
+ override def endsWith(str: String): Boolean = {
+ var i = 1
+ while (i <= str.length && i <= length && apply(length - i) == str(str.length - i)) i += 1
+ i > str.length
+ }
- // ----- Collections integration -------------------------------------
+ def lastIndexOf(ch: Char, start: Int = length - 1): Int = {
+ var i = start
+ while (i >= 0 && apply(i) != ch) i -= 1
+ i
+ }
- override protected[this] def thisCollection: WrappedString = new WrappedString(repr.toString)
- override protected[this] def toCollection(repr: Name): WrappedString = new WrappedString(repr.toString)
+ def lastIndexOfSlice(str: String): Int = toString.lastIndexOfSlice(str)
- override protected[this] def newBuilder: Builder[Char, Name] = unsupported("newBuilder")
+ override def replace(from: Char, to: Char): SimpleTermName = {
+ val cs = new Array[Char](length)
+ Array.copy(chrs, start, cs, 0, length)
+ for (i <- 0 until length) {
+ if (cs(i) == from) cs(i) = to
+ }
+ termName(cs, 0, length)
+ }
- override def apply(index: Int): Char = chrs(start + index)
+ def slice(from: Int, until: Int): SimpleTermName = {
+ assert(0 <= from && from <= until && until <= length)
+ termName(chrs, start + from, until - from)
+ }
- override def slice(from: Int, until: Int): ThisName =
- fromChars(chrs, start + from, until - from)
+ def drop(n: Int) = slice(n, length)
+ def take(n: Int) = slice(0, n)
+ def dropRight(n: Int) = slice(0, length - n)
+ def takeRight(n: Int) = slice(length - n, length)
- override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+ def head = apply(0)
+ def last = apply(length - 1)
- override def seq = toCollection(this)
- }
+ def isSimple = true
+ def asSimpleName = this
+ def toSimpleName = this
+ def mangled = this
- class TermName(val start: Int, val length: Int, @sharable private[Names] var next: TermName) extends Name {
- // `next` is @sharable because it is only modified in the synchronized block of termName.
- type ThisName = TermName
- def isTypeName = false
- def isTermName = true
+ def rewrite(f: PartialFunction[Name, Name]): ThisName =
+ if (f.isDefinedAt(this)) likeSpaced(f(this)) else this
+ def collect[T](f: PartialFunction[Name, T]): Option[T] = f.lift(this)
+ def mapLast(f: SimpleTermName => SimpleTermName) = f(this)
+ def mapParts(f: SimpleTermName => SimpleTermName) = f(this)
- @sharable // because it is only modified in the synchronized block of toTypeName.
- @volatile private[this] var _typeName: TypeName = null
+ def encode: SimpleTermName =
+ if (dontEncode(toTermName)) this else NameTransformer.encode(this)
- def toTypeName: TypeName = {
- if (_typeName == null)
- synchronized {
- if (_typeName == null)
- _typeName = new TypeName(start, length, this)
- }
- _typeName
- }
- def toTermName = this
- def asTypeName = throw new ClassCastException(this + " is not a type name")
- def asTermName = this
+ /** Replace \$op_name's by corresponding operator symbols. */
+ def decode: SimpleTermName =
+ if (contains('$')) termName(NameTransformer.decode(toString)) else this
+
+ def firstPart = this
+ def lastPart = this
override def hashCode: Int = start
- override protected[this] def newBuilder: Builder[Char, Name] = termNameBuilder
+ override def toString =
+ if (length == 0) "" else new String(chrs, start, length)
- def fromChars(cs: Array[Char], offset: Int, len: Int): TermName = termName(cs, offset, len)
+ def debugString: String = toString
}
- class TypeName(val start: Int, val length: Int, val toTermName: TermName) extends Name {
+ class TypeName(val toTermName: TermName) extends Name {
+
+ def isEmpty = toTermName.isEmpty
+
+ def encode = toTermName.encode.toTypeName
+ def decode = toTermName.decode.toTypeName
+ def firstPart = toTermName.firstPart
+ def lastPart = toTermName.lastPart
+
type ThisName = TypeName
def isTypeName = true
def isTermName = false
@@ -190,12 +308,77 @@ object Names {
def asTypeName = this
def asTermName = throw new ClassCastException(this + " is not a term name")
- override def hashCode: Int = -start
+ def isSimple = toTermName.isSimple
+ def asSimpleName = toTermName.asSimpleName
+ def toSimpleName = toTermName.toSimpleName
+ def mangled = toTermName.toSimpleName.toTypeName
- override protected[this] def newBuilder: Builder[Char, Name] =
- termNameBuilder.mapResult(_.toTypeName)
+ def rewrite(f: PartialFunction[Name, Name]): ThisName = toTermName.rewrite(f).toTypeName
+ def collect[T](f: PartialFunction[Name, T]): Option[T] = toTermName.collect(f)
+ def mapLast(f: SimpleTermName => SimpleTermName) = toTermName.mapLast(f).toTypeName
+ def mapParts(f: SimpleTermName => SimpleTermName) = toTermName.mapParts(f).toTypeName
- def fromChars(cs: Array[Char], offset: Int, len: Int): TypeName = typeName(cs, offset, len)
+ def likeSpaced(name: Name): TypeName = name.toTypeName
+
+ def derived(info: NameInfo): TypeName = toTermName.derived(info).toTypeName
+ def exclude(kind: NameKind): TypeName = toTermName.exclude(kind).toTypeName
+ def is(kind: NameKind) = toTermName.is(kind)
+
+ override def toString = toTermName.toString
+ override def debugString = toTermName.debugString + "/T"
+ }
+
+ /** A term name that's derived from an `underlying` name and that
+ * adds `info` to it.
+ */
+ case class DerivedTermName(override val underlying: TermName, override val info: NameInfo)
+ extends TermName {
+ def isEmpty = false
+ def encode: Name = underlying.encode.derived(info.map(_.encode))
+ def decode: Name = underlying.decode.derived(info.map(_.decode))
+ def firstPart = underlying.firstPart
+ def lastPart = info match {
+ case qual: QualifiedInfo => qual.name
+ case _ => underlying.lastPart
+ }
+ override def toString = info.mkString(underlying)
+ override def debugString = s"${underlying.debugString}[$info]"
+
+ def isSimple = false
+ def asSimpleName = throw new UnsupportedOperationException(s"$debugString is not a simple name")
+
+ private[this] var simpleName: SimpleTermName = null
+ def toSimpleName = {
+ if (simpleName == null) simpleName = termName(toString)
+ simpleName
+ }
+ def mangled = toSimpleName
+
+ def rewrite(f: PartialFunction[Name, Name]): ThisName =
+ if (f.isDefinedAt(this)) likeSpaced(f(this))
+ else info match {
+ case qual: QualifiedInfo => this
+ case _ => underlying.rewrite(f).derived(info)
+ }
+
+ def collect[T](f: PartialFunction[Name, T]): Option[T] =
+ if (f.isDefinedAt(this)) Some(f(this))
+ else info match {
+ case qual: QualifiedInfo => None
+ case _ => underlying.collect(f)
+ }
+
+ def mapLast(f: SimpleTermName => SimpleTermName): ThisName =
+ info match {
+ case qual: QualifiedInfo => underlying.derived(qual.map(f))
+ case _ => underlying.mapLast(f).derived(info)
+ }
+
+ def mapParts(f: SimpleTermName => SimpleTermName): ThisName =
+ info match {
+ case qual: QualifiedInfo => underlying.mapParts(f).derived(qual.map(f))
+ case _ => underlying.mapParts(f).derived(info)
+ }
}
// Nametable
@@ -214,7 +397,7 @@ object Names {
/** Hashtable for finding term names quickly. */
@sharable // because it's only mutated in synchronized block of termName
- private var table = new Array[TermName](InitialHashSize)
+ private var table = new Array[SimpleTermName](InitialHashSize)
/** The number of defined names. */
@sharable // because it's only mutated in synchronized block of termName
@@ -242,7 +425,7 @@ object Names {
/** Create a term name from the characters in cs[offset..offset+len-1].
* Assume they are already encoded.
*/
- def termName(cs: Array[Char], offset: Int, len: Int): TermName = synchronized {
+ def termName(cs: Array[Char], offset: Int, len: Int): SimpleTermName = synchronized {
util.Stats.record("termName")
val h = hashValue(cs, offset, len) & (table.size - 1)
@@ -266,7 +449,7 @@ object Names {
}
/** Rehash chain of names */
- def rehash(name: TermName): Unit =
+ def rehash(name: SimpleTermName): Unit =
if (name != null) {
val oldNext = name.next
val h = hashValue(chrs, name.start, name.length) & (table.size - 1)
@@ -280,7 +463,7 @@ object Names {
size += 1
if (size.toDouble / table.size > fillFactor) {
val oldTable = table
- table = new Array[TermName](table.size * 2)
+ table = new Array[SimpleTermName](table.size * 2)
for (i <- 0 until oldTable.size) rehash(oldTable(i))
}
}
@@ -292,7 +475,7 @@ object Names {
return name
name = name.next
}
- name = new TermName(nc, len, next)
+ name = new SimpleTermName(nc, len, next)
enterChars()
table(h) = name
incTableSize()
@@ -308,7 +491,7 @@ object Names {
/** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1].
* Assume they are already encoded.
*/
- def termName(bs: Array[Byte], offset: Int, len: Int): TermName = {
+ def termName(bs: Array[Byte], offset: Int, len: Int): SimpleTermName = {
val chars = Codec.fromUTF8(bs, offset, len)
termName(chars, 0, chars.length)
}
@@ -320,53 +503,75 @@ object Names {
termName(bs, offset, len).toTypeName
/** Create a term name from a string, without encoding operators */
- def termName(s: String): TermName = termName(s.toCharArray, 0, s.length)
+ def termName(s: String): SimpleTermName = termName(s.toCharArray, 0, s.length)
/** Create a type name from a string, without encoding operators */
def typeName(s: String): TypeName = typeName(s.toCharArray, 0, s.length)
- /** The term name represented by the empty string */
- val EmptyTermName = new TermName(-1, 0, null)
+ table(0) = new SimpleTermName(-1, 0, null)
- table(0) = EmptyTermName
+ /** The term name represented by the empty string */
+ val EmptyTermName: TermName = table(0)
/** The type name represented by the empty string */
val EmptyTypeName = EmptyTermName.toTypeName
// can't move CONSTRUCTOR/EMPTY_PACKAGE to `nme` because of bootstrap failures in `encode`.
- val CONSTRUCTOR = termName("<init>")
- val STATIC_CONSTRUCTOR = termName("<clinit>")
- val EMPTY_PACKAGE = termName("<empty>")
-
- val dontEncode = Set(CONSTRUCTOR, EMPTY_PACKAGE)
+ val CONSTRUCTOR: TermName = termName("<init>")
+ val STATIC_CONSTRUCTOR: TermName = termName("<clinit>")
+ val EMPTY_PACKAGE: TermName = termName("<empty>")
+ val REFINEMENT: TermName = termName("<refinement>")
- def termNameBuilder: Builder[Char, TermName] =
- StringBuilder.newBuilder.mapResult(termName)
-
- implicit val nameCanBuildFrom: CanBuildFrom[Name, Char, Name] = new CanBuildFrom[Name, Char, Name] {
- def apply(from: Name): Builder[Char, Name] =
- StringBuilder.newBuilder.mapResult(s => from.fromChars(s.toCharArray, 0, s.length))
- def apply(): Builder[Char, Name] = termNameBuilder
- }
+ val dontEncode = Set(CONSTRUCTOR, EMPTY_PACKAGE, REFINEMENT)
implicit val NameOrdering: Ordering[Name] = new Ordering[Name] {
+ private def compareInfos(x: NameInfo, y: NameInfo): Int =
+ if (x.kind.tag != y.kind.tag) x.kind.tag - y.kind.tag
+ else x match {
+ case x: QualifiedInfo =>
+ y match {
+ case y: QualifiedInfo =>
+ compareSimpleNames(x.name, y.name)
+ }
+ case x: NumberedInfo =>
+ y match {
+ case y: NumberedInfo =>
+ x.num - y.num
+ }
+ case _ =>
+ assert(x == y)
+ 0
+ }
+ private def compareSimpleNames(x: SimpleTermName, y: SimpleTermName): Int = {
+ val until = x.length min y.length
+ var i = 0
+ while (i < until && x(i) == y(i)) i = i + 1
+ if (i < until) {
+ if (x(i) < y(i)) -1
+ else /*(x(i) > y(i))*/ 1
+ } else {
+ x.length - y.length
+ }
+ }
+ private def compareTermNames(x: TermName, y: TermName): Int = x match {
+ case x: SimpleTermName =>
+ y match {
+ case y: SimpleTermName => compareSimpleNames(x, y)
+ case _ => -1
+ }
+ case DerivedTermName(xPre, xInfo) =>
+ y match {
+ case DerivedTermName(yPre, yInfo) =>
+ val s = compareInfos(xInfo, yInfo)
+ if (s == 0) compareTermNames(xPre, yPre) else s
+ case _ => 1
+ }
+ }
def compare(x: Name, y: Name): Int = {
if (x.isTermName && y.isTypeName) 1
else if (x.isTypeName && y.isTermName) -1
else if (x eq y) 0
- else {
- val until = x.length min y.length
- var i = 0
-
- while (i < until && x(i) == y(i)) i = i + 1
-
- if (i < until) {
- if (x(i) < y(i)) -1
- else /*(x(i) > y(i))*/ 1
- } else {
- x.length - y.length
- }
- }
+ else compareTermNames(x.toTermName, y.toTermName)
}
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala
index 6090079e5..205798474 100644
--- a/compiler/src/dotty/tools/dotc/core/Scopes.scala
+++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala
@@ -32,7 +32,7 @@ object Scopes {
* This value must be a power of two, so that the index of an element can
* be computed as element.hashCode & (hashTable.length - 1)
*/
- private final val MinHash = 8
+ final val MinHashedScopeSize = 8
/** The maximal permissible number of recursions when creating
* a hashtable
@@ -60,7 +60,7 @@ object Scopes {
* or to delete them. These methods are provided by subclass
* MutableScope.
*/
- abstract class Scope extends DotClass with printing.Showable with Iterable[Symbol] {
+ abstract class Scope extends DotClass with printing.Showable {
/** The last scope-entry from which all others are reachable via `prev` */
private[dotc] def lastEntry: ScopeEntry
@@ -76,18 +76,37 @@ object Scopes {
/** The symbols in this scope in the order they were entered;
* inherited from outer ones first.
*/
- def toList: List[Symbol]
+ def toList(implicit ctx: Context): List[Symbol]
/** Return all symbols as an iterator in the order they were entered in this scope.
*/
- def iterator: Iterator[Symbol] = toList.iterator
+ def iterator(implicit ctx: Context): Iterator[Symbol] = toList.iterator
+
+ /** Is the scope empty? */
+ def isEmpty: Boolean = lastEntry eq null
+
+ def foreach[U](p: Symbol => U)(implicit ctx: Context): Unit = toList foreach p
+
+ def filter(p: Symbol => Boolean)(implicit ctx: Context): List[Symbol] = {
+ ensureComplete()
+ var syms: List[Symbol] = Nil
+ var e = lastEntry
+ while ((e ne null) && e.owner == this) {
+ val sym = e.sym
+ if (p(sym)) syms = sym :: syms
+ e = e.prev
+ }
+ syms
+ }
+
+ def find(p: Symbol => Boolean)(implicit ctx: Context): Symbol = filter(p) match {
+ case sym :: _ => sym
+ case _ => NoSymbol
+ }
/** Returns a new mutable scope with the same content as this one. */
def cloneScope(implicit ctx: Context): MutableScope
- /** Is the scope empty? */
- override def isEmpty: Boolean = lastEntry eq null
-
/** Lookup a symbol entry matching given name. */
def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry
@@ -144,6 +163,12 @@ object Scopes {
final def toText(printer: Printer): Text = printer.toText(this)
def checkConsistent()(implicit ctx: Context) = ()
+
+ /** Ensure that all elements of this scope have been entered.
+ * Overridden by SymbolLoaders.PackageLoader#PackageScope, where it
+ * makes sure that all names with `$`'s have been added.
+ */
+ protected def ensureComplete()(implicit ctx: Context): Unit = ()
}
/** A subclass of Scope that defines methods for entering and
@@ -155,9 +180,10 @@ object Scopes {
class MutableScope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0)
extends Scope {
+ /** Scope shares elements with `base` */
protected[Scopes] def this(base: Scope)(implicit ctx: Context) = {
this(base.lastEntry, base.size, base.nestingLevel + 1)
- ensureCapacity(MinHash)(ctx) // WTH? it seems the implicit is not in scope for a secondary constructor call.
+ ensureCapacity(MinHashedScopeSize)(ctx) // WTH? it seems the implicit is not in scope for a secondary constructor call.
}
def this() = this(null, 0, 0)
@@ -178,6 +204,8 @@ object Scopes {
*/
private var elemsCache: List[Symbol] = null
+ protected def newScopeLikeThis() = new MutableScope()
+
/** Clone scope, taking care not to force the denotations of any symbols in the scope.
*/
def cloneScope(implicit ctx: Context): MutableScope = {
@@ -187,7 +215,7 @@ object Scopes {
entries += e
e = e.prev
}
- val scope = newScope
+ val scope = newScopeLikeThis()
for (i <- entries.length - 1 to 0 by -1) {
val e = entries(i)
scope.newScopeEntry(e.name, e.sym)
@@ -197,7 +225,7 @@ object Scopes {
/** create and enter a scope entry with given name and symbol */
protected def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry = {
- ensureCapacity(if (hashTable ne null) hashTable.length else MinHash)
+ ensureCapacity(if (hashTable ne null) hashTable.length else MinHashedScopeSize)
val e = new ScopeEntry(name, sym, this)
e.prev = lastEntry
lastEntry = e
@@ -338,8 +366,9 @@ object Scopes {
/** Returns all symbols as a list in the order they were entered in this scope.
* Does _not_ include the elements of inherited scopes.
*/
- override final def toList: List[Symbol] = {
+ override final def toList(implicit ctx: Context): List[Symbol] = {
if (elemsCache eq null) {
+ ensureComplete()
elemsCache = Nil
var e = lastEntry
while ((e ne null) && e.owner == this) {
@@ -351,6 +380,7 @@ object Scopes {
}
override def implicitDecls(implicit ctx: Context): List[TermRef] = {
+ ensureComplete()
var irefs = new mutable.ListBuffer[TermRef]
var e = lastEntry
while (e ne null) {
@@ -365,25 +395,13 @@ object Scopes {
/** Vanilla scope - symbols are stored in declaration order.
*/
- final def sorted: List[Symbol] = toList
-
- override def foreach[U](p: Symbol => U): Unit = toList foreach p
-
- override def filter(p: Symbol => Boolean): List[Symbol] = {
- var syms: List[Symbol] = Nil
- var e = lastEntry
- while ((e ne null) && e.owner == this) {
- val sym = e.sym
- if (p(sym)) syms = sym :: syms
- e = e.prev
- }
- syms
- }
+ final def sorted(implicit ctx: Context): List[Symbol] = toList
override def openForMutations: MutableScope = this
/** Check that all symbols in this scope are in their correct hashtable buckets. */
override def checkConsistent()(implicit ctx: Context) = {
+ ensureComplete()
var e = lastEntry
while (e != null) {
var e1 = lookupEntry(e.name)
@@ -407,9 +425,6 @@ object Scopes {
scope
}
- /** Create new scope for the members of package `pkg` */
- def newPackageScope(pkgClass: Symbol): MutableScope = newScope
-
/** Transform scope of members of `owner` using operation `op`
* This is overridden by the reflective compiler to avoid creating new scopes for packages
*/
@@ -425,7 +440,7 @@ object Scopes {
override private[dotc] def lastEntry = null
override def size = 0
override def nestingLevel = 0
- override def toList = Nil
+ override def toList(implicit ctx: Context) = Nil
override def cloneScope(implicit ctx: Context): MutableScope = unsupported("cloneScope")
override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = null
override def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = null
diff --git a/compiler/src/dotty/tools/dotc/core/Signature.scala b/compiler/src/dotty/tools/dotc/core/Signature.scala
index fcd1e2376..4699cecf2 100644
--- a/compiler/src/dotty/tools/dotc/core/Signature.scala
+++ b/compiler/src/dotty/tools/dotc/core/Signature.scala
@@ -34,6 +34,14 @@ import scala.annotation.tailrec
case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
import Signature._
+/* FIXME does not compile under dotty, we get a missing param error
+ def checkUnqual(name: TypeName) = name mapParts { part =>
+ assert(!part.contains('.'), name)
+ part
+ }
+ paramsSig.foreach(checkUnqual)
+ checkUnqual(resSig)
+*/
/** Two names are consistent if they are the same or one of them is tpnme.Uninstantiated */
private def consistent(name1: TypeName, name2: TypeName) =
name1 == name2 || name1 == tpnme.Uninstantiated || name2 == tpnme.Uninstantiated
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index e7928fd09..92befdacb 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -15,6 +15,34 @@ object StdNames {
/** Base strings from which synthetic names are derived. */
+ object str {
+ final val SETTER_SUFFIX = "_$eq"
+ final val EXPAND_SEPARATOR = "$$"
+ final val TRAIT_SETTER_SEPARATOR = "$_setter_$"
+ final val SUPER_PREFIX = "super$"
+ final val INITIALIZER_PREFIX = "initial$"
+ final val SHADOWED_PREFIX = "(shadowed)"
+ final val AVOID_CLASH_SUFFIX = "$_avoid_name_clash_$"
+ final val MODULE_SUFFIX = NameTransformer.MODULE_SUFFIX_STRING
+ final val DEFAULT_GETTER = "$default$"
+ final val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
+ final val ANON_CLASS = "$anon"
+ final val ANON_FUN = "$anonfun"
+
+ final val INTERPRETER_IMPORT_WRAPPER = "$iw"
+ final val INTERPRETER_LINE_PREFIX = "line"
+ final val INTERPRETER_VAR_PREFIX = "res"
+ final val INTERPRETER_WRAPPER_SUFFIX = "$object"
+
+ final val Function = "Function"
+ final val ImplicitFunction = "ImplicitFunction"
+ final val AbstractFunction = "AbstractFunction"
+ final val Tuple = "Tuple"
+ final val Product = "Product"
+
+ def sanitize(str: String) = str.replaceAll("""[<>]""", """\$""")
+ }
+
abstract class DefinedNames[N <: Name] {
protected implicit def fromString(s: String): N
protected def fromName(name: Name): N = fromString(name.toString)
@@ -84,44 +112,30 @@ object StdNames {
final val HASHkw: N = kw("#")
final val ATkw: N = kw("@")
- val ANON_CLASS: N = "$anon"
- val ANON_FUN: N = "$anonfun"
- val BITMAP_PREFIX: N = "bitmap$"
+ val ANON_CLASS: N = str.ANON_CLASS
+ val ANON_FUN: N = str.ANON_FUN
+ val BITMAP_PREFIX: N = "bitmap$" // @darkdimius: $bitmap? Also, the next 4 names are unused.
val BITMAP_NORMAL: N = BITMAP_PREFIX // initialization bitmap for public/protected lazy vals
val BITMAP_TRANSIENT: N = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals
val BITMAP_CHECKINIT: N = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values
val BITMAP_CHECKINIT_TRANSIENT: N = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values
- val DEFAULT_GETTER: N = "$default$"
- val DEFAULT_GETTER_INIT: N = NameTransformer.encode("<init>")
+ val DEFAULT_GETTER: N = str.DEFAULT_GETTER
+ val DEFAULT_GETTER_INIT: N = "$lessinit$greater"
val DO_WHILE_PREFIX: N = "doWhile$"
+ val DOLLAR_VALUES: N = "$values"
+ val DOLLAR_NEW: N = "$new"
val EMPTY: N = ""
val EMPTY_PACKAGE: N = Names.EMPTY_PACKAGE.toString
- val EVIDENCE_PARAM_PREFIX: N = "evidence$"
- val DEP_PARAM_PREFIX = "<param>"
val EXCEPTION_RESULT_PREFIX: N = "exceptionResult"
- val EXPAND_SEPARATOR: N = "$$"
+ val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR
val IMPL_CLASS_SUFFIX: N = "$class"
val IMPORT: N = "<import>"
- val INLINE_ACCESSOR_PREFIX = "$inlineAccessor$"
- val INTERPRETER_IMPORT_WRAPPER: N = "$iw"
- val INTERPRETER_LINE_PREFIX: N = "line"
- val INTERPRETER_VAR_PREFIX: N = "res"
- val INTERPRETER_WRAPPER_SUFFIX: N = "$object"
- val LOCALDUMMY_PREFIX: N = "<local " // owner of local blocks
val MODULE_SUFFIX: N = NameTransformer.MODULE_SUFFIX_STRING
- val AVOID_CLASH_SUFFIX: N = "$_avoid_name_clash_$"
- val MODULE_VAR_SUFFIX: N = "$module"
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
- val USCORE_PARAM_PREFIX: N = "_$"
val OPS_PACKAGE: N = "<special-ops>"
val OVERLOADED: N = "<overloaded>"
val PACKAGE: N = "package"
- val PACKAGE_CLS: N = "package$"
- val PROTECTED_PREFIX: N = "protected$"
- val PROTECTED_SET_PREFIX: N = PROTECTED_PREFIX + "set"
val ROOT: N = "<root>"
- val SHADOWED: N = "(shadowed)" // tag to be used until we have proper name kinds
- val SINGLETON_SUFFIX: N = ".type"
val SPECIALIZED_SUFFIX: N = "$sp"
val SUPER_PREFIX: N = "super$"
val WHILE_PREFIX: N = "while$"
@@ -129,11 +143,7 @@ object StdNames {
val INITIALIZER_PREFIX: N = "initial$"
val COMPANION_MODULE_METHOD: N = "companion$module"
val COMPANION_CLASS_METHOD: N = "companion$class"
- val TRAIT_SETTER_SEPARATOR: N = "$_setter_$"
- val DIRECT_SUFFIX: N = "$direct"
- val LAZY_IMPLICIT_PREFIX: N = "$lazy_implicit$"
- val DOLLAR_VALUES: N = "$values"
- val DOLLAR_NEW: N = "$new"
+ val TRAIT_SETTER_SEPARATOR: N = str.TRAIT_SETTER_SEPARATOR
// value types (and AnyRef) are all used as terms as well
// as (at least) arguments to the @specialize annotation.
@@ -167,7 +177,6 @@ object StdNames {
// fictions we use as both types and terms
final val ERROR: N = "<error>"
- final val ERRORenc: N = encode("<error>")
final val NO_NAME: N = "<none>" // formerly NOSYMBOL
final val WILDCARD: N = "_"
@@ -181,23 +190,18 @@ object StdNames {
final val REIFY_TREECREATOR_PREFIX: N = "$treecreator"
final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator"
- final val AbstractFunction: N = "AbstractFunction"
final val Any: N = "Any"
final val AnyVal: N = "AnyVal"
final val ExprApi: N = "ExprApi"
- final val Function: N = "Function"
- final val ImplicitFunction: N = "ImplicitFunction"
final val Mirror: N = "Mirror"
final val Nothing: N = "Nothing"
final val Null: N = "Null"
final val Object: N = "Object"
final val PartialFunction: N = "PartialFunction"
final val PrefixType: N = "PrefixType"
- final val Product: N = "Product"
final val Serializable: N = "Serializable"
final val Singleton: N = "Singleton"
final val Throwable: N = "Throwable"
- final val Tuple: N = "Tuple"
final val ClassfileAnnotation: N = "ClassfileAnnotation"
final val ClassManifest: N = "ClassManifest"
@@ -241,11 +245,8 @@ object StdNames {
val EVT2U: N = "evt2u$"
val EQEQ_LOCAL_VAR: N = "eqEqTemp$"
val FAKE_LOCAL_THIS: N = "this$"
- val LAZY_LOCAL: N = "$lzy"
- val LAZY_LOCAL_INIT: N = "$lzyINIT"
val LAZY_FIELD_OFFSET: N = "OFFSET$"
val LAZY_SLOW_SUFFIX: N = "$lzycompute"
- val LOCAL_SUFFIX: N = "$$local"
val UNIVERSE_BUILD_PREFIX: N = "$u.build."
val UNIVERSE_BUILD: N = "$u.build"
val UNIVERSE_PREFIX: N = "$u."
@@ -259,13 +260,10 @@ object StdNames {
val REIFY_SYMDEF_PREFIX: N = "symdef$"
val MODULE_INSTANCE_FIELD: N = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: N = "$outer"
- val OUTER_LOCAL: N = "$outer "
- val OUTER_SELECT: N = "_<outer>" // emitted by inliner, replaced by outer path in explicitouter
val REFINE_CLASS: N = "<refinement>"
val ROOTPKG: N = "_root_"
val SELECTOR_DUMMY: N = "<unapply-selector>"
val SELF: N = "$this"
- val SETTER_SUFFIX: N = encode("_=")
val SKOLEM: N = "<skolem>"
val SPECIALIZED_INSTANCE: N = "specInstance$"
val THIS: N = "_$this"
@@ -440,7 +438,6 @@ object StdNames {
val lang: N = "lang"
val length: N = "length"
val lengthCompare: N = "lengthCompare"
- val liftedTree: N = "liftedTree"
val `macro` : N = "macro"
val macroThis : N = "_this"
val macroContext : N = "c"
@@ -458,7 +455,6 @@ object StdNames {
val ne: N = "ne"
val newFreeTerm: N = "newFreeTerm"
val newFreeType: N = "newFreeType"
- val newNestedSymbol: N = "newNestedSymbol"
val newScopeWith: N = "newScopeWith"
val next: N = "next"
val nmeNewTermName: N = "newTermName"
@@ -541,6 +537,11 @@ object StdNames {
val synthSwitch: N = "$synthSwitch"
val _scope: N = "$scope"
+ val nothingClass: N = "Nothing$"
+ val nullClass: N = "Null$"
+
+ val falseModuleClassNames = Set(nothingClass, nullClass, nothingRuntimeClass, nullRuntimeClass)
+
// unencoded operators
object raw {
final val AMP : N = "&"
@@ -661,22 +662,6 @@ object StdNames {
val isBoxedNumberOrBoolean: N = "isBoxedNumberOrBoolean"
val isBoxedNumber: N = "isBoxedNumber"
-
- val reflPolyCacheName: N = "reflPoly$Cache"
- val reflClassCacheName: N = "reflClass$Cache"
- val reflParamsCacheName: N = "reflParams$Cache"
- val reflMethodCacheName: N = "reflMethod$Cache"
- val reflMethodName: N = "reflMethod$Method"
-
- private val reflectionCacheNames = Set[N](
- reflPolyCacheName,
- reflClassCacheName,
- reflParamsCacheName,
- reflMethodCacheName,
- reflMethodName
- )
-
- def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _)
}
class ScalaTermNames extends ScalaNames[TermName] {
@@ -723,7 +708,7 @@ object StdNames {
}
def localDummyName(clazz: Symbol)(implicit ctx: Context): TermName =
- LOCALDUMMY_PREFIX ++ clazz.name ++ ">"
+ termName(str.LOCALDUMMY_PREFIX + clazz.name + ">")
def newBitmapName(bitmapPrefix: TermName, n: Int): TermName = bitmapPrefix ++ n.toString
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
index 602848a50..1e0beb5f3 100644
--- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -4,7 +4,7 @@ package core
import Periods._, Contexts._, Symbols._, Denotations._, Names._, NameOps._, Annotations._
import Types._, Flags._, Decorators._, DenotTransformers._, StdNames._, Scopes._, Comments._
-import NameOps._
+import NameOps._, NameKinds._
import Scopes.Scope
import collection.mutable
import collection.immutable.BitSet
@@ -107,7 +107,7 @@ object SymDenotations {
class SymDenotation private[SymDenotations] (
symbol: Symbol,
ownerIfExists: Symbol,
- final val name: Name,
+ initName: Name,
initFlags: FlagSet,
initInfo: Type,
initPrivateWithin: Symbol = NoSymbol) extends SingleDenotation(symbol) {
@@ -125,11 +125,18 @@ object SymDenotations {
// ------ Getting and setting fields -----------------------------
+ private[this] var myName = initName
private[this] var myFlags: FlagSet = adaptFlags(initFlags)
private[this] var myInfo: Type = initInfo
private[this] var myPrivateWithin: Symbol = initPrivateWithin
private[this] var myAnnotations: List[Annotation] = Nil
+ /** The name of the symbol */
+ def name = myName
+
+ /** Update the name; only called when unpickling top-level classes */
+ def name_=(n: Name) = myName = n
+
/** The owner of the symbol; overridden in NoDenotation */
def owner: Symbol = ownerIfExists
@@ -252,7 +259,7 @@ object SymDenotations {
*/
def effectiveName(implicit ctx: Context) =
if (this is ModuleClass) name.stripModuleClassSuffix
- else name.stripAvoidClashSuffix
+ else name.exclude(AvoidClashName)
/** The privateWithin boundary, NoSymbol if no boundary is given.
*/
@@ -367,7 +374,7 @@ object SymDenotations {
/** The expanded name of this denotation. */
final def expandedName(implicit ctx: Context) =
- if (is(ExpandedName) || isConstructor) name
+ if (name.is(ExpandedName) || isConstructor) name
else {
def legalize(name: Name): Name = // JVM method names may not contain `<' or `>' characters
if (is(Method)) name.replace('<', '(').replace('>', ')') else name
@@ -377,49 +384,50 @@ object SymDenotations {
// might have been moved from different origins into the same class
/** The name with which the denoting symbol was created */
- final def originalName(implicit ctx: Context) = {
- val d = initial
- if (d is ExpandedName) d.name.unexpandedName else d.name // !!!DEBUG, was: effectiveName
- }
+ final def originalName(implicit ctx: Context) =
+ initial.effectiveName
/** The encoded full path name of this denotation, where outer names and inner names
* are separated by `separator` strings.
* Never translates expansions of operators back to operator symbol.
- * Drops package objects. Represents terms in the owner chain by a simple `~`.
+ * Drops package objects. Represents each term in the owner chain by a simple `~`.
* (Note: scalac uses nothing to represent terms, which can cause name clashes
* between same-named definitions in different enclosing methods. Before this commit
* we used `$' but this can cause ambiguities with the class separator '$').
* A separator "" means "flat name"; the real separator in this case is "$" and
* enclosing packages do not form part of the name.
*/
- def fullNameSeparated(separator: String)(implicit ctx: Context): Name = {
- var sep = separator
- var stopAtPackage = false
- if (sep.isEmpty) {
- sep = "$"
- stopAtPackage = true
- }
+ def fullNameSeparated(kind: QualifiedNameKind)(implicit ctx: Context): Name =
if (symbol == NoSymbol ||
owner == NoSymbol ||
owner.isEffectiveRoot ||
- stopAtPackage && owner.is(PackageClass)) name
+ kind == FlatName && owner.is(PackageClass)) name
else {
+ var filler = ""
var encl = owner
while (!encl.isClass && !encl.isPackageObject) {
encl = encl.owner
- sep += "~"
+ filler += "~"
+ }
+ var prefix = encl.fullNameSeparated(kind)
+ if (kind.separator == "$")
+ // duplicate scalac's behavior: don't write a double '$$' for module class members.
+ prefix = prefix.exclude(ModuleClassName)
+ def qualify(n: SimpleTermName) =
+ kind(prefix.toTermName, if (filler.isEmpty) n else termName(filler + n))
+ val fn = name rewrite {
+ case name: SimpleTermName => qualify(name)
+ case name @ AnyQualifiedName(_, _) => qualify(name.toSimpleName)
}
- if (owner.is(ModuleClass, butNot = Package) && sep == "$") sep = "" // duplicate scalac's behavior: don't write a double '$$' for module class members.
- val fn = encl.fullNameSeparated(separator) ++ sep ++ name
if (isType) fn.toTypeName else fn.toTermName
}
- }
+
/** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */
- def flatName(implicit ctx: Context): Name = fullNameSeparated("")
+ def flatName(implicit ctx: Context): Name = fullNameSeparated(FlatName)
/** `fullName` where `.' is the separator character */
- def fullName(implicit ctx: Context): Name = fullNameSeparated(".")
+ def fullName(implicit ctx: Context): Name = fullNameSeparated(QualifiedName)
// ----- Tests -------------------------------------------------
@@ -460,13 +468,13 @@ object SymDenotations {
/** Is this symbol an anonymous class? */
final def isAnonymousClass(implicit ctx: Context): Boolean =
- isClass && (initial.name startsWith tpnme.ANON_CLASS)
+ isClass && (initial.name startsWith str.ANON_CLASS)
final def isAnonymousFunction(implicit ctx: Context) =
- this.symbol.is(Method) && (initial.name startsWith nme.ANON_FUN)
+ this.symbol.is(Method) && (initial.name startsWith str.ANON_FUN)
final def isAnonymousModuleVal(implicit ctx: Context) =
- this.symbol.is(ModuleVal) && (initial.name startsWith nme.ANON_CLASS)
+ this.symbol.is(ModuleVal) && (initial.name startsWith str.ANON_CLASS)
/** Is this a companion class method or companion object method?
* These methods are generated by Symbols#synthesizeCompanionMethod
@@ -505,8 +513,10 @@ object SymDenotations {
/** Is this symbol a package object or its module class? */
def isPackageObject(implicit ctx: Context): Boolean = {
- val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE
- (name.toTermName == poName) && (owner is Package) && (this is Module)
+ val nameMatches =
+ if (isType) name == tpnme.PACKAGE.moduleClassName
+ else name == nme.PACKAGE
+ nameMatches && (owner is Package) && (this is Module)
}
/** Is this symbol an abstract type? */
@@ -922,14 +932,15 @@ object SymDenotations {
* and which is also defined in the same scope and compilation unit.
* NoSymbol if this class does not exist.
*/
- final def companionClass(implicit ctx: Context): Symbol = {
- val companionMethod = info.decls.denotsNamed(nme.COMPANION_CLASS_METHOD, selectPrivate).first
-
- if (companionMethod.exists)
- companionMethod.info.resultType.classSymbol
- else
- NoSymbol
- }
+ final def companionClass(implicit ctx: Context): Symbol =
+ if (is(Package)) NoSymbol
+ else {
+ val companionMethod = info.decls.denotsNamed(nme.COMPANION_CLASS_METHOD, selectPrivate).first
+ if (companionMethod.exists)
+ companionMethod.info.resultType.classSymbol
+ else
+ NoSymbol
+ }
final def scalacLinkedClass(implicit ctx: Context): Symbol =
if (this is ModuleClass) companionNamed(effectiveName.toTypeName)
@@ -1198,9 +1209,7 @@ object SymDenotations {
/** If denotation is private, remove the Private flag and expand the name if necessary */
def ensureNotPrivate(implicit ctx: Context) =
if (is(Private))
- copySymDenotation(
- name = expandedName,
- initFlags = this.flags &~ Private | ExpandedName)
+ copySymDenotation(name = expandedName, initFlags = this.flags &~ Private)
else this
}
@@ -1209,18 +1218,19 @@ object SymDenotations {
class ClassDenotation private[SymDenotations] (
symbol: Symbol,
ownerIfExists: Symbol,
- name: Name,
+ initName: Name,
initFlags: FlagSet,
initInfo: Type,
initPrivateWithin: Symbol,
initRunId: RunId)
- extends SymDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) {
+ extends SymDenotation(symbol, ownerIfExists, initName, initFlags, initInfo, initPrivateWithin) {
import util.LRUCache
// ----- denotation fields and accessors ------------------------------
- if (initFlags is (Module, butNot = Package)) assert(name.isModuleClassName, s"module naming inconsistency: $name")
+ if (initFlags is (Module, butNot = Package))
+ assert(name.is(ModuleClassName), s"module naming inconsistency: ${name.debugString}")
/** The symbol asserted to have type ClassSymbol */
def classSymbol: ClassSymbol = symbol.asInstanceOf[ClassSymbol]
@@ -1493,6 +1503,9 @@ object SymDenotations {
myMemberCache
}
+ /** Hook to do a pre-enter test. Overridden in PackageDenotation */
+ protected def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = true
+
/** Enter a symbol in current scope, and future scopes of same denotation.
* Note: We require that this does not happen after the first time
* someone does a findMember on a subclass.
@@ -1510,19 +1523,13 @@ object SymDenotations {
scope
case _ => unforcedDecls.openForMutations
}
- if (this is PackageClass) {
- val entry = mscope.lookupEntry(sym.name)
- if (entry != null) {
- if (entry.sym == sym) return
- mscope.unlink(entry)
- entry.sym.denot = sym.denot // to avoid stale symbols
+ if (proceedWithEnter(sym, mscope)) {
+ enterNoReplace(sym, mscope)
+ val nxt = this.nextInRun
+ if (nxt.validFor.code > this.validFor.code) {
+ this.nextInRun.asSymDenotation.asClass.enter(sym)
}
}
- enterNoReplace(sym, mscope)
- val nxt = this.nextInRun
- if (nxt.validFor.code > this.validFor.code) {
- this.nextInRun.asSymDenotation.asClass.enter(sym)
- }
}
/** Enter a symbol in given `scope` without potentially replacing the old copy. */
@@ -1533,8 +1540,8 @@ object SymDenotations {
!(this is Frozen) ||
(scope ne this.unforcedDecls) ||
sym.hasAnnotation(defn.ScalaStaticAnnot) ||
- sym.name.isInlineAccessor ||
- isUsecase)
+ sym.name.is(InlineAccessorName) ||
+ isUsecase, i"trying to enter $sym in $this, frozen = ${this is Frozen}")
scope.enter(sym)
@@ -1755,13 +1762,13 @@ object SymDenotations {
}
}
- private[this] var fullNameCache: SimpleMap[String, Name] = SimpleMap.Empty
- override final def fullNameSeparated(separator: String)(implicit ctx: Context): Name = {
- val cached = fullNameCache(separator)
+ private[this] var fullNameCache: SimpleMap[QualifiedNameKind, Name] = SimpleMap.Empty
+ override final def fullNameSeparated(kind: QualifiedNameKind)(implicit ctx: Context): Name = {
+ val cached = fullNameCache(kind)
if (cached != null) cached
else {
- val fn = super.fullNameSeparated(separator)
- fullNameCache = fullNameCache.updated(separator, fn)
+ val fn = super.fullNameSeparated(kind)
+ fullNameCache = fullNameCache.updated(kind, fn)
fn
}
}
@@ -1773,8 +1780,8 @@ object SymDenotations {
def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol
// denotsNamed returns Symbols in reverse order of occurrence
if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) // ignore normal constructor
- else
- constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR))
+ else if (this.is(Package)) NoSymbol
+ else constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR))
}
/** The parameter accessors of this class. Term and type accessors,
@@ -1800,7 +1807,7 @@ object SymDenotations {
/** The denotation of a package class.
* It overrides ClassDenotation to take account of package objects when looking for members
*/
- class PackageClassDenotation private[SymDenotations] (
+ final class PackageClassDenotation private[SymDenotations] (
symbol: Symbol,
ownerIfExists: Symbol,
name: Name,
@@ -1823,15 +1830,33 @@ object SymDenotations {
packageObjCache
}
- /** Look first for members in package; if none are found look in package object */
- override def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation = {
- val denots = super.computeNPMembersNamed(name, inherited)
- if (denots.exists) denots
- else packageObj.moduleClass.denot match {
- case pcls: ClassDenotation => pcls.computeNPMembersNamed(name, inherited)
- case _ => denots
+ /** Looks in both the package object and the package for members. The precise algorithm
+ * is as follows:
+ *
+ * If this is the scala package look in the package first, and if nothing is found
+ * there, look in the package object second. Otherwise, look in the package object
+ * first, and if nothing is found there, in the package second.
+ *
+ * The reason for the special treatment of the scala package is that if we
+ * complete it too early, we freeze its superclass Any, so that no members can
+ * be entered in it. As a consequence, there should be no entry in the scala package
+ * object that hides a class or object in the scala package of the same name, because
+ * the behavior would then be unintuitive for such members.
+ */
+ override def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation =
+ packageObj.moduleClass.denot match {
+ case pcls: ClassDenotation if !pcls.isCompleting =>
+ if (symbol eq defn.ScalaPackageClass) {
+ val denots = super.computeNPMembersNamed(name, inherited)
+ if (denots.exists) denots else pcls.computeNPMembersNamed(name, inherited)
+ }
+ else {
+ val denots = pcls.computeNPMembersNamed(name, inherited)
+ if (denots.exists) denots else super.computeNPMembersNamed(name, inherited)
+ }
+ case _ =>
+ super.computeNPMembersNamed(name, inherited)
}
- }
/** The union of the member names of the package and the package object */
override def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = {
@@ -1841,6 +1866,21 @@ object SymDenotations {
case _ => ownNames
}
}
+
+ /** If another symbol with the same name is entered, unlink it,
+ * and, if symbol is a package object, invalidate the packageObj cache.
+ * @return `sym` is not already entered
+ */
+ override def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = {
+ val entry = mscope.lookupEntry(sym.name)
+ if (entry != null) {
+ if (entry.sym == sym) return false
+ mscope.unlink(entry)
+ entry.sym.denot = sym.denot // to avoid stale symbols
+ if (sym.name == nme.PACKAGE) packageObjRunId = NoRunId
+ }
+ true
+ }
}
class NoDenotation extends SymDenotation(
diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 79f8a6a45..63c2817a6 100644
--- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -9,11 +9,13 @@ package core
import java.io.IOException
import scala.compat.Platform.currentTime
-import dotty.tools.io.{ ClassPath, AbstractFile }
+import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile }
+import classpath._
import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util.Positions._, Names._
import StdNames._, NameOps._
import Decorators.{PreNamedString, StringInterpolators}
import classfile.ClassfileParser
+import util.Stats
import scala.util.control.NonFatal
object SymbolLoaders {
@@ -59,8 +61,7 @@ class SymbolLoaders {
/** Enter package with given `name` into scope of `owner`
* and give them `completer` as type.
*/
- def enterPackage(owner: Symbol, pkg: ClassPath)(implicit ctx: Context): Symbol = {
- val pname = pkg.name.toTermName
+ def enterPackage(owner: Symbol, pname: TermName, completer: (TermSymbol, ClassSymbol) => PackageLoader)(implicit ctx: Context): Symbol = {
val preExisting = owner.info.decls lookup pname
if (preExisting != NoSymbol) {
// Some jars (often, obfuscated ones) include a package and
@@ -83,7 +84,7 @@ class SymbolLoaders {
}
}
ctx.newModuleSymbol(owner, pname, PackageCreationFlags, PackageCreationFlags,
- (module, modcls) => new PackageLoader(module, pkg)).entered
+ completer).entered
}
/** Enter class and module with given `name` into scope of `owner`
@@ -125,7 +126,7 @@ class SymbolLoaders {
/** Initialize toplevel class and module symbols in `owner` from class path representation `classRep`
*/
- def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context): Unit = {
+ def initializeFromClassPath(owner: Symbol, classRep: ClassRepresentation)(implicit ctx: Context): Unit = {
((classRep.binary, classRep.source): @unchecked) match {
case (Some(bin), Some(src)) if needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
if (ctx.settings.verbose.value) ctx.inform("[symloader] picked up newer source file for " + src.path)
@@ -143,31 +144,99 @@ class SymbolLoaders {
/** Load contents of a package
*/
- class PackageLoader(_sourceModule: TermSymbol, classpath: ClassPath)
+ class PackageLoader(_sourceModule: TermSymbol, classPath: ClassPath)
extends SymbolLoader {
override def sourceModule(implicit ctx: Context) = _sourceModule
- def description = "package loader " + classpath.name
+ def description(implicit ctx: Context) = "package loader " + sourceModule.fullName
- private[core] val currentDecls: MutableScope = newScope
+ private var enterFlatClasses: Option[Context => Unit] = None
+
+ Stats.record("package scopes")
+
+ /** The scope of a package. This is different from a normal scope
+ * in three aspects:
+ *
+ * 1. Names of scope entries are kept in mangled form.
+ * 2. Some function types in the `scala` package are synthesized.
+ */
+ final class PackageScope extends MutableScope {
+ override def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry =
+ super.newScopeEntry(name.mangled, sym)
+
+ override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
+ val mangled = name.mangled
+ val e = super.lookupEntry(mangled)
+ if (e != null) e
+ else if (_sourceModule.initialDenot.name == nme.scala_ && _sourceModule == defn.ScalaPackageVal &&
+ name.isTypeName && name.isSyntheticFunction)
+ newScopeEntry(defn.newFunctionNTrait(name.asTypeName))
+ else if (isFlatName(mangled.toSimpleName) && enterFlatClasses.isDefined) {
+ Stats.record("package scopes with flatnames entered")
+ enterFlatClasses.get(ctx)
+ lookupEntry(name)
+ }
+ else e
+ }
+
+ override def ensureComplete()(implicit ctx: Context) =
+ for (enter <- enterFlatClasses) enter(ctx)
+
+ override def newScopeLikeThis() = new PackageScope
+ }
+
+ private[core] val currentDecls: MutableScope = new PackageScope()
+
+ def isFlatName(name: SimpleTermName) = name.lastIndexOf('$', name.length - 2) >= 0
+
+ def isFlatName(classRep: ClassRepresentation) = {
+ val idx = classRep.name.indexOf('$')
+ idx >= 0 && idx < classRep.name.length - 1
+ }
+
+ def maybeModuleClass(classRep: ClassRepresentation) = classRep.name.last == '$'
+
+ private def enterClasses(root: SymDenotation, packageName: String, flat: Boolean)(implicit ctx: Context) = {
+ def isAbsent(classRep: ClassRepresentation) =
+ !root.unforcedDecls.lookup(classRep.name.toTypeName).exists
+
+ if (!root.isRoot) {
+ val classReps = classPath.classes(packageName)
+
+ for (classRep <- classReps)
+ if (!maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
+ (!flat || isAbsent(classRep))) // on 2nd enter of flat names, check that the name has not been entered before
+ initializeFromClassPath(root.symbol, classRep)
+ for (classRep <- classReps)
+ if (maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
+ isAbsent(classRep))
+ initializeFromClassPath(root.symbol, classRep)
+ }
+ }
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = {
assert(root is PackageClass, root)
- def maybeModuleClass(classRep: ClassPath#ClassRep) = classRep.name.last == '$'
val pre = root.owner.thisType
root.info = ClassInfo(pre, root.symbol.asClass, Nil, currentDecls, pre select sourceModule)
if (!sourceModule.isCompleted)
sourceModule.completer.complete(sourceModule)
- if (!root.isRoot) {
- for (classRep <- classpath.classes)
- if (!maybeModuleClass(classRep))
- initializeFromClassPath(root.symbol, classRep)
- for (classRep <- classpath.classes)
- if (maybeModuleClass(classRep) && !root.unforcedDecls.lookup(classRep.name.toTypeName).exists)
- initializeFromClassPath(root.symbol, classRep)
+
+ val packageName = if (root.isEffectiveRoot) "" else root.fullName.toString
+
+ enterFlatClasses = Some { ctx =>
+ enterFlatClasses = None
+ enterClasses(root, packageName, flat = true)(ctx)
}
+ enterClasses(root, packageName, flat = false)
if (!root.isEmptyPackage)
- for (pkg <- classpath.packages)
- enterPackage(root.symbol, pkg)
+ for (pkg <- classPath.packages(packageName)) {
+ val fullName = pkg.name
+ val name =
+ if (packageName.isEmpty) fullName
+ else fullName.substring(packageName.length + 1)
+
+ enterPackage(root.symbol, name.toTermName,
+ (module, modcls) => new PackageLoader(module, classPath))
+ }
}
}
}
@@ -185,7 +254,7 @@ abstract class SymbolLoader extends LazyType {
/** Description of the resource (ClassPath, AbstractFile)
* being processed by this loader
*/
- def description: String
+ def description(implicit ctx: Context): String
override def complete(root: SymDenotation)(implicit ctx: Context): Unit = {
def signalError(ex: Exception): Unit = {
@@ -226,7 +295,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
override def sourceFileOrNull: AbstractFile = classfile
- def description = "class file " + classfile.toString
+ def description(implicit ctx: Context) = "class file " + classfile.toString
def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
val linkedDenot = rootDenot.scalacLinkedClass.denot match {
@@ -261,7 +330,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
}
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
- def description = "source file " + srcfile.toString
+ def description(implicit ctx: Context) = "source file " + srcfile.toString
override def sourceFileOrNull = srcfile
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = unsupported("doComplete")
}
diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala
index 95ff1cb75..e0d9aca2b 100644
--- a/compiler/src/dotty/tools/dotc/core/Symbols.scala
+++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala
@@ -19,6 +19,7 @@ import util.Positions._
import DenotTransformers._
import StdNames._
import NameOps._
+import NameKinds.LazyImplicitName
import ast.tpd.Tree
import ast.TreeTypeMap
import Constants.Constant
@@ -260,7 +261,7 @@ trait Symbols { this: Context =>
/** Create a synthetic lazy implicit value */
def newLazyImplicit(info: Type) =
- newSymbol(owner, freshName(nme.LAZY_IMPLICIT_PREFIX).toTermName, Lazy, info)
+ newSymbol(owner, LazyImplicitName.fresh(), Lazy, info)
/** Create a symbol representing a selftype declaration for class `cls`. */
def newSelfSym(cls: ClassSymbol, name: TermName = nme.WILDCARD, selfInfo: Type = NoType): TermSymbol =
diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
index 94b726491..b37ed2b0a 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -11,6 +11,7 @@ import util.Stats._
import util.common._
import Names._
import NameOps._
+import NameKinds._
import Flags._
import StdNames.tpnme
import util.Positions.Position
@@ -428,7 +429,7 @@ class TypeApplications(val self: Type) extends AnyVal {
case dealiased: LazyRef =>
LazyRef(() => dealiased.ref.appliedTo(args))
case dealiased: WildcardType =>
- dealiased
+ WildcardType(dealiased.optBounds.appliedTo(args).bounds)
case dealiased: TypeRef if dealiased.symbol == defn.NothingClass =>
dealiased
case _ if typParams.isEmpty || typParams.head.isInstanceOf[LambdaParam] =>
@@ -464,11 +465,6 @@ class TypeApplications(val self: Type) extends AnyVal {
self
case _ =>
val v = tparam.paramVariance
- /* Not neeeded.
- if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self)
- else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self)
- else
- */
TypeAlias(self, v)
}
@@ -510,13 +506,14 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type = ctx.traceIndented(s"btwa ${self.show} wrt $base", core, show = true) {
def default = self.baseTypeRef(base).appliedTo(baseArgInfos(base))
+ def isExpandedTypeParam(sym: Symbol) = sym.is(TypeParam) && sym.name.is(ExpandedName)
self match {
case tp: TypeRef =>
tp.info match {
case TypeBounds(_, hi) => hi.baseTypeWithArgs(base)
case _ => default
}
- case tp @ RefinedType(parent, name, _) if !tp.member(name).symbol.is(ExpandedTypeParam) =>
+ case tp @ RefinedType(parent, name, _) if !isExpandedTypeParam(tp.member(name).symbol) =>
tp.wrapIfMember(parent.baseTypeWithArgs(base))
case tp: TermRef =>
tp.underlying.baseTypeWithArgs(base)
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index da6d63387..54b96a253 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -726,10 +726,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
tycon2 match {
case param2: TypeParamRef =>
- isMatchingApply(tp1) || {
- if (canConstrain(param2)) canInstantiate(param2)
- else compareLower(bounds(param2), tyconIsTypeRef = false)
- }
+ isMatchingApply(tp1) ||
+ canConstrain(param2) && canInstantiate(param2) ||
+ compareLower(bounds(param2), tyconIsTypeRef = false)
case tycon2: TypeRef =>
isMatchingApply(tp1) ||
compareLower(tycon2.info.bounds, tyconIsTypeRef = true)
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 8ae3aa7ad..c8c1886cc 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -7,6 +7,7 @@ import Symbols._
import Flags._
import Names._
import StdNames._, NameOps._
+import NameKinds.{ShadowedName, SkolemName}
import Scopes._
import Constants._
import Contexts._
@@ -107,10 +108,11 @@ object Types {
final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[TypeLambda]
/** Does this type denote a stable reference (i.e. singleton type)? */
- @tailrec final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
- case tp: TermRef => tp.termSymbol.isStable && tp.prefix.isStable
+ final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
+ case tp: TermRef => tp.termSymbol.isStable && tp.prefix.isStable || tp.info.isStable
case _: SingletonType | NoPrefix => true
case tp: RefinedOrRecType => tp.parent.isStable
+ case tp: ExprType => tp.resultType.isStable
case _ => false
}
@@ -1504,20 +1506,29 @@ object Types {
case _ => NoType
}
assert(
- (lastSymbol eq sym) ||
- (lastSymbol eq null) || {
+ (lastSymbol eq sym)
+ ||
+ (lastSymbol eq null)
+ || {
val lastDefRunId = lastDenotation match {
case d: SymDenotation => d.validFor.runId
case _ => lastSymbol.defRunId
}
(lastDefRunId != sym.defRunId) ||
(lastDefRunId == NoRunId)
- } ||
- (lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] ||
+ }
+ ||
+ lastSymbol.infoOrCompleter.isInstanceOf[ErrorType]
+ ||
+ sym.isPackageObject // package objects can be visited before we get around to index them
+ ||
sym.owner != lastSymbol.owner &&
- (sym.owner.derivesFrom(lastSymbol.owner) ||
- selfTypeOf(sym).derivesFrom(lastSymbol.owner) ||
- selfTypeOf(lastSymbol).derivesFrom(sym.owner))),
+ (sym.owner.derivesFrom(lastSymbol.owner)
+ ||
+ selfTypeOf(sym).derivesFrom(lastSymbol.owner)
+ ||
+ selfTypeOf(lastSymbol).derivesFrom(sym.owner)
+ ),
i"""data race? overwriting symbol of type $this,
|long form = $toString of class $getClass,
|last sym id = ${lastSymbol.id}, new sym id = ${sym.id},
@@ -1584,7 +1595,7 @@ object Types {
}
protected def asMemberOf(prefix: Type, allowPrivate: Boolean)(implicit ctx: Context): Denotation =
- if (name.isShadowedName) prefix.nonPrivateMember(name.revertShadowed)
+ if (name.is(ShadowedName)) prefix.nonPrivateMember(name.exclude(ShadowedName))
else if (!allowPrivate) prefix.nonPrivateMember(name)
else prefix.member(name)
@@ -1720,7 +1731,7 @@ object Types {
* the public name.
*/
def shadowed(implicit ctx: Context): NamedType =
- NamedType(prefix, name.shadowedName)
+ NamedType(prefix, name.derived(ShadowedName))
override def equals(that: Any) = that match {
case that: NamedType =>
@@ -1794,7 +1805,7 @@ object Types {
fixDenot(TermRef.withSig(prefix, name, sig), prefix)
override def shadowed(implicit ctx: Context): NamedType =
- fixDenot(TermRef.withSig(prefix, name.shadowedName, sig), prefix)
+ fixDenot(TermRef.withSig(prefix, name.derived(ShadowedName), sig), prefix)
override def equals(that: Any) = that match {
case that: TermRefWithSignature =>
@@ -2990,9 +3001,9 @@ object Types {
override def hashCode: Int = identityHash
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
- private var myRepr: String = null
- def repr(implicit ctx: Context) = {
- if (myRepr == null) myRepr = ctx.freshName("?")
+ private var myRepr: Name = null
+ def repr(implicit ctx: Context): Name = {
+ if (myRepr == null) myRepr = SkolemName.fresh()
myRepr
}
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index da875c906..26c823f97 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -5,6 +5,7 @@ package classfile
import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._, Decorators._
import SymDenotations._, unpickleScala2.Scala2Unpickler._, Constants._, Annotations._, util.Positions._
+import NameKinds.{ModuleClassName, DefaultGetterName}
import ast.tpd._
import java.io.{ File, IOException }
import java.lang.Integer.toHexString
@@ -25,6 +26,8 @@ class ClassfileParser(
classRoot: ClassDenotation,
moduleRoot: ClassDenotation)(ictx: Context) {
+ //println(s"parsing ${classRoot.name.debugString} ${moduleRoot.name.debugString}")
+
import ClassfileConstants._
import ClassfileParser._
@@ -36,7 +39,7 @@ class ClassfileParser(
protected val staticScope: MutableScope = newScope // the scope of all static definitions
protected var pool: ConstantPool = _ // the classfile's constant pool
- protected var currentClassName: Name = _ // JVM name of the current class
+ protected var currentClassName: SimpleTermName = _ // JVM name of the current class
protected var classTParams = Map[Name,Symbol]()
classRoot.info = (new NoCompleter).withDecls(instanceScope)
@@ -44,8 +47,8 @@ class ClassfileParser(
private def currentIsTopLevel(implicit ctx: Context) = classRoot.owner is Flags.PackageClass
- private def mismatchError(c: Symbol) =
- throw new IOException(s"class file '${in.file}' has location not matching its contents: contains $c")
+ private def mismatchError(className: SimpleTermName) =
+ throw new IOException(s"class file '${in.file}' has location not matching its contents: contains class $className")
def run()(implicit ctx: Context): Option[Embedded] = try {
ctx.debuglog("[class] >> " + classRoot.fullName)
@@ -89,10 +92,8 @@ class ClassfileParser(
val nameIdx = in.nextChar
currentClassName = pool.getClassName(nameIdx)
- if (currentIsTopLevel) {
- val c = pool.getClassSymbol(nameIdx)
- if (c != classRoot.symbol) mismatchError(c)
- }
+ if (currentIsTopLevel && currentClassName != classRoot.fullName.toSimpleName)
+ mismatchError(currentClassName)
addEnclosingTParams()
@@ -239,21 +240,21 @@ class ClassfileParser(
final def objToAny(tp: Type)(implicit ctx: Context) =
if (tp.isDirectRef(defn.ObjectClass) && !ctx.phase.erasedTypes) defn.AnyType else tp
- private def sigToType(sig: TermName, owner: Symbol = null)(implicit ctx: Context): Type = {
+ private def sigToType(sig: SimpleTermName, owner: Symbol = null)(implicit ctx: Context): Type = {
var index = 0
val end = sig.length
def accept(ch: Char): Unit = {
assert(sig(index) == ch, (sig(index), ch))
index += 1
}
- def subName(isDelimiter: Char => Boolean): TermName = {
+ def subName(isDelimiter: Char => Boolean): SimpleTermName = {
val start = index
while (!isDelimiter(sig(index))) { index += 1 }
sig.slice(start, index)
}
// Warning: sigToType contains nested completers which might be forced in a later run!
// So local methods need their own ctx parameters.
- def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean)(implicit ctx: Context): Type = {
+ def sig2type(tparams: immutable.Map[Name, Symbol], skiptvs: Boolean)(implicit ctx: Context): Type = {
val tag = sig(index); index += 1
(tag: @switch) match {
case BYTE_TAG => defn.ByteType
@@ -590,7 +591,7 @@ class ClassfileParser(
def addDefaultGetter(attr: Symbol, n: Int) =
ctx.newSymbol(
owner = moduleRoot.symbol,
- name = nme.CONSTRUCTOR.defaultGetterName(n),
+ name = DefaultGetterName(nme.CONSTRUCTOR, n),
flags = attr.flags & Flags.AccessFlags,
info = defn.NothingType).entered
@@ -647,7 +648,10 @@ class ClassfileParser(
* and implicitly current class' superclasses.
*/
private def enterOwnInnerClasses()(implicit ctx: Context): Unit = {
- def className(name: Name): Name = name.drop(name.lastIndexOf('.') + 1)
+ def className(name: Name): Name = {
+ val name1 = name.toSimpleName
+ name1.drop(name1.lastIndexOf('.') + 1)
+ }
def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) = {
ctx.base.loaders.enterClassAndModule(
@@ -661,7 +665,7 @@ class ClassfileParser(
for (entry <- innerClasses.values) {
// create a new class member for immediate inner classes
if (entry.outerName == currentClassName) {
- val file = ctx.platform.classPath.findBinaryFile(entry.externalName.toString) getOrElse {
+ val file = ctx.platform.classPath.findClassFile(entry.externalName.toString) getOrElse {
throw new AssertionError(entry.externalName)
}
enterClassAndModule(entry, file, entry.jflags)
@@ -883,7 +887,7 @@ class ClassfileParser(
private val len = in.nextChar
private val starts = new Array[Int](len)
private val values = new Array[AnyRef](len)
- private val internalized = new Array[TermName](len)
+ private val internalized = new Array[SimpleTermName](len)
{ var i = 1
while (i < starts.length) {
@@ -910,12 +914,12 @@ class ClassfileParser(
}
/** Return the name found at given index. */
- def getName(index: Int): TermName = {
+ def getName(index: Int): SimpleTermName = {
if (index <= 0 || len <= index)
errorBadIndex(index)
values(index) match {
- case name: TermName => name
+ case name: SimpleTermName => name
case null =>
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
@@ -926,7 +930,7 @@ class ClassfileParser(
}
/** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
- def getExternalName(index: Int): TermName = {
+ def getExternalName(index: Int): SimpleTermName = {
if (index <= 0 || len <= index)
errorBadIndex(index)
@@ -943,9 +947,9 @@ class ClassfileParser(
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
val name = getExternalName(in.getChar(start + 1))
- if (name.isModuleClassName && (name ne nme.nothingRuntimeClass) && (name ne nme.nullRuntimeClass))
+ if (name.endsWith("$") && (name ne nme.nothingRuntimeClass) && (name ne nme.nullRuntimeClass))
// Null$ and Nothing$ ARE classes
- c = ctx.requiredModule(name.sourceModuleName)
+ c = ctx.requiredModule(name.dropRight(1))
else c = classNameToSymbol(name)
values(index) = c
}
@@ -955,7 +959,7 @@ class ClassfileParser(
/** Return the external name of the class info structure found at 'index'.
* Use 'getClassSymbol' if the class is sure to be a top-level class.
*/
- def getClassName(index: Int): TermName = {
+ def getClassName(index: Int): SimpleTermName = {
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
getExternalName(in.getChar(start + 1))
@@ -995,7 +999,7 @@ class ClassfileParser(
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
val name = getExternalName(in.getChar(start + 1))
- if (name(0) == ARRAY_TAG) {
+ if (name.firstPart(0) == ARRAY_TAG) {
c = sigToType(name)
values(index) = c
} else {
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
index 2c93819d5..28916a781 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
@@ -19,12 +19,12 @@ object DottyUnpickler {
class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler])
extends SectionUnpickler[TreeUnpickler]("ASTs") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
- new TreeUnpickler(reader, tastyName, posUnpickler)
+ def unpickle(reader: TastyReader, nameAtRef: NameTable) =
+ new TreeUnpickler(reader, nameAtRef, posUnpickler)
}
class PositionsSectionUnpickler extends SectionUnpickler[PositionUnpickler]("Positions") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table) =
+ def unpickle(reader: TastyReader, nameAtRef: NameTable) =
new PositionUnpickler(reader)
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
index 3ff7298ce..270d6be56 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/NameBuffer.scala
@@ -4,84 +4,83 @@ package core
package tasty
import collection.mutable
-import Names.{Name, chrs}
-import Decorators._, NameOps._
+import Names.{Name, chrs, SimpleTermName, DerivedTermName}
+import NameOps.NameDecorator
+import NameKinds._
+import Decorators._
import TastyBuffer._
import scala.io.Codec
-import TastyName._
import TastyFormat._
class NameBuffer extends TastyBuffer(10000) {
import NameBuffer._
- private val nameRefs = new mutable.LinkedHashMap[TastyName, NameRef]
+ private val nameRefs = new mutable.LinkedHashMap[Name, NameRef]
- def nameIndex(name: TastyName): NameRef = nameRefs.get(name) match {
- case Some(ref) =>
- ref
- case None =>
- val ref = NameRef(nameRefs.size)
- nameRefs(name) = ref
- ref
- }
def nameIndex(name: Name): NameRef = {
- val tname =
- if (name.isShadowedName) Shadowed(nameIndex(name.revertShadowed))
- else Simple(name.toTermName)
- nameIndex(tname)
- }
-
- def nameIndex(str: String): NameRef = nameIndex(str.toTermName)
-
- def fullNameIndex(name: Name): NameRef = {
- val pos = name.lastIndexOf('.')
- if (pos > 0)
- nameIndex(Qualified(fullNameIndex(name.take(pos)), nameIndex(name.drop(pos + 1))))
- else
- nameIndex(name)
+ val name1 = name.toTermName
+ nameRefs.get(name1) match {
+ case Some(ref) =>
+ ref
+ case None =>
+ name1 match {
+ case SignedName(original, Signature(params, result)) =>
+ nameIndex(original); nameIndex(result); params.foreach(nameIndex)
+ case AnyQualifiedName(prefix, name) =>
+ nameIndex(prefix); nameIndex(name)
+ case AnyUniqueName(original, separator, num) =>
+ nameIndex(separator.toTermName)
+ if (!original.isEmpty) nameIndex(original)
+ case DerivedTermName(original, _) =>
+ nameIndex(original)
+ case _ =>
+ }
+ val ref = NameRef(nameRefs.size)
+ nameRefs(name1) = ref
+ ref
+ }
}
private def withLength(op: => Unit, lengthWidth: Int = 1): Unit = {
val lengthAddr = currentAddr
for (i <- 0 until lengthWidth) writeByte(0)
op
- val length = currentAddr.index - lengthAddr.index - 1
+ val length = currentAddr.index - lengthAddr.index - lengthWidth
putNat(lengthAddr, length, lengthWidth)
}
- def writeNameRef(ref: NameRef) = writeNat(ref.index)
+ def writeNameRef(ref: NameRef): Unit = writeNat(ref.index)
+ def writeNameRef(name: Name): Unit = writeNameRef(nameRefs(name.toTermName))
- def pickleName(name: TastyName): Unit = name match {
- case Simple(name) =>
- val bytes =
- if (name.length == 0) new Array[Byte](0)
- else Codec.toUTF8(chrs, name.start, name.length)
- writeByte(UTF8)
- writeNat(bytes.length)
- writeBytes(bytes, bytes.length)
- case Qualified(qualified, selector) =>
- writeByte(QUALIFIED)
- withLength { writeNameRef(qualified); writeNameRef(selector) }
- case Signed(original, params, result) =>
- writeByte(SIGNED)
- withLength(
+ def pickleNameContents(name: Name): Unit = {
+ val tag = name.toTermName.info.kind.tag
+ writeByte(tag)
+ name.toTermName match {
+ case name: SimpleTermName =>
+ val bytes =
+ if (name.length == 0) new Array[Byte](0)
+ else Codec.toUTF8(chrs, name.start, name.length)
+ writeNat(bytes.length)
+ writeBytes(bytes, bytes.length)
+ case AnyQualifiedName(prefix, name) =>
+ withLength { writeNameRef(prefix); writeNameRef(name) }
+ case AnyUniqueName(original, separator, num) =>
+ withLength {
+ writeNameRef(separator.toTermName)
+ writeNat(num)
+ if (!original.isEmpty) writeNameRef(original)
+ }
+ case VariantName(original, sign) =>
+ withLength { writeNameRef(original); writeNat(sign + 1) }
+ case AnyNumberedName(original, num) =>
+ withLength { writeNameRef(original); writeNat(num) }
+ case SignedName(original, Signature(params, result)) =>
+ withLength(
{ writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) },
if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2)
- case Expanded(prefix, original) =>
- writeByte(EXPANDED)
- withLength { writeNameRef(prefix); writeNameRef(original) }
- case ModuleClass(module) =>
- writeByte(OBJECTCLASS)
- withLength { writeNameRef(module) }
- case SuperAccessor(accessed) =>
- writeByte(SUPERACCESSOR)
- withLength { writeNameRef(accessed) }
- case DefaultGetter(method, paramNumber) =>
- writeByte(DEFAULTGETTER)
- withLength { writeNameRef(method); writeNat(paramNumber) }
- case Shadowed(original) =>
- writeByte(SHADOWED)
- withLength { writeNameRef(original) }
+ case DerivedTermName(original, _) =>
+ withLength { writeNameRef(original) }
+ }
}
override def assemble(): Unit = {
@@ -89,7 +88,7 @@ class NameBuffer extends TastyBuffer(10000) {
for ((name, ref) <- nameRefs) {
assert(ref.index == i)
i += 1
- pickleName(name)
+ pickleNameContents(name)
}
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyBuffer.scala
index 13bc95028..40782f534 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyBuffer.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyBuffer.scala
@@ -26,6 +26,9 @@ object TastyBuffer {
* the value of 4 gives a maximal array size of 256M.
*/
final val AddrWidth = 4
+
+ /** An address referring to a serialized name */
+ case class NameRef(index: Int) extends AnyVal
}
import TastyBuffer._
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index 8b2255e94..f03e279c6 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -33,11 +33,11 @@ Macro-format:
QUALIFIED Length qualified_NameRef selector_NameRef
SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef*
EXPANDED Length original_NameRef
+ UNIQUE Length separator_NameRef num_Nat original_NameRef?
OBJECTCLASS Length module_NameRef
SUPERACCESSOR Length accessed_NameRef
DEFAULTGETTER Length method_NameRef paramNumber_Nat
SHADOWED Length original_NameRef
- MANGLED Length mangle_NameRef name_NameRef
...
NameRef = Nat // ordinal number of name in name table, starting from 1.
@@ -222,12 +222,30 @@ object TastyFormat {
final val UTF8 = 1
final val QUALIFIED = 2
- final val SIGNED = 3
+ final val FLATTENED = 3
final val EXPANDED = 4
- final val OBJECTCLASS = 5
- final val SUPERACCESSOR = 6
- final val DEFAULTGETTER = 7
- final val SHADOWED = 8
+ final val EXPANDPREFIX = 5
+ final val TRAITSETTER = 6
+ final val UNIQUE = 10
+ final val DEFAULTGETTER = 11
+ final val VARIANT = 12
+ final val OUTERSELECT = 13
+
+ final val SUPERACCESSOR = 20
+ final val PROTECTEDACCESSOR = 21
+ final val PROTECTEDSETTER = 22
+ final val INITIALIZER = 23
+ final val SHADOWED = 24
+ final val AVOIDCLASH = 30
+ final val DIRECT = 31
+ final val FIELD = 32
+ final val SETTER = 33
+ final val EXTMETH = 34
+ final val OBJECTVAR = 39
+ final val OBJECTCLASS = 40
+
+ final val SIGNED = 63
+ final val firstInternalTag = 64
// AST tags
@@ -411,11 +429,14 @@ object TastyFormat {
def nameTagToString(tag: Int): String = tag match {
case UTF8 => "UTF8"
case QUALIFIED => "QUALIFIED"
- case SIGNED => "SIGNED"
+ case FLATTENED => "FLATTENED"
case EXPANDED => "EXPANDED"
+ case SIGNED => "SIGNED"
case OBJECTCLASS => "OBJECTCLASS"
case SUPERACCESSOR => "SUPERACCESSOR"
case DEFAULTGETTER => "DEFAULTGETTER"
+ case SHADOWED => "SHADOWED"
+ case VARIANT => "VARIANT"
}
def astTagToString(tag: Int): String = tag match {
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala
deleted file mode 100644
index 26807115c..000000000
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyName.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package dotty.tools
-package dotc
-package core
-package tasty
-
-import core.Names.TermName
-import collection.mutable
-
-abstract class TastyName
-
-object TastyName {
-
- case class NameRef(index: Int) extends AnyVal
-
- case class Simple(name: TermName) extends TastyName
- case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName
- case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
- case class Expanded(prefix: NameRef, original: NameRef) extends TastyName
- case class ModuleClass(module: NameRef) extends TastyName
- case class SuperAccessor(accessed: NameRef) extends TastyName
- case class DefaultGetter(method: NameRef, num: Int) extends TastyName
- case class Shadowed(original: NameRef) extends TastyName
-
- class Table extends (NameRef => TastyName) {
- private val names = new mutable.ArrayBuffer[TastyName]
- def add(name: TastyName) = names += name
- def apply(ref: NameRef) = names(ref.index)
- def contents: Iterable[TastyName] = names
- }
-}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
index c844d522e..cc2e4dd58 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
@@ -9,10 +9,11 @@ import TastyBuffer._
import java.util.UUID
import core.Symbols.Symbol
import ast.tpd
+import Decorators._
class TastyPickler {
- private val sections = new mutable.ArrayBuffer[(TastyName.NameRef, TastyBuffer)]
+ private val sections = new mutable.ArrayBuffer[(NameRef, TastyBuffer)]
val uuid = UUID.randomUUID()
private val headerBuffer = {
@@ -28,7 +29,7 @@ class TastyPickler {
val nameBuffer = new NameBuffer
def newSection(name: String, buf: TastyBuffer) =
- sections += ((nameBuffer.nameIndex(name), buf))
+ sections += ((nameBuffer.nameIndex(name.toTermName), buf))
def assembleParts(): Array[Byte] = {
def lengthWithLength(buf: TastyBuffer) = {
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
index ce3722ff1..a5c870881 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
@@ -4,34 +4,24 @@ package tasty
import Contexts._, Decorators._
import printing.Texts._
-import TastyName._
+import Names.Name
import StdNames._
import TastyUnpickler._
-import TastyBuffer.Addr
+import TastyBuffer.{Addr, NameRef}
import util.Positions.{Position, offsetToInt}
import collection.mutable
class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
val unpickler = new TastyUnpickler(bytes)
- import unpickler.{tastyName, unpickle}
+ import unpickler.{nameAtRef, unpickle}
- def nameToString(name: TastyName): String = name match {
- case Simple(name) => name.toString
- case Qualified(qual, name) => nameRefToString(qual) + "." + nameRefToString(name)
- case Signed(original, params, result) =>
- i"${nameRefToString(original)}@${params.map(nameRefToString)}%,%:${nameRefToString(result)}"
- case Expanded(prefix, original) => s"$prefix${nme.EXPAND_SEPARATOR}$original"
- case ModuleClass(original) => nameRefToString(original) + "/MODULECLASS"
- case SuperAccessor(accessed) => nameRefToString(accessed) + "/SUPERACCESSOR"
- case DefaultGetter(meth, num) => nameRefToString(meth) + "/DEFAULTGETTER" + num
- case Shadowed(original) => nameRefToString(original) + "/SHADOWED"
- }
+ def nameToString(name: Name): String = name.debugString
- def nameRefToString(ref: NameRef): String = nameToString(tastyName(ref))
+ def nameRefToString(ref: NameRef): String = nameToString(nameAtRef(ref))
def printNames() =
- for ((name, idx) <- tastyName.contents.zipWithIndex) {
+ for ((name, idx) <- nameAtRef.contents.zipWithIndex) {
val index = "%4d: ".format(idx)
println(index + nameToString(name))
}
@@ -46,7 +36,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
class TreeSectionUnpickler extends SectionUnpickler[Unit]("ASTs") {
import TastyFormat._
- def unpickle(reader: TastyReader, tastyName: TastyName.Table): Unit = {
+ def unpickle(reader: TastyReader, tastyName: NameTable): Unit = {
import reader._
var indent = 0
def newLine() = {
@@ -116,7 +106,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
}
class PositionSectionUnpickler extends SectionUnpickler[Unit]("Positions") {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table): Unit = {
+ def unpickle(reader: TastyReader, tastyName: NameTable): Unit = {
print(s"${reader.endAddr.index - reader.currentAddr.index}")
val positions = new PositionUnpickler(reader).positions
println(s" position bytes:")
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyReader.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyReader.scala
index e583c4793..af5e78891 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyReader.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyReader.scala
@@ -4,7 +4,6 @@ package core
package tasty
import TastyBuffer._
-import TastyName.NameRef
import collection.mutable
/** A byte array buffer that can be filled with bytes or natural numbers in TASTY format,
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
index 8a1f58acd..37a3c2e76 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala
@@ -4,14 +4,23 @@ package tasty
import scala.collection.mutable
import TastyFormat._
-import Names.{Name, termName}
+import TastyBuffer.NameRef
+import Names.{Name, TermName, termName, EmptyTermName}
+import NameKinds._
import java.util.UUID
object TastyUnpickler {
class UnpickleException(msg: String) extends Exception(msg)
abstract class SectionUnpickler[R](val name: String) {
- def unpickle(reader: TastyReader, tastyName: TastyName.Table): R
+ def unpickle(reader: TastyReader, nameAtRef: NameTable): R
+ }
+
+ class NameTable extends (NameRef => TermName) {
+ private val names = new mutable.ArrayBuffer[TermName]
+ def add(name: TermName) = names += name
+ def apply(ref: NameRef) = names(ref.index)
+ def contents: Iterable[TermName] = names
}
}
@@ -23,18 +32,15 @@ class TastyUnpickler(reader: TastyReader) {
def this(bytes: Array[Byte]) = this(new TastyReader(bytes))
private val sectionReader = new mutable.HashMap[String, TastyReader]
- val tastyName = new TastyName.Table
+ val nameAtRef = new NameTable
- def check(cond: Boolean, msg: => String) =
+ private def check(cond: Boolean, msg: => String) =
if (!cond) throw new UnpickleException(msg)
- def readString(): String = {
- val TastyName.Simple(name) = tastyName(readNameRef())
- name.toString
- }
+ private def readName(): TermName = nameAtRef(readNameRef())
+ private def readString(): String = readName().toString
- def readName(): TastyName = {
- import TastyName._
+ private def readNameContents(): TermName = {
val tag = readByte()
val length = readNat()
val start = currentAddr
@@ -42,24 +48,30 @@ class TastyUnpickler(reader: TastyReader) {
val result = tag match {
case UTF8 =>
goto(end)
- Simple(termName(bytes, start.index, length))
- case QUALIFIED =>
- Qualified(readNameRef(), readNameRef())
- case SIGNED =>
- val original = readNameRef()
- val result = readNameRef()
- val params = until(end)(readNameRef())
- Signed(original, params, result)
- case EXPANDED =>
- Expanded(readNameRef(), readNameRef())
- case OBJECTCLASS =>
- ModuleClass(readNameRef())
- case SUPERACCESSOR =>
- SuperAccessor(readNameRef())
+ termName(bytes, start.index, length)
+ case QUALIFIED | FLATTENED | EXPANDED | EXPANDPREFIX =>
+ qualifiedNameKindOfTag(tag)(readName(), readName().asSimpleName)
+ case UNIQUE =>
+ val separator = readName().toString
+ val num = readNat()
+ val originals = until(end)(readName())
+ val original = if (originals.isEmpty) EmptyTermName else originals.head
+ uniqueNameKindOfSeparator(separator)(original, num)
case DEFAULTGETTER =>
- DefaultGetter(readNameRef(), readNat())
- case SHADOWED =>
- Shadowed(readNameRef())
+ DefaultGetterName(readName(), readNat())
+ case VARIANT =>
+ VariantName(readName(), readNat() - 1)
+ case OUTERSELECT =>
+ OuterSelectName(readName(), readNat())
+ case SIGNED =>
+ val original = readName()
+ val result = readName().toTypeName
+ val params = until(end)(readName().toTypeName)
+ var sig = Signature(params, result)
+ if (sig == Signature.NotAMethod) sig = Signature.NotAMethod
+ SignedName(original, sig)
+ case _ =>
+ simpleNameKindOfTag(tag)(readName())
}
assert(currentAddr == end, s"bad name $result $start $currentAddr $end")
result
@@ -77,10 +89,10 @@ class TastyUnpickler(reader: TastyReader) {
new UUID(readUncompressedLong(), readUncompressedLong())
}
- val uuid = readHeader()
+ private val uuid = readHeader()
locally {
- until(readEnd()) { tastyName.add(readName()) }
+ until(readEnd()) { nameAtRef.add(readNameContents()) }
while (!isAtEnd) {
val secName = readString()
val secEnd = readEnd()
@@ -91,5 +103,5 @@ class TastyUnpickler(reader: TastyReader) {
def unpickle[R](sec: SectionUnpickler[R]): Option[R] =
for (reader <- sectionReader.get(sec.name)) yield
- sec.unpickle(reader, tastyName)
+ sec.unpickle(reader, nameAtRef)
}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 902d01c21..5d33738c2 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -9,16 +9,18 @@ import TastyFormat._
import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._, StdNames.tpnme, NameOps._
import collection.mutable
import typer.Inliner
-import NameOps._
+import NameOps._, NameKinds._
import StdNames.nme
import TastyBuffer._
import TypeApplications._
+import transform.SymUtils._
+import config.Config
class TreePickler(pickler: TastyPickler) {
val buf = new TreeBuffer
pickler.newSection("ASTs", buf)
import buf._
- import pickler.nameBuffer.{nameIndex, fullNameIndex}
+ import pickler.nameBuffer.nameIndex
import ast.tpd._
private val symRefs = new mutable.HashMap[Symbol, Addr]
@@ -52,28 +54,8 @@ class TreePickler(pickler: TastyPickler) {
}
private def pickleName(name: Name): Unit = writeNat(nameIndex(name).index)
- private def pickleName(name: TastyName): Unit = writeNat(nameIndex(name).index)
- private def pickleNameAndSig(name: Name, sig: Signature) = {
- val Signature(params, result) = sig
- pickleName(TastyName.Signed(nameIndex(name), params.map(fullNameIndex), fullNameIndex(result)))
- }
-
- private def pickleName(sym: Symbol)(implicit ctx: Context): Unit = {
- def encodeSuper(name: Name): TastyName.NameRef =
- if (sym is Flags.SuperAccessor) {
- val SuperAccessorName(n) = name
- nameIndex(TastyName.SuperAccessor(nameIndex(n)))
- }
- else nameIndex(name)
- val nameRef =
- if (sym is Flags.ExpandedName)
- nameIndex(
- TastyName.Expanded(
- nameIndex(sym.name.expandedPrefix),
- encodeSuper(sym.name.unexpandedName)))
- else encodeSuper(sym.name)
- writeNat(nameRef.index)
- }
+ private def pickleNameAndSig(name: Name, sig: Signature) =
+ pickleName(SignedName(name.toTermName, sig))
private def pickleSymRef(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match {
case Some(label) =>
@@ -126,7 +108,7 @@ class TreePickler(pickler: TastyPickler) {
writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue))
case StringTag =>
writeByte(STRINGconst)
- writeNat(nameIndex(c.stringValue).index)
+ pickleName(c.stringValue.toTermName)
case NullTag =>
writeByte(NULLconst)
case ClazzTag =>
@@ -160,7 +142,7 @@ class TreePickler(pickler: TastyPickler) {
withLength { pickleType(tycon); args.foreach(pickleType(_)) }
case ConstantType(value) =>
pickleConstant(value)
- case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) =>
+ case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.isAliasPreferred =>
pickleType(tpe.superType)
case tpe: WithFixedSym =>
val sym = tpe.symbol
@@ -178,7 +160,7 @@ class TreePickler(pickler: TastyPickler) {
}
if (sym.is(Flags.Package)) {
writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg)
- pickleName(qualifiedName(sym))
+ pickleName(sym.fullName)
}
else if (sym is Flags.BindDefinedType) {
registerDef(sym)
@@ -278,7 +260,7 @@ class TreePickler(pickler: TastyPickler) {
def picklePackageRef(pkg: Symbol)(implicit ctx: Context): Unit = {
writeByte(TERMREFpkg)
- pickleName(qualifiedName(pkg))
+ pickleName(pkg.fullName)
}
def pickleMethodic(tag: Int, tpe: LambdaType)(implicit ctx: Context) = {
@@ -312,7 +294,7 @@ class TreePickler(pickler: TastyPickler) {
registerDef(sym)
writeByte(tag)
withLength {
- pickleName(sym)
+ pickleName(sym.name)
pickleParams
tpt match {
case templ: Template => pickleTree(tpt)
@@ -370,7 +352,7 @@ class TreePickler(pickler: TastyPickler) {
case Select(qual, name) =>
writeByte(if (name.isTypeName) SELECTtpt else SELECT)
val realName = tree.tpe match {
- case tp: NamedType if tp.name.isShadowedName => tp.name
+ case tp: NamedType if tp.name.is(ShadowedName) => tp.name
case _ => name
}
val sig = tree.tpe.signature
@@ -575,10 +557,6 @@ class TreePickler(pickler: TastyPickler) {
pickleName(id.name)
}
- def qualifiedName(sym: Symbol)(implicit ctx: Context): TastyName =
- if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName)
- else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name))
-
def pickleModifiers(sym: Symbol)(implicit ctx: Context): Unit = {
import Flags._
val flags = sym.flags
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index a186d1ce4..2908c541e 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -5,6 +5,7 @@ package tasty
import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._
import StdNames._, Denotations._, Flags._, Constants._, Annotations._
+import NameKinds._
import util.Positions._
import ast.{tpd, Trees, untpd}
import Trees._
@@ -15,15 +16,15 @@ import scala.collection.mutable.ListBuffer
import scala.collection.{ mutable, immutable }
import config.Printers.pickling
import typer.Checking
+import config.Config
/** Unpickler for typed trees
* @param reader the reader from which to unpickle
* @param tastyName the nametable
* @param posUNpicklerOpt the unpickler for positions, if it exists
*/
-class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpicklerOpt: Option[PositionUnpickler]) {
+class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpicklerOpt: Option[PositionUnpickler]) {
import TastyFormat._
- import TastyName._
import TreeUnpickler._
import tpd._
@@ -74,20 +75,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
new TreeReader(reader).readTopLevel()(ctx.addMode(Mode.AllowDependentFunctions))
}
- def toTermName(tname: TastyName): TermName = tname match {
- case Simple(name) => name
- case Qualified(qual, name) => toTermName(qual) ++ "." ++ toTermName(name)
- case Signed(original, params, result) => toTermName(original)
- case Shadowed(original) => toTermName(original).shadowedName
- case Expanded(prefix, original) => toTermName(original).expandedName(toTermName(prefix))
- case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
- case SuperAccessor(accessed) => toTermName(accessed).superName
- case DefaultGetter(meth, num) => ???
- }
-
- def toTermName(ref: NameRef): TermName = toTermName(tastyName(ref))
- def toTypeName(ref: NameRef): TypeName = toTermName(ref).toTypeName
-
class Completer(owner: Symbol, reader: TastyReader) extends LazyType {
import reader._
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
@@ -165,17 +152,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
else tag
}
- def readName(): TermName = toTermName(readNameRef())
-
- def readNameSplitSig()(implicit ctx: Context): Any /* TermName | (TermName, Signature) */ =
- tastyName(readNameRef()) match {
- case Signed(original, params, result) =>
- var sig = Signature(params map toTypeName, toTypeName(result))
- if (sig == Signature.NotAMethod) sig = Signature.NotAMethod
- (toTermName(original), sig)
- case name =>
- toTermName(name)
- }
+ def readName(): TermName = nameAtRef(readNameRef())
// ------ Reading types -----------------------------------------------------
@@ -305,9 +282,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val name = readName().toTypeName
TypeRef(readType(), name)
case TERMREF =>
- readNameSplitSig() match {
- case name: TermName => TermRef.all(readType(), name)
- case (name: TermName, sig: Signature) => TermRef.withSig(readType(), name, sig)
+ readName() match {
+ case SignedName(name, sig) => TermRef.withSig(readType(), name, sig)
+ case name => TermRef.all(readType(), name)
}
case THIS =>
ThisType.raw(readType().asInstanceOf[TypeRef])
@@ -438,9 +415,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val start = currentAddr
val tag = readByte()
val end = readEnd()
- val rawName = tastyName(readNameRef())
- var name: Name = toTermName(rawName)
+ var name: Name = readName()
if (tag == TYPEDEF || tag == TYPEPARAM) name = name.toTypeName
+ val mname = name.mangled
skipParams()
val ttag = nextUnsharedTag
val isAbsType = isAbstractType(ttag)
@@ -451,19 +428,15 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val rhsIsEmpty = noRhs(end)
if (!rhsIsEmpty) skipTree()
val (givenFlags, annots, privateWithin) = readModifiers(end)
- def nameFlags(tname: TastyName): FlagSet = tname match {
- case TastyName.Expanded(_, original) => ExpandedName | nameFlags(tastyName(original))
- case TastyName.SuperAccessor(_) => Flags.SuperAccessor
- case _ => EmptyFlags
- }
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
- val flags = normalizeFlags(tag, givenFlags | nameFlags(rawName), name, isAbsType, rhsIsEmpty)
+ val flags = normalizeFlags(tag, givenFlags, name, isAbsType, rhsIsEmpty)
def adjustIfModule(completer: LazyType) =
if (flags is Module) ctx.adjustModuleCompleter(completer, name) else completer
val sym =
- roots.find(root => (root.owner eq ctx.owner) && root.name == name) match {
+ roots.find(root => (root.owner eq ctx.owner) && root.name.mangled == mname) match {
case Some(rootd) =>
pickling.println(i"overwriting ${rootd.symbol} # ${rootd.hashCode}")
+ rootd.name = name
rootd.info = adjustIfModule(
new Completer(ctx.owner, subReader(start, end)) with SymbolLoaders.SecondCompleter)
rootd.flags = flags &~ Touched // allow one more completion
@@ -886,7 +859,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val localCtx =
if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx
val qual = readTerm()(localCtx)
- val unshadowed = if (name.isShadowedName) name.revertShadowed else name
+ val unshadowed = name.exclude(ShadowedName)
untpd.Select(qual, unshadowed).withType(tpf(qual.tpe.widenIfUnstable))
}
@@ -905,9 +878,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
case SELECT =>
def readRest(name: Name, sig: Signature) =
completeSelect(name, TermRef.withSig(_, name.asTermName, sig))
- readNameSplitSig match {
- case name: Name => readRest(name, Signature.NotAMethod)
- case (name: Name, sig: Signature) => readRest(name, sig)
+ readName() match {
+ case SignedName(name, sig) => readRest(name, sig)
+ case name => readRest(name, Signature.NotAMethod)
}
case SELECTtpt =>
val name = readName().toTypeName
diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala
index 6ee9f1f9e..2a789dca9 100644
--- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala
+++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala
@@ -224,12 +224,12 @@ object PickleBuffer {
DEFAULTPARAM -> (DefaultParameterized, Trait),
BRIDGE -> Bridge,
ACCESSOR -> Accessor,
- SUPERACCESSOR -> SuperAccessor,
+ SUPERACCESSOR -> Scala2SuperAccessor,
PARAMACCESSOR -> ParamAccessor,
MODULEVAR -> Scala2ModuleVar,
LAZY -> Lazy,
MIXEDIN -> (MixedIn, Scala2Existential),
- EXPANDEDNAME -> ExpandedName,
+ EXPANDEDNAME -> Scala2ExpandedName,
IMPLCLASS -> (Scala2PreSuper, ImplClass),
SPECIALIZED -> Specialized,
VBRIDGE -> VBridge,
diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index cf99bb022..1db3ebcb0 100644
--- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -9,6 +9,7 @@ import java.lang.Double.longBitsToDouble
import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._
import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._
+import NameKinds.{Scala2MethodNameKinds, SuperAccessorName, ExpandedName}
import dotty.tools.dotc.typer.ProtoTypes.{FunProtoTyped, FunProto}
import util.Positions._
import dotty.tools.dotc.ast.{tpd, Trees, untpd}, ast.tpd._
@@ -18,6 +19,7 @@ import printing.Printer
import io.AbstractFile
import util.common._
import typer.Checking.checkNonCyclic
+import transform.SymUtils._
import PickleBuffer._
import PickleFormat._
import Decorators._
@@ -361,7 +363,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
}
def slowSearch(name: Name): Symbol =
- owner.info.decls.find(_.name == name).getOrElse(NoSymbol)
+ owner.info.decls.find(_.name == name)
def nestedObjectSymbol: Symbol = {
// If the owner is overloaded (i.e. a method), it's not possible to select the
@@ -420,10 +422,10 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
// symbols that were pickled with Pickler.writeSymInfo
val nameref = readNat()
- val name0 = at(nameref, readName)
+ var name = at(nameref, readName)
val owner = readSymbolRef()
- var flags = unpickleScalaFlags(readLongNat(), name0.isTypeName)
+ var flags = unpickleScalaFlags(readLongNat(), name.isTypeName)
if (flags is DefaultParameter) {
// DefaultParameterized flag now on method, not parameter
//assert(flags is Param, s"$name0 in $owner")
@@ -431,18 +433,33 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
owner.setFlag(DefaultParameterized)
}
- val name1 = name0.adjustIfModuleClass(flags)
- val name = if (name1 == nme.TRAIT_CONSTRUCTOR) nme.CONSTRUCTOR else name1
+ name = name.adjustIfModuleClass(flags)
+ if (flags is Method) {
+ name =
+ if (name == nme.TRAIT_CONSTRUCTOR) nme.CONSTRUCTOR
+ else name.asTermName.unmangle(Scala2MethodNameKinds)
+ }
+ if ((flags is Scala2ExpandedName) && name.isSimple) {
+ name = name.unmangle(ExpandedName)
+ flags = flags &~ Scala2ExpandedName
+ }
+ if (flags is Scala2SuperAccessor) {
+ name = name.asTermName.unmangle(SuperAccessorName)
+ flags = flags &~ Scala2SuperAccessor
+ }
- def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass)
- def isModuleClassRoot = (name == moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module)
- def isModuleRoot = (name == moduleClassRoot.name.sourceModuleName) && (owner == moduleClassRoot.owner) && (flags is Module)
+ val mname = name.mangled
+ def nameMatches(rootName: Name) = mname == rootName.mangled
+ def isClassRoot = nameMatches(classRoot.name) && (owner == classRoot.owner) && !(flags is ModuleClass)
+ def isModuleClassRoot = nameMatches(moduleClassRoot.name) && (owner == moduleClassRoot.owner) && (flags is Module)
+ def isModuleRoot = nameMatches(moduleClassRoot.name.sourceModuleName) && (owner == moduleClassRoot.owner) && (flags is Module)
//if (isClassRoot) println(s"classRoot of $classRoot found at $readIndex, flags = $flags") // !!! DEBUG
//if (isModuleRoot) println(s"moduleRoot of $moduleRoot found at $readIndex, flags = $flags") // !!! DEBUG
//if (isModuleClassRoot) println(s"moduleClassRoot of $moduleClassRoot found at $readIndex, flags = $flags") // !!! DEBUG
def completeRoot(denot: ClassDenotation, completer: LazyType): Symbol = {
+ denot.name = name
denot.setFlag(flags)
denot.resetFlag(Touched) // allow one more completion
denot.info = completer
@@ -470,7 +487,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
var flags1 = flags
if (flags is TypeParam) {
name1 = name1.expandedName(owner)
- flags1 |= owner.typeParamCreationFlags | ExpandedName
+ flags1 |= owner.typeParamCreationFlags
}
ctx.newSymbol(owner, name1, flags1, localMemberUnpickler, coord = start)
case CLASSsym =>
@@ -546,9 +563,9 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
else tp1
if (denot.isConstructor) addConstructorTypeParams(denot)
if (atEnd) {
- assert(!(denot is SuperAccessor), denot)
+ assert(!denot.isSuperAccessor, denot)
} else {
- assert(denot is (SuperAccessor | ParamAccessor), denot)
+ assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
def disambiguate(alt: Symbol) = { // !!! DEBUG
ctx.debugTraceIndented(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
denot.info matches denot.owner.thisType.memberInfo(alt)
@@ -1022,7 +1039,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
val rhs = readTreeRef()
val params = until(end, readIdentRef)
val ldef = DefDef(symbol.asTerm, rhs)
- def isCaseLabel(sym: Symbol) = sym.name.startsWith(nme.CASEkw)
+ def isCaseLabel(sym: Symbol) = sym.name.startsWith(nme.CASEkw.toString)
if (isCaseLabel(symbol)) ldef
else Block(ldef :: Nil, Apply(Ident(symbol.termRef), Nil))