summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-12 18:23:58 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-12 18:23:58 +0000
commiteecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043 (patch)
treed6e914ff40d9b3499ac64856e6f37b7c394298c9 /src/compiler/scala/tools
parent5d449bfbc1a39aaf2cb78f04241990c8c6c37d5f (diff)
downloadscala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.tar.gz
scala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.tar.bz2
scala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.zip
added early field initialization.
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala14
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala176
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala29
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
9 files changed, 159 insertions, 96 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index c94ed6c94e..dd837012d9 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -452,11 +452,19 @@ trait Trees requires Global {
ret.symbol = vd.symbol
ret
}))
+ val (vdefs, rest) = body span treeInfo.isPreSuper
+ val (lvdefs, gvdefs) = List.unzip {
+ vdefs map {
+ case vdef @ ValDef(mods, name, tpt, rhs) =>
+ (copy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs),
+ copy.ValDef(vdef, mods, name, TypeTree(), EmptyTree))
+ }
+ }
val constrs =
if (constrMods hasFlag TRAIT) {
if (body forall treeInfo.isInterfaceMember) List()
else List(
- DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(), Literal(()))))
+ DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(()))))
} else {
if (vparamss1.isEmpty ||
!vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0)
@@ -464,9 +472,9 @@ trait Trees requires Global {
val superRef: Tree = Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR)
val superCall = posAssigner.atPos(parents.head.pos) { (superRef /: argss) (Apply) }
List(
- DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(List(superCall), Literal(()))))
+ DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(()))))
}
- Template(parents, List.flatten(vparamss) ::: constrs ::: body)
+ Template(parents, gvdefs ::: List.flatten(vparamss) ::: constrs ::: rest)
}
/** Block of expressions (semicolon separated expressions) */
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 1868ab2108..45beab0d28 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1009,7 +1009,7 @@ trait Parsers requires SyntaxAnalyzer {
}
}
- /* SimpleExpr ::= new AnnotType {`(' [Exprs [`,']] `)'} {`with' AnnotType} [TemplateBody]
+ /* SimpleExpr ::= new ClassTemplate
* | BlockExpr
* | SimpleExpr1
* SimpleExpr1 ::= literal
@@ -1047,19 +1047,8 @@ trait Parsers requires SyntaxAnalyzer {
canApply = false
case NEW =>
t = atPos(in.skipToken()) {
- val parents = new ListBuffer[Tree] + annotType(false)
- val argss = new ListBuffer[List[Tree]]
- if (in.token == LPAREN)
- do { argss += argumentExprs() } while (in.token == LPAREN)
- else argss += List()
- while (in.token == WITH) {
- in.nextToken()
- parents += annotType(false)
- }
- newLineOptWhenFollowedBy(LBRACE)
- val (self, stats) = if (in.token == LBRACE) templateBody()
- else (emptyValDef, List())
- makeNew(parents.toList, self, stats, argss.toList)
+ val (parents, argss, self, stats) = template(false)
+ makeNew(parents, self, stats, argss)
}
canApply = false
case _ =>
@@ -1133,50 +1122,54 @@ trait Parsers requires SyntaxAnalyzer {
ts.toList
}
- /** CaseClause : =>= case Pattern [if PostfixExpr] `=>' Block
+ /** CaseClause ::= case Pattern [Guard] `=>' Block
*/
def caseClause(): CaseDef =
atPos(accept(CASE)) {
val pat = pattern()
- val guard =
- if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) }
- else EmptyTree
- makeCaseDef(pat, guard, atPos(accept(ARROW))(block()))
+ val gd = guard()
+ makeCaseDef(pat, gd, atPos(accept(ARROW))(block()))
}
+ /** Guard ::= if PostfixExpr
+ */
+ def guard(): Tree =
+ if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) }
+ else EmptyTree
+
/** Enumerators ::= Generator {semi Enumerator}
- * Enumerator ::= Generator
- * | val Pattern1 `=' Expr
- * | Expr
+ * Enumerator ::= Generator
+ * | Guard
+ * | val Pattern1 `=' Expr
*/
def enumerators(): List[Enumerator] = {
val newStyle = in.token != VAL
- val enums = new ListBuffer[Enumerator] + generator(false)
+ val enums = new ListBuffer[Enumerator]
+ generator(enums, false)
while (isStatSep) {
in.nextToken()
- enums += {
- if (newStyle) {
- if (in.token == IF) { in.nextToken(); Filter(expr()) }
- else generator(true)
- } else {
- if (in.token == VAL) generator(true)
- else Filter(expr())
- }
+ if (newStyle) {
+ if (in.token == IF) enums += Filter(guard())
+ else generator(enums, true)
+ } else {
+ if (in.token == VAL) generator(enums, true)
+ else enums += Filter(expr())
}
}
enums.toList
}
- /** Generator ::= val Pattern1 `<-' Expr
+ /** Generator ::= val Pattern1 `<-' Expr [Guard]
*/
- def generator(eqOK: boolean): Enumerator = {
+ def generator(enums: ListBuffer[Enumerator], eqOK: boolean) {
val pos = in.currentPos;
if (in.token == VAL) in.nextToken()
val pat = pattern1(false)
val tok = in.token
if (tok == EQUALS && eqOK) in.nextToken()
else accept(LARROW)
- makeGenerator(pos, pat, tok == EQUALS, expr)
+ enums += makeGenerator(pos, pat, tok == EQUALS, expr)
+ if (in.token == IF) enums += Filter(guard())
}
//////// PATTERNS ////////////////////////////////////////////////////////////
@@ -1972,8 +1965,8 @@ trait Parsers requires SyntaxAnalyzer {
}
/** ClassDef ::= Id [TypeParamClause] Annotations
- [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplate
- * TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplate
+ [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplateOpt
+ * TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt
*/
def classDef(mods: Modifiers): ClassDef =
atPos(in.skipToken()) {
@@ -1992,7 +1985,7 @@ trait Parsers requires SyntaxAnalyzer {
else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE)))
val thistpe = requiresTypeOpt()
val (self0, template) =
- classTemplate(mods, name, constrMods withAnnotations constrAnnots, vparamss)
+ templateOpt(mods, name, constrMods withAnnotations constrAnnots, vparamss)
val mods1 = if (mods.hasFlag(Flags.TRAIT) &&
(template.body forall treeInfo.isInterfaceMember))
mods | Flags.INTERFACE
@@ -2003,12 +1996,12 @@ trait Parsers requires SyntaxAnalyzer {
result
}
- /** ObjectDef ::= Id ClassTemplate
+ /** ObjectDef ::= Id ClassTemplateOpt
*/
def objectDef(mods: Modifiers): ModuleDef =
atPos(in.skipToken()) {
val name = ident()
- val (self, template0) = classTemplate(mods, name, NoMods, List())
+ val (self, template0) = templateOpt(mods, name, NoMods, List())
val template = self match {
case ValDef(mods, name, tpt, EmptyTree) if (name != nme.WILDCARD) =>
val vd = ValDef(mods, name, tpt, This(nme.EMPTY.toTypeName)) setPos self.pos
@@ -2019,12 +2012,58 @@ trait Parsers requires SyntaxAnalyzer {
ModuleDef(mods, name, template)
}
- /** ClassTemplate ::= [extends TemplateParents] [TemplateBody]
- * TemplateParents ::= AnnotType {`(' [Exprs] `)'} {`with' AnnotType}
- * TraitTemplate ::= [extends MixinParents] [TemplateBody]
- * MixinParents ::= AnnotType {with AnnotType}
+
+ /** ClassParents ::= AnnotType {`(' [Exprs [`,']] `)'} {with AnnotType}
+ * TraitParents ::= AnnotType {with AnnotType}
+ */
+ def templateParents(isTrait: boolean): (List[Tree], List[List[Tree]]) = {
+ val parents = new ListBuffer[Tree] + annotType(false)
+ val argss = new ListBuffer[List[Tree]]
+ if (in.token == LPAREN && !isTrait)
+ do { argss += argumentExprs() } while (in.token == LPAREN)
+ else argss += List()
+ while (in.token == WITH) {
+ in.nextToken()
+ parents += annotType(false)
+ }
+ (parents.toList, argss.toList)
+ }
+
+ /** ClassTemplate ::= [EarlyDefs with] ClassParents [TemplateBody]
+ * TraitTemplate ::= [EarlyDefs with] TraitParents [TemplateBody]
+ * EarlyDefs ::= `{' [EarlyDef {semi EarlyDef}] `}'
+ * EarlyDef ::= Annotations Modifiers PatDef
*/
- def classTemplate(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): (ValDef, Template) = {
+ def template(isTrait: boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = {
+ newLineOptWhenFollowedBy(LBRACE)
+ if (in.token == LBRACE) {
+ val (self, body) = templateBody()
+ if (in.token == WITH && (self eq emptyValDef)) {
+ val vdefs: List[ValDef] = body flatMap {
+ case vdef @ ValDef(mods, name, tpt, rhs) if !(mods hasFlag Flags.DEFERRED) =>
+ List(copy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs))
+ case stat =>
+ syntaxError(stat.pos, "only concrete field definitions allowed in early object initialization section", false)
+ List()
+ }
+ in.nextToken()
+ val (parents, argss) = templateParents(isTrait)
+ val (self1, body1) = templateBodyOpt()
+ (parents, argss, self1, vdefs ::: body1)
+ } else {
+ (List(), List(List()), self, body)
+ }
+ } else {
+ val (parents, argss) = templateParents(isTrait)
+ val (self, body) = templateBodyOpt()
+ (parents, argss, self, body)
+ }
+ }
+
+ /** ClassTemplateOpt ::= [extends ClassTemplate | TemplateBody]
+ * TraitTemplateOpt ::= [extends TraitTemplate | TemplateBody]
+ */
+ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): (ValDef, Template) = {
val pos = in.currentPos;
def acceptEmptyTemplateBody(msg: String): unit = {
if (in.token == LPAREN && settings.migrate.value)
@@ -2032,38 +2071,21 @@ trait Parsers requires SyntaxAnalyzer {
if (!(isStatSep || in.token == COMMA || in.token == RBRACE || in.token == EOF))
syntaxError(msg, true)
}
- val parents = new ListBuffer[Tree]
- val argss = new ListBuffer[List[Tree]]
- if (in.token == EXTENDS) {
- in.nextToken()
- val parent = annotType(false)
- // System.err.println("classTempl: " + parent)
- parents += parent
- if (in.token == LPAREN && !mods.hasFlag(Flags.TRAIT))
- do { argss += argumentExprs() } while (in.token == LPAREN)
- else argss += List()
- while (in.token == WITH) {
+ val (parents0, argss, self, body) =
+ if (in.token == EXTENDS) {
in.nextToken()
- parents += annotType(false)
+ template(mods hasFlag Flags.TRAIT)
+ } else {
+ newLineOptWhenFollowedBy(LBRACE)
+ val (self, body) =
+ if (in.token == LBRACE) templateBody()
+ else { acceptEmptyTemplateBody("`extends' or `{' expected"); (emptyValDef, List()) }
+ (List(), List(List()), self, body)
}
- } else {
- if (in.token == WITH && settings.migrate.value)
- syntaxErrorMigrate("`extends' needed before `with'")
- newLineOptWhenFollowedBy(LBRACE)
- if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected")
- argss += List()
- }
- if (name != nme.ScalaObject.toTypeName)
- parents += scalaScalaObjectConstr
- if (mods.hasFlag(Flags.CASE)) {
- parents += productConstr
- }
- val ps = parents.toList
- newLineOptWhenFollowedBy(LBRACE)
- val (self, body) =
- if (in.token == LBRACE) templateBody()
- else { acceptEmptyTemplateBody("`{' expected"); (emptyValDef, List()) }
- (self, atPos(pos) { Template(ps, constrMods, vparamss, argss.toList, body) })
+ var parents = parents0
+ if (name != nme.ScalaObject.toTypeName) parents = parents ::: List(scalaScalaObjectConstr)
+ if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr)
+ (self, atPos(pos) { Template(parents, constrMods, vparamss, argss, body) })
}
////////// TEMPLATES ////////////////////////////////////////////////////////////
@@ -2077,6 +2099,12 @@ trait Parsers requires SyntaxAnalyzer {
if (stats.isEmpty) (self, List(EmptyTree)) else result
}
+ def templateBodyOpt(): (ValDef, List[Tree]) = {
+ newLineOptWhenFollowedBy(LBRACE)
+ if (in.token == LBRACE) templateBody()
+ else (emptyValDef, List())
+ }
+
/** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}'
*/
def refinement(): List[Tree] = {
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index a0fffdbbef..ae712c7deb 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -123,6 +123,10 @@ trait Definitions requires SymbolTable {
typeRef(sym.typeConstructor.prefix, sym, elems)
} else NoType;
+ var ProductRootClass: Symbol = _
+ def Product_productArity = getMember(ProductRootClass, nme.productArity)
+ def Product_productElement = getMember(ProductRootClass, nme.productElement)
+ def Product_productPrefix = getMember(ProductRootClass, nme.productPrefix)
val MaxProductArity = 22
/* <unapply> */
val ProductClass: Array[Symbol] = new Array(MaxProductArity + 1)
@@ -791,6 +795,7 @@ trait Definitions requires SymbolTable {
//UnsealedClass = getClass("scala.unsealed") //todo: remove once 2.4 is out.
UncheckedClass = getClass("scala.unchecked")
OptionClass = getClass("scala.Option")
+ ProductRootClass = getClass("scala.Product")
for (val i <- 1 to MaxTupleArity) {
TupleClass(i) = getClass( "scala.Tuple" + i)
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 2566e687b0..3e8e7792ae 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -113,7 +113,7 @@ object Flags {
ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC
final val FieldFlags =
- MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL
+ MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER
final val AccessFlags = PRIVATE | PROTECTED
final val VARIANCES = COVARIANT | CONTRAVARIANT
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index fcb09f31e9..f7f7a7869d 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1319,7 +1319,7 @@ trait Types requires SymbolTable {
if(attributes.isEmpty)
""
else
- attributes.mkString("", " ", "")
+ attributes.mkString("@", " @", " ")
attString + tp
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index d9355bf24e..71f9c9d828 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -120,7 +120,25 @@ abstract class Constructors extends Transform {
val defBuf = new ListBuffer[Tree]
val constrStatBuf = new ListBuffer[Tree]
val constrPrefixBuf = new ListBuffer[Tree]
- constrBody.stats foreach (constrStatBuf +=)
+ val presupers = treeInfo.preSuperFields(stats)
+ for (val stat <- constrBody.stats) {
+ constrStatBuf += stat
+ stat match {
+ case ValDef(mods, name, _, _) if (mods hasFlag PRESUPER) =>
+ constrStatBuf +=
+ localTyper.typed {
+ atPos(stat.pos) {
+ val fields = presupers filter (
+ vdef => nme.localToGetter(vdef.name) == name)
+ assert(fields.length == 1)
+ Assign(
+ gen.mkAttributedRef(clazz.thisType, fields.head.symbol),
+ Ident(stat.symbol))
+ }
+ }
+ case _ =>
+ }
+ }
for (val stat <- stats) stat match {
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index eafe154756..d7554ea95d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -305,7 +305,8 @@ trait Namers requires Analyzer {
case ValDef(mods, name, tp, rhs) =>
if (context.owner.isClass && (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)) {
val accflags = ACCESSOR |
- (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE else mods.flags | STABLE)
+ (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER
+ else mods.flags & ~PRESUPER | STABLE)
val getter = owner.newMethod(tree.pos, name).setFlag(accflags)
getter.setInfo(namerOf(getter).getterTypeCompleter(tree))
setPrivateWithin(tree, getter, mods)
@@ -668,7 +669,7 @@ trait Namers requires Analyzer {
ErrorType
} else {
tpt.tpe = deconstIfNotFinal(sym,
- newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType))
+ newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType))
tpt.tpe
}
} else typer1.typedType(tpt).tpe
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index b66a534c89..07b95fe0f7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -40,16 +40,17 @@ trait SyntheticMethods requires Analyzer {
*/
def addSyntheticMethods(templ: Template, clazz: Symbol, unit: CompilationUnit): Template = {
- def hasImplementation(name: Name): Boolean = {
+ def hasImplementation(name: Name): boolean = {
val sym = clazz.info.nonPrivateMember(name)
- (sym.isTerm &&
- (sym.owner == clazz ||
- !(ObjectClass isNonBottomSubClass sym.owner) && !(sym hasFlag DEFERRED)))
+ sym.isTerm && !(sym hasFlag DEFERRED)
}
- def hasDirectImplementation(name: Name): Boolean = {
- val sym = clazz.info.nonPrivateMember(name)
- (sym.isTerm && sym.owner == clazz)
+ def hasOverridingImplementation(meth: Symbol): boolean = {
+ val sym = clazz.info.nonPrivateMember(meth.name)
+ sym.alternatives exists { sym =>
+ sym != meth && !(sym hasFlag DEFERRED) &&
+ (clazz.thisType.memberType(sym) matches clazz.thisType.memberType(meth))
+ }
}
def syntheticMethod(name: Name, flags: Int, tpe: Type) =
@@ -239,22 +240,22 @@ trait SyntheticMethods requires Analyzer {
if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
if (clazz.isModuleClass) {
- if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod
+ if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
} else {
- if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_)
- if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_)
- if (!hasImplementation(nme.equals_)) ts += equalsMethod
+ if (!hasOverridingImplementation(Object_hashCode)) ts += forwardingMethod(nme.hashCode_)
+ if (!hasOverridingImplementation(Object_toString)) ts += forwardingMethod(nme.toString_)
+ if (!hasOverridingImplementation(Object_equals)) ts += equalsMethod
}
- if (!hasDirectImplementation(nme.productPrefix)) ts += productPrefixMethod
+ if (!hasOverridingImplementation(Product_productPrefix)) ts += productPrefixMethod
val accessors = clazz.caseFieldAccessors
if (!hasImplementation("arity")) // remove after starr update
ts += OLDproductArityMethod(accessors.length)
- if (!hasImplementation(nme.productArity))
+ if (!hasOverridingImplementation(Product_productArity))
ts += productArityMethod(accessors.length)
if (!hasImplementation("element")) // remove after starr update
ts += OLDproductElementMethod(accessors)
- if (!hasImplementation(nme.productElement))
+ if (!hasOverridingImplementation(Product_productElement))
ts += productElementMethod(accessors)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 5d1b3e6310..cde3d11de2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -6,6 +6,8 @@
//todo: rewrite or disllow new T where T is a mixin (currently: <init> not a member of T)
//todo: use inherited type info also for vars and values
+//todo: disallow C#D in superclass
+//todo: treat :::= correctly
package scala.tools.nsc.typechecker
import scala.collection.mutable.{HashMap, ListBuffer}