summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-08-21 17:18:33 +0000
committerMartin Odersky <odersky@gmail.com>2006-08-21 17:18:33 +0000
commit1536b1c67ecff52027a0c24d6791fb978fb88db4 (patch)
treeee544f3b5126e4393a2746d0b04281d413b1812e /src
parent7f3d535727ff3fd8ba38e6fd55d474f76ed3ed90 (diff)
downloadscala-1536b1c67ecff52027a0c24d6791fb978fb88db4.tar.gz
scala-1536b1c67ecff52027a0c24d6791fb978fb88db4.tar.bz2
scala-1536b1c67ecff52027a0c24d6791fb978fb88db4.zip
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala13
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala24
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala20
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala22
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala65
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala38
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala27
-rw-r--r--src/compiler/scala/tools/nsc/util/HashSet.scala11
16 files changed, 179 insertions, 98 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 0ba00d49b7..20c5b1ec56 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -191,7 +191,7 @@ abstract class TreeInfo {
case Apply(fn, _) =>
fn.symbol != null &&
!fn.symbol.hasFlag(CASE) &&
- fn.symbol.isSubClass(definitions.SeqClass)
+ fn.symbol.isNonBottomSubClass(definitions.SeqClass)
case Bind(name, body) =>
isSequencePattern(body)
case Alternative(ts) =>
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 5ed234ea19..64daebb8a7 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -56,7 +56,7 @@ abstract class TreePrinters {
def printValueParams(ts: List[ValDef]): unit = {
print("(")
- if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, nme.EMPTY.toTypeName)
+ if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "")
printSeq(ts){printParam}{print(", ")}
print(")")
}
@@ -88,18 +88,17 @@ abstract class TreePrinters {
def printModifiers(tree: Tree, mods: Modifiers): unit = {
if (tree.symbol == NoSymbol)
- printFlags(mods.flags, mods.privateWithin)
+ printFlags(mods.flags, mods.privateWithin.toString)
else if (tree.symbol.privateWithin == NoSymbol ||
tree.symbol.privateWithin == tree.symbol.owner)
- printFlags(tree.symbol.flags, nme.EMPTY.toTypeName)
+ printFlags(tree.symbol.flags, "")
else
- printFlags(tree.symbol.flags, tree.symbol.privateWithin.name)
+ printFlags(tree.symbol.flags, tree.symbol.privateWithin.name.toString)
}
- def printFlags(flags: long, privateWithin: Name): unit = {
+ def printFlags(flags: long, privateWithin: String): unit = {
var mask = if (settings.debug.value) -1 else PrintableFlags
- val s = flagsToString(flags & mask)
- if (!privateWithin.isEmpty) print("private[" + privateWithin + "] ")
+ val s = flagsToString(flags & mask, privateWithin.toString)
if (s.length() != 0) print(s + " ")
}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 61ae3b6013..3c94b9334a 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -1269,6 +1269,12 @@ trait Trees requires Global {
override def traverse(tree: Tree): unit = tree match {
case EmptyTree | TypeTree() =>
;
+ case Template(parents, body) =>
+ tree.symbol = NoSymbol
+ tree.tpe = null
+ for (val stat <- body)
+ if (stat.isDef) erasedSyms.addEntry(stat.symbol)
+ super.traverse(tree)
case _: DefTree =>
erasedSyms.addEntry(tree.symbol)
tree.symbol = NoSymbol
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index b942f73b22..282d2b5ce3 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1132,11 +1132,19 @@ trait Parsers requires SyntaxAnalyzer {
/** Modifiers ::= {Modifier}
* Modifier ::= LocalModifier
- * | private [ "[" Id "]" ]
- * | protected | override
+ * | override
+ * | (private | protected) [ "[" Id "]" ]
*/
def modifiers(): Modifiers = {
var privateWithin: Name = nme.EMPTY.toTypeName;
+ def qualifierOpt: unit =
+ if (in.token == LBRACKET) {
+ in.nextToken()
+ if (privateWithin != nme.EMPTY.toTypeName)
+ syntaxError("duplicate private/protected qualifier", false)
+ privateWithin = ident().toTypeName
+ accept(RBRACKET)
+ }
def loop(mods: int): int = in.token match {
case ABSTRACT =>
loop(addMod(mods, Flags.ABSTRACT))
@@ -1146,15 +1154,13 @@ trait Parsers requires SyntaxAnalyzer {
loop(addMod(mods, Flags.SEALED))
case PRIVATE =>
var mods1 = addMod(mods, Flags.PRIVATE)
- if (in.token == LBRACKET) {
- in.nextToken()
- privateWithin = ident().toTypeName
- accept(RBRACKET)
- mods1 = mods
- }
+ qualifierOpt
+ if (privateWithin != nme.EMPTY.toTypeName) mods1 = mods
loop(mods1)
case PROTECTED =>
- loop(addMod(mods, Flags.PROTECTED))
+ val mods1 = addMod(mods, Flags.PROTECTED)
+ qualifierOpt
+ loop(mods1)
case OVERRIDE =>
loop(addMod(mods, Flags.OVERRIDE))
case IMPLICIT =>
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index cff53734fe..12a56d5dc8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -703,7 +703,7 @@ abstract class GenJVM extends SubComponent {
case Dynamic =>
if (method.owner.hasFlag(Flags.INTERFACE) ||
(method.owner.hasFlag(Flags.JAVA) &&
- method.owner.isSubClass(definitions.AttributeClass)))
+ method.owner.isNonBottomSubClass(definitions.AttributeClass)))
jcode.emitINVOKEINTERFACE(owner,
javaName(method),
javaType(method).asInstanceOf[JMethodType])
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index 12327875a0..eb245709df 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -117,9 +117,24 @@ object Flags {
/** Module flags inherited by their module-class */
final val ModuleToClassFlags = AccessFlags | PACKAGE | CASE;
+ private def listToString(ss: List[String]): String = ss.filter("" !=).mkString("", " ", "")
+
def flagsToString(flags: long): String =
- (for (val i <- List.range(0, 63)) yield flagToString(flags & (1L << i)))
- .filter("" !=).mkString("", " ", "");
+ listToString(for (val i <- List.range(0, 63)) yield flagToString(flags & (1L << i)))
+
+ def flagsToString(flags: long, privateWithin: String): String = {
+ var f = flags;
+ val pw =
+ if (privateWithin == "") {
+ ""
+ } else if ((f & PROTECTED) != 0) {
+ f = f & ~PROTECTED
+ "protected["+privateWithin+"]"
+ } else {
+ "private["+privateWithin+"]"
+ }
+ listToString(List(flagsToString(f), pw))
+ }
private def flagToString(flag: long): String = {
if (flag == IS_ERROR) "<is-error>"
@@ -172,6 +187,7 @@ object Flags {
case _ => ""
}
}
+
class Flag(mods : int) {
def isPrivate = ((mods & PRIVATE ) != 0);
def isProtected = ((mods & PROTECTED) != 0);
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index cdde98a999..03e4549711 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -311,6 +311,16 @@ trait Symbols requires SymbolTable {
final def hasFlag(mask: long): boolean = (flags & mask) != 0
final def resetFlags: unit = { rawflags = rawflags & TopLevelCreationFlags }
+ /** The class up to which this symbol is accessible,
+ * or NoSymbol if it is public or not a class member
+ */
+ final def accessBoundary(base: Symbol): Symbol = {
+ if (hasFlag(PRIVATE)) owner
+ else if (privateWithin != NoSymbol && !phase.erasedTypes) privateWithin
+ else if (hasFlag(PROTECTED)) base
+ else NoSymbol
+ }
+
// Info and Type -------------------------------------------------------------------
private var infos: TypeHistory = null
@@ -446,7 +456,7 @@ trait Symbols requires SymbolTable {
}
def getAttributes(clazz: Symbol): List[AttrInfo] =
- attributes.filter(._1.symbol.isSubClass(clazz))
+ attributes.filter(._1.symbol.isNonBottomSubClass(clazz))
/** Reset symbol to initial state
*/
@@ -484,14 +494,18 @@ trait Symbols requires SymbolTable {
owner == that || owner != NoSymbol && (owner isNestedIn that)
/** Is this class symbol a subclass of that symbol? */
- final def isSubClass(that: Symbol): boolean = (
+ final def isNonBottomSubClass(that: Symbol): boolean = {
this == that || this.isError || that.isError ||
- info.closurePos(that) >= 0 ||
+ info.closurePos(that) >= 0
+ }
+
+ final def isSubClass(that: Symbol): boolean = {
+ isNonBottomSubClass(that) ||
this == AllClass ||
this == AllRefClass &&
(that == AnyClass ||
that != AllClass && (that isSubClass AnyRefClass))
- )
+ }
// Overloaded Alternatives ---------------------------------------------------------
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 15006f7879..cfc4fd7c75 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1326,7 +1326,8 @@ trait Types requires SymbolTable {
case ThisType(sym) =>
def toPrefix(pre: Type, clazz: Symbol): Type =
if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) tp
- else if ((sym isSubClass clazz) && (pre.widen.symbol isSubClass sym)) pre
+ else if ((sym isNonBottomSubClass clazz) &&
+ (pre.widen.symbol isNonBottomSubClass sym)) pre
else toPrefix(pre.baseType(clazz).prefix, clazz.owner);
toPrefix(pre, clazz)
case TypeRef(prefix, sym, args) if (sym.isTypeParameter) =>
@@ -1341,7 +1342,7 @@ trait Types requires SymbolTable {
if (ps.isEmpty) throwError
else if (sym eq ps.head) as.head
else instParam(ps.tail, as.tail);
- if (symclazz == clazz && (pre.widen.symbol isSubClass symclazz))
+ if (symclazz == clazz && (pre.widen.symbol isNonBottomSubClass symclazz))
pre.baseType(symclazz) match {
case TypeRef(_, basesym, baseargs) =>
// System.out.println("instantiating " + sym + " from " + basesym + " with " + basesym.typeParams + " and " + baseargs);//DEBUG
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 98dfb5ef24..0cfb70dc44 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -243,7 +243,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
pt))
}
}
- else if (pt.symbol.isSubClass(BoxedArrayClass) && tree.tpe.symbol == ObjectClass)
+ else if (pt.symbol.isNonBottomSubClass(BoxedArrayClass) && tree.tpe.symbol == ObjectClass)
typed {
atPos(tree.pos) {
evalOnce(tree, x =>
@@ -321,7 +321,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
// convert numeric type casts
atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List()))
else if (isValueClass(targClass) ||
- (targClass == ArrayClass && (qualClass isSubClass BoxedArrayClass)))
+ (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)))
unbox(qual1, targ.tpe)
else if (targClass == ArrayClass && qualClass == ObjectClass)
cast(qual1, targ.tpe)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index b1a4b74133..27f3310c11 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -243,25 +243,22 @@ trait Contexts requires Analyzer {
/** Is `clazz' a subclass of an enclosing class? */
def isSubClassOfEnclosing(clazz: Symbol): boolean = {
var c = this.enclClass
- while (c != NoContext && !clazz.isSubClass(c.owner)) c = c.outer.enclClass
+ while (c != NoContext && !clazz.isNonBottomSubClass(c.owner)) c = c.outer.enclClass
c != NoContext
}
- ( pre == NoPrefix
- ||
- (!sym.hasFlag(PRIVATE | PROTECTED))
- ||
- (accessWithin(sym.owner) || accessWithin(sym.owner.linkedClassOfClass)) &&
- (!sym.hasFlag(LOCAL) || pre =:= sym.owner.thisType)
- ||
- (!sym.hasFlag(PRIVATE) &&
+ (pre == NoPrefix) || {
+ val ab = sym.accessBoundary(sym.owner)
+ ((ab == NoSymbol)
+ ||
+ (accessWithin(ab) || accessWithin(ab.linkedClassOfClass)) &&
+ (!sym.hasFlag(LOCAL) || pre =:= sym.owner.thisType)
+ ||
+ (sym hasFlag PROTECTED) &&
(superAccess ||
- (pre.widen.symbol.isSubClass(sym.owner) && isSubClassOfEnclosing(pre.widen.symbol))))
- ) && (
- sym.privateWithin == NoSymbol
- ||
- phase.erasedTypes || accessWithin(sym.privateWithin)
- )
+ (pre.widen.symbol.isNonBottomSubClass(sym.owner) &&
+ isSubClassOfEnclosing(pre.widen.symbol))))
+ }
}
def pushTypeBounds(sym: Symbol): unit = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index b2cc60b3be..67a7c5e5ec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -20,6 +20,10 @@ trait Infer requires Analyzer {
/* -- Type parameter inference utility functions -------------------------------------- */
+ def assertNonCyclic(tvar: TypeVar) = {
+ assert(tvar.constr.inst != tvar, tvar.origin)
+ }
+
/** The formal parameter types corresponding to `formals'.
* If `formals' has a repeated last parameter, a list of
* (nargs - params.length + 1) copies of its type is returned. */
@@ -58,7 +62,6 @@ trait Infer requires Analyzer {
case WildcardType | NoType =>
throw new NoInstance("undetermined type");
case TypeVar(origin, constr) =>
- assert(constr.inst != null);//debug
if (constr.inst != NoType) instantiate(constr.inst)
else throw new DeferredNoInstance(() =>
"no unique instantiation of type variable " + origin + " could be found");
@@ -131,6 +134,7 @@ trait Infer requires Analyzer {
//Console.println("solveOne2 "+tvar+" "+config+" "+tvar.constr.hibounds);//DEBUG
tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
tvar.constr.inst = if (up) glb(tvar.constr.hibounds) else lub(tvar.constr.lobounds)
+ assertNonCyclic(tvar)//debug
}
}
for (val Pair(tvar, Pair(tparam, variance)) <- config) solveOne(tvar, tparam, variance);
@@ -306,13 +310,16 @@ trait Infer requires Analyzer {
instantiate(tvar.constr.inst)
} else if ((variance & COVARIANT) != 0 && !tvar.constr.hibounds.isEmpty) {
tvar.constr.inst = glb(tvar.constr.hibounds);
+ assertNonCyclic(tvar)//debug
instantiate(tvar.constr.inst)
} else if ((variance & CONTRAVARIANT) != 0 && !tvar.constr.lobounds.isEmpty) {
tvar.constr.inst = lub(tvar.constr.lobounds);
+ assertNonCyclic(tvar)//debug
instantiate(tvar.constr.inst)
} else if (!tvar.constr.hibounds.isEmpty && !tvar.constr.lobounds.isEmpty &&
glb(tvar.constr.hibounds) <:< lub(tvar.constr.lobounds)) {
tvar.constr.inst = glb(tvar.constr.hibounds);
+ assertNonCyclic(tvar)//debug
instantiate(tvar.constr.inst)
} else {
WildcardType
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8089e3079f..f0f19d839d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -91,20 +91,10 @@ trait Namers requires Analyzer {
(!prev.sym.isSourceMethod ||
nme.isSetterName(sym.name) ||
sym.owner.isPackageClass)) {
-/*
- if (sym.sourceFile == null && prev.sym.sourceFile == null) {}
-
- else if (sym.sourceFile != null && prev.sym.sourceFile != null &&
- sym.sourceFile.equals(prev.sym.sourceFile)) {}
- else {
- System.err.println("SYM: " + sym.sourceFile);
- System.err.println("PRV: " + prev.sym.sourceFile);
-*/
- doubleDefError(sym.pos, prev.sym);
-// }
- }
- }
- context.scope enter sym;
+ doubleDefError(sym.pos, prev.sym)
+ sym setInfo ErrorType
+ } else context.scope enter sym
+ } else context.scope enter sym
sym
}
@@ -509,18 +499,41 @@ trait Namers requires Analyzer {
new Namer(context.makeNewScope(tree, sym)).aliasTypeSig(sym, tparams, rhs)
case AbsTypeDef(_, _, lo, hi) =>
- //System.out.println("bounds of " + sym + ":" + sym.tpe + " = " + typer.typedType(hi).tpe);
- TypeBounds(typer.typedType(lo).tpe, typer.typedType(hi).tpe);
+ var lt = typer.typedType(lo).tpe
+ if (lt.isError) lt = AllClass.tpe
+ var ht = typer.typedType(hi).tpe
+ if (ht.isError) ht = AnyClass.tpe
+ TypeBounds(lt, ht)
case Import(expr, selectors) =>
val expr1 = typer.typedQualifier(expr);
val base = expr1.tpe;
typer.checkStable(expr1);
+ def checkNotRedundant(pos: int, from: Name, to: Name): boolean = {
+ if (!base.symbol.isPackage && base.member(from) != NoSymbol) {
+ val e = context.scope.lookupEntry(to)
+ def warnRedundant(sym: Symbol) =
+ context.unit.warning(pos, "imported `"+to+
+ "' is permanently hidden by definition of "+sym+
+ sym.locationString)
+ if (e != null && e.owner == context.scope) {
+ warnRedundant(e.sym); return false
+ } else if (context eq context.enclClass) {
+ val defSym = context.prefix.member(to) filter (
+ sym => sym.exists && context.isAccessible(sym, context.prefix, false))
+ if (defSym != NoSymbol) { warnRedundant(defSym); return false }
+ }
+ }
+ true
+ }
def checkSelectors(selectors: List[Pair[Name, Name]]): unit = selectors match {
case Pair(from, to) :: rest =>
- if (from != nme.WILDCARD && base != ErrorType &&
- base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol)
- context.error(tree.pos, from.decode + " is not a member of " + expr);
+ if (from != nme.WILDCARD && base != ErrorType) {
+ if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol)
+ context.error(tree.pos, from.decode + " is not a member of " + expr);
+ if (checkNotRedundant(tree.pos, from, to))
+ checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName)
+ }
if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from)))
context.error(tree.pos, from.decode + " is renamed twice");
if (to != null && to != nme.WILDCARD && (rest exists (sel => sel._2 == to)))
@@ -597,18 +610,19 @@ trait Namers requires Analyzer {
}
/* Type `elemtp' is contained in type `tp' is one of the following holds:
- * - elemtp is the same as some part of tp
+ * - elemtp is the same as some proper part of tp
* - tp is a function type and elemtp is not
* - tp and elemtp are function types, and arity of tp is greater than arity of elemtp
* - tp and elemtp are both parameterized types with same type constructor and prefix,
* and each type argument of elemtp is contained in the corresponding type argument of tp.
*/
private class ContainsTraverser(elemtp: Type) extends TypeTraverser {
+ var nested = false
var result = false;
def traverse(tp: Type): ContainsTraverser = {
if (!result) {
if (elemtp =:= tp)
- result = true
+ result = nested
else if (isFunctionType(tp) &&
(!isFunctionType(elemtp) || tp.typeArgs.length > elemtp.typeArgs.length))
result = true
@@ -619,7 +633,14 @@ trait Namers requires Analyzer {
case _ =>
}
}
- if (!result) mapOver(tp);
+ if (!result) {
+ tp match {
+ case SingleType(_, _) => nested = true
+ case TypeRef(_, _, _) => nested = true
+ case _ =>
+ }
+ mapOver(tp)
+ }
this
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 5a2d7f8b7b..6a9d3b9ab4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -69,8 +69,6 @@ abstract class RefChecks extends InfoTransform {
* 1.8.2 M is of type []S, O is of type ()T and S <: T, or
* 1.8.3 M is of type ()S, O is of type []T and S <: T, or
* 2. Check that only abstract classes have deferred members
- * 3. Check that every member with an `override' modifier
- * overrides some other member.
*/
private def checkAllOverrides(clazz: Symbol): unit = {
@@ -113,6 +111,14 @@ abstract class RefChecks extends InfoTransform {
}
}
+ def overrideAccessError(): unit = {
+ val pwString = if (other.privateWithin == NoSymbol) ""
+ else other.privateWithin.name.toString
+ val otherAccess = flagsToString(other getFlag (PRIVATE | PROTECTED), pwString)
+ overrideError("has weaker access privileges; it should be "+
+ (if (otherAccess == "") "public" else "at least "+otherAccess))
+ }
+
//System.out.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
// return if we already checked this combination elsewhere
@@ -136,13 +142,16 @@ abstract class RefChecks extends InfoTransform {
}
if (member hasFlag PRIVATE) { // (1.1)
- overrideError("has weaker access privileges; it should not be private");
- } else if (member.privateWithin != NoSymbol &&
- !other.privateWithin.ownerChain.contains(member.privateWithin)) {
- overrideError("has weaker access privileges; it should at least be private["+other.privateWithin.name+"]");
- } else if ((member hasFlag PROTECTED) && !(other hasFlag PROTECTED)) { // 1
- overrideError("has weaker access privileges; it should not be protected");
- } else if (other hasFlag FINAL) { // (1.2)
+ overrideError("has weaker access privileges; it should not be private")
+ }
+ val mb = member.accessBoundary(member.owner)
+ val ob = other.accessBoundary(member.owner)
+ if (mb != NoSymbol &&
+ (ob == NoSymbol ||
+ mb != ob && !(ob.ownerChain contains mb) ||
+ (other hasFlag PROTECTED) && !(member hasFlag PROTECTED))) {
+ overrideAccessError()
+ } else if (other hasFlag FINAL) { // (1.2)
overrideError("cannot override final member");
} else if (!(other hasFlag DEFERRED) && !(member hasFlag (OVERRIDE | ABSOVERRIDE))) { // (1.3)
overrideError("needs `override' modifier");
@@ -230,17 +239,6 @@ abstract class RefChecks extends InfoTransform {
else ""))
}
}
-
- // 3. Check that every defined member with an `override' modifier overrides some other member.
- for (val member <- clazz.info.decls.toList)
- if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
- (clazz.info.baseClasses.tail forall {
- bc => member.matchingSymbol(bc, clazz.thisType) == NoSymbol
- })) {
- // for (val bc <- clazz.info.baseClasses.tail) System.out.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG
- unit.error(member.pos, member.toString() + " overrides nothing");
- member resetFlag OVERRIDE
- }
}
// Basetype Checking --------------------------------------------------------
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 12a289d662..7c71ddbc84 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -30,7 +30,7 @@ trait SyntheticMethods requires Analyzer {
val sym = clazz.info.nonPrivateMember(name)
(sym.isTerm &&
(sym.owner == clazz ||
- !(ObjectClass isSubClass sym.owner) && !(sym hasFlag DEFERRED)))
+ !(ObjectClass isNonBottomSubClass sym.owner) && !(sym hasFlag DEFERRED)))
}
def syntheticMethod(name: Name, flags: Int, tpe: Type) =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 7153fa49eb..c9b75eaf73 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -428,7 +428,7 @@ trait Typers requires Analyzer {
throw t;
}
tree1
- } else if (clazz.isSubClass(SeqClass)) { // (5.2)
+ } else if (clazz.isNonBottomSubClass(SeqClass)) { // (5.2)
val restpe = pt.baseType(clazz)
restpe.baseType(SeqClass) match {
case TypeRef(pre, seqClass, args) =>
@@ -947,8 +947,9 @@ trait Typers requires Analyzer {
else
Triple(FunctionClass(fun.vparams.length), fun.vparams map (x => NoType), WildcardType)
- val Triple(clazz, argpts, respt) =
- decompose(if (!forCLDC && (pt.symbol isSubClass CodeClass)) pt.typeArgs.head else pt)
+ val codeExpected = !forCLDC && (pt.symbol isNonBottomSubClass CodeClass)
+
+ val Triple(clazz, argpts, respt) = decompose(if (codeExpected) pt.typeArgs.head else pt)
if (fun.vparams.length != argpts.length)
errorTree(fun, "wrong number of parameters; expected = "+argpts.length)
@@ -974,7 +975,7 @@ trait Typers requires Analyzer {
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(restpe))
val fun1 = copy.Function(fun, vparams, checkNoEscaping.locals(context.scope, restpe, body))
.setType(funtpe)
- if (!forCLDC && (pt.symbol isSubClass CodeClass)) {
+ if (codeExpected) {
val liftPoint = Apply(Select(Ident(CodeModule), nme.lift_), List(fun1))
typed(atPos(fun.pos)(liftPoint))
} else fun1
@@ -999,8 +1000,20 @@ trait Typers requires Analyzer {
stat.symbol.initialize
EmptyTree
case _ =>
- (if (!inBlock && (!stat.isDef || stat.isInstanceOf[LabelDef]))
- newTyper(context.make(stat, exprOwner)) else this).typed(stat)
+ val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
+ else newTyper(context.make(stat, exprOwner))
+ val stat1 = localTyper.typed(stat)
+ val member = stat1.symbol
+ // Check that every defined member with an `override' modifier
+ // overrides some other member
+ if (stat1.isDef &&
+ (member hasFlag(OVERRIDE | ABSOVERRIDE)) &&
+ (context.owner.info.baseClasses.tail forall
+ (bc => member.matchingSymbol(bc, context.owner.thisType) == NoSymbol))) {
+ error(member.pos, member.toString+" overrides nothing")
+ member resetFlag OVERRIDE
+ }
+ stat1
}
}
val scope = if (inBlock) context.scope else context.owner.info.decls;
@@ -1097,7 +1110,7 @@ trait Typers requires Analyzer {
val args1 = List.map2(args, formals)(typedArgToPoly)
if (args1 exists (.tpe.isError)) setError(tree)
else {
- if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(.tpe)+", pt = "+pt+", lobounds = "+tparams.map(.tpe.bounds.lo));//debug
+ if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(.tpe)+", pt = "+pt+", lobounds = "+tparams.map(.tpe.bounds.lo)+", parambounds = "+tparams.map(.info));//debug
val undetparams = inferMethodInstance(fun, tparams, args1, pt)
val result = typedApply(tree, fun, args1, mode, pt)
context.undetparams = undetparams
diff --git a/src/compiler/scala/tools/nsc/util/HashSet.scala b/src/compiler/scala/tools/nsc/util/HashSet.scala
index de84f9ca77..61ee86e180 100644
--- a/src/compiler/scala/tools/nsc/util/HashSet.scala
+++ b/src/compiler/scala/tools/nsc/util/HashSet.scala
@@ -24,13 +24,16 @@ class HashSet[T >: Null <: AnyRef](initialCapacity: int) extends Set[T] {
}
def addEntry(x: T): unit = {
- if (used >= (capacity >> 2)) growTable;
- used = used + 1;
var h = x.hashCode() % capacity;
- while (table(h) != null) {
+ var entry = table(h);
+ while (entry != null) {
+ if (entry == x) return
h = (h + 1) % capacity
+ entry = table(h)
}
- table(h) = x
+ table(h) = x;
+ used = used + 1;
+ if (used >= (capacity >> 2)) growTable;
}
def elements = new Iterator[T] {