From 67105e3f36378d652aa919e23aa3b2678004bdc6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Mar 2017 11:18:36 +0100 Subject: Start to use structured ModuleNames Subject to flags Config.semanticNames. --- compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 79f8a6a45..40e561d3f 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -39,7 +39,7 @@ class SymbolLoaders { def enterClass( owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: Context): Symbol = { - val cls = ctx.newClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull) + val cls = ctx.newClassSymbol(owner, name.toTypeName.unmangleClassName, flags, completer, assocFile = completer.sourceFileOrNull) enterNew(owner, cls, completer, scope) } @@ -152,7 +152,7 @@ class SymbolLoaders { def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = { assert(root is PackageClass, root) - def maybeModuleClass(classRep: ClassPath#ClassRep) = classRep.name.last == '$' + 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) @@ -162,7 +162,8 @@ class SymbolLoaders { if (!maybeModuleClass(classRep)) initializeFromClassPath(root.symbol, classRep) for (classRep <- classpath.classes) - if (maybeModuleClass(classRep) && !root.unforcedDecls.lookup(classRep.name.toTypeName).exists) + if (maybeModuleClass(classRep) && + !root.unforcedDecls.lookup(classRep.name.toTypeName.unmangleClassName).exists) initializeFromClassPath(root.symbol, classRep) } if (!root.isEmptyPackage) @@ -247,8 +248,11 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { (module, _) => new NoCompleter() withDecls newScope withSourceModule (_ => module)) .moduleClass.denot.asClass } + val res = if (rootDenot is ModuleClass) (linkedDenot, rootDenot) else (rootDenot, linkedDenot) + println(s"root denots of ${rootDenot.name.debugString} = ${res._1.name.debugString}, ${res._2.name.debugString} / ${rootDenot is ModuleClass}") + res } override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = -- cgit v1.2.3 From e1181d9f5b3fc56baafbe859d3d3441dfdb113a1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Mar 2017 11:30:26 +0100 Subject: Fix typos and redundant statements in previous commits --- compiler/src/dotty/tools/dotc/config/Config.scala | 2 +- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 3 +-- compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index a225b3019..65e9d3856 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -10,7 +10,7 @@ object Config { final val checkCacheMembersNamed = false - final val semanticNames = true + final val semanticNames = false /** When updating a constraint bound, check that the constrained parameter * does not appear at the top-level of either of its bounds. diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 150bb1584..0483e0ca1 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -433,9 +433,8 @@ object SymDenotations { val fn2 = fullNameSeparated(separator, true) assert(fn1.toString == fn2.toString, s"mismatch, was: $fn1, sem: $fn2") fn2 - } + } else fullNameSeparated(separator, false) - } /** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */ def flatName(implicit ctx: Context): Name = fullNameSeparated("") diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 40e561d3f..0ea643e0d 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -248,11 +248,8 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { (module, _) => new NoCompleter() withDecls newScope withSourceModule (_ => module)) .moduleClass.denot.asClass } - val res = if (rootDenot is ModuleClass) (linkedDenot, rootDenot) else (rootDenot, linkedDenot) - println(s"root denots of ${rootDenot.name.debugString} = ${res._1.name.debugString}, ${res._2.name.debugString} / ${rootDenot is ModuleClass}") - res } override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = -- cgit v1.2.3 From e4780e574f9613346e6908f7947f40a58327e376 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 1 Apr 2017 17:21:39 +0200 Subject: Keep package member names mangled Once we start using unencoded operators internally, we will face the problem that one cannot decode realiably a class file filename. We therefore turn things around, keeping members of package scopes in mangled and encoded form. This is compensated by (1) mangling names for lookup of such members and (2) when unpickling from Scala 2 info or Tasty, comparing mangled names when matching a read class or module object against a root. --- compiler/src/dotty/tools/dotc/core/Denotations.scala | 2 +- compiler/src/dotty/tools/dotc/core/Scopes.scala | 10 +++++++++- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 13 ++++++++++--- compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala | 4 ++-- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 4 +++- .../tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 9 ++++++--- 6 files changed, 31 insertions(+), 11 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index fca77fc06..fd42bde36 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -1207,7 +1207,7 @@ object Denotations { } recurSimple(path.length, wrap) } - recur(path.unmangleClassName) + recur(path) } /** If we are looking for a non-existing term name in a package, diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 6090079e5..032442421 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -394,6 +394,14 @@ object Scopes { } } + class PackageScope extends MutableScope { + override final def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry = + super.newScopeEntry(name.toSimpleName, sym) + + override final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = + super.lookupEntry(name.toSimpleName) + } + /** Create a new scope */ def newScope: MutableScope = new MutableScope() @@ -408,7 +416,7 @@ object Scopes { } /** Create new scope for the members of package `pkg` */ - def newPackageScope(pkgClass: Symbol): MutableScope = newScope + def newPackageScope(pkgClass: Symbol): MutableScope = new PackageScope() /** Transform scope of members of `owner` using operation `op` * This is overridden by the reflective compiler to avoid creating new scopes for packages diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 1c7206533..b8cd7bb18 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -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 @@ -1208,12 +1215,12 @@ 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 diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 0ea643e0d..75deb8bb5 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -39,7 +39,7 @@ class SymbolLoaders { def enterClass( owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: Context): Symbol = { - val cls = ctx.newClassSymbol(owner, name.toTypeName.unmangleClassName, flags, completer, assocFile = completer.sourceFileOrNull) + val cls = ctx.newClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull) enterNew(owner, cls, completer, scope) } @@ -163,7 +163,7 @@ class SymbolLoaders { initializeFromClassPath(root.symbol, classRep) for (classRep <- classpath.classes) if (maybeModuleClass(classRep) && - !root.unforcedDecls.lookup(classRep.name.toTypeName.unmangleClassName).exists) + !root.unforcedDecls.lookup(classRep.name.toTypeName).exists) initializeFromClassPath(root.symbol, classRep) } if (!root.isEmptyPackage) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 96bf29a70..81519727c 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -416,6 +416,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val tag = readByte() val end = readEnd() var name: Name = readName() + val sname = name.toSimpleName if (tag == TYPEDEF || tag == TYPEPARAM) name = name.toTypeName skipParams() val ttag = nextUnsharedTag @@ -432,9 +433,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi 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.toSimpleName == sname && root.isType == name.isTypeName) 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 diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 5871ec46c..1e8fbe54b 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -448,15 +448,18 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas 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 sname = name.toSimpleName + def nameMatches(rootName: Name) = sname == rootName.toSimpleName + 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 -- cgit v1.2.3 From bd992dd3158f192fd391605a6b51e1c23e09171d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 1 Apr 2017 19:28:42 +0200 Subject: Fix and activate package scopes Prevviously they were actually unused. --- .../src/dotty/tools/dotc/core/Definitions.scala | 2 +- compiler/src/dotty/tools/dotc/core/Scopes.scala | 42 ++++++++++++++++------ compiler/src/dotty/tools/dotc/core/StdNames.scala | 1 - .../src/dotty/tools/dotc/core/SymbolLoaders.scala | 2 +- 4 files changed, 33 insertions(+), 14 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index d4d652d6b..8925724fd 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -938,7 +938,7 @@ class Definitions { private def makeScalaSpecial()(implicit ctx: Context) = { val oldInfo = ScalaPackageClass.classInfo val oldDecls = oldInfo.decls - val newDecls = new MutableScope(oldDecls) { + val newDecls = new PackageScope(oldDecls) { override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { val res = super.lookupEntry(name) if (res == null && name.isTypeName && name.isSyntheticFunction) diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 023fe35c5..9e6be7651 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -144,6 +144,11 @@ object Scopes { final def toText(printer: Printer): Text = printer.toText(this) def checkConsistent()(implicit ctx: Context) = () + + /** Hook for transforming a name before it is used in a lookup or creation. + * Used to mangle names in package scopes. + */ + protected def normalize(name: Name): Name = name } /** A subclass of Scope that defines methods for entering and @@ -155,6 +160,7 @@ 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. @@ -178,6 +184,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 +195,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) @@ -198,7 +206,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) - val e = new ScopeEntry(name, sym, this) + val e = new ScopeEntry(normalize(name), sym, this) e.prev = lastEntry lastEntry = e if (hashTable ne null) enterInHash(e) @@ -234,7 +242,7 @@ object Scopes { enter(sym) } - private def ensureCapacity(tableSize: Int)(implicit ctx: Context): Unit = + protected def ensureCapacity(tableSize: Int)(implicit ctx: Context): Unit = if (size >= tableSize * FillFactor) createHash(tableSize * 2) private def createHash(tableSize: Int)(implicit ctx: Context): Unit = @@ -310,15 +318,16 @@ object Scopes { /** Lookup a symbol entry matching given name. */ override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { + val normalized = normalize(name) var e: ScopeEntry = null if (hashTable ne null) { - e = hashTable(name.hashCode & (hashTable.length - 1)) - while ((e ne null) && e.name != name) { + e = hashTable(normalized.hashCode & (hashTable.length - 1)) + while ((e ne null) && e.name != normalized) { e = e.tail } } else { e = lastEntry - while ((e ne null) && e.name != name) { + while ((e ne null) && e.name != normalized) { e = e.prev } } @@ -394,12 +403,23 @@ object Scopes { } } - class PackageScope extends MutableScope { - override final def newScopeEntry(name: Name, sym: Symbol)(implicit ctx: Context): ScopeEntry = - super.newScopeEntry(name.mangled, sym) + /** The scope of a package. This is different from a normal scope + * in that names of scope entries are kept in mangled form. + */ + class PackageScope protected[Scopes](initElems: ScopeEntry, initSize: Int, nestingLevel: Int) + extends MutableScope(initElems, initSize, nestingLevel) { + + /** Scope shares elements with `base` */ + 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. + } + + def this() = this(null, 0, 0) + + override def newScopeLikeThis() = new PackageScope() - override final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = - super.lookupEntry(name.mangled) + override protected def normalize(name: Name) = name.mangled } /** Create a new scope */ diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 815940eb0..9272c32ed 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -454,7 +454,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" diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 75deb8bb5..ad0d02fa8 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -148,7 +148,7 @@ class SymbolLoaders { override def sourceModule(implicit ctx: Context) = _sourceModule def description = "package loader " + classpath.name - private[core] val currentDecls: MutableScope = newScope + private[core] val currentDecls: MutableScope = new PackageScope() def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = { assert(root is PackageClass, root) -- cgit v1.2.3 From 264211f6b7129923c01c2e3c402b157685d64b1f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 2 Apr 2017 11:43:03 +0200 Subject: Scope refactoring Since we now have separate package-scopes, it's easier to have them take into account the special role played by the scala package. So we can drop the funky logic of `makeScalaSpecial`. --- .../src/dotty/tools/dotc/core/Definitions.scala | 21 +---------- compiler/src/dotty/tools/dotc/core/Scopes.scala | 44 ++++------------------ .../src/dotty/tools/dotc/core/SymbolLoaders.scala | 22 +++++++++++ 3 files changed, 31 insertions(+), 56 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 8925724fd..c7b1538c7 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -108,7 +108,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 @@ -932,23 +932,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 PackageScope(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, @@ -976,8 +959,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/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 9e6be7651..c256e7071 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 @@ -144,11 +144,6 @@ object Scopes { final def toText(printer: Printer): Text = printer.toText(this) def checkConsistent()(implicit ctx: Context) = () - - /** Hook for transforming a name before it is used in a lookup or creation. - * Used to mangle names in package scopes. - */ - protected def normalize(name: Name): Name = name } /** A subclass of Scope that defines methods for entering and @@ -163,7 +158,7 @@ object Scopes { /** 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) @@ -205,8 +200,8 @@ 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) - val e = new ScopeEntry(normalize(name), sym, this) + ensureCapacity(if (hashTable ne null) hashTable.length else MinHashedScopeSize) + val e = new ScopeEntry(name, sym, this) e.prev = lastEntry lastEntry = e if (hashTable ne null) enterInHash(e) @@ -242,7 +237,7 @@ object Scopes { enter(sym) } - protected def ensureCapacity(tableSize: Int)(implicit ctx: Context): Unit = + private def ensureCapacity(tableSize: Int)(implicit ctx: Context): Unit = if (size >= tableSize * FillFactor) createHash(tableSize * 2) private def createHash(tableSize: Int)(implicit ctx: Context): Unit = @@ -318,16 +313,15 @@ object Scopes { /** Lookup a symbol entry matching given name. */ override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { - val normalized = normalize(name) var e: ScopeEntry = null if (hashTable ne null) { - e = hashTable(normalized.hashCode & (hashTable.length - 1)) - while ((e ne null) && e.name != normalized) { + e = hashTable(name.hashCode & (hashTable.length - 1)) + while ((e ne null) && e.name != name) { e = e.tail } } else { e = lastEntry - while ((e ne null) && e.name != normalized) { + while ((e ne null) && e.name != name) { e = e.prev } } @@ -403,25 +397,6 @@ object Scopes { } } - /** The scope of a package. This is different from a normal scope - * in that names of scope entries are kept in mangled form. - */ - class PackageScope protected[Scopes](initElems: ScopeEntry, initSize: Int, nestingLevel: Int) - extends MutableScope(initElems, initSize, nestingLevel) { - - /** Scope shares elements with `base` */ - 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. - } - - def this() = this(null, 0, 0) - - override def newScopeLikeThis() = new PackageScope() - - override protected def normalize(name: Name) = name.mangled - } - /** Create a new scope */ def newScope: MutableScope = new MutableScope() @@ -435,9 +410,6 @@ object Scopes { scope } - /** Create new scope for the members of package `pkg` */ - def newPackageScope(pkgClass: Symbol): MutableScope = new PackageScope() - /** Transform scope of members of `owner` using operation `op` * This is overridden by the reflective compiler to avoid creating new scopes for packages */ diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index ad0d02fa8..168908ced 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -148,6 +148,28 @@ class SymbolLoaders { override def sourceModule(implicit ctx: Context) = _sourceModule def description = "package loader " + classpath.name + /** 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 e = super.lookupEntry(name.mangled) + if (e == null && + _sourceModule.name == nme.scala_ && _sourceModule == defn.ScalaPackageVal && + name.isTypeName && name.isSyntheticFunction) + newScopeEntry(defn.newFunctionNTrait(name.asTypeName)) + else e + } + + override def newScopeLikeThis() = new PackageScope + } + private[core] val currentDecls: MutableScope = new PackageScope() def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = { -- cgit v1.2.3 From d0efabf2817468c248db8a2a6d5a6c0b58747867 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 2 Apr 2017 19:11:34 +0200 Subject: Lazy entering of names with internal $'s in package scopes Names with internal $'s are entered in package scopes only if - we look for a name with internal $'s. - we want to know all the members of a package scope This optimization seems to be fairly effective. The typical range of package scopes that need $-names is between 0 and 20%. The optimization seems to improve execution time of all unit tests by about 3%. Also. drop the inheritance from Iterable to Scope. The reason is that we now need a context parameter for toList and other Iterable operations which makes them impossible to fit into the Iterable framework. --- .../tools/backend/jvm/DottyBackendInterface.scala | 2 +- compiler/src/dotty/tools/dotc/core/Contexts.scala | 2 +- compiler/src/dotty/tools/dotc/core/Scopes.scala | 59 ++++++++++++------- .../src/dotty/tools/dotc/core/SymDenotations.scala | 21 +++---- .../src/dotty/tools/dotc/core/SymbolLoaders.scala | 68 ++++++++++++++++------ .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../tools/dotc/reporting/diagnostic/messages.scala | 2 +- compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala | 4 +- .../dotty/tools/dotc/transform/ExplicitOuter.scala | 2 +- .../tools/dotc/transform/PrimitiveForwarders.scala | 2 +- .../dotty/tools/dotc/transform/TreeChecker.scala | 4 +- .../dotty/tools/dotc/transform/ValueClasses.scala | 7 +-- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 4 +- 13 files changed, 113 insertions(+), 66 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala') diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index a300857ec..8e054c9c2 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -794,7 +794,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def memberInfo(s: Symbol): Type = tp.memberInfo(s) - def decls: List[Symbol] = tp.decls.map(_.symbol).toList + def decls: List[Symbol] = tp.decls.toList def members: List[Symbol] = tp.memberDenots(takeAllFilter, (name, buf) => buf ++= tp.member(name).alternatives).map(_.symbol).toList diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index c80ad876a..b299de434 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -294,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/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index c256e7071..205798474 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -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 @@ -341,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) { @@ -354,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) { @@ -368,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) @@ -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/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index b8cd7bb18..5a277cacb 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -930,14 +930,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) @@ -1777,8 +1778,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, diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 168908ced..e4d2d446f 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -14,6 +14,7 @@ import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util import StdNames._, NameOps._ import Decorators.{PreNamedString, StringInterpolators} import classfile.ClassfileParser +import util.Stats import scala.util.control.NonFatal object SymbolLoaders { @@ -148,46 +149,79 @@ class SymbolLoaders { override def sourceModule(implicit ctx: Context) = _sourceModule def description = "package loader " + classpath.name + 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. + * 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 e = super.lookupEntry(name.mangled) - if (e == null && - _sourceModule.name == nme.scala_ && _sourceModule == defn.ScalaPackageVal && - name.isTypeName && name.isSyntheticFunction) + 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: ClassPath#ClassRep) = { + val idx = classRep.name.indexOf('$') + idx >= 0 && idx < classRep.name.length - 1 + } + + def maybeModuleClass(classRep: ClassPath#ClassRep) = classRep.name.last == '$' + + private def enterClasses(root: SymDenotation, flat: Boolean)(implicit ctx: Context) = { + def isAbsent(classRep: ClassPath#ClassRep) = + !root.unforcedDecls.lookup(classRep.name.toTypeName).exists + + if (!root.isRoot) { + for (classRep <- classpath.classes) + 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 <- classpath.classes) + 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) + enterFlatClasses = Some { ctx => + enterFlatClasses = None + enterClasses(root, flat = true)(ctx) } + enterClasses(root, flat = false) if (!root.isEmptyPackage) for (pkg <- classpath.packages) enterPackage(root.symbol, pkg) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index f3bb99b27..1db3ebcb0 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -363,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 diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 87837fd82..20cd08426 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -237,7 +237,7 @@ object messages { val msg = { import core.Flags._ val maxDist = 3 - val decls = site.decls.flatMap { sym => + val decls = site.decls.toList.flatMap { sym => if (sym.flagsUNSAFE.is(Synthetic | PrivateOrLocal) || sym.isConstructor) Nil else List((sym.name.show, sym)) } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index db19bf6b6..5488d1979 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -214,7 +214,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // and can therefore be ignored. def alwaysPresent(s: Symbol) = s.isCompanionMethod || (csym.is(ModuleClass) && s.isConstructor) - val decls = cinfo.decls.filterNot(alwaysPresent).toList + val decls = cinfo.decls.filter(!alwaysPresent(_)).toList val apiDecls = apiDefinitions(decls) val declSet = decls.toSet @@ -224,7 +224,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // We cannot filter out `LegacyApp` because it contains the main method, // see the comment about main class discovery in `computeType`. .filter(bc => !bc.is(Scala2x) || bc.eq(LegacyAppClass)) - .flatMap(_.classInfo.decls.filterNot(s => s.is(Private) || declSet.contains(s))) + .flatMap(_.classInfo.decls.filter(s => !(s.is(Private) || declSet.contains(s)))) // Inherited members need to be computed lazily because a class might contain // itself as an inherited member, like in `class A { class B extends A }`, // this works because of `classLikeCache` diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index c302aa61b..7ad7fb348 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -217,7 +217,7 @@ object ExplicitOuter { def outerAccessor(cls: ClassSymbol)(implicit ctx: Context): Symbol = if (cls.isStatic) NoSymbol // fast return to avoid scanning package decls else cls.info.member(outerAccName(cls)).suchThat(_ is OuterAccessor).symbol orElse - cls.info.decls.find(_ is OuterAccessor).getOrElse(NoSymbol) + cls.info.decls.find(_ is OuterAccessor) /** Class has an outer accessor. Can be called only after phase ExplicitOuter. */ private def hasOuter(cls: ClassSymbol)(implicit ctx: Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala index d752ce8e7..7c51ba593 100644 --- a/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala +++ b/compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala @@ -43,7 +43,7 @@ class PrimitiveForwarders extends MiniPhaseTransform with IdentityDenotTransform import ops._ def methodPrimitiveForwarders: List[Tree] = - for (meth <- mixins.flatMap(_.info.decls.flatMap(needsPrimitiveForwarderTo)).distinct) + for (meth <- mixins.flatMap(_.info.decls.toList.flatMap(needsPrimitiveForwarderTo)).distinct) yield polyDefDef(implementation(meth.asTerm), forwarder(meth)) cpy.Template(impl)(body = methodPrimitiveForwarders ::: impl.body) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 44c26ecd9..eb7773ef3 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -391,11 +391,11 @@ class TreeChecker extends Phase with SymTransformer { !x.isCompanionMethod && !x.isValueClassConvertMethod - val symbolsNotDefined = cls.classInfo.decls.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol + val symbolsNotDefined = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol assert(symbolsNotDefined.isEmpty, i" $cls tree does not define methods: ${symbolsNotDefined.toList}%, %\n" + - i"expected: ${cls.classInfo.decls.toSet.filter(isNonMagicalMethod).toList}%, %\n" + + i"expected: ${cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod)}%, %\n" + i"defined: ${impl.body.map(_.symbol)}%, %") super.typedClassDef(cdef, cls) diff --git a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala index b398c2767..00d491486 100644 --- a/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala +++ b/compiler/src/dotty/tools/dotc/transform/ValueClasses.scala @@ -28,13 +28,10 @@ object ValueClasses { !d.isSuperAccessor && !d.is(Macro) - /** The member that of a derived value class that unboxes it. */ + /** The member of a derived value class that unboxes it. */ def valueClassUnbox(d: ClassDenotation)(implicit ctx: Context): Symbol = // (info.decl(nme.unbox)).orElse(...) uncomment once we accept unbox methods - d.classInfo.decls - .find(d => d.isTerm && d.symbol.is(ParamAccessor)) - .map(_.symbol) - .getOrElse(NoSymbol) + d.classInfo.decls.find(_.is(TermParamAccessor)) /** For a value class `d`, this returns the synthetic cast from the underlying type to * ErasedValueType defined in the companion module. This method is added to the module diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index ead4ad5cb..ec6fb1770 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -91,8 +91,8 @@ trait TypeAssigner { else parent } - val refinableDecls = info.decls.filterNot( - sym => sym.is(TypeParamAccessor | Private) || sym.isConstructor) + val refinableDecls = info.decls.filter( + sym => !(sym.is(TypeParamAccessor | Private) || sym.isConstructor)) val fullType = (parentType /: refinableDecls)(addRefinement) mapOver(fullType) case TypeBounds(lo, hi) if variance > 0 => -- cgit v1.2.3