summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2008-12-08 19:06:16 +0000
committerMartin Odersky <odersky@gmail.com>2008-12-08 19:06:16 +0000
commit0dde1442dca20cec6142d012b12398d99c1e6b82 (patch)
tree00cf4270efa5839b9744916ca6dba563b4e2c2dc /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parentc8107b0d95890b29ffebe101fc54ce0885511de4 (diff)
downloadscala-0dde1442dca20cec6142d012b12398d99c1e6b82.tar.gz
scala-0dde1442dca20cec6142d012b12398d99c1e6b82.tar.bz2
scala-0dde1442dca20cec6142d012b12398d99c1e6b82.zip
added comments; better errror messages; trace u...
added comments; better errror messages; trace utility
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala49
1 files changed, 36 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index d1f0edc7c1..486fe6b391 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -10,6 +10,7 @@ import symtab.Flags._
import collection.mutable.{HashSet, HashMap}
import transform.InfoTransform
import scala.tools.nsc.util.{Position, NoPosition}
+import scala.collection.mutable.ListBuffer
/** <p>
* Post-attribution checking and transformation.
@@ -92,6 +93,21 @@ abstract class RefChecks extends InfoTransform {
*/
private def checkAllOverrides(clazz: Symbol) {
+ case class MixinOverrideError(member: Symbol, msg: String)
+
+ var mixinOverrideErrors = new ListBuffer[MixinOverrideError]()
+
+ def printMixinOverrideErrors() {
+ mixinOverrideErrors.toList match {
+ case List() =>
+ case List(MixinOverrideError(_, msg)) =>
+ unit.error(clazz.pos, msg)
+ case MixinOverrideError(member, msg) :: others =>
+ unit.error(clazz.pos, msg+";\n other members with override errors are: "+
+ (others.map(_.member.name).filter(member.name != _).removeDuplicates mkString ", "))
+ }
+ }
+
val self = clazz.thisType
def isAbstractTypeWithoutFBound(sym: Symbol) = // (part of DEVIRTUALIZE)
@@ -130,18 +146,19 @@ abstract class RefChecks extends InfoTransform {
* <code>member</code> are met.
*/
def checkOverride(clazz: Symbol, member: Symbol, other: Symbol) {
- val pos = if (member.owner == clazz) member.pos else clazz.pos
def overrideError(msg: String) {
- if (other.tpe != ErrorType && member.tpe != ErrorType)
- unit.error(pos, "overriding " + infoStringWithLocation(other) +
- ";\n " + infoString(member) + " " + msg +
- (if ((other.owner isSubClass member.owner) &&
- other.isDeferred && !member.isDeferred)
- ";\n (Note that "+infoStringWithLocation(other)+" is abstract,"+
- "\n and is therefore overridden by concrete "+
- infoStringWithLocation(member)+")"
- else ""))
+ if (other.tpe != ErrorType && member.tpe != ErrorType) {
+ val fullmsg =
+ "overriding "+infoStringWithLocation(other)+";\n "+
+ infoString(member)+" "+msg+
+ (if ((other.owner isSubClass member.owner) && other.isDeferred && !member.isDeferred)
+ ";\n (Note that "+infoStringWithLocation(other)+" is abstract,"+
+ "\n and is therefore overridden by concrete "+infoStringWithLocation(member)+")"
+ else "")
+ if (member.owner == clazz) unit.error(member.pos, fullmsg)
+ else mixinOverrideErrors += new MixinOverrideError(member, fullmsg)
+ }
}
def overrideTypeError() {
@@ -198,7 +215,7 @@ abstract class RefChecks extends InfoTransform {
(other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.hasFlag(LAZY)) {
overrideError("cannot override a mutable variable")
} else if (other.isStable && !member.isStable) { // (1.4)
- overrideError("is not stable")
+ overrideError("needs to be a stable, immutable value")
} else if (member.isValue && (member hasFlag LAZY) &&
other.isValue && !other.isSourceMethod && !other.isDeferred && !(other hasFlag LAZY)) {
overrideError("cannot override a concrete non-lazy value")
@@ -219,7 +236,7 @@ abstract class RefChecks extends InfoTransform {
// overrideError("may not be parameterized");
var memberTp = self.memberType(member)
val otherTp = self.memberInfo(other)
- if (!(otherTp.bounds containsType memberTp)) { // (1.7.1) {
+ if (!(otherTp.bounds containsType memberTp)) { // (1.7.1)
overrideTypeError(); // todo: do an explaintypes with bounds here
explainTypes(_.bounds containsType _, otherTp, memberTp)
}
@@ -261,6 +278,8 @@ abstract class RefChecks extends InfoTransform {
opc.next
}
+ printMixinOverrideErrors()
+
// 2. Check that only abstract classes have deferred members
if (clazz.isClass && !clazz.isTrait) {
def abstractClassError(mustBeMixin: Boolean, msg: String) {
@@ -430,10 +449,14 @@ abstract class RefChecks extends InfoTransform {
val v = relativeVariance(sym);
if (v != AnyVariance && sym.variance != v * variance) {
//Console.println("relativeVariance(" + base + "," + sym + ") = " + v);//DEBUG
+ def tpString(tp: Type) = tp match {
+ case ClassInfoType(parents, _, clazz) => "supertype "+intersectionType(parents, clazz.owner)
+ case _ => "type "+tp
+ }
unit.error(base.pos,
varianceString(sym.variance) + " " + sym +
" occurs in " + varianceString(v * variance) +
- " position in type " + base.info + " of " + base);
+ " position in " + tpString(base.info) + " of " + base);
}
}
validateVariance(pre, variance)