diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/Symbols.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 317 |
1 files changed, 189 insertions, 128 deletions
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 2aec15894..c37bd0bdc 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -19,110 +19,189 @@ import io.AbstractFile /** Creation methods for symbols */ trait Symbols { this: Context => -// ---- Fundamental symbol creation methods ---------------------------------- +// ---- Factory methods for symbol creation ---------------------- +// +// All symbol creations should be done via the next two methods. - def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, coord: Coord = NoCoord) = - new Symbol(coord, new LazySymDenotation(_, owner, name, initFlags, completer)) { - type ThisName = N - } + /** Create a symbol without a denotation. + * Note this uses a cast instead of a direct type refinement because + * it's debug-friendlier not to create an anonymous class here. + */ + def newNakedSymbol[N <: Name](coord: Coord = NoCoord): Symbol { type ThisName = N } = + new Symbol(coord).asInstanceOf - def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, coord: Coord = NoCoord) = - new ClassSymbol(coord, new LazyClassDenotation(_, owner, name, initFlags, completer)(this), assocFile) + /** Create a class symbol without a denotation. */ + def newNakedClassSymbol(coord: Coord = NoCoord, assocFile: AbstractFile = null) = + new ClassSymbol(coord, assocFile) - def newLazyModuleSymbols(owner: Symbol, - name: TermName, +// ---- Symbol creation methods ---------------------------------- + + /** Create a symbol from a function producing its denotation */ + def newSymbolDenoting[N <: Name](denotFn: Symbol => SymDenotation, coord: Coord = NoCoord): Symbol { type ThisName = N } = { + val sym = newNakedSymbol[N](coord) + sym.denot = denotFn(sym) + sym + } + + /** Create a symbol from its fields (info may be lazy) */ + def newSymbol[N <: Name]( + owner: Symbol, + name: N, flags: FlagSet, - completer: ClassCompleter, - assocFile: AbstractFile = null, - coord: Coord = NoCoord): (TermSymbol, ClassSymbol) - = { - val module = newLazySymbol( - owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed), coord) - val modcls = newLazyClassSymbol( - owner, name.toTypeName, flags | ModuleClassCreationFlags, completer, assocFile, coord) - module.denot.asInstanceOf[LazySymDenotation].info = - TypeRef(owner.thisType(ctx), modcls) - modcls.denot.asInstanceOf[LazyClassDenotation].selfType = - TermRef(owner.thisType, module) - (module, modcls) + info: Type, + privateWithin: Symbol = NoSymbol, + coord: Coord = NoCoord): Symbol { type ThisName = N } = { + val sym = newNakedSymbol[N](coord) + val denot = SymDenotation(sym, owner, name, flags, info, privateWithin) + sym.denot = denot + sym } - def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = - new Symbol(coord, CompleteSymDenotation(_, owner, name, flags, info, privateWithin)) { - type ThisName = N - } + /** Create a class symbol from a function producing its denotation */ + def newClassSymbolDenoting(denotFn: ClassSymbol => SymDenotation, coord: Coord = NoCoord, assocFile: AbstractFile = null): ClassSymbol = { + val cls = newNakedClassSymbol(coord, assocFile) + cls.denot = denotFn(cls) + cls + } + /** Create a class symbol from its non-info fields and a function + * producing its info (the info may be lazy). + */ def newClassSymbol( owner: Symbol, name: TypeName, flags: FlagSet, - parents: List[TypeRef], + infoFn: ClassSymbol => Type, privateWithin: Symbol = NoSymbol, - optSelfType: Type = NoType, - decls: Scope = newScope, - assocFile: AbstractFile = null, - coord: Coord = NoCoord) - = - new ClassSymbol(coord, new CompleteClassDenotation( - _, owner, name, flags, parents, privateWithin, optSelfType, decls)(this), assocFile) + coord: Coord = NoCoord, + assocFile: AbstractFile = null): ClassSymbol + = { + val cls = newNakedClassSymbol(coord, assocFile) + val denot = SymDenotation(cls, owner, name, flags, infoFn(cls)) + cls.denot = denot + cls + } - def newModuleSymbols( + /** Create a class symbol from its non-info fields and the fields of its info. */ + def newCompleteClassSymbol( owner: Symbol, - name: TermName, + name: TypeName, flags: FlagSet, - classFlags: FlagSet, parents: List[TypeRef], - privateWithin: Symbol = NoSymbol, decls: Scope = newScope, - assocFile: AbstractFile = null, - coord: Coord = NoCoord): (TermSymbol, ClassSymbol) + optSelfType: Type = NoType, + privateWithin: Symbol = NoSymbol, + coord: Coord = NoCoord, + assocFile: AbstractFile = null): ClassSymbol = + newClassSymbol( + owner, name, flags, + ClassInfo(owner.thisType, _, parents, decls, optSelfType), + privateWithin, coord, assocFile) + + /** Create a module symbol with associated module class + * from its non-info fields and a function producing the info + * of the module class (this info may be lazy). + * @param flags The combined flags of the module and the module class + * These are masked with RetainedModuleFlags/RetainedModuleClassFlags. + */ + def newModuleSymbol( + owner: Symbol, + name: TermName, + flags: FlagSet, + infoFn: (TermSymbol, ClassSymbol) => Type, + privateWithin: Symbol = NoSymbol, + coord: Coord = NoCoord, + assocFile: AbstractFile = null): TermSymbol = { - val module = newLazySymbol( - owner, name, flags | ModuleCreationFlags, - new ModuleCompleter(condensed), coord) - val modcls = newClassSymbol( - owner, name.toTypeName, classFlags | ModuleClassCreationFlags, parents, privateWithin, - optSelfType = TermRef(owner.thisType, module), - decls, assocFile, coord) - module.denot.asInstanceOf[LazySymDenotation].info = - TypeRef(owner.thisType, modcls) - (module, modcls) + val base = owner.thisType + val module = newNakedSymbol[TermName](coord) + val modcls = newNakedClassSymbol(coord, assocFile) + val cdenot = SymDenotation( + modcls, owner, name.toTypeName, + flags & RetainedModuleClassFlags | ModuleClassCreationFlags, + infoFn(module, modcls), privateWithin) + val mdenot = SymDenotation( + module, owner, name, + flags & RetainedModuleFlags | ModuleCreationFlags, + if (cdenot.isCompleted) TypeRef(owner.thisType, modcls) + else new LazyModuleInfo(modcls)(condensed)) + module.denot = mdenot + modcls.denot = cdenot + module } + /** Create a module symbol with associated module class + * from its non-info fields and the fields of the module class info. + * @param flags The combined flags of the module and the module class + * These are masked with RetainedModuleFlags/RetainedModuleClassFlags. + */ + def newCompleteModuleSymbol( + owner: Symbol, + name: TermName, + flags: FlagSet, + parents: List[TypeRef], + decls: Scope, + privateWithin: Symbol = NoSymbol, + coord: Coord = NoCoord, + assocFile: AbstractFile = null): TermSymbol = + newModuleSymbol( + owner, name, flags, + (module, modcls) => ClassInfo( + owner.thisType, modcls, parents, decls, TermRef(owner.thisType, module)), + privateWithin, coord, assocFile) + + /** Create a package symbol with associated package class + * from its non-info fields and a lazy type for loading the package's members. + */ + def newPackageSymbol( + owner: Symbol, + name: TermName, + info: LazyType): TermSymbol = + newModuleSymbol(owner, name, PackageCreationFlags, info) + + /** Create a package symbol with associated package class + * from its non-info fields and the fields of the package class info. + */ + def newCompletePackageSymbol( + owner: Symbol, + name: TermName, + flags: FlagSet = EmptyFlags, + decls: Scope = newScope): TermSymbol = + newCompleteModuleSymbol(owner, name, flags | PackageCreationFlags, Nil, decls) + + + /** Create a stub symbol that will issue a missing reference error + * when attempted to be completed. + */ def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null): Symbol = { - def stub = new StubCompleter(ctx.condensed) + def stub = new StubInfo()(condensed) name match { - case name: TermName => ctx.newLazyModuleSymbols(owner, name, EmptyFlags, stub, file)._1 - case name: TypeName => ctx.newLazyClassSymbol(owner, name, EmptyFlags, stub, file) + case name: TermName => + newModuleSymbol(owner, name, EmptyFlags, stub, assocFile = file) + case name: TypeName => + newClassSymbol(owner, name, EmptyFlags, stub, assocFile = file) } } -// ---- Derived symbol creation methods ------------------------------------- - - def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) = - newLazyModuleSymbols(owner, name, PackageCreationFlags, completer) - - def newPackageSymbols( - owner: Symbol, - name: TermName, - decls: Scope = newScope) = - newModuleSymbols( - owner, name, PackageCreationFlags, PackageCreationFlags, Nil, NoSymbol, decls) - + /** Create the local template dummy of given class `cls`. */ def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) = newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType) + /** Create an import symbol pointing back to given qualifier `expr`. */ def newImportSymbol(expr: Shared[Type], coord: Coord = NoCoord) = newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord) + /** Create a class constructor symbol for given class `cls`. */ def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes)(_ => cls.typeConstructor), privateWithin, coord) + /** Create an empty default constructor symbol for given class `cls`. */ def newDefaultConstructor(cls: ClassSymbol) = newConstructor(cls, EmptyFlags, Nil, Nil) + /** Create a symbol representing a selftype declaration for class `cls`. */ def newSelfSym(cls: ClassSymbol) = - ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.selfType) + ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.classInfo.selfType) /** Create new type parameters with given owner, names, and flags. * @param boundsFn A function that, given type refs to the newly created @@ -133,12 +212,11 @@ trait Symbols { this: Context => names: List[TypeName], flags: FlagSet, boundsFn: List[TypeRef] => List[Type]) = { - lazy val tparams: List[TypeSymbol] = names map { name => - newLazySymbol(owner, name, flags | TypeParam, { denot => - denot.info = bounds(denot.symbol.asType) - }) + val tparams = names map (_ => newNakedSymbol[TypeName](NoCoord)) + val bounds = boundsFn(tparams map (_.symbolicRef)) + (names, tparams, bounds).zipped foreach { (name, tparam, bound) => + tparam.denot = SymDenotation(tparam, owner, name, flags, bound) } - lazy val bounds = (tparams zip boundsFn(tparams map (_.typeConstructor))).toMap tparams } @@ -148,38 +226,30 @@ trait Symbols { this: Context => * references are brought over from originals to copies. * Do not copy any symbols if all their attributes stay the same. */ - def mapSymbols(originals: List[Symbol], typeMap: TypeMap = IdentityTypeMap, ownerMap: OwnerMap = identity) = { + def mapSymbols( + originals: List[Symbol], + typeMap: TypeMap = IdentityTypeMap, + ownerMap: OwnerMap = identity) + = if (originals forall (sym => - sym.isInvariantUnder(typeMap) && ownerMap(sym.owner) == sym.owner)) + (typeMap(sym.info) eq sym.info) && (ownerMap(sym.owner) eq sym.owner))) originals else { - lazy val copies: List[Symbol] = originals map { orig => - if (orig.isClass) - newLazyClassSymbol(ownerMap(orig.owner), orig.asClass.name, orig.flags, copyClassCompleter, orig.asClass.associatedFile, orig.coord) - else - newLazySymbol(ownerMap(orig.owner), orig.name, orig.flags, copySymCompleter, orig.coord) - } - lazy val prev = (copies zip originals).toMap - lazy val copyTypeMap = typeMap andThen ((tp: Type) => tp.substSym(originals, copies)) - lazy val mapper = new TypedTrees.TreeMapper(typeMap, ownerMap) - def mapAnnotations(denot: isLazy[_]): Unit = { - denot.annotations = denot.annotations.mapConserve(mapper.apply) - denot.privateWithin = ownerMap(denot.privateWithin) - } - def copySymCompleter(denot: LazySymDenotation): Unit = { - denot.info = copyTypeMap(prev(denot.symbol).info) - mapAnnotations(denot) - } - def copyClassCompleter(denot: LazyClassDenotation): Unit = { - denot.parents = prev(denot.symbol).asClass.parents mapConserve ( - tp => copyTypeMap(tp).asInstanceOf[TypeRef]) - denot.selfType = copyTypeMap(prev(denot.symbol).asClass.selfType) - denot.decls = copyTypeMap.mapOver(prev(denot.symbol).asClass.decls) - mapAnnotations(denot) + val copies: List[Symbol] = for (original <- originals) yield + newNakedSymbol[original.ThisName](original.coord) + val copyTypeMap = typeMap andThen ((tp: Type) => tp.substSym(originals, copies)) + val copyTreeMap = new TypedTrees.TreeMapper(copyTypeMap, ownerMap) + (originals, copies).zipped foreach {(original, copy) => + val odenot = original.denot + copy.denot = odenot.copySymDenotation( + symbol = copy, + owner = ownerMap(odenot.owner), + info = copyTypeMap(odenot.info), + privateWithin = ownerMap(odenot.privateWithin), + annotations = odenot.annotations.mapConserve(copyTreeMap.apply)) } copies } - } // ----- Locating predefined symbols ---------------------------------------- @@ -197,7 +267,7 @@ object Symbols { /** A Symbol represents a Scala definition/declaration or a package. */ - class Symbol(val coord: Coord, denotf: Symbol => SymDenotation) extends DotClass { + class Symbol private[Symbols] (val coord: Coord) extends DotClass { type ThisName <: Name @@ -219,7 +289,11 @@ object Symbols { } /** The last denotation of this symbol */ - private[this] var lastDenot: SymDenotation = denotf(this) + private[this] var lastDenot: SymDenotation = _ + + /** Set the denotation of this symbol */ + private[Symbols] def denot_=(d: SymDenotation) = + lastDenot = d /** The current denotation of this symbol */ final def denot(implicit ctx: Context): SymDenotation = { @@ -257,7 +331,9 @@ object Symbols { /** The current name of this symbol */ final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName] - /** The source or class file from which this class was generated, null if not applicable. */ + /** The source or class file from which this class or + * the class containing this symbol was generated, null if not applicable. + */ def associatedFile(implicit ctx: Context): AbstractFile = this.denot.topLevelClass.symbol.associatedFile @@ -289,7 +365,8 @@ object Symbols { type TermSymbol = Symbol { type ThisName = TermName } type TypeSymbol = Symbol { type ThisName = TypeName } - class ClassSymbol(coord: Coord, denotf: ClassSymbol => ClassDenotation, assocFile: AbstractFile) extends Symbol(coord, s => denotf(s.asClass)) { + class ClassSymbol private[Symbols] (coord: Coord, assocFile: AbstractFile) + extends Symbol(coord) { type ThisName = TypeName @@ -324,12 +401,14 @@ object Symbols { } } - class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord, sym => underlying.denot) { + class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord) { type ThisName = underlying.ThisName + denot = underlying.denot } - object NoSymbol extends Symbol(NoCoord, sym => NoDenotation) { + object NoSymbol extends Symbol(NoCoord) { override def exists = false + denot = NoDenotation } implicit class Copier[N <: Name](sym: Symbol { type ThisName = N })(implicit ctx: Context) { @@ -338,37 +417,19 @@ object Symbols { owner: Symbol = sym.owner, name: N = sym.name, flags: FlagSet = sym.flags, - privateWithin: Symbol = sym.privateWithin, info: Type = sym.info, - coord: Coord = sym.coord): Symbol = - if (sym.isClass) { - assert(info eq sym.info) - new ClassCopier(sym.asClass).copy(owner, name.asTypeName, flags, privateWithin = privateWithin, coord = coord) - } else - ctx.newSymbol(owner, name, flags, info, privateWithin, sym.coord) - } - - implicit class ClassCopier(cls: ClassSymbol)(implicit ctx: Context) { - /** Copy a class symbol, overriding selective fields */ - def copy( - owner: Symbol = cls.owner, - name: TypeName = cls.name.asTypeName, - flags: FlagSet = cls.flags, - parents: List[TypeRef] = cls.classDenot.parents, - privateWithin: Symbol = cls.privateWithin, - selfType: Type = cls.selfType, - decls: Scope = cls.decls, - associatedFile: AbstractFile = cls.associatedFile, - coord: Coord = cls.coord) = - ctx.newClassSymbol(owner, name, flags, parents, privateWithin, selfType, decls, associatedFile, coord) + privateWithin: Symbol = sym.privateWithin, + coord: Coord = sym.coord, + associatedFile: AbstractFile = sym.associatedFile): Symbol = + if (sym.isClass) + ctx.newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord, associatedFile) + else + ctx.newSymbol(owner, name, flags, info, privateWithin, coord) } implicit def defn(implicit ctx: Context): Definitions = ctx.definitions - implicit def toFlagSet(sym: Symbol)(implicit ctx: Context): FlagSet = sym.flags - implicit def toDenot(sym: Symbol)(implicit ctx: Context): SymDenotation = sym.denot implicit def toClassDenot(cls: ClassSymbol)(implicit ctx: Context): ClassDenotation = cls.classDenot - } |