summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-10-22 21:09:11 +0000
committerPaul Phillips <paulp@improving.org>2011-10-22 21:09:11 +0000
commit290f687fb6ab91b6aef62d871036ddc3829f12b4 (patch)
treea55663699fa69315ba4e640252cc6694cbd805d6 /src
parent0c97d8c73fdf4e1dd33ee98ea2e14bc51388bb5f (diff)
downloadscala-290f687fb6ab91b6aef62d871036ddc3829f12b4.tar.gz
scala-290f687fb6ab91b6aef62d871036ddc3829f12b4.tar.bz2
scala-290f687fb6ab91b6aef62d871036ddc3829f12b4.zip
Overhaul of Namers continues.
Starting to see a glimmer of the other side now. I nudged a few things into more sensible places. No review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala8
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala7
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala106
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala493
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala17
8 files changed, 393 insertions, 259 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index c0b894dc01..35069d2edd 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -637,7 +637,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
// Trying to allow for deprecated locations
sym.isAliasType && isMetaAnnotation(sym.info.typeSymbol)
)
-
+ def hasBeanAnnotation(sym: Symbol) = (
+ (sym hasAnnotation BeanPropertyAttr)
+ || (sym hasAnnotation BooleanBeanPropertyAttr)
+ )
lazy val metaAnnotations = Set(
FieldTargetClass, ParamTargetClass,
GetterTargetClass, SetterTargetClass,
@@ -647,8 +650,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val AnnotationDefaultAttr: Symbol = {
val attr = newClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.typeConstructor))
// This attribute needs a constructor so that modifiers in parsed Java code make sense
- attr.info.decls enter (attr newConstructor NoPosition setInfo MethodType(Nil, attr.tpe))
- attr
+ attr.info.decls enter attr.newClassConstructor(NoPosition)
}
def getPackageObjectClass(fullname: Name): Symbol =
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index 61868db3c5..209ca94e50 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -232,6 +232,13 @@ class Flags extends ModifierFlags {
final val FieldFlags: Long =
MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER | LAZY
+ /** Masks for getters and setters, where the flags are derived from those
+ * on the field's modifiers. Both getters and setters get the ACCESSOR flag.
+ * Getters of immutable values also get STABLE.
+ */
+ final val GetterFlags = ~(PRESUPER | MUTABLE)
+ final val SetterFlags = ~(PRESUPER | MUTABLE | STABLE | CASEACCESSOR)
+
/** When a symbol for a default getter is created, it inherits these
* flags from the method with the default. Other flags applied at creation
* time are SYNTHETIC, DEFAULTPARAM, and possibly OVERRIDE.
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 00e9200076..cb4d2bbf94 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -91,8 +91,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
new MethodSymbol(this, pos, name).setFlag(METHOD)
final def newLabel(pos: Position, name: TermName) =
newMethod(pos, name).setFlag(LABEL)
+
+ /** Propagates ConstrFlags (JAVA, specifically) from owner to constructor. */
final def newConstructor(pos: Position) =
- newMethod(pos, nme.CONSTRUCTOR)
+ newMethod(pos, nme.CONSTRUCTOR) setFlag getFlag(ConstrFlags)
+ /** Static constructor with info set. */
+ def newStaticConstructor(pos: Position) =
+ newConstructor(pos) setFlag STATIC setInfo UnitClass.tpe
+ /** Instance constructor with info set. */
+ def newClassConstructor(pos: Position) =
+ newConstructor(pos) setInfo MethodType(Nil, this.tpe)
private def finishModule(m: ModuleSymbol, clazz: ClassSymbol): ModuleSymbol = {
// Top-level objects can be automatically marked final, but others
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 44ac9c68cf..04d0ee3796 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -570,10 +570,7 @@ abstract class ClassfileParser {
(sflags & INTERFACE) == 0L))
{
//Console.println("adding constructor to " + clazz);//DEBUG
- instanceDefs.enter(
- clazz.newConstructor(NoPosition)
- .setFlag(clazz.flags & ConstrFlags)
- .setInfo(MethodType(List(), clazz.tpe)))
+ instanceDefs enter clazz.newClassConstructor(NoPosition)
}
()
} :: loaders.pendingLoadActions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 095ea88a72..7a0a8946f9 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -710,10 +710,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
treeCopy.DefDef(ctor, mods, name, tparams, vparamss, tpt, newBlock)
case None =>
// create new static ctor
- val staticCtorSym = currentClass.newConstructor(template.pos)
- .setFlag(STATIC)
- .setInfo(UnitClass.tpe)
- val rhs = Block(newStaticInits.toList, Literal(Constant()))
+ val staticCtorSym = currentClass.newStaticConstructor(template.pos)
+ val rhs = Block(newStaticInits.toList, Literal(Constant()))
val staticCtorTree = DefDef(staticCtorSym, rhs)
localTyper.typed { atPos(template.pos)(staticCtorTree) }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
new file mode 100644
index 0000000000..882b43bf2b
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -0,0 +1,106 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.tools.nsc
+package typechecker
+
+import symtab.Flags._
+
+object listutil {
+ def mexists[T](xss: List[List[T]])(p: T => Boolean) =
+ xss exists (_ exists p)
+ def mmap[T, U](xss: List[List[T]])(f: T => U) =
+ xss map (_ map f)
+ def mforeach[T](xss: List[List[T]])(f: T => Unit) =
+ xss foreach (_ foreach f)
+ def mfind[T](xss: List[List[T]])(p: T => Boolean): Option[T] = {
+ for (xs <- xss; x <- xs)
+ if (p(x)) return Some(x)
+ None
+ }
+ def mfilter[T](xss: List[List[T]])(p: T => Boolean) =
+ for (xs <- xss; x <- xs; if p(x)) yield x
+}
+
+/** Logic related to method synthesis which involves cooperation between
+ * Namer and Typer.
+ */
+trait MethodSynthesis {
+ self: Analyzer =>
+
+ import global._
+ import definitions._
+
+ trait MethodSynth {
+ self: Namer =>
+
+ private def createAccessorSymbol(tree: ValDef, name: Name, mask: Long): TermSymbol = (
+ context.owner.newMethod(tree.pos.focus, name) setFlag tree.mods.flags & mask
+ )
+
+ // TODO
+ object Derived {
+ def apply(tree: Tree): Derived = tree match {
+ case vd @ ValDef(mods, name, _, _) =>
+ if (mods hasAnnotationNamed tpnme.BeanPropertyAnnot)
+ BeanGetter(vd)
+ else if (mods hasAnnotationNamed tpnme.BooleanBeanPropertyAnnot)
+ BooleanBeanGetter(vd)
+ else
+ NoDerived
+ case _ => NoDerived
+ }
+ }
+ object NoDerived extends Derived {
+ def name = nme.NO_NAME
+ def flagsMask = 0L
+ def flagsExtra = 0L
+ def completer(sym: Symbol) = NoType
+ }
+ trait Derived {
+ def name: TermName
+ def flagsMask: Long
+ def flagsExtra: Long
+ def completer(sym: Symbol): Type
+ }
+ trait DerivedAccessor extends Derived {
+ def tree: ValDef
+ def isSetter: Boolean
+ def completer(sym: Symbol) = namerOf(sym).accessorTypeCompleter(tree, isSetter)
+ def enterAccessor(): Symbol = {
+ val sym = createAccessorSymbol(tree, name, flagsMask) setFlag flagsExtra
+ setPrivateWithin(tree, sym)
+ enterInScope(sym)
+ sym setInfo completer(sym)
+ }
+ }
+ case class Getter(tree: ValDef) extends DerivedAccessor {
+ def name = tree.name
+ def isSetter = false
+ def flagsMask = GetterFlags
+ def flagsExtra = ACCESSOR | ( if (tree.mods.isMutable) 0 else STABLE )
+ }
+ case class Setter(tree: ValDef) extends DerivedAccessor {
+ def name = nme.getterToSetter(tree.name)
+ def isSetter = true
+ def flagsMask = SetterFlags
+ def flagsExtra = ACCESSOR
+ }
+ case class Field(tree: ValDef) extends DerivedAccessor {
+ def name = nme.getterToLocal(tree.name)
+ def isSetter = false
+ def flagsMask = FieldFlags
+ def flagsExtra = PrivateLocal
+ }
+
+ sealed abstract class BeanAccessor(bean: String, val isSetter: Boolean) extends DerivedAccessor {
+ def name = bean + tree.name.toString.capitalize
+ def flagsMask = BeanPropertyFlags
+ def flagsExtra = 0
+ }
+ case class BooleanBeanGetter(tree: ValDef) extends BeanAccessor("is", false)
+ case class BeanGetter(tree: ValDef) extends BeanAccessor("get", false)
+ case class BeanSetter(tree: ValDef) extends BeanAccessor("set", true)
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 34aabe4af7..1f5d891d2e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -7,6 +7,7 @@ package scala.tools.nsc
package typechecker
import scala.collection.mutable
+import scala.annotation.tailrec
import scala.ref.WeakReference
import symtab.Flags._
import scala.tools.nsc.io.AbstractFile
@@ -16,34 +17,15 @@ import scala.tools.nsc.io.AbstractFile
* @author Martin Odersky
* @version 1.0
*/
-trait Namers { self: Analyzer =>
+trait Namers extends MethodSynthesis {
+ self: Analyzer =>
+
import global._
import definitions._
private var _lockedCount = 0
def lockedCount = this._lockedCount
- /** Convert to corresponding type parameters all skolems of method parameters
- * which appear in `tparams`.
- */
- class DeSkolemizeMap(tparams: List[Symbol]) extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args)
- if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) =>
-// println("DESKOLEMIZING "+sym+" in "+sym.owner)
- mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
-/*
- case PolyType(tparams1, restpe) =>
- new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp)
- case ClassInfoType(parents, decls, clazz) =>
- val parents1 = parents mapConserve (this)
- if (parents1 eq parents) tp else ClassInfoType(parents1, decls, clazz)
-*/
- case _ =>
- mapOver(tp)
- }
- }
-
/** Replaces any Idents for which cond is true with fresh TypeTrees().
* Does the same for any trees containing EmptyTrees.
*/
@@ -67,6 +49,8 @@ trait Namers { self: Analyzer =>
private class NormalNamer(context: Context) extends Namer(context)
def newNamer(context: Context): Namer = new NormalNamer(context)
+ def newNamerFor(context: Context, tree: Tree): Namer =
+ newNamer(context.makeNewScope(tree, tree.symbol))
// In the typeCompleter (templateSig) of a case class (resp it's module),
// synthetic `copy` (reps `apply`, `unapply`) methods are added. To compute
@@ -89,19 +73,37 @@ trait Namers { self: Analyzer =>
classAndNamerOfModule.clear()
}
- abstract class Namer(val context: Context) {
+ abstract class Namer(val context: Context) extends MethodSynth {
val typer = newTyper(context)
- private lazy val innerNamer = makeInnerNamer()
+ private lazy val innerNamer =
+ if (isTemplateContext(context)) createInnerNamer() else this
+
+ def createNamer(tree: Tree): Namer = {
+ val sym = tree match {
+ case ModuleDef(_, _, _) => tree.symbol.moduleClass
+ case _ => tree.symbol
+ }
+ newNamer(context.makeNewScope(tree, sym))
+ }
+ def createInnerNamer() = {
+ newNamer(context.make(context.tree, owner, new Scope))
+ }
+ def createPrimaryConstructorParameterNamer: Namer = { //todo: can we merge this with SCCmode?
+ val classContext = context.enclClass
+ val outerContext = classContext.outer.outer
+ val paramContext = outerContext.makeNewScope(outerContext.tree, outerContext.owner)
+
+ owner.unsafeTypeParams foreach (paramContext.scope enter _)
+ newNamer(paramContext)
+ }
def enterValueParams(vparamss: List[List[ValDef]]): List[List[Symbol]] = {
- for (vparams <- vparamss) yield {
- for (param <- vparams) yield {
- val sym = assignSymbol(param, param.name, mask = ValueParameterFlags)
- setPrivateWithin(param, sym)
- enterInScope(sym)
- sym setInfo monoTypeCompleter(param)
- }
+ listutil.mmap(vparamss) { param =>
+ val sym = assignSymbol(param, param.name, mask = ValueParameterFlags)
+ setPrivateWithin(param, sym)
+ enterInScope(sym)
+ sym setInfo monoTypeCompleter(param)
}
}
@@ -113,13 +115,13 @@ trait Namers { self: Analyzer =>
typer.reportTypeError(pos, ex)
alt
}
- private def isPureField(vd: ValDef) = {
+ private def hasNoAccessors(vd: ValDef) = {
val ValDef(mods, name, _, _) = vd
!mods.isLazy && (
!owner.isClass
|| (mods.isPrivateLocal && !mods.isCaseAccessor)
- || name.startsWith(nme.OUTER)
+ || (name startsWith nme.OUTER)
|| isInJava
)
}
@@ -168,31 +170,13 @@ trait Namers { self: Analyzer =>
}
sym
}
- protected def makeConstructorScope(classContext : Context) : Context = {
- val outerContext = classContext.outer.outer
- outerContext.makeNewScope(outerContext.tree, outerContext.owner)
- }
- private def makeInnerNamer() = {
- if (!isTemplateContext(context)) this
- else newNamer(context.make(context.tree, owner, new Scope))
- }
-
def namerOf(sym: Symbol): Namer = {
- def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode?
- val classContext = context.enclClass
- val paramContext = makeConstructorScope(classContext)
- val unsafeTypeParams = owner.unsafeTypeParams
-
- unsafeTypeParams foreach (paramContext.scope enter _)
- newNamer(paramContext)
- }
-
val usePrimary = sym.isTerm && (
(sym.isParamAccessor)
|| (sym.isParameter && sym.owner.isPrimaryConstructor)
)
- if (usePrimary) primaryConstructorParamNamer
+ if (usePrimary) createPrimaryConstructorParameterNamer
else innerNamer
}
@@ -253,7 +237,6 @@ trait Namers { self: Analyzer =>
case tree @ ClassDef(_, _, _, _) => enterClassDef(tree)
case tree @ ModuleDef(_, _, _) => enterModuleDef(tree)
case tree @ ValDef(_, _, _, _) => enterValDef(tree)
- case tree @ DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => enterConstructor(tree)
case tree @ DefDef(_, _, _, _, _, _) => enterDefDef(tree)
case tree @ TypeDef(_, _, _, _) => enterTypeDef(tree)
case DocDef(_, defn) => enterSym(defn)
@@ -287,7 +270,7 @@ trait Namers { self: Analyzer =>
setPrivateWithin(tree, sym)
enterInScope(sym)
}
- def assignAndEnterLazyInfoSymbol(tree: MemberDef): Symbol = {
+ def assignAndEnterFinishedSymbol(tree: MemberDef): Symbol = {
val sym = assignAndEnterSymbol(tree)
sym setInfo completerOf(tree)
log("[+info] " + sym.fullLocationString)
@@ -309,7 +292,7 @@ trait Namers { self: Analyzer =>
val pos = tree.pos
val isParameter = tree.mods.isParameter
val sym = tree match {
- case TypeDef(_, _, _, _) if isParameter => owner.newAbstractType(pos, name.toTypeName)
+ case TypeDef(_, _, _, _) if isParameter => owner.newTypeParameter(pos, name.toTypeName)
case TypeDef(_, _, _, _) => owner.newAliasType(pos, name.toTypeName)
case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => owner.newConstructor(pos)
case DefDef(_, _, _, _, _, _) => owner.newMethod(pos, name.toTermName)
@@ -321,7 +304,6 @@ trait Namers { self: Analyzer =>
}
sym setFlag (tree.mods.flags & mask)
}
-
private def createFieldSymbol(tree: ValDef): TermSymbol = (
owner.newValue(tree.pos, nme.getterToLocal(tree.name))
setFlag tree.mods.flags & FieldFlags | PrivateLocal
@@ -552,12 +534,11 @@ trait Namers { self: Analyzer =>
val mono = namerOf(tree.symbol) monoTypeCompleter tree
if (tparams.isEmpty) mono
else {
- val sym = tree.symbol
//@M! TypeDef's type params are handled differently
//@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x
//@M x is only in scope in `A[x <: B]'
- if (!sym.isAbstractType) //@M TODO: change to isTypeMember ?
- newNamer(context.makeNewScope(tree, sym)) enterSyms tparams
+ if (!tree.symbol.isAbstractType) //@M TODO: change to isTypeMember ?
+ createNamer(tree) enterSyms tparams
new PolyTypeCompleter(tparams, mono, tree, context) //@M
}
@@ -565,16 +546,20 @@ trait Namers { self: Analyzer =>
def enterIfNotThere(sym: Symbol) {
val scope = context.scope
- var e = scope.lookupEntry(sym.name)
- while ((e ne null) && (e.owner eq scope) && (e.sym ne sym)) e = e.tail
- if (!((e ne null) && (e.owner eq scope))) context.scope.enter(sym)
+ @tailrec def search(e: ScopeEntry) {
+ if ((e eq null) || (e.owner ne scope))
+ scope enter sym
+ else if (e.sym ne sym) // otherwise, aborts since we found sym
+ search(e.tail)
+ }
+ search(scope lookupEntry sym.name)
}
def enterValDef(tree: ValDef) {
val ValDef(mods, name, tp, rhs) = tree
- if (isPureField(tree))
- enterPureField(tree)
+ if (hasNoAccessors(tree))
+ assignAndEnterFinishedSymbol(tree)
else {
if (mods.isPrivateLocal && !mods.isLazy)
context.error(tree.pos, "private[this] not allowed for case class parameters")
@@ -582,9 +567,9 @@ trait Namers { self: Analyzer =>
context.error(tree.pos, "Names of vals or vars may not end in `_='")
// add getter and possibly also setter
- val getter = enterGetterDef(tree, name)
+ val getter = enterGetter(tree)
if (mods.isMutable)
- enterSetterDef(tree, name)
+ enterSetter(tree)
tree.symbol = (
if (mods.isDeferred) getter setPos tree.pos // unfocus getter position, no separate value
@@ -593,7 +578,7 @@ trait Namers { self: Analyzer =>
)
if (!forMSIL)
- addBeanGetterSetter(tree, getter)
+ addBeanGetterSetter(tree, getter.owner)
}
}
@@ -604,8 +589,10 @@ trait Namers { self: Analyzer =>
def enterLazyVal(tree: ValDef): TermSymbol = {
// If the owner is not a class, this is a lazy val from a method,
- // and not a field. It has $lzy appended to its name and its flags
- // are different. Unknown: why the IMPLICIT flag is reset.
+ // with no associated field. It has an accessor with $lzy appended to its name and
+ // its flags are set differently. The implicit flag is reset because otherwise
+ // a local implicit "lazy val x" will create an ambiguity with itself
+ // via "x$lzy" as can be seen in test #3927.
val sym = (
if (owner.isClass) createFieldSymbol(tree)
else owner.newValue(tree.pos, tree.name + "$lzy") setFlag tree.mods.flags resetFlag IMPLICIT
@@ -620,19 +607,19 @@ trait Namers { self: Analyzer =>
sym setInfo namerOf(sym).monoTypeCompleter(tree)
}
- def enterConstructor(tree: DefDef) = assignAndEnterLazyInfoSymbol(tree) setFlag owner.getFlag(ConstrFlags)
- def enterTypeDef(tree: TypeDef) = assignAndEnterLazyInfoSymbol(tree)
- def enterPureField(tree: ValDef) = assignAndEnterLazyInfoSymbol(tree)
+ def enterTypeDef(tree: TypeDef) = assignAndEnterFinishedSymbol(tree)
- def enterDefDef(tree: DefDef) {
- val DefDef(mods, name, tparams, _, _, _) = tree
- val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE else 0
- val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag
+ def enterDefDef(tree: DefDef): Unit = tree match {
+ case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) =>
+ assignAndEnterFinishedSymbol(tree)
+ case DefDef(mods, name, tparams, _, _, _) =>
+ val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE else 0
+ val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag
- if (name == nme.copy || (tree.symbol.name.startsWith(nme.copy + nme.DEFAULT_GETTER_STRING)))
- enterCopyMethodOrGetter(tree, tparams)
- else
- sym setInfo completerOf(tree, tparams)
+ if (name == nme.copy || tree.symbol.name.startsWith(nme.copy + nme.DEFAULT_GETTER_STRING))
+ enterCopyMethodOrGetter(tree, tparams)
+ else
+ sym setInfo completerOf(tree, tparams)
}
def enterClassDef(tree: ClassDef) {
@@ -648,7 +635,7 @@ trait Namers { self: Analyzer =>
caseClassOfModuleClass(m.moduleClass) = new WeakReference(tree)
}
val hasDefault = impl.body exists {
- case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => vparamss.flatten exists (_.mods.hasDefault)
+ case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => listutil.mexists(vparamss)(_.mods.hasDefault)
case _ => false
}
if (hasDefault) {
@@ -681,26 +668,15 @@ trait Namers { self: Analyzer =>
this.context
}
+ def enterSetter(tree: ValDef) = Setter(tree).enterAccessor()
+ def enterGetter(tree: ValDef) = Getter(tree).enterAccessor()
def enterSyntheticSym(tree: Tree): Symbol = {
enterSym(tree)
context.unit.synthetics(tree.symbol) = tree
tree.symbol
}
- def enterAccessorMethod(tree: MemberDef, name: Name, flags: Long): Symbol = {
- val sym = owner.newMethod(tree.pos.focus, name.toTermName) setFlag flags
- setPrivateWithin(tree, sym)
- enterInScope(sym)
- }
- def enterGetterDef(tree: ValDef, name: Name) = {
- val getter = enterAccessorMethod(tree, name, getterFlags(tree.mods.flags))
- getter setInfo namerOf(getter).getterTypeCompleter(tree)
- }
- def enterSetterDef(tree: ValDef, name: Name) = {
- val setter = enterAccessorMethod(tree, nme.getterToSetter(name), setterFlags(tree.mods.flags))
- setter setInfo namerOf(setter).setterTypeCompleter(tree)
- }
- private def addBeanGetterSetter(tree: ValDef, getter: Symbol) {
+ private def addBeanGetterSetter(tree: ValDef, inClazz: Symbol) {
val ValDef(mods, name, tpt, _) = tree
val hasBP = mods hasAnnotationNamed tpnme.BeanPropertyAnnot
val hasBoolBP = mods hasAnnotationNamed tpnme.BooleanBeanPropertyAnnot
@@ -712,27 +688,27 @@ trait Namers { self: Analyzer =>
// avoids name clashes with private fields in traits
context.error(tree.pos, "`BeanProperty' annotation can be applied only to non-private fields")
else {
- val flags = mods.flags & BeanPropertyFlags
- val beanName = name.toString.capitalize
- val getterName = if (hasBoolBP) "is" + beanName else "get" + beanName
- val getterMods = Modifiers(flags, mods.privateWithin, Nil) setPositions mods.positions
+ val flags = mods.flags & BeanPropertyFlags
+ val beanName = name.toString.capitalize
+ val getterName: Name = if (hasBoolBP) "is" + beanName else "get" + beanName
+ val getterMods = Modifiers(flags, mods.privateWithin, Nil) setPositions mods.positions
+ // TODO: unify with the other accessor creations
+ // BeanGetter(getterTree).enterAccessor()
enterSyntheticSym {
atPos(tree.pos.focus) {
DefDef(getterMods, getterName, Nil, List(Nil), tpt.duplicate,
if (mods.isDeferred) EmptyTree
- else Select(This(getter.owner.name.toTypeName), name)
+ else Select(This(inClazz), name)
)
}
}
- if (mods.isMutable) {
- // can't use "enterSyntheticSym", because the parameter type is not yet
- // known. instead, uses the same machinery as for the non-bean setter:
- // create and enter the symbol here, add the tree in Typer.addGettterSetter.
- val setter = enterAccessorMethod(tree, "set" + beanName, flags)
- setter setPos tree.pos.focus setInfo namerOf(setter).setterTypeCompleter(tree)
- }
+ // can't use "enterSyntheticSym", because the parameter type is not yet
+ // known. instead, uses the same machinery as for the non-bean setter:
+ // create and enter the symbol here, add the tree in Typer.addGettterSetter.
+ if (mods.isMutable)
+ BeanSetter(tree).enterAccessor()
}
}
}
@@ -752,10 +728,11 @@ trait Namers { self: Analyzer =>
def monoTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym =>
logAndValidate(sym) {
- val tp = initializeLowerBounds(typeSig(tree))
- val info = if (sym.isJavaDefined) RestrictJavaArraysMap(tp) else tp
- sym setInfo info
-
+ val tp = initializeLowerBounds(typeSig(tree))
+ sym setInfo {
+ if (sym.isJavaDefined) RestrictJavaArraysMap(tp)
+ else tp
+ }
// this early test is there to avoid infinite baseTypes when
// adding setters and getters --> bug798
val needsCycleCheck = (sym.isAliasType || sym.isAbstractType) && !sym.isParameter
@@ -772,14 +749,14 @@ trait Namers { self: Analyzer =>
}
}
- def getterTypeCompleter(tree: ValDef) = mkTypeCompleter(tree) { sym =>
- logAndValidate(sym)(sym setInfo NullaryMethodType(typeSig(tree)))
- }
-
- def setterTypeCompleter(tree: ValDef) = mkTypeCompleter(tree) { sym =>
+ def accessorTypeCompleter(tree: ValDef, isSetter: Boolean = false) = mkTypeCompleter(tree) { sym =>
logAndValidate(sym) {
- val param = sym.newSyntheticValueParam(typeSig(tree))
- sym setInfo MethodType(List(param), UnitClass.tpe)
+ sym setInfo {
+ if (isSetter)
+ MethodType(List(sym.newSyntheticValueParam(typeSig(tree))), UnitClass.tpe)
+ else
+ NullaryMethodType(typeSig(tree))
+ }
}
}
@@ -837,29 +814,44 @@ trait Namers { self: Analyzer =>
else if (!sym.isFinal) tpe1
else tpe
}
+ /** Computes the type of the body in a ValDef or DefDef, and
+ * assigns the type to the tpt's node. Returns the type.
+ */
+ private def assignTypeToTree(tree: ValOrDefDef, defnTyper: Typer, pt: Type): Type = {
+ // compute result type from rhs
+ val typedBody = defnTyper.computeType(tree.rhs, pt)
+ val sym = if (owner.isMethod) owner else tree.symbol
+ val typedDefn = widenIfNecessary(sym, typedBody, pt)
- def enterSelf(self: ValDef) {
- val clazz = context.owner
- val ValDef(mods, name, tpt, rhs) = self
+ tree.tpt defineType typedDefn setPos tree.pos.focus
+ tree.tpt.tpe
+ }
- if (!tpt.isEmpty) {
- clazz.typeOfThis = selfTypeCompleter(self.tpt)
- self.symbol = clazz.thisSym.setPos(self.pos)
- }
- else {
- self.tpt defineType NoType
- if (self.name != nme.WILDCARD) {
- clazz.typeOfThis = clazz.tpe
- self.symbol = clazz.thisSym
- }
- else if (self ne emptyValDef) {
- self.symbol = clazz.newThisSym(self.pos) setInfo clazz.tpe
- }
- }
- if (self.name != nme.WILDCARD) {
- self.symbol.name = self.name
- self.symbol = context.scope enter self.symbol
+ // owner is the class with the self type
+ def enterSelf(self: ValDef) {
+ val ValDef(_, name, tpt, _) = self
+ if (self eq emptyValDef)
+ return
+
+ val hasName = name != nme.WILDCARD
+ val hasType = !tpt.isEmpty
+ if (!hasType)
+ tpt defineType NoType
+
+ if (hasType || hasName) {
+ owner.typeOfThis =
+ if (hasType) selfTypeCompleter(tpt)
+ else owner.tpe
}
+ val sym = (
+ if (hasType) owner.thisSym setPos self.pos
+ else if (hasName) owner.thisSym
+ else owner.newThisSym(self.pos) setInfo owner.tpe
+ )
+ if (hasName)
+ sym.name = name
+
+ self.symbol = context.scope enter sym
}
private def templateSig(templ: Template): Type = {
@@ -916,13 +908,6 @@ trait Namers { self: Analyzer =>
case (cdef, _) =>
classAndNamerOfModule(module) = (cdef, templateNamer)
}
-
- debuglog({
- val ps = parents map (_.typeSymbol) mkString ("\n ", ", ", "")
- val ds = decls map (">> " + _) mkString ("\n ", "\n ", "")
-
- "ClassInfoType(%s, %s, %s)".format(ps, ds, clazz)
- })
ClassInfoType(parents, decls, clazz)
}
@@ -933,7 +918,7 @@ trait Namers { self: Analyzer =>
polyType(tparams0, resultType)
}
- private def methodSig(mods: Modifiers, tparams: List[TypeDef],
+ private def methodSig(ddef: DefDef, mods: Modifiers, tparams: List[TypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): Type = {
val meth = owner
val clazz = meth.owner
@@ -941,11 +926,14 @@ trait Namers { self: Analyzer =>
val tparamSyms = typer.reenterTypeParams(tparams)
// since the skolemized tparams are in scope, the TypeRefs in vparamSymss refer to skolemized tparams
var vparamSymss = enterValueParams(vparamss)
+
// DEPMETTODO: do we need to skolemize value parameter symbols?
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) {
tpt defineType context.enclClass.owner.tpe
tpt setPos meth.pos.focus
}
+ var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe
+ val site = clazz.thisType
/** Called for all value parameter lists, right to left
* @param vparams the symbols of one parameter list
@@ -957,11 +945,11 @@ trait Namers { self: Analyzer =>
// enters them in scope, and all have a lazy type. so they may depend on other params. but: need to
// check that params only depend on ones in earlier sections, not the same. (done by checkDependencies,
// so re-use / adapt that)
- val params = vparams map (vparam =>
- if (meth.isJavaDefined) vparam.setInfo(objToAny(vparam.tpe)) else vparam)
- // TODODEPMET necessary?? new dependent types: replace symbols in restpe with the ones in vparams
- if (meth.isJavaDefined) JavaMethodType(params, restpe)
- else MethodType(params, restpe)
+ if (owner.isJavaDefined)
+ // TODODEPMET necessary?? new dependent types: replace symbols in restpe with the ones in vparams
+ JavaMethodType(vparams map (p => p setInfo objToAny(p.tpe)), restpe)
+ else
+ MethodType(vparams, restpe)
}
def thisMethodType(restpe: Type) = {
@@ -978,24 +966,30 @@ trait Namers { self: Analyzer =>
)
}
- var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe
- val site = clazz.thisType
+ def transformedResult =
+ thisMethodType(resultPt).substSym(tparams map (_.symbol), tparamSyms)
- def overriddenSymbol = intersectionType(clazz.info.parents).nonPrivateMember(meth.name).filter(sym => {
- // luc: added .substSym from skolemized to deSkolemized
- // site.memberType(sym): PolyType(tparams, MethodType(..., ...)) ==> all references to tparams are deSkolemized
- // thisMethodType: tparams in PolyType are deSkolemized, the references in the MethodTypes are skolemized. ==> the two didn't match
- // for instance, B.foo would not override A.foo, and the default on parameter b would not be inherited
- // class A { def foo[T](a: T)(b: T = a) = a }
- // class B extends A { override def foo[U](a: U)(b: U) = b }
- sym != NoSymbol && (site.memberType(sym) matches thisMethodType(resultPt).substSym(tparams map (_.symbol), tparamSyms))
- })
+ // luc: added .substSym from skolemized to deSkolemized
+ // site.memberType(sym): PolyType(tparams, MethodType(..., ...))
+ // ==> all references to tparams are deSkolemized
+ // thisMethodType: tparams in PolyType are deSkolemized, the references in the MethodTypes are skolemized.
+ // ==> the two didn't match
+ //
+ // for instance, B.foo would not override A.foo, and the default on parameter b would not be inherited
+ // class A { def foo[T](a: T)(b: T = a) = a }
+ // class B extends A { override def foo[U](a: U)(b: U) = b }
+ def overriddenSymbol =
+ intersectionType(clazz.info.parents).nonPrivateMember(meth.name).filter { sym =>
+ sym != NoSymbol && (site.memberType(sym) matches transformedResult)
+ }
+ // TODO: see whether this or something similar would work instead.
+ //
+ // def overriddenSymbol = meth.nextOverriddenSymbol
// fill in result type and parameter types from overridden symbol if there is a unique one.
- if (clazz.isClass && (tpt.isEmpty || vparamss.exists(_.exists(_.tpt.isEmpty)))) {
+ if (clazz.isClass && (tpt.isEmpty || listutil.mexists(vparamss)(_.tpt.isEmpty))) {
// try to complete from matching definition in base type
- for (vparams <- vparamss; vparam <- vparams)
- if (vparam.tpt.isEmpty) vparam.symbol setInfo WildcardType
+ listutil.mforeach(vparamss)(v => if (v.tpt.isEmpty) v.symbol setInfo WildcardType)
val overridden = overriddenSymbol
if (overridden != NoSymbol && !overridden.isOverloaded) {
overridden.cookJavaRawInfo() // #3404 xform java rawtypes into existentials
@@ -1034,23 +1028,24 @@ trait Namers { self: Analyzer =>
_.info.isInstanceOf[MethodType])) {
vparamSymss = List(List())
}
- for (vparams <- vparamss; vparam <- vparams if vparam.tpt.isEmpty) {
- context.error(vparam.pos, "missing parameter type")
- vparam.tpt defineType ErrorType
+ listutil.mforeach(vparamss) { vparam =>
+ if (vparam.tpt.isEmpty) {
+ context.error(vparam.pos, "missing parameter type")
+ vparam.tpt defineType ErrorType
+ }
}
-
addDefaultGetters(meth, vparamss, tparams, overriddenSymbol)
thisMethodType({
- val rt = if (tpt.isEmpty) {
- // replace deSkolemized symbols with skolemized ones
- // (for resultPt computed by looking at overridden symbol, right?)
- val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
- // compute result type from rhs
- tpt defineType widenIfNecessary(meth, typer.computeType(rhs, pt), pt)
- tpt setPos meth.pos.focus
- tpt.tpe
- } else typer.typedType(tpt).tpe
+ val rt = (
+ if (tpt.isEmpty) {
+ // replace deSkolemized symbols with skolemized ones
+ // (for resultPt computed by looking at overridden symbol, right?)
+ val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
+ assignTypeToTree(ddef, typer, pt)
+ }
+ else typer.typedType(tpt).tpe
+ )
// #2382: return type of default getters are always @uncheckedVariance
if (meth.hasDefaultFlag)
rt.withAnnotation(AnnotationInfo(uncheckedVarianceClass.tpe, List(), List()))
@@ -1110,12 +1105,12 @@ trait Namers { self: Analyzer =>
// Create trees for the defaultGetter. Uses tools from Unapplies.scala
var deftParams = tparams map copyUntyped[TypeDef]
- val defvParamss = previous map (_.map(p => {
+ val defvParamss = listutil.mmap(previous) { p =>
// in the default getter, remove the default parameter
val p1 = atPos(p.pos.focus) { ValDef(p.mods &~ DEFAULTPARAM, p.name, p.tpt.duplicate, EmptyTree) }
UnTyper.traverse(p1)
p1
- }))
+ }
val parentNamer = if (isConstr) {
val (cdef, nmr) = moduleNamer.getOrElse {
@@ -1181,7 +1176,7 @@ trait Namers { self: Analyzer =>
if (overrides) baseParams = baseParams.tail
}
if (overrides) baseParamss = baseParamss.tail
- previous ::: List(vparams)
+ previous :+ vparams
}
}
@@ -1272,42 +1267,42 @@ trait Namers { self: Analyzer =>
// We used to only decorate the module class with annotations, which is
// clearly wrong. Now we decorate both the class and the object.
// But maybe some annotations are only meant for one of these but not for the other?
+ //
+ // TODO: meta-annotations to indicate class vs. object.
annotate(sym)
if (sym.isModule) annotate(sym.moduleClass)
def getSig = tree match {
case ClassDef(_, _, tparams, impl) =>
- newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl)
+ createNamer(tree).classSig(tparams, impl)
case ModuleDef(_, _, impl) =>
val clazz = sym.moduleClass
- val namer = newNamer(context.makeNewScope(tree, clazz))
- val tp = namer templateSig impl
- clazz setInfo tp
- //clazz.typeOfThis = singleType(sym.owner.thisType, sym);
+ clazz setInfo createNamer(tree).templateSig(impl)
clazz.tpe
- case DefDef(mods, _, tparams, vparamss, tpt, rhs) =>
- newNamer(context.makeNewScope(tree, sym)).methodSig(mods, tparams, vparamss, tpt, rhs)
+ case ddef @ DefDef(mods, _, tparams, vparamss, tpt, rhs) =>
+ // TODO: cleanup parameter list
+ createNamer(tree).methodSig(ddef, mods, tparams, vparamss, tpt, rhs)
case vdef @ ValDef(mods, name, tpt, rhs) =>
- val typer1 = typer.constrTyperIf(sym.hasFlag(PARAM | PRESUPER) && !mods.isJavaDefined && sym.owner.isConstructor)
+ val isBeforeSupercall = (
+ (sym hasFlag PARAM | PRESUPER)
+ && !mods.isJavaDefined
+ && sym.owner.isConstructor
+ )
+ val typer1 = typer.constrTyperIf(isBeforeSupercall)
if (tpt.isEmpty) {
if (rhs.isEmpty) {
context.error(tpt.pos, "missing parameter type");
ErrorType
- } else {
- tpt defineType widenIfNecessary(
- sym,
- newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType),
- WildcardType)
- tpt setPos vdef.pos.focus
- tpt.tpe
}
- } else typer1.typedType(tpt).tpe
+ else assignTypeToTree(vdef, newTyper(typer1.context.make(vdef, sym)), WildcardType)
+ }
+ else typer1.typedType(tpt).tpe
case TypeDef(_, _, tparams, rhs) =>
- newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M!
+ createNamer(tree).typeDefSig(sym, tparams, rhs) //@M!
case Import(expr, selectors) =>
val expr1 = typer.typedQualifier(expr)
@@ -1330,10 +1325,8 @@ trait Namers { self: Analyzer =>
catch typeErrorHandler(tree.pos, ErrorType)
result match {
- case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm =>
- new DeSkolemizeMap(tparams) mapOver result
- case _ =>
- result
+ case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => typer.deskolemizeTypeParams(tparams)(result)
+ case _ => result
}
}
@@ -1376,62 +1369,72 @@ trait Namers { self: Analyzer =>
* - declarations only in mixins or abstract classes (when not @native)
*/
def validate(sym: Symbol) {
+ def fail(msg: String) = context.error(sym.pos, msg)
+ def checkWithDeferred(flag: Int) {
+ if (sym hasFlag flag)
+ fail("abstract member may not have " + flagsToString(flag) + " modifier")
+ }
def checkNoConflict(flag1: Int, flag2: Int) {
- if (sym.hasFlag(flag1) && sym.hasFlag(flag2))
- context.error(sym.pos,
- if (flag1 == DEFERRED)
- "abstract member may not have " + flagsToString(flag2) + " modifier";
- else
- "illegal combination of modifiers: " +
- flagsToString(flag1) + " and " + flagsToString(flag2) +
- " for: " + sym);
+ if (sym hasAllFlags flag1 | flag2)
+ fail("illegal combination of modifiers: %s and %s for: %s".format(
+ flagsToString(flag1), flagsToString(flag2), sym))
}
-
- if (sym.isConstructor) {
- if (sym.isAnyOverride)
- context.error(sym.pos, "`override' modifier not allowed for constructors")
- if (sym.isImplicit)
- context.error(sym.pos, "`implicit' modifier not allowed for constructors")
+ if (sym.isImplicit) {
+ if (sym.isConstructor)
+ fail("`implicit' modifier not allowed for constructors")
+ if (!sym.isTerm)
+ fail("`implicit' modifier can be used only for values, variables and methods")
+ if (sym.owner.isPackageClass)
+ fail("`implicit' modifier cannot be used for top-level objects")
+ }
+ if (sym.isClass) {
+ if (sym.isAnyOverride && !sym.hasFlag(TRAIT))
+ fail("`override' modifier not allowed for classes")
+ }
+ else {
+ if (sym.isSealed)
+ fail("`sealed' modifier can be used only for classes")
+ if (sym.hasFlag(ABSTRACT))
+ fail("`abstract' modifier can be used only for classes; it should be omitted for abstract members")
}
- if (sym.hasFlag(IMPLICIT) && !sym.isTerm)
- context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods")
- if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass)
- context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects")
- if (sym.hasFlag(SEALED) && !sym.isClass)
- context.error(sym.pos, "`sealed' modifier can be used only for classes")
- if (sym.hasFlag(ABSTRACT) && !sym.isClass)
- context.error(sym.pos, "`abstract' modifier can be used only for classes; " +
- "\nit should be omitted for abstract members")
- if (sym.isAnyOverride && !sym.hasFlag(TRAIT) && sym.isClass)
- context.error(sym.pos, "`override' modifier not allowed for classes")
+ if (sym.isConstructor && sym.isAnyOverride)
+ fail("`override' modifier not allowed for constructors")
if (sym.isAbstractOverride && !sym.owner.isTrait)
- context.error(sym.pos, "`abstract override' modifier only allowed for members of traits")
+ fail("`abstract override' modifier only allowed for members of traits")
if (sym.isLazy && sym.hasFlag(PRESUPER))
- context.error(sym.pos, "`lazy' definitions may not be initialized early")
- if (sym.info.typeSymbol == FunctionClass(0) &&
- sym.isValueParameter && sym.owner.isCaseClass)
- context.error(sym.pos, "pass-by-name arguments not allowed for case class parameters")
- if (sym hasFlag DEFERRED) { // virtual classes count, too
- if (sym.hasAnnotation(NativeAttr))
- sym.resetFlag(DEFERRED)
- else if (!sym.isValueParameter && !sym.isTypeParameterOrSkolem &&
- !context.tree.isInstanceOf[ExistentialTypeTree] &&
- (!sym.owner.isClass || sym.owner.isModuleClass || sym.owner.isAnonymousClass)) {
- context.error(sym.pos,
- "only classes can have declared but undefined members" + abstractVarMessage(sym))
- sym.resetFlag(DEFERRED)
+ fail("`lazy' definitions may not be initialized early")
+ if (sym.info.typeSymbol == FunctionClass(0) && sym.isValueParameter && sym.owner.isCaseClass)
+ fail("pass-by-name arguments not allowed for case class parameters")
+
+ if (sym.isDeferred) {
+ // Is this symbol type always allowed the deferred flag?
+ def symbolAllowsDeferred = (
+ sym.isValueParameter
+ || sym.isTypeParameterOrSkolem
+ || context.tree.isInstanceOf[ExistentialTypeTree]
+ )
+ // Does the symbol owner require no undefined members?
+ def ownerRequiresConcrete = (
+ !sym.owner.isClass
+ || sym.owner.isModuleClass
+ || sym.owner.isAnonymousClass
+ )
+ if (sym hasAnnotation NativeAttr)
+ sym resetFlag DEFERRED
+ else if (!symbolAllowsDeferred && ownerRequiresConcrete) {
+ fail("only classes can have declared but undefined members" + abstractVarMessage(sym))
+ sym resetFlag DEFERRED
}
+ checkWithDeferred(PRIVATE)
+ checkWithDeferred(FINAL)
}
- checkNoConflict(DEFERRED, PRIVATE)
checkNoConflict(FINAL, SEALED)
checkNoConflict(PRIVATE, PROTECTED)
// checkNoConflict(PRIVATE, OVERRIDE) // this one leads to bad error messages like #4174, so catch in refchecks
// checkNoConflict(PRIVATE, FINAL) // can't do this because FINAL also means compile-time constant
checkNoConflict(ABSTRACT, FINAL)
- checkNoConflict(DEFERRED, FINAL)
-
// @PP: I added this as a sanity check because these flags are supposed to be
// converted to ABSOVERRIDE before arriving here.
checkNoConflict(ABSTRACT, OVERRIDE)
@@ -1470,7 +1473,7 @@ trait Namers { self: Analyzer =>
// @M an abstract type's type parameters are entered.
// TODO: change to isTypeMember ?
if (ownerSym.isAbstractType)
- newNamer(ctx.makeNewScope(owner, ownerSym)) enterSyms tparams //@M
+ newNamerFor(ctx, owner) enterSyms tparams //@M
restp complete sym
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e2e23f6f7e..cdcc3ad044 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1455,8 +1455,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val setter = getter.setter(value.owner)
gs.append(setterDef(setter))
}
- if (!forMSIL && (value.hasAnnotation(BeanPropertyAttr) ||
- value.hasAnnotation(BooleanBeanPropertyAttr))) {
+ if (!forMSIL && hasBeanAnnotation(value)) {
val nameSuffix = name.toString.capitalize
val beanGetterName =
(if (value.hasAnnotation(BooleanBeanPropertyAttr)) "is" else "get") +
@@ -3019,6 +3018,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
(new Deskolemizer).substitute()
}
+ /** Convert to corresponding type parameters all skolems of method
+ * parameters which appear in `tparams`.
+ */
+ def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
+ class DeSkolemizeMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
+ mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ new DeSkolemizeMap mapOver tp
+ }
protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = {
for (wc <- tree.whereClauses)