summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-04-27 16:36:39 +0000
committerPaul Phillips <paulp@improving.org>2010-04-27 16:36:39 +0000
commit9b16201d2c982095c54b9803cee8c76b4f12024e (patch)
tree09721c98e76094311602b9debf3d8c4eb1a5ba23 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent0675d244e45ea0f71a64568c832c846b19beea56 (diff)
downloadscala-9b16201d2c982095c54b9803cee8c76b4f12024e.tar.gz
scala-9b16201d2c982095c54b9803cee8c76b4f12024e.tar.bz2
scala-9b16201d2c982095c54b9803cee8c76b4f12024e.zip
Created TypeDiagnostics trait and have begun op...
Created TypeDiagnostics trait and have begun opportunistically moving code into it. Along the way, some improvements to error messages. The situation described in ticket #2206 has always had an applicable error message, but it wasn't making it out to the user. More kinds of ambiguity are disambiguated, see the test cases. And overload errors are printed with some formatting so one has some hope of parsing. Review by odersky.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala125
1 files changed, 46 insertions, 79 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ed7c1dec15..b6271b8ef1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -161,7 +161,7 @@ trait Typers { self: Analyzer =>
else mode
}
- abstract class Typer(context0: Context) {
+ abstract class Typer(context0: Context) extends TyperDiagnostics {
import context0.unit
val infer = new Inferencer(context0) {
@@ -252,35 +252,6 @@ trait Typers { self: Analyzer =>
private[typechecker] var context = context0
def context1 = context
- /** Report a type error.
- *
- * @param pos0 The position where to report the error
- * @param ex The exception that caused the error
- */
- def reportTypeError(pos: Position, ex: TypeError) {
- if (ex.pos == NoPosition) ex.pos = pos
- if (!context.reportGeneralErrors) throw ex
- if (settings.debug.value) ex.printStackTrace()
- ex match {
- case CyclicReference(sym, info: TypeCompleter) =>
- val msg =
- info.tree match {
- case ValDef(_, _, tpt, _) if (tpt.tpe eq null) =>
- "recursive "+sym+" needs type"
- case DefDef(_, _, _, _, tpt, _) if (tpt.tpe eq null) =>
- (if (sym.owner.isClass && sym.owner.info.member(sym.name).hasFlag(OVERLOADED)) "overloaded "
- else "recursive ")+sym+" needs result type"
- case _ =>
- ex.getMessage()
- }
- context.error(ex.pos, msg)
- if (sym == ObjectClass)
- throw new FatalError("cannot redefine root "+sym)
- case _ =>
- context.error(ex.pos, ex)
- }
- }
-
/** Check that <code>tree</code> is a stable expression.
*
* @param tree ...
@@ -2936,6 +2907,8 @@ trait Typers { self: Analyzer =>
* @return ...
*/
protected def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
+ def isPatternMode = (mode & PATTERNmode) != 0
+
//Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")")
def ptOrLub(tps: List[Type]) = if (isFullyDefined(pt)) (pt, false) else weakLub(tps map (_.deconst))
@@ -3056,32 +3029,36 @@ trait Typers { self: Analyzer =>
}
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
- val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType)
- val varsym = lhs1.symbol
- if ((varsym ne null) && treeInfo.mayBeVarGetter(varsym))
+ val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType)
+ val varsym = lhs1.symbol
+ def failMsg =
+ if (varsym != null && varsym.isValue) "reassignment to val"
+ else "assignment to non variable"
+
+ def fail = {
+ if (!lhs1.tpe.isError)
+ error(tree.pos, failMsg)
+
+ setError(tree)
+ }
+ if (varsym == null)
+ return fail
+
+ if (treeInfo.mayBeVarGetter(varsym)) {
lhs1 match {
case Select(qual, name) =>
- return typed(
- Apply(
- Select(qual, nme.getterToSetter(name)) setPos lhs.pos,
- List(rhs)) setPos tree.pos,
- mode, pt)
+ val sel = Select(qual, nme.getterToSetter(name)) setPos lhs.pos
+ val app = Apply(sel, List(rhs)) setPos tree.pos
+ return typed(app, mode, pt)
case _ =>
-
}
- if ((varsym ne null) && (varsym.isVariable || varsym.isValue && phase.erasedTypes)) {
+ }
+ if (varsym.isVariable || varsym.isValue && phase.erasedTypes) {
val rhs1 = typed(rhs, EXPRmode | BYVALmode, lhs1.tpe)
treeCopy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
- } else {
- if (!lhs1.tpe.isError) {
- //println(lhs1+" = "+rhs+" "+varsym+" "+mayBeVarGetter(varsym)+" "+varsym.ownerChain+" "+varsym.info)// DEBUG
- error(tree.pos,
- if ((varsym ne null) && varsym.isValue) "reassignment to val"
- else "assignment to non variable")
- }
- setError(tree)
}
+ else fail
}
def typedIf(cond: Tree, thenp: Tree, elsep: Tree) = {
@@ -3227,19 +3204,19 @@ trait Typers { self: Analyzer =>
t
case ex: TypeError =>
stopTimer(failedApplyNanos, start)
- def errorInResult(tree: Tree): Boolean = tree.pos == ex.pos || {
- tree match {
- case Block(_, r) => errorInResult(r)
- case Match(_, cases) => cases exists errorInResult
- case CaseDef(_, _, r) => errorInResult(r)
- case Annotated(_, r) => errorInResult(r)
- case If(_, t, e) => errorInResult(t) || errorInResult(e)
- case Try(b, catches, _) => errorInResult(b) || (catches exists errorInResult)
- case Typed(r, Function(List(), EmptyTree)) => errorInResult(r)
- case _ => false
- }
- }
- if (errorInResult(fun) || (args exists errorInResult) || errorInResult(tree)) {
+ def treesInResult(tree: Tree): List[Tree] = tree :: (tree match {
+ case Block(_, r) => treesInResult(r)
+ case Match(_, cases) => cases
+ case CaseDef(_, _, r) => treesInResult(r)
+ case Annotated(_, r) => treesInResult(r)
+ case If(_, t, e) => treesInResult(t) ++ treesInResult(e)
+ case Try(b, catches, _) => treesInResult(b) ++ catches
+ case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r)
+ case _ => Nil
+ })
+ def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == ex.pos)
+
+ if (fun :: tree :: args exists errorInResult) {
if (printTypings) println("second try for: "+fun+" and "+args)
val Select(qual, name) = fun
val args1 = tryTypedArgs(args, argMode(fun, mode), ex)
@@ -3260,11 +3237,11 @@ trait Typers { self: Analyzer =>
def typedApply(fun: Tree, args: List[Tree]) = {
val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable
- if (stableApplication && (mode & PATTERNmode) != 0) {
+ if (stableApplication && isPatternMode) {
// treat stable function applications f() as expressions.
typed1(tree, mode & ~PATTERNmode | EXPRmode, pt)
} else {
- val funpt = if ((mode & PATTERNmode) != 0) pt else WildcardType
+ val funpt = if (isPatternMode) pt else WildcardType
val appStart = startTimer(failedApplyNanos)
val opeqStart = startTimer(failedOpEqNanos)
silent(_.typed(fun, funMode(mode), funpt)) match {
@@ -3305,7 +3282,7 @@ trait Typers { self: Analyzer =>
case ex: TypeError =>
fun match {
case Select(qual, name)
- if (mode & PATTERNmode) == 0 && nme.isOpAssignmentName(name.decode) =>
+ if !isPatternMode && nme.isOpAssignmentName(name.decode) =>
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
stopTimer(failedOpEqNanos, opeqStart)
@@ -3482,19 +3459,9 @@ trait Typers { self: Analyzer =>
if (name == nme.ERROR && onlyPresentation)
return makeErrorTree
- if (!qual.tpe.widen.isErroneous) {
- error(tree.pos,
- if (name == nme.CONSTRUCTOR)
- qual.tpe.widen+" does not have a constructor"
- else
- decode(name)+" is not a member of "+
- (if (qual.tpe.typeSymbol.isTypeParameterOrSkolem) "type parameter " else "") +
- qual.tpe.widen +
- (if ((context.unit ne null) && // Martin: why is this condition needed?
- qual.pos.isDefined && tree.pos.isDefined && qual.pos.line < tree.pos.line)
- "\npossible cause: maybe a semicolon is missing before `"+decode(name)+"'?"
- else ""))
- }
+ if (!qual.tpe.widen.isErroneous)
+ notAMember(tree, qual, name)
+
if (onlyPresentation) makeErrorTree else setError(tree)
} else {
val tree1 = tree match {
@@ -3634,7 +3601,7 @@ trait Typers { self: Analyzer =>
if (settings.debug.value) {
log(context.imports)//debug
}
- error(tree.pos, "not found: "+decode(name))
+ error(tree.pos, "not found: "+decodeWithNamespace(name))
defSym = context.owner.newErrorSymbol(name)
}
}
@@ -3871,7 +3838,7 @@ trait Typers { self: Analyzer =>
val tpt1 = typedType(tpt, mode)
val expr1 = typed(expr, mode & stickyModes, tpt1.tpe.deconst)
val owntype =
- if ((mode & PATTERNmode) != 0) inferTypedPattern(tpt1.pos, tpt1.tpe, pt)
+ if (isPatternMode) inferTypedPattern(tpt1.pos, tpt1.tpe, pt)
else tpt1.tpe
//Console.println(typed pattern: "+tree+":"+", tp = "+tpt1.tpe+", pt = "+pt+" ==> "+owntype)//DEBUG
treeCopy.Typed(tree, expr1, tpt1) setType owntype