summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
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/compiler/scala/tools/nsc/typechecker
parent7f3d535727ff3fd8ba38e6fd55d474f76ed3ed90 (diff)
downloadscala-1536b1c67ecff52027a0c24d6791fb978fb88db4.tar.gz
scala-1536b1c67ecff52027a0c24d6791fb978fb88db4.tar.bz2
scala-1536b1c67ecff52027a0c24d6791fb978fb88db4.zip
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-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
6 files changed, 102 insertions, 66 deletions
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