summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2010-05-04 14:40:10 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2010-05-04 14:40:10 +0000
commit185b1c828a7f859b32b136e873373a9b79edc304 (patch)
tree984febdc294a050184ad7f55cb4d3d1bddae75b9 /src/compiler
parent20192c84a98212ba2de6f52553b4ec7dafb6c6c3 (diff)
downloadscala-185b1c828a7f859b32b136e873373a9b79edc304.tar.gz
scala-185b1c828a7f859b32b136e873373a9b79edc304.tar.bz2
scala-185b1c828a7f859b32b136e873373a9b79edc304.zip
close #3384.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala102
3 files changed, 60 insertions, 66 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 8758dd834c..82c4c01b79 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -487,6 +487,15 @@ trait Contexts { self: Analyzer =>
implicitsCache
}
+ /**
+ * Find a symbol in this context or one of its outers.
+ *
+ * Used to find symbols are owned by methods (or fields), they can't be
+ * found in some scope.
+ *
+ * Examples: companion module of classes owned by a method, default getter
+ * methods of nested methods. See NamesDefaults.scala
+ */
def lookup(name: Name, expectedOwner: Symbol) = {
var res: Symbol = NoSymbol
var ctx = this
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index a7f573f98b..37f8a21bf8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -607,17 +607,6 @@ trait Namers { self: Analyzer =>
vparamss.map(_.map(enterValueParam))
}
- /**
- * Finds the companion module of a class symbol. Calling .companionModule
- * does not work for classes defined inside methods.
- */
- private def companionModuleOf(clazz: Symbol) = {
- var res = clazz.companionModule
- if (res == NoSymbol)
- res = context.lookup(clazz.name.toTermName, clazz.owner)
- res
- }
-
private def templateSig(templ: Template): Type = {
val clazz = context.owner
def checkParent(tpt: Tree): Type = {
@@ -738,7 +727,7 @@ trait Namers { self: Analyzer =>
// @check: this seems to work only if the type completer of the class runs before the one of the
// module class: the one from the module class removes the entry form caseClassOfModuleClass (see above).
if (clazz.isClass && !clazz.hasFlag(MODULE)) {
- Namers.this.caseClassOfModuleClass get companionModuleOf(clazz).moduleClass match {
+ Namers.this.caseClassOfModuleClass get companionModuleOf(clazz, context).moduleClass match {
case Some(cdef) =>
def hasCopy(decls: Scope) = {
decls.iterator exists (_.name == nme.copy)
@@ -997,7 +986,7 @@ trait Namers { self: Analyzer =>
val parentNamer = if (isConstr) {
val (cdef, nmr) = moduleNamer.getOrElse {
- val module = companionModuleOf(meth.owner)
+ val module = companionModuleOf(meth.owner, context)
module.initialize // call type completer (typedTemplate), adds the
// module's templateNamer to classAndNamerOfModule
val (cdef, nmr) = classAndNamerOfModule(module)
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 18102a8bb4..ef2c3c3071 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -178,60 +178,52 @@ trait NamesDefaults { self: Analyzer =>
b
}
- def moduleQual(pos: Position, tree: Symbol => Tree) = {
- val module = baseFun.symbol.owner.companionModule
- if (module == NoSymbol) None
- else Some(atPos(pos.focus)(tree(module)))
+ def moduleQual(pos: Position, classType: Type) = {
+ // prefix does 'normalize', which fixes #3384
+ val pre = classType.prefix
+ if (pre == NoType) {
+ None
+ } else {
+ val module = companionModuleOf(baseFun.symbol.owner, context)
+ if (module == NoSymbol) None
+ else Some(atPos(pos.focus)(gen.mkAttributedRef(pre, module)))
+ }
}
baseFun1 match {
// constructor calls
case Select(New(tp @ TypeTree()), _) if isConstr =>
- // fixes #3338. Same qualifier for selecting the companion object as for the class.
- val dq = tp.tpe match {
- case TypeRef(pre, _, _) if (!pre.typeSymbol.isEmptyPackageClass) =>
- moduleQual(tp.pos, mod => gen.mkAttributedSelect(gen.mkAttributedQualifier(pre), mod))
- case _ => None
- }
- blockWithoutQualifier(dq)
+ // 'moduleQual' fixes #3338. Same qualifier for selecting the companion object as for the class.
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
case Select(TypeApply(New(tp @ TypeTree()), _), _) if isConstr =>
- val dq = tp.tpe match {
- case TypeRef(pre, _, _) if (!pre.typeSymbol.isEmptyPackageClass) =>
- moduleQual(tp.pos, mod => gen.mkAttributedSelect(gen.mkAttributedQualifier(pre), mod))
- case _ => None
- }
- blockWithoutQualifier(dq)
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
- case Select(New(Ident(_)), _) if isConstr =>
- blockWithoutQualifier(None)
- case Select(TypeApply(New(Ident(_)), _), _) if isConstr =>
- blockWithoutQualifier(None)
+ case Select(New(tp @ Ident(_)), _) if isConstr =>
+ // 'moduleQual' fixes #3344
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
+ case Select(TypeApply(New(tp @ Ident(_)), _), _) if isConstr =>
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
- case Select(New(Select(qual, _)), _) if isConstr =>
+ case Select(New(tp @ Select(qual, _)), _) if isConstr =>
// in `new q.C()', q is always stable
assert(treeInfo.isPureExpr(qual), qual)
- // #2057
- val defaultQual = moduleQual(qual.pos, mod => gen.mkAttributedSelect(qual.duplicate, mod))
- blockWithoutQualifier(defaultQual)
-
- case Select(TypeApply(New(Select(qual, _)), _), _) if isConstr =>
+ // 'moduleQual' fixes #2057
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
+ case Select(TypeApply(New(tp @ Select(qual, _)), _), _) if isConstr =>
assert(treeInfo.isPureExpr(qual), qual)
- val defaultQual = moduleQual(qual.pos, mod => gen.mkAttributedSelect(qual.duplicate, mod))
- blockWithoutQualifier(defaultQual)
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
// super constructor calls
case Select(sp @ Super(_, _), _) if isConstr =>
- // fix for #3207. selection of the companion module of the superclass
- // needs to have the same prefix as the the superclass.
- val superprefix = sp.symbol.tpe.parents.head.prefix
- val defaultQual = moduleQual(baseFun.pos, mod => gen.mkAttributedRef(superprefix, mod))
- blockWithoutQualifier(defaultQual)
+ // 'moduleQual' fixes #3207. selection of the companion module of the
+ // superclass needs to have the same prefix as the the superclass.
+ blockWithoutQualifier(moduleQual(baseFun.pos, sp.symbol.tpe.parents.head))
// self constructor calls (in secondary constructors)
- case Select(qual, name) if isConstr =>
- assert(treeInfo.isPureExpr(qual), qual)
- blockWithoutQualifier(None)
+ case Select(tp, name) if isConstr =>
+ assert(treeInfo.isPureExpr(tp), tp)
+ blockWithoutQualifier(moduleQual(tp.pos, tp.tpe))
// other method calls
@@ -361,11 +353,8 @@ trait NamesDefaults { self: Analyzer =>
if (missing forall (_.hasFlag(DEFAULTPARAM))) {
val defaultArgs = missing map (p => {
var default1 = qual match {
- case Some(q) => gen.mkAttributedSelect(q.duplicate, defaultGetter(p, context)._1)
- case None =>
- val (m, q) = defaultGetter(p, context)
- if (q.isDefined) gen.mkAttributedSelect(q.get, m)
- else gen.mkAttributedRef(m)
+ case Some(q) => gen.mkAttributedSelect(q.duplicate, defaultGetter(p, context))
+ case None => gen.mkAttributedRef(defaultGetter(p, context))
}
default1 = if (targs.isEmpty) default1
else TypeApply(default1, targs.map(_.duplicate))
@@ -383,32 +372,28 @@ trait NamesDefaults { self: Analyzer =>
/**
* For a parameter with default argument, find the method symbol of
- * the default getter. Can return a qualifier tree for the selecting
- * the method's symbol (part of #3334 fix).
+ * the default getter.
*/
- def defaultGetter(param: Symbol, context: Context): (Symbol, Option[Tree]) = {
+ def defaultGetter(param: Symbol, context: Context): Symbol = {
val i = param.owner.paramss.flatten.findIndexOf(p => p.name == param.name) + 1
if (i > 0) {
if (param.owner.isConstructor) {
val defGetterName = "init$default$"+ i
- var mod = param.owner.owner.companionModule
- // if the class's owner is a method, .companionModule does not work
- if (mod == NoSymbol)
- mod = context.lookup(param.owner.owner.name.toTermName, param.owner.owner.owner)
- (mod.info.member(defGetterName), Some(gen.mkAttributedRef(mod)))
+ val mod = companionModuleOf(param.owner.owner, context)
+ mod.info.member(defGetterName)
} else {
val defGetterName = param.owner.name +"$default$"+ i
// isClass also works for methods in objects, owner is the ModuleClassSymbol
if (param.owner.owner.isClass) {
// .toInterface: otherwise we get the method symbol of the impl class
- (param.owner.owner.toInterface.info.member(defGetterName), None)
+ param.owner.owner.toInterface.info.member(defGetterName)
} else {
// the owner of the method is another method. find the default
// getter in the context.
- (context.lookup(defGetterName, param.owner.owner), None)
+ context.lookup(defGetterName, param.owner.owner)
}
}
- } else (NoSymbol, None)
+ } else NoSymbol
}
/**
@@ -487,4 +472,15 @@ trait NamesDefaults { self: Analyzer =>
}
(namelessArgs, argPos)
}
+
+ /**
+ * Finds the companion module of a class symbol. Calling .companionModule
+ * does not work for classes defined inside methods.
+ */
+ def companionModuleOf(clazz: Symbol, context: Context) = {
+ var res = clazz.companionModule
+ if (res == NoSymbol)
+ res = context.lookup(clazz.name.toTermName, clazz.owner)
+ res
+ }
}