@@ -14,6 +14,7 @@ import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util
14
14
import StdNames ._ , NameOps ._
15
15
import Decorators .{PreNamedString , StringInterpolators }
16
16
import classfile .ClassfileParser
17
+ import util .Stats
17
18
import scala .util .control .NonFatal
18
19
19
20
object SymbolLoaders {
@@ -148,46 +149,79 @@ class SymbolLoaders {
148
149
override def sourceModule (implicit ctx : Context ) = _sourceModule
149
150
def description = " package loader " + classpath.name
150
151
152
+ private var enterFlatClasses : Option [Context => Unit ] = None
153
+
154
+ Stats .record(" package scopes" )
155
+
151
156
/** 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.
156
161
*/
157
162
final class PackageScope extends MutableScope {
158
163
override def newScopeEntry (name : Name , sym : Symbol )(implicit ctx : Context ): ScopeEntry =
159
164
super .newScopeEntry(name.mangled, sym)
160
165
161
166
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)
166
172
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
+ }
167
178
else e
168
179
}
169
180
181
+ override def ensureComplete ()(implicit ctx : Context ) =
182
+ for (enter <- enterFlatClasses) enter(ctx)
183
+
170
184
override def newScopeLikeThis () = new PackageScope
171
185
}
172
186
173
187
private [core] val currentDecls : MutableScope = new PackageScope ()
174
188
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
+
175
214
def doComplete (root : SymDenotation )(implicit ctx : Context ): Unit = {
176
215
assert(root is PackageClass , root)
177
- def maybeModuleClass (classRep : ClassPath # ClassRep ) = classRep.name.last == '$'
178
216
val pre = root.owner.thisType
179
217
root.info = ClassInfo (pre, root.symbol.asClass, Nil , currentDecls, pre select sourceModule)
180
218
if (! sourceModule.isCompleted)
181
219
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)
190
223
}
224
+ enterClasses(root, flat = false )
191
225
if (! root.isEmptyPackage)
192
226
for (pkg <- classpath.packages)
193
227
enterPackage(root.symbol, pkg)
0 commit comments