aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-20 14:34:55 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-20 14:34:55 +0200
commit7fb9cd47f3a5ce10e1001b9a9aa5672dc38bf16e (patch)
tree260eb25604162d4d47de2f3a62f1823bc4e22a18 /src/dotty/tools
parentb048b321f5f700804ce4e3e67720eb65297eaf39 (diff)
downloaddotty-7fb9cd47f3a5ce10e1001b9a9aa5672dc38bf16e.tar.gz
dotty-7fb9cd47f3a5ce10e1001b9a9aa5672dc38bf16e.tar.bz2
dotty-7fb9cd47f3a5ce10e1001b9a9aa5672dc38bf16e.zip
Fixes handling of modules in namer.
Now we make sure we keep mode invariants at all times.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala5
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala19
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala101
5 files changed, 84 insertions, 45 deletions
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 1ca3bc418..6b365babb 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -105,9 +105,12 @@ object NameOps {
name
}
- /** Convert this name to a module name */
+ /** Convert this module name to corresponding module class name */
def moduleClassName: TypeName = (name ++ tpnme.MODULE_SUFFIX).toTypeName
+ /** Convert this module class name to corresponding source module name */
+ def sourceModuleName: TermName = stripModuleClassSuffix.toTermName
+
/** If name ends in module class suffix, drop it */
def stripModuleClassSuffix: Name =
if (isModuleClassName) name dropRight MODULE_SUFFIX.length else name
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index f05712d78..621023ab7 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -103,10 +103,12 @@ object SymDenotations {
}
protected[dotc] final def info_=(tp: Type) = {
- if ((this is ModuleClass) && !(this is PackageClass))
+ def illegal: String = s"illegal type for module $this: $tp"
+ if (this is Module) // make sure module invariants that allow moduleClass and sourceModule to work are kept.
tp match {
- case ClassInfo(_, _, _, _, ost) =>
- assert(ost.isInstanceOf[TermRef] || ost.isInstanceOf[TermSymbol], tp)
+ case tp: ClassInfo => assert(tp.selfInfo.isInstanceOf[TermRefBySym], illegal)
+ case tp: NamedType => assert(tp.isInstanceOf[TypeRefBySym], illegal)
+ case tp: ExprType => assert(tp.resultType.isInstanceOf[TypeRefBySym], illegal)
case _ =>
}
myInfo = tp
@@ -458,10 +460,7 @@ object SymDenotations {
case info: LazyType => info.moduleClass
case _ => println(s"missing module class for $name: $myInfo"); NoSymbol
}
- else {
- println(s"missing module class for non-module $name");
- NoSymbol
- }
+ else NoSymbol
/** The module implemented by this module class, NoSymbol if not applicable. */
final def sourceModule: Symbol = myInfo match {
@@ -1062,7 +1061,7 @@ object SymDenotations {
private var myDecls: Scope = EmptyScope
private var mySourceModuleFn: () => Symbol = NoSymbolFn
- private var myModuleClass: Symbol = NoSymbol
+ private var myModuleClassFn: () => Symbol = NoSymbolFn
def proxy: LazyType = new LazyType {
override def complete(denot: SymDenotation) = self.complete(denot)
@@ -1070,11 +1069,11 @@ object SymDenotations {
def decls: Scope = myDecls
def sourceModule: Symbol = mySourceModuleFn()
- def moduleClass: Symbol = myModuleClass
+ def moduleClass: Symbol = myModuleClassFn()
def withDecls(decls: Scope): this.type = { myDecls = decls; this }
def withSourceModule(sourceModule: => Symbol): this.type = { mySourceModuleFn = () => sourceModule; this }
- def withModuleClass(moduleClass: Symbol): this.type = { myModuleClass = moduleClass; this }
+ def withModuleClass(moduleClass: => Symbol): this.type = { myModuleClassFn = () => moduleClass; this }
}
val NoSymbolFn = () => NoSymbol
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index ce26c604e..344508c11 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -794,7 +794,7 @@ class ClassfileParser(
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
val name = getExternalName(in.getChar(start + 1))
- if (name.isModuleClassName) c = cctx.requiredModule(name.stripModuleClassSuffix.asTermName)
+ if (name.isModuleClassName) c = cctx.requiredModule(name.sourceModuleName)
else c = classNameToSymbol(name)
values(index) = c
}
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index d99bc0278..e2f1af5f9 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -456,7 +456,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
val unpickler = new LocalUnpickler() withDecls symScope(cls)
if (flags is ModuleClass)
unpickler withSourceModule (
- cls.owner.decls.lookup(cls.name.stripModuleClassSuffix.toTermName)
+ cls.owner.decls.lookup(cls.name.sourceModuleName)
.suchThat(_ is Module).symbol)
else unpickler
}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index cdda4f05a..0bd841098 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -107,6 +107,14 @@ class Namer { typer: Typer =>
}
}
+ /** Find moduleClass/sourceModule in effective scope */
+ private def findModuleBuddy(name: Name)(implicit ctx: Context) = {
+ val scope = ctx.effectiveScope
+ val it = scope.lookupAll(name).filter(_ is Module)
+ assert(it.hasNext, s"no companion $name in $scope")
+ it.next
+ }
+
/** If this tree is a member def or an import, create a symbol of it
* and store in symOfTree map.
*/
@@ -120,15 +128,29 @@ class Namer { typer: Typer =>
sym
}
+ /** Add moduleClass/sourceModule to completer if it is for a module val or class */
+ def adjustIfModule(completer: LazyType, tree: MemberDef) =
+ if (tree.mods is Module) {
+ val name = tree.name
+ if (name.isTermName)
+ completer withModuleClass findModuleBuddy(name.moduleClassName)
+ else
+ completer withSourceModule findModuleBuddy(name.sourceModuleName)
+ }
+ else completer
+
println(i"creating symbol for $tree")
tree match {
case tree: TypeDef if tree.isClassDef =>
record(tree, ctx.newClassSymbol(
- ctx.owner, tree.name, tree.mods.flags, new Completer(tree) withDecls newScope,
+ ctx.owner, tree.name, tree.mods.flags,
+ adjustIfModule(new Completer(tree), tree),
privateWithinClass(tree.mods), tree.pos, ctx.source.file))
case tree: MemberDef =>
+ var completer = new Completer(tree)
record(tree, ctx.newSymbol(
- ctx.owner, tree.name, tree.mods.flags, new Completer(tree),
+ ctx.owner, tree.name, tree.mods.flags,
+ adjustIfModule(new Completer(tree), tree),
privateWithinClass(tree.mods), tree.pos))
case imp: Import =>
record(imp, ctx.newSymbol(
@@ -252,7 +274,7 @@ class Namer { typer: Typer =>
typer1.defDefSig(tree, sym)(localContext.withTyper(typer1))
case tree: TypeDef =>
if (tree.isClassDef)
- classDefSig(tree, sym.asClass, decls.asInstanceOf[MutableScope])(localContext)
+ classDefSig(tree, sym.asClass)(localContext)
else
typeDefSig(tree, sym)(localContext.withNewScope)
case imp: Import =>
@@ -260,7 +282,50 @@ class Namer { typer: Typer =>
ImportType(tpd.SharedTree(expr1))
}
- sym.info = typeSig(original)
+ /** The type signature of a ClassDef with given symbol */
+ def classDefSig(cdef: TypeDef, cls: ClassSymbol)(implicit ctx: Context): Type = {
+
+ def parentType(constr: untpd.Tree): Type = {
+ val Trees.Select(Trees.New(tpt), _) = methPart(constr)
+ val ptype = typedAheadType(tpt).tpe
+ if (ptype.uninstantiatedTypeParams.isEmpty) ptype
+ else typedAheadExpr(constr).tpe
+ }
+
+ 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
+ }
+ val decls = newScope
+ 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 = adjustIfModule(ClassInfo(cls.owner.thisType, cls, Nil, decls, selfInfo))
+ val parentTypes = parents map parentType
+ val parentRefs = ctx.normalizeToRefs(parentTypes, cls, decls)
+ index(constr)
+ index(rest)(inClassContext(selfInfo))
+ ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
+ }
+
+ def adjustIfModule(sig: Type): Type =
+ if (denot is Module)
+ sig match {
+ case sig: TypeRefBySym =>
+ sig
+ case sig: TypeRef =>
+ TypeRef.withSym(sig.prefix, sig.symbol.asType)
+ case sig: ClassInfo =>
+ sig.derivedClassInfo(sig.prefix, sig.classParents, TermRef.withSym(sig.prefix, sourceModule.asTerm))
+ case _ =>
+ sig
+ }
+ else sig
+
+ sym.info = adjustIfModule(typeSig(original))
}
}
@@ -352,32 +417,4 @@ class Namer { typer: Typer =>
else TypeBounds(rhsType, rhsType)
}
}
-
- /** The type signature of a ClassDef with given symbol */
- def classDefSig(cdef: TypeDef, cls: ClassSymbol, decls: MutableScope)(implicit ctx: Context): Type = {
-
- def parentType(constr: untpd.Tree): Type = {
- val Trees.Select(Trees.New(tpt), _) = methPart(constr)
- val ptype = typedAheadType(tpt).tpe
- if (ptype.uninstantiatedTypeParams.isEmpty) ptype
- else typedAheadExpr(constr).tpe
- }
-
- 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
- }
- 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, selfInfo)
- val parentTypes = parents map parentType
- val parentRefs = ctx.normalizeToRefs(parentTypes, cls, decls)
- index(constr)
- index(rest)(inClassContext(selfInfo))
- ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
- }
} \ No newline at end of file