summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@gmail.com>2012-01-25 11:33:53 +0100
committerHubert Plociniczak <hubert.plociniczak@gmail.com>2012-01-25 11:33:53 +0100
commitc800d1fec5241ed8c29e5af30465856f9b583246 (patch)
treea37c194bb2d632adf9adeda17a107913f63864ba /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parentde2b0c68785afc0f801fbe8d2750366e90c9fa70 (diff)
downloadscala-c800d1fec5241ed8c29e5af30465856f9b583246.tar.gz
scala-c800d1fec5241ed8c29e5af30465856f9b583246.tar.bz2
scala-c800d1fec5241ed8c29e5af30465856f9b583246.zip
Use context for buffering errors that cannot/shouldn't be reported in the given moment (instead of throwing type errors). This avoids previous problems where we were creating fake error trees in some incorrect places like in type completers in Namers etc. Implicits relied heavily on type errors being thrown but performance should stay the same due to some explicit checks/returns.
Some of the problems involved how ambiguous error messages were collected/reported because it was very random (similarly for divergent implicits). This should be more explicit now. Reduced the number of unnecessary cyclic references being thrown (apart from those in Symbols/Types which don't have a context and need to stay for now as is). Review by @paulp, @odersky.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala27
1 files changed, 14 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 112aa47114..0405163ef3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1240,11 +1240,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
/* Check whether argument types conform to bounds of type parameters */
- private def checkBounds(pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type], pos: Position): Unit =
- try typer.infer.checkBounds(pos, pre, owner, tparams, argtps, "")
+ private def checkBounds(tree0: Tree, pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type]): Unit =
+ try typer.infer.checkBounds(tree0, pre, owner, tparams, argtps, "")
catch {
case ex: TypeError =>
- unit.error(pos, ex.getMessage());
+ unit.error(tree0.pos, ex.getMessage())
if (settings.explaintypes.value) {
val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds)
(argtps, bounds).zipped map ((targ, bound) => explainTypes(bound.lo, targ))
@@ -1374,22 +1374,22 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
false
}
- private def checkTypeRef(tp: Type, pos: Position) = tp match {
+ private def checkTypeRef(tp: Type, tree: Tree) = tp match {
case TypeRef(pre, sym, args) =>
- checkDeprecated(sym, pos)
+ checkDeprecated(sym, tree.pos)
if(sym.isJavaDefined)
sym.typeParams foreach (_.cookJavaRawInfo())
if (!tp.isHigherKinded)
- checkBounds(pre, sym.owner, sym.typeParams, args, pos)
+ checkBounds(tree, pre, sym.owner, sym.typeParams, args)
case _ =>
}
- private def checkAnnotations(tpes: List[Type], pos: Position) = tpes foreach (tp => checkTypeRef(tp, pos))
+ private def checkAnnotations(tpes: List[Type], tree: Tree) = tpes foreach (tp => checkTypeRef(tp, tree))
private def doTypeTraversal(tree: Tree)(f: Type => Unit) = if (!inPattern) tree.tpe foreach f
private def applyRefchecksToAnnotations(tree: Tree): Unit = {
def applyChecks(annots: List[AnnotationInfo]) = {
- checkAnnotations(annots map (_.atp), tree.pos)
+ checkAnnotations(annots map (_.atp), tree)
transformTrees(annots flatMap (_.args))
}
@@ -1404,7 +1404,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case tpt@TypeTree() =>
if(tpt.original != null) {
tpt.original foreach {
- case dc@TypeTreeWithDeferredRefCheck() => applyRefchecksToAnnotations(dc.check()) // #2416
+ case dc@TypeTreeWithDeferredRefCheck() =>
+ applyRefchecksToAnnotations(dc.check()) // #2416
case _ =>
}
}
@@ -1450,7 +1451,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
unit.error(tree.pos, "too many dimensions for array creation")
Literal(Constant(null))
} else {
- localTyper.getManifestTree(tree.pos, etpe, false)
+ localTyper.getManifestTree(tree, etpe, false)
}
}
val newResult = localTyper.typedPos(tree.pos) {
@@ -1578,13 +1579,13 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case ExistentialType(tparams, tpe) =>
existentialParams ++= tparams
case t: TypeRef =>
- checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree.pos)
+ checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree)
case _ =>
}
tree
case TypeApply(fn, args) =>
- checkBounds(NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe), tree.pos)
+ checkBounds(tree, NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe))
transformCaseApply(tree, ())
case x @ Apply(_, _) =>
@@ -1641,7 +1642,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
result
} catch {
case ex: TypeError =>
- if (settings.debug.value) ex.printStackTrace();
+ if (settings.debug.value) ex.printStackTrace()
unit.error(tree.pos, ex.getMessage())
tree
} finally {