summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
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
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')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala29
3 files changed, 57 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 8d9fed4006..661f225bf3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -772,12 +772,12 @@ trait Infer {
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
- if(!kindErrors.isEmpty)
+ if(!kindErrors.isEmpty) {
error(pos,
- prefix + "the kinds of the type arguments " + targs.mkString("(", ",", ")") +
+ prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
" do not conform to the expected kinds of the type parameters "+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
kindErrors.toList.mkString("\n", ", ", ""))
- else if (!isWithinBounds(pre, owner, tparams, targs)) {
+ } else if (!isWithinBounds(pre, owner, tparams, targs)) {
if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
//val bounds = instantiatedBounds(pre, owner, tparams, targs)//DEBUG
//println("bounds = "+bounds+", targs = "+targs+", targclasses = "+(targs map (_.getClass))+", parents = "+(targs map (_.parents)))
@@ -876,7 +876,7 @@ trait Infer {
}
val errors = new ListBuffer[String]
- (tparams zip targs).foreach{ case (tparam, targ) if(targ.isHigherKinded || !tparam.typeParams.isEmpty) => //println("check: "+(tparam, targ))
+ (tparams zip targs).foreach{ case (tparam, targ) if (targ.isHigherKinded || !tparam.typeParams.isEmpty) => //println("check: "+(tparam, targ))
val (arityMismatches, varianceMismatches, stricterBounds) =
checkKindBoundsHK(targ.typeParams, targ.typeSymbolDirect, tparam, tparam.owner) // NOTE: *not* targ.typeSymbol, which normalizes
// NOTE 2: must use the typeParams of the type targ, not the typeParams of the symbol of targ!!
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)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 209760a66e..34a7eb5732 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2841,7 +2841,8 @@ trait Typers { self: Analyzer =>
case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name)
}
val result = stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt)
- if (!global.phase.erasedTypes && settings.Xchecknull.value &&
+ if (phase.id <= currentRun.typerPhase.id &&
+ settings.Xchecknull.value &&
!sym.isConstructor &&
!(qual.tpe <:< NotNullClass.tpe) && !qual.tpe.isNotNull)
unit.warning(tree.pos, "potential null pointer dereference: "+tree)
@@ -3336,7 +3337,19 @@ trait Typers { self: Analyzer =>
* @param pt ...
* @return ...
*/
- def typed(tree: Tree, mode: Int, pt: Type): Tree =
+ def typed(tree: Tree, mode: Int, pt: Type): Tree = {
+
+ def dropExistential(tp: Type): Type = tp match {
+ case ExistentialType(tparams, tpe) =>
+ if (settings.debug.value) println("drop ex "+tree+" "+tp)
+ new SubstWildcardMap(tparams).apply(tp)
+ case TypeRef(_, sym, _) if sym.isAliasType =>
+ val tp0 = tp.normalize
+ val tp1 = dropExistential(tp0)
+ if (tp1 eq tp0) tp else tp1
+ case _ => tp
+ }
+
try {
if (settings.debug.value)
assert(pt ne null, tree)//debug
@@ -3346,16 +3359,7 @@ trait Typers { self: Analyzer =>
if (tree.hasSymbol) tree.symbol = NoSymbol
}
if (printTypings) println("typing "+tree+", "+context.undetparams+(mode & TYPEPATmode)); //DEBUG
- def dropExistential(tp: Type): Type = tp match {
- case ExistentialType(tparams, tpe) =>
- if (settings.debug.value) println("drop ex "+tree+" "+tp)
- new SubstWildcardMap(tparams).apply(tp)
- case TypeRef(_, sym, _) if sym.isAliasType =>
- val tp0 = tp.normalize
- val tp1 = dropExistential(tp0)
- if (tp1 eq tp0) tp else tp1
- case _ => tp
- }
+
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt); //DEBUG
@@ -3380,6 +3384,7 @@ trait Typers { self: Analyzer =>
logError("AT: " + (tree.pos).dbgString, ex);
throw(ex)
}
+ }
def atOwner(owner: Symbol): Typer =
newTyper(context.make(context.tree, owner))