From 71cadcea87220b89b7eff80c8ff7daaf5cb34b49 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 8 May 2017 19:14:23 +0200 Subject: [PATCH] Generalize function symbol synthesis logic We will need other synthesized symbols down the road (e.g. function types in phantom universes). With this commit one can provide for that by installing a synthesizer in a scope. --- .../dotty/tools/dotc/core/Definitions.scala | 11 +++++++++-- .../src/dotty/tools/dotc/core/Scopes.scala | 19 ++++++++++++++++++- .../dotty/tools/dotc/core/SymbolLoaders.scala | 3 --- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 0920ca946598..803ad3773350 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 * } */ - def newFunctionNTrait(name: TypeName) = { + def newFunctionNTrait(name: TypeName): ClassSymbol = { val completer = new LazyType { def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { val cls = denot.asClass.classSymbol @@ -189,7 +189,14 @@ class Definitions { lazy val ScalaPackageVal = ctx.requiredPackage("scala") lazy val ScalaMathPackageVal = ctx.requiredPackage("scala.math") - lazy val ScalaPackageClass = ScalaPackageVal.moduleClass.asClass + lazy val ScalaPackageClass = { + val cls = ScalaPackageVal.moduleClass.asClass + cls.info.decls.openForMutations.useSynthesizer( + name => ctx => + if (name.isTypeName && name.isSyntheticFunction) newFunctionNTrait(name.asTypeName) + else NoSymbol) + cls + } lazy val JavaPackageVal = ctx.requiredPackage("java") lazy val JavaLangPackageVal = ctx.requiredPackage("java.lang") // fundamental modules diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 205798474c80..92ffb76d6bb1 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -39,6 +39,12 @@ object Scopes { */ private final val MaxRecursions = 1000 + /** A function that optionally produces synthesized symbols with + * the given name in the given context. Returns `NoSymbol` if the + * no symbol should be synthesized for the given name. + */ + type SymbolSynthesizer = Name => Context => Symbol + class ScopeEntry private[Scopes] (val name: Name, _sym: Symbol, val owner: Scope) { var sym: Symbol = _sym @@ -204,6 +210,12 @@ object Scopes { */ private var elemsCache: List[Symbol] = null + /** The synthesizer to be used, or `null` if no synthesis is done on this scope */ + private var synthesize: SymbolSynthesizer = null + + /** Use specified synthesize for this scope */ + def useSynthesizer(s: SymbolSynthesizer): Unit = synthesize = s + protected def newScopeLikeThis() = new MutableScope() /** Clone scope, taking care not to force the denotations of any symbols in the scope. @@ -220,6 +232,7 @@ object Scopes { val e = entries(i) scope.newScopeEntry(e.name, e.sym) } + scope.synthesize = synthesize scope } @@ -350,7 +363,11 @@ object Scopes { e = e.prev } } - e + if ((e eq null) && (synthesize != null)) { + val sym = synthesize(name)(ctx) + if (sym.exists) newScopeEntry(sym) else e + } + else e } /** lookup next entry with same name as this one */ diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 24e0d9841801..b6f5cde3b029 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -167,9 +167,6 @@ class SymbolLoaders { 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)