@@ -14,6 +14,7 @@ import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util
1414import StdNames ._ , NameOps ._
1515import Decorators .{PreNamedString , StringInterpolators }
1616import classfile .ClassfileParser
17+ import util .Stats
1718import scala .util .control .NonFatal
1819
1920object SymbolLoaders {
@@ -148,46 +149,79 @@ class SymbolLoaders {
148149 override def sourceModule (implicit ctx : Context ) = _sourceModule
149150 def description = " package loader " + classpath.name
150151
152+ private var enterFlatClasses : Option [Context => Unit ] = None
153+
154+ Stats .record(" package scopes" )
155+
151156 /** The scope of a package. This is different from a normal scope
152- * in three aspects:
153- *
154- * 1. Names of scope entries are kept in mangled form.
155- * 2. Some function types in the `scala` package are synthesized.
157+ * in three aspects:
158+ *
159+ * 1. Names of scope entries are kept in mangled form.
160+ * 2. Some function types in the `scala` package are synthesized.
156161 */
157162 final class PackageScope extends MutableScope {
158163 override def newScopeEntry (name : Name , sym : Symbol )(implicit ctx : Context ): ScopeEntry =
159164 super .newScopeEntry(name.mangled, sym)
160165
161166 override def lookupEntry (name : Name )(implicit ctx : Context ): ScopeEntry = {
162- val e = super .lookupEntry(name.mangled)
163- if (e == null &&
164- _sourceModule.name == nme.scala_ && _sourceModule == defn.ScalaPackageVal &&
165- name.isTypeName && name.isSyntheticFunction)
167+ val mangled = name.mangled
168+ val e = super .lookupEntry(mangled)
169+ if (e != null ) e
170+ else if (_sourceModule.initialDenot.name == nme.scala_ && _sourceModule == defn.ScalaPackageVal &&
171+ name.isTypeName && name.isSyntheticFunction)
166172 newScopeEntry(defn.newFunctionNTrait(name.asTypeName))
173+ else if (isFlatName(mangled.toSimpleName) && enterFlatClasses.isDefined) {
174+ Stats .record(" package scopes with flatnames entered" )
175+ enterFlatClasses.get(ctx)
176+ lookupEntry(name)
177+ }
167178 else e
168179 }
169180
181+ override def ensureComplete ()(implicit ctx : Context ) =
182+ for (enter <- enterFlatClasses) enter(ctx)
183+
170184 override def newScopeLikeThis () = new PackageScope
171185 }
172186
173187 private [core] val currentDecls : MutableScope = new PackageScope ()
174188
189+ def isFlatName (name : SimpleTermName ) = name.lastIndexOf('$' , name.length - 2 ) >= 0
190+
191+ def isFlatName (classRep : ClassPath # ClassRep ) = {
192+ val idx = classRep.name.indexOf('$' )
193+ idx >= 0 && idx < classRep.name.length - 1
194+ }
195+
196+ def maybeModuleClass (classRep : ClassPath # ClassRep ) = classRep.name.last == '$'
197+
198+ private def enterClasses (root : SymDenotation , flat : Boolean )(implicit ctx : Context ) = {
199+ def isAbsent (classRep : ClassPath # ClassRep ) =
200+ ! root.unforcedDecls.lookup(classRep.name.toTypeName).exists
201+
202+ if (! root.isRoot) {
203+ for (classRep <- classpath.classes)
204+ if (! maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
205+ (! flat || isAbsent(classRep))) // on 2nd enter of flat names, check that the name has not been entered before
206+ initializeFromClassPath(root.symbol, classRep)
207+ for (classRep <- classpath.classes)
208+ if (maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
209+ isAbsent(classRep))
210+ initializeFromClassPath(root.symbol, classRep)
211+ }
212+ }
213+
175214 def doComplete (root : SymDenotation )(implicit ctx : Context ): Unit = {
176215 assert(root is PackageClass , root)
177- def maybeModuleClass (classRep : ClassPath # ClassRep ) = classRep.name.last == '$'
178216 val pre = root.owner.thisType
179217 root.info = ClassInfo (pre, root.symbol.asClass, Nil , currentDecls, pre select sourceModule)
180218 if (! sourceModule.isCompleted)
181219 sourceModule.completer.complete(sourceModule)
182- if (! root.isRoot) {
183- for (classRep <- classpath.classes)
184- if (! maybeModuleClass(classRep))
185- initializeFromClassPath(root.symbol, classRep)
186- for (classRep <- classpath.classes)
187- if (maybeModuleClass(classRep) &&
188- ! root.unforcedDecls.lookup(classRep.name.toTypeName).exists)
189- initializeFromClassPath(root.symbol, classRep)
220+ enterFlatClasses = Some { ctx =>
221+ enterFlatClasses = None
222+ enterClasses(root, flat = true )(ctx)
190223 }
224+ enterClasses(root, flat = false )
191225 if (! root.isEmptyPackage)
192226 for (pkg <- classpath.packages)
193227 enterPackage(root.symbol, pkg)
0 commit comments