aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-19 16:19:03 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-19 16:19:03 +0200
commit62131749d08657a0103c922c626a0b918cf385b5 (patch)
treee8c49a9bb6eb41f3f5d4e3ca7e75a431a25c33b9
parentedb9facac55f61540e0f9af8d06ac9390830fcb8 (diff)
downloaddotty-62131749d08657a0103c922c626a0b918cf385b5.tar.gz
dotty-62131749d08657a0103c922c626a0b918cf385b5.tar.bz2
dotty-62131749d08657a0103c922c626a0b918cf385b5.zip
Several fixes and refactorings for typechecking
1) Refactoring of package loaders that ensures that a package is always loaded before new members are entered. This led to a refactoring of sourceModule in completers into its own trait 2) Refactoring of optSelfType ot selfInfo. Class Infos may now have a reference to a symbol in their selfInfo field, instead of always a type, as it was before. This allows to introduce laziness for self type evaluation. Laziness is needed so that modules can be desugared and the desugared version be compiled without special tricks. 3) <init> and $init members are no longer inherited. 4) Refactoring of createSymbol and enterSym, so that creating symbols and entering them in a scope is decoupled. Renamed the driver operation form `enterSym(s)` to `index`.
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala16
-rw-r--r--src/dotty/tools/dotc/ast/TypedTrees.scala2
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala7
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala10
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala26
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala8
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala8
-rw-r--r--src/dotty/tools/dotc/core/Types.scala29
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala29
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala2
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala92
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala13
-rw-r--r--src/dotty/tools/dotc/util/Positions.scala3
14 files changed, 141 insertions, 110 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 0ce7b3707..9f1fbe446 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -210,16 +210,24 @@ object desugar {
flatTree(cdef1 :: companions ::: implicitWrappers)
}
- /** Expand to:
- * <module> val name: name$ = New(name$)
- * <module> final class name$ extends parents { self: name.type => body }
+ /** Expand
+ *
+ * object name extends parents { self => body }
+ *
+ * to:
+ * <module> val name: name$ = New(name$)
+ * <module> final class name$ extends parents { self: name.type => body }
*/
def moduleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = {
val ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) = mdef
val clsName = name.moduleClassName
val clsRef = Ident(clsName)
val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) withPos mdef.pos
- val clsTmpl = cpy.Template(tmpl, constr, parents, EmptyValDef, body)
+ val ValDef(selfMods, selfName, selfTpt, selfRhs) = self
+ if (!selfTpt.isEmpty) ctx.error("object definition may not have a self type", self.pos)
+ val clsSelf = ValDef(selfMods, selfName, SingletonTypeTree(clsRef), selfRhs)
+ .withPos(self.pos orElse tmpl.pos.startPos)
+ val clsTmpl = cpy.Template(tmpl, constr, parents, clsSelf, body)
val cls = TypeDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, clsTmpl)
Thicket(modul, cls)
}
diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala
index 9942728b3..8ac37a104 100644
--- a/src/dotty/tools/dotc/ast/TypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/TypedTrees.scala
@@ -253,7 +253,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ClassDef(cls: ClassSymbol, constr: DefDef, body: List[Tree])(implicit ctx: Context): TypeDef = {
val parents = cls.info.parents map (TypeTree(_))
val selfType =
- if (cls.classInfo.optSelfType.exists) ValDef(ctx.newSelfSym(cls))
+ if (cls.classInfo.selfInfo ne NoType) ValDef(ctx.newSelfSym(cls))
else EmptyValDef
def isOwnTypeParamAccessor(stat: Tree) =
(stat.symbol is TypeParam) && stat.symbol.owner == cls
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index ea2682516..4b167baad 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -55,8 +55,11 @@ class Definitions(implicit ctx: Context) {
private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
newSymbol(cls, name.encode, flags | Method, info).entered.asTerm
- private def newAliasType(name: TypeName, tpe: Type, flags: FlagSet = EmptyFlags): TypeSymbol =
- newSymbol(ScalaPackageClass, name, flags, TypeAlias(tpe)).entered.asType
+ private def newAliasType(name: TypeName, tpe: Type, flags: FlagSet = EmptyFlags): TypeSymbol = {
+ val sym = newSymbol(ScalaPackageClass, name, flags, TypeAlias(tpe))
+ ScalaPackageClass.preDecls.enter(sym)
+ sym
+ }
private def newPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = {
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index bfd150999..272b6f505 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -333,11 +333,11 @@ object Denotations {
/** An overloaded denotation consisting of the alternatives of both given denotations.
*/
case class MultiDenotation(denot1: Denotation, denot2: Denotation) extends Denotation {
- final def symbol = unsupported("symbol")
- final def info = unsupported("info")
+ final def symbol = multiHasNot("symbol")
+ final def info = multiHasNot("info")
final def validFor = denot1.validFor & denot2.validFor
final def isType = false
- def signature(implicit ctx: Context) = unsupported("signature")
+ def signature(implicit ctx: Context) = multiHasNot("signature")
def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
denot1.atSignature(sig) orElse denot2.atSignature(sig)
def current(implicit ctx: Context): Denotation =
@@ -364,6 +364,10 @@ object Denotations {
def derivedMultiDenotation(d1: Denotation, d2: Denotation) =
if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2)
override def toString = alternatives.mkString(" <and> ")
+
+ private def multiHasNot(op: String): Nothing =
+ throw new UnsupportedOperationException(
+ s"multi-denotation with alternatives $alternatives does not implement operation $op")
}
/** A non-overloaded denotation */
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 91f157e2c..16dab0df8 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -106,7 +106,7 @@ object SymDenotations {
if ((this is ModuleClass) && !(this is PackageClass))
tp match {
case ClassInfo(_, _, _, _, ost) =>
- assert(ost.isInstanceOf[TermRef], tp)
+ assert(ost.isInstanceOf[TermRef] || ost.isInstanceOf[TermSymbol], tp)
case _ =>
}
myInfo = tp
@@ -162,6 +162,17 @@ object SymDenotations {
case _ => info.decls
}
+ /** If this is a package class, the symbols entered in it
+ * before it is completed. (this is needed to eagerly enter synthetic
+ * aliases such as AnyRef into a package class without forcing it.
+ * Right now, I believe the only usage is for the three synthetic aliases
+ * in Definitions.
+ */
+ final def preDecls(implicit ctx: Context): MutableScope = myInfo match {
+ case pinfo: SymbolLoaders # PackageLoader => pinfo.preDecls
+ case _ => decls.asInstanceOf[MutableScope]
+ }
+
// ------ Names ----------------------------------------------
/** The name with which the denoting symbol was created */
@@ -451,7 +462,7 @@ object SymDenotations {
final def sourceModule: Symbol = myInfo match {
case ClassInfo(_, _, _, _, selfType: TermRefBySym) if this is ModuleClass =>
selfType.fixedSym
- case info: ClassCompleterWithDecls =>
+ case info: ModuleClassCompleter =>
info.sourceModule
case _ =>
NoSymbol
@@ -909,7 +920,8 @@ object SymDenotations {
case nil =>
denots
}
- collect(ownDenots, classParents)
+ if (name.isConstructorName) ownDenots
+ else collect(ownDenots, classParents)
} else NoDenotation
override final def findMember(name: Name, pre: Type, excluded: FlagSet)(implicit ctx: Context): Denotation =
@@ -1044,20 +1056,24 @@ object SymDenotations {
def apply(module: TermSymbol, modcls: ClassSymbol) = this
}
+ /** A base type for completers of module classes that knows about `sourceModule` */
+ trait ModuleClassCompleter extends LazyType {
+ def sourceModule: Symbol
+ }
+
/** A lazy type for completing a class that already has a scope with all
* declarations in the class.
*/
class ClassCompleterWithDecls(val decls: Scope, underlying: LazyType = NoCompleter)
extends LazyType {
def complete(denot: SymDenotation): Unit = underlying.complete(denot)
- def sourceModule: Symbol = NoSymbol
}
/** A lazy type for completing a class that already has a scope with all
* declarations in the class.
*/
class ModuleClassCompleterWithDecls(module: Symbol, decls: Scope, underlying: LazyType = NoCompleter)
- extends ClassCompleterWithDecls(decls, underlying) {
+ extends ClassCompleterWithDecls(decls, underlying) with ModuleClassCompleter {
override def sourceModule = module
}
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index dc65b77f4..2fbe147c7 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -142,13 +142,15 @@ class SymbolLoaders {
/** Load contents of a package
*/
class PackageLoader(override val sourceModule: TermSymbol, classpath: ClassPath)(implicit val cctx: CondensedContext)
- extends ClassCompleterWithDecls(newScope) with SymbolLoader { // !!! TODO: ClassCompleter needed?
+ extends SymbolLoader with ModuleClassCompleter {
def description = "package loader " + classpath.name
+ private[core] val preDecls: MutableScope = newScope
+
def doComplete(root: SymDenotation) {
assert(root is PackageClass, root)
val pre = root.owner.thisType
- root.info = ClassInfo(pre, root.symbol.asClass, Nil, root.decls, TermRef.withSym(pre, sourceModule))
+ root.info = ClassInfo(pre, root.symbol.asClass, Nil, preDecls, TermRef.withSym(pre, sourceModule))
if (!sourceModule.isCompleted)
sourceModule.completer.complete(sourceModule)
if (!root.isRoot) {
@@ -205,7 +207,7 @@ class SymbolLoaders {
/** A lazy type that completes itself by calling parameter doComplete.
* Any linked modules/classes or module classes are also initialized.
*/
-trait SymbolLoader extends LazyType {
+abstract class SymbolLoader extends LazyType {
implicit val cctx: CondensedContext
/** Load source or class file for `root`, return */
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 3e8b13320..f7b079a69 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -92,13 +92,13 @@ trait Symbols { this: Context =>
flags: FlagSet,
parents: List[TypeRef],
decls: Scope = newScope,
- optSelfType: Type = NoType,
+ selfInfo: Type = NoType,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile = null): ClassSymbol =
newClassSymbol(
owner, name, flags,
- ClassInfo(owner.thisType, _, parents, decls, optSelfType),
+ ClassInfo(owner.thisType, _, parents, decls, selfInfo),
privateWithin, coord, assocFile)
/** Create a module symbol with associated module class
@@ -213,8 +213,8 @@ trait Symbols { this: Context =>
newConstructor(cls, EmptyFlags, Nil, Nil)
/** Create a symbol representing a selftype declaration for class `cls`. */
- def newSelfSym(cls: ClassSymbol, name: TermName = nme.WILDCARD, optSelfType: Type = NoType): TermSymbol =
- ctx.newSymbol(cls, name, SelfSymFlags, optSelfType orElse cls.classInfo.selfType, coord = cls.coord)
+ def newSelfSym(cls: ClassSymbol, name: TermName = nme.WILDCARD, selfInfo: Type = NoType): TermSymbol =
+ ctx.newSymbol(cls, name, SelfSymFlags, selfInfo orElse cls.classInfo.selfType, coord = cls.coord)
/** Create new type parameters with given owner, names, and flags.
* @param boundsFn A function that, given type refs to the newly created
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index cf756859f..1bc8f1646 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1774,17 +1774,22 @@ object Types {
* These are all normalized to be TypeRefs by moving any refinements
* to be member definitions of the class itself.
* @param decls The symbols defined directly in this class.
- * @param optSelfType The type of `this` in this class, if explicitly given, NoType otherwise.
+ * @param selfInfo The type of `this` in this class, if explicitly given,
+ * NoType otherwise. If class is compiled from source, can also
+ * be a reference to the self symbol containing the type.
*/
abstract case class ClassInfo(
prefix: Type,
cls: ClassSymbol,
classParents: List[TypeRef],
decls: Scope,
- optSelfType: Type) extends CachedGroundType with TypeType {
+ selfInfo: DotClass /* should be: Type | Symbol */) extends CachedGroundType with TypeType {
- def selfType(implicit ctx: Context): Type =
- if (optSelfType.exists) optSelfType else cls.typeConstructor
+ def selfType(implicit ctx: Context): Type = selfInfo match {
+ case NoType => cls.typeConstructor
+ case self: Symbol => self.info
+ case tp: Type => tp
+ }
def rebase(tp: Type)(implicit ctx: Context): Type =
if ((prefix eq cls.owner.thisType) || !cls.owner.isClass) tp
@@ -1812,21 +1817,21 @@ object Types {
def derivedClassInfo(prefix: Type)(implicit ctx: Context) =
if (prefix eq this.prefix) this
- else ClassInfo(prefix, cls, classParents, decls, optSelfType)
+ else ClassInfo(prefix, cls, classParents, decls, selfInfo)
- def derivedClassInfo(prefix: Type, classParents: List[TypeRef], optSelfType: Type)(implicit ctx: Context) =
- if ((prefix eq this.prefix) && (classParents eq this.classParents) && (optSelfType eq this.optSelfType)) this
- else ClassInfo(prefix, cls, classParents, decls, optSelfType)
+ def derivedClassInfo(prefix: Type, classParents: List[TypeRef], selfInfo: Type)(implicit ctx: Context) =
+ if ((prefix eq this.prefix) && (classParents eq this.classParents) && (selfInfo eq this.selfInfo)) this
+ else ClassInfo(prefix, cls, classParents, decls, selfInfo)
override def computeHash = doHash(cls, prefix)
}
- final class CachedClassInfo(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, optSelfType: Type)
- extends ClassInfo(prefix, cls, classParents, decls, optSelfType)
+ final class CachedClassInfo(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, selfInfo: DotClass)
+ extends ClassInfo(prefix, cls, classParents, decls, selfInfo)
object ClassInfo {
- def apply(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, optSelfType: Type = NoType)(implicit ctx: Context) =
- unique(new CachedClassInfo(prefix, cls, classParents, decls, optSelfType))
+ def apply(prefix: Type, cls: ClassSymbol, classParents: List[TypeRef], decls: Scope, selfInfo: DotClass = NoType)(implicit ctx: Context) =
+ unique(new CachedClassInfo(prefix, cls, classParents, decls, selfInfo))
}
/** Type bounds >: lo <: hi */
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 23fb79f8f..2b18e2263 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -84,7 +84,7 @@ object UnPickler {
tp.derivedPolyType(paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
}
- def setClassInfo(denot: ClassDenotation, info: Type, optSelfType: Type = NoType)(implicit ctx: Context): Unit = {
+ def setClassInfo(denot: ClassDenotation, info: Type, selfInfo: Type = NoType)(implicit ctx: Context): Unit = {
val cls = denot.classSymbol
val (tparams, TempClassInfoType(parents, decls, clazz)) = info match {
case TempPolyType(tps, cinfo) => (tps, cinfo)
@@ -97,9 +97,9 @@ object UnPickler {
else denot.enter(tparam, decls)
}
val ost =
- if ((optSelfType eq NoType) && (denot is ModuleClass))
+ if ((selfInfo eq NoType) && (denot is ModuleClass))
TermRef.withSym(denot.owner.thisType, denot.sourceModule.asTerm)
- else optSelfType
+ else selfInfo
denot.info = ClassInfo(denot.owner.thisType, denot.classSymbol, parentRefs, decls, ost)
}
}
@@ -452,13 +452,14 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
// create a type alias instead
cctx.newSymbol(owner, name, flags, localMemberUnpickler, coord = start)
else {
- def completer(cls: Symbol) = new LocalClassUnpickler(cls) {
- override def sourceModule =
- if (flags is ModuleClass)
- cls.owner.decls.lookup(cls.name.stripModuleClassSuffix.toTermName)
- .suchThat(_ is Module).symbol
- else NoSymbol
- }
+ def completer(cls: Symbol) =
+ if (flags is ModuleClass)
+ new LocalClassUnpickler(cls) with ModuleClassCompleter {
+ override def sourceModule =
+ cls.owner.decls.lookup(cls.name.stripModuleClassSuffix.toTermName)
+ .suchThat(_ is Module).symbol
+ }
+ else new LocalClassUnpickler(cls)
cctx.newClassSymbol(owner, name.asTypeName, flags, completer, coord = start)
}
case MODULEsym | VALsym =>
@@ -491,8 +492,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
val tp = at(inforef, readType)
denot match {
case denot: ClassDenotation =>
- val optSelfType = if (atEnd) NoType else readTypeRef()
- setClassInfo(denot, tp, optSelfType)
+ val selfInfo = if (atEnd) NoType else readTypeRef()
+ setClassInfo(denot, tp, selfInfo)
case denot =>
val tp1 = depoly(tp, denot)
denot.info = if (tag == ALIASsym) TypeAlias(tp1) else tp1
@@ -529,7 +530,9 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
extends ClassCompleterWithDecls(symScope(cls), localMemberUnpickler)
def rootClassUnpickler(start: Coord, cls: Symbol, module: Symbol) =
- new ClassCompleterWithDecls(symScope(cls), new AtStartUnpickler(start)) with SymbolLoaders.SecondCompleter {
+ new ClassCompleterWithDecls(symScope(cls), new AtStartUnpickler(start))
+ with ModuleClassCompleter
+ with SymbolLoaders.SecondCompleter {
override def sourceModule = module
}
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
index 31679f05e..55a65dd87 100644
--- a/src/dotty/tools/dotc/core/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -57,7 +57,7 @@ object Erasure {
tp.paramNames, tp.paramTypes.mapConserve(erasure), resultErasure(tp.resultType))
case tp: PolyType =>
erasure(tp.resultType)
- case tp @ ClassInfo(pre, cls, classParents, decls, optSelfType) =>
+ case tp @ ClassInfo(pre, cls, classParents, decls, _) =>
val parents: List[TypeRef] =
if (cls == defn.ObjectClass || cls.isPrimitiveValueClass) Nil
else if (cls == defn.ArrayClass) defn.ObjectClass.typeConstructor :: Nil
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index fe67f5b89..9e5786126 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -204,14 +204,14 @@ class PlainPrinter(_ctx: Context) extends Printer {
else
(if (lo == defn.NothingType) Text() else " >: " ~ toText(lo)) ~
(if (hi == defn.AnyType) Text() else " <: " ~ toText(hi))
- case ClassInfo(pre, cls, cparents, decls, optSelfType) =>
+ case tp @ ClassInfo(pre, cls, cparents, decls, selfInfo) =>
val preText = toTextLocal(pre)
val (tparams, otherDecls) = decls.toList partition treatAsTypeParam
val tparamsText =
if (tparams.isEmpty) Text() else ("[" ~ dclsText(tparams) ~ "]").close
val selfText =
- if (optSelfType.exists)
- "this: " ~ atPrec(InfixPrec) { toText(optSelfType) } ~ " =>"
+ if (selfInfo ne NoType)
+ "this: " ~ atPrec(InfixPrec) { toText(tp.selfType) } ~ " =>"
else Text()
val parentsText = Text(cparents.map(p =>
toTextLocal(reconstituteParent(cls, p))), " with ")
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 024577b47..479b29cd8 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -117,35 +117,17 @@ class Namer { typer: Typer =>
def record(tree: Tree, sym: Symbol): Symbol = {
symOfTree(tree) = sym
- println(s"entered: $sym in ${ctx.owner} and ${ctx.effectiveScope}")
sym
}
- def recordEnter(tree: Tree, sym: Symbol) = {
- if (sym.owner is PackageClass) {
- val preExisting = sym.owner.decls.lookup(sym.name)
- if (preExisting.defRunId == ctx.runId)
- ctx.error(s"${sym.showLocated} is compiled twice", tree.pos)
- }
- record(tree, ctx.enter(sym))
- }
-
println(i"creating symbol for $tree")
tree match {
case tree: TypeDef if tree.isClassDef =>
- recordEnter(tree, ctx.newClassSymbol(
+ record(tree, ctx.newClassSymbol(
ctx.owner, tree.name, tree.mods.flags, new ClassCompleter(tree),
privateWithinClass(tree.mods), tree.pos, ctx.source.file))
- case Thicket((moduleDef: ValDef) :: (modclsDef: TypeDef) :: Nil) =>
- assert(moduleDef.mods is Module)
- val module = ctx.newModuleSymbol(
- ctx.owner, moduleDef.name, moduleDef.mods.flags, modclsDef.mods.flags,
- (modul, modcls) => new ClassCompleter(modclsDef, modul),
- privateWithinClass(moduleDef.mods), modclsDef.pos, ctx.source.file)
- recordEnter(modclsDef, module.moduleClass)
- recordEnter(moduleDef, module)
case tree: MemberDef =>
- recordEnter(tree, ctx.newSymbol(
+ record(tree, ctx.newSymbol(
ctx.owner, tree.name, tree.mods.flags, new Completer(tree),
privateWithinClass(tree.mods), tree.pos))
case imp: Import =>
@@ -156,6 +138,22 @@ class Namer { typer: Typer =>
}
}
+ /** If `sym` exists, enter it in effective scope. Check that
+ * package members are not entered twice in the same run.
+ */
+ def enterSymbol(sym: Symbol)(implicit ctx: Context) = {
+ if (sym.exists) {
+ println(s"entered: $sym in ${ctx.owner} and ${ctx.effectiveScope}")
+ if (sym.owner is PackageClass) {
+ val preExisting = sym.owner.decls.lookup(sym.name)
+ if (preExisting.defRunId == ctx.runId)
+ ctx.error(s"${sym.showLocated} is compiled twice", sym.pos)
+ }
+ ctx.enter(sym)
+ }
+ sym
+ }
+
/** All PackageClassInfoTypes come from here. */
private def createPackageSymbol(pid: RefTree)(implicit ctx: Context): Symbol = {
val pkgOwner = pid match {
@@ -179,37 +177,35 @@ class Namer { typer: Typer =>
ctx.fresh.withImportInfo(new ImportInfo(sym, selectors))
/** A new context for the interior of a class */
- def inClassContext(cls: ClassSymbol, selfName: TermName)(implicit ctx: Context): Context = {
+ def inClassContext(selfInfo: DotClass /* Should be Type | Symbol*/)(implicit ctx: Context): Context = {
val localCtx: Context = ctx.fresh.withNewScope
- if (selfName != nme.WILDCARD)
- localCtx.enter(localCtx.newSelfSym(cls, selfName, cls.thisType))
+ selfInfo match {
+ case sym: Symbol if sym.exists && sym.name != nme.WILDCARD => localCtx.enter(sym)
+ case _ =>
+ }
localCtx
}
- /** Enter statement */
- def enterSym(stat: Tree)(implicit ctx: Context): Context = stat match {
+ /** Create top-level symbols for statement and enter them into symbol table */
+ def index(stat: Tree)(implicit ctx: Context): Context = stat match {
case pcl: PackageDef =>
val pkg = createPackageSymbol(pcl.pid)
- enterSyms(pcl.stats)(ctx.fresh.withOwner(pkg.moduleClass))
+ index(pcl.stats)(ctx.fresh.withOwner(pkg.moduleClass))
ctx
case imp: Import =>
importContext(createSymbol(imp), imp.selectors)
- case mdef: ModuleDef =>
- createSymbol(expansion(mdef))
- ctx
case mdef: MemberDef =>
- expansion(mdef).toList foreach createSymbol
+ expansion(mdef).toList foreach (tree => enterSymbol(createSymbol(tree)))
ctx
case _ =>
ctx
}
- /** Enter all statements in stats.
- */
- def enterSyms(stats: List[Tree])(implicit ctx: Context): Context = {
+ /** Create top-level symbols for statements and enter them into symbol table */
+ def index(stats: List[Tree])(implicit ctx: Context): Context = {
@tailrec def traverse(stats: List[Tree])(implicit ctx: Context): Context = stats match {
case stat :: stats1 =>
- traverse(stats1)(enterSym(stat))
+ traverse(stats1)(index(stat))
case nil =>
ctx
}
@@ -266,12 +262,12 @@ class Namer { typer: Typer =>
}
/** The completer for a symbol defined by a class definition */
- class ClassCompleter(original: TypeDef, override val sourceModule: Symbol = NoSymbol)(implicit ctx: Context)
+ class ClassCompleter(original: TypeDef)(implicit ctx: Context)
extends ClassCompleterWithDecls(newScope) {
override def complete(denot: SymDenotation): Unit = {
val cls = denot.symbol.asClass
def localContext = ctx.fresh.withOwner(cls)
- println(s"completing ${cls.show}, sourceModule = ${sourceModule.show}")
+ println(s"completing ${cls.show}")
cls.info = classDefSig(original, cls, decls.asInstanceOf[MutableScope])(localContext)
}
}
@@ -288,7 +284,7 @@ class Namer { typer: Typer =>
/** Enter and typecheck parameter list */
def completeParams(params: List[MemberDef])(implicit ctx: Context) = {
- enterSyms(params)
+ index(params)
for (param <- params) typedAheadExpr(param)
}
@@ -375,29 +371,21 @@ class Namer { typer: Typer =>
else typedAheadExpr(constr).tpe
}
- val TypeDef(_, _, impl @ Template(constr, parents, self, body)) = cdef
+ val TypeDef(_, name, impl @ Template(constr, parents, self, body)) = cdef
val (params, rest) = body span {
case td: TypeDef => td.mods is Param
case td: ValDef => td.mods is ParamAccessor
case _ => false
}
- enterSyms(params)
- def defaultSelfType =
- if (cls is Module) TermRef.withSym(ctx.owner.thisType, cls.sourceModule.asTerm)
- else NoType
+ index(params)
+ val selfInfo = if (self.isEmpty) NoType else createSymbol(self)
// pre-set info, so that parent types can refer to type params
- cls.info = ClassInfo(cls.owner.thisType, cls, Nil, decls, defaultSelfType)
+ cls.info = ClassInfo(cls.owner.thisType, cls, Nil, decls, selfInfo)
val parentTypes = parents map parentType
val parentRefs = ctx.normalizeToRefs(parentTypes, cls, decls)
- val optSelfType =
- if (self.tpt.isEmpty) defaultSelfType
- else {
- val t = typedAheadType(self.tpt).tpe
- if (!t.isError) t else defaultSelfType
- }
- enterSym(constr)
- enterSyms(rest)(inClassContext(cls, self.name))
- ClassInfo(cls.owner.thisType, cls, parentRefs, decls, optSelfType)
+ index(constr)
+ index(rest)(inClassContext(selfInfo))
+ ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
}
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 6a36eaaa5..7f2ba2959 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -430,7 +430,7 @@ class Typer extends Namer with Applications with Implicits {
}
def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = {
- val exprCtx = enterSyms(tree.stats)
+ val exprCtx = index(tree.stats)
val stats1 = typedStats(tree.stats, ctx.owner)
val expr1 = typedExpr(tree.expr, pt)(exprCtx)
val result = cpy.Block(tree, stats1, expr1).withType(blockType(stats1, expr1.tpe))
@@ -632,8 +632,7 @@ class Typer extends Namer with Applications with Implicits {
def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(implicit ctx: Context): RefinedTypeTree = {
val tpt1 = typedAheadType(tree.tpt)
val refineClsDef = desugar.refinedTypeToClass(tree)
- val throwAwayScopeCtx = ctx.fresh.withNewScope
- val refineCls = createSymbol(refineClsDef)(throwAwayScopeCtx).asClass
+ val refineCls = createSymbol(refineClsDef).asClass
val TypeDef(_, _, Template(_, _, _, refinements1)) = typed(refineClsDef)
assert(tree.refinements.length == refinements1.length, s"${tree.refinements} != $refinements1")
def addRefinement(parent: Type, refinement: Tree): Type = {
@@ -721,11 +720,9 @@ class Typer extends Namer with Applications with Implicits {
val mods1 = typedModifiers(mods)
val constr1 = typed(constr).asInstanceOf[DefDef]
val parents1 = parents mapconserve (typed(_))
- val self1 = cpy.ValDef(self, typedModifiers(self.mods), self.name, typedType(self.tpt), EmptyTree)
- .withType(NoType)
-
+ val self1 = typed(self).asInstanceOf[ValDef]
val localDummy = ctx.newLocalDummy(cls, impl.pos)
- val body1 = typedStats(body, localDummy)(inClassContext(cls, self.name))
+ val body1 = typedStats(body, localDummy)(inClassContext(self1.symbol))
val impl1 = cpy.Template(impl, constr1, parents1, self1, body1)
.withType(localDummy.symRef)
@@ -931,6 +928,8 @@ class Typer extends Namer with Applications with Implicits {
*/
def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = {
+ println(i"adapting $tree of type ${tree.tpe} to $pt")
+
def adaptOverloaded(ref: TermRef) = {
val altDenots = ref.denot.alternatives
val alts = altDenots map (alt =>
diff --git a/src/dotty/tools/dotc/util/Positions.scala b/src/dotty/tools/dotc/util/Positions.scala
index 281540321..334a3deb6 100644
--- a/src/dotty/tools/dotc/util/Positions.scala
+++ b/src/dotty/tools/dotc/util/Positions.scala
@@ -49,6 +49,9 @@ object Positions {
def pointDelta =
(coords >>> (StartEndBits * 2)).toInt
+ def orElse(that: Position) =
+ if (this.exists) this else that
+
/** The union of two positions. This is the least range that encloses
* both positions. It is always a synthetic position.
*/