aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Namer.scala
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/dotc/typer/Namer.scala
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/dotc/typer/Namer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala101
1 files changed, 69 insertions, 32 deletions
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