summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-10-12 10:51:06 -0700
committerPaul Phillips <paulp@improving.org>2013-10-12 10:51:06 -0700
commit72736f7238616f4e56a0ee28e9d204d95e81107f (patch)
tree43e1bb16ed50dd42df67ee1300883a3f65959e5d /src
parentede4a958aa79aa07ed62283fc74314f2611d3dc4 (diff)
parent83feb8609161bf19247a8a310f8c5a9e3d8469f5 (diff)
downloadscala-72736f7238616f4e56a0ee28e9d204d95e81107f.tar.gz
scala-72736f7238616f4e56a0ee28e9d204d95e81107f.tar.bz2
scala-72736f7238616f4e56a0ee28e9d204d95e81107f.zip
Merge pull request #3024 from retronym/ticket/7895
SI-7895 Error reporting: avoid cascading, truncation
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
2 files changed, 49 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index abc5363423..5e5619d034 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -329,6 +329,7 @@ trait Contexts { self: Analyzer =>
/** The first error, if any, in the report buffer */
def firstError: Option[AbsTypeError] = reportBuffer.firstError
+ def errors: Seq[AbsTypeError] = reportBuffer.errors
/** Does the report buffer contain any errors? */
def hasErrors = reportBuffer.hasErrors
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ecd987b031..7bf342f475 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -79,12 +79,25 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case SilentResultValue(value) if !p(value) => SilentTypeError(TypeErrorWrapper(new TypeError(NoPosition, "!p")))
case _ => this
}
- @inline final def orElse[T1 >: T](f: AbsTypeError => T1): T1 = this match {
+ @inline final def orElse[T1 >: T](f: Seq[AbsTypeError] => T1): T1 = this match {
case SilentResultValue(value) => value
- case SilentTypeError(err) => f(err)
+ case s : SilentTypeError => f(s.reportableErrors)
}
}
- case class SilentTypeError(err: AbsTypeError) extends SilentResult[Nothing] { }
+ class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ def err: AbsTypeError = errors.head
+ def reportableErrors = errors match {
+ case (e1: AmbiguousImplicitTypeError) +: _ =>
+ List(e1) // DRYer error reporting for neg/t6436b.scala
+ case all =>
+ all
+ }
+ }
+ object SilentTypeError {
+ def apply(errors: AbsTypeError*): SilentTypeError = new SilentTypeError(errors.toList)
+ def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
+ }
+
case class SilentResultValue[+T](value: T) extends SilentResult[T] { }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -682,14 +695,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
context.undetparams = context1.undetparams
context.savedTypeBounds = context1.savedTypeBounds
context.namedApplyBlockInfo = context1.namedApplyBlockInfo
- context1.firstError match {
- case Some(err) =>
- stopStats()
- SilentTypeError(err)
- case None =>
- // If we have a successful result, emit any warnings it created.
- context1.flushAndIssueWarnings()
- SilentResultValue(result)
+ if (context1.hasErrors) {
+ stopStats()
+ SilentTypeError(context1.errors: _*)
+ } else {
+ // If we have a successful result, emit any warnings it created.
+ context1.flushAndIssueWarnings()
+ SilentResultValue(result)
}
} else {
assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
@@ -1258,9 +1270,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
reportError
}
- silent(_.adaptToMember(qual, HasMember(name), reportAmbiguous = false)) orElse (err =>
+ silent(_.adaptToMember(qual, HasMember(name), reportAmbiguous = false)) orElse (errs =>
onError {
- if (reportAmbiguous) context issue err
+ if (reportAmbiguous) errs foreach (context issue _)
setError(tree)
}
)
@@ -2392,9 +2404,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (pat1.tpe.paramSectionCount > 0)
pat1 modifyType (_.finalResultType)
- for (bind @ Bind(name, _) <- cdef.pat)
- if (name.toTermName != nme.WILDCARD && bind.symbol != null && bind.symbol != NoSymbol)
- namer.enterIfNotThere(bind.symbol)
+ for (bind @ Bind(name, _) <- cdef.pat) {
+ val sym = bind.symbol
+ if (name.toTermName != nme.WILDCARD && sym != null) {
+ if (sym == NoSymbol) {
+ if (context.scope.lookup(name) == NoSymbol)
+ namer.enterInScope(context.owner.newErrorSymbol(name))
+ } else
+ namer.enterIfNotThere(sym)
+ }
+ }
val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
else typed(cdef.guard, BooleanTpe)
@@ -2701,7 +2720,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val FunctionSymbol = FunctionClass(numVparams)
val (argpts, respt) = pt baseType FunctionSymbol match {
case TypeRef(_, FunctionSymbol, args :+ res) => (args, res)
- case _ => (fun.vparams map (_ => NoType), WildcardType)
+ case _ => (fun.vparams map (_ => if (pt == ErrorType) ErrorType else NoType), WildcardType)
}
if (argpts.lengthCompare(numVparams) != 0)
WrongNumberOfParametersError(fun, argpts)
@@ -3779,7 +3798,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
}
- def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err))
+ def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err.head))
}
def typed1(tree: Tree, mode: Mode, pt: Type): Tree = {
@@ -4166,7 +4185,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
- def onError(typeError: AbsTypeError): Tree = {
+ def onError(typeErrors: Seq[AbsTypeError]): Tree = {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -4191,13 +4210,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case TypeApply(fun, args) => treesInResult(fun) ++ args.flatMap(treesInResult)
case _ => Nil
})
- def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos)
+ def errorInResult(tree: Tree) = treesInResult(tree) exists (err => typeErrors.exists(_.errPos == err.pos))
- val retry = (typeError.errPos != null) && (fun :: tree :: args exists errorInResult)
+ val retry = (typeErrors.forall(_.errPos != null)) && (fun :: tree :: args exists errorInResult)
typingStack.printTyping({
val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ")
if (retry) "second try: " + funStr
- else "no second try: " + funStr + " because error not in result: " + typeError.errPos+"!="+tree.pos
+ else "no second try: " + funStr + " because error not in result: " + typeErrors.head.errPos+"!="+tree.pos
})
if (retry) {
val Select(qual, name) = fun
@@ -4213,7 +4232,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case _ => ()
}
}
- issue(typeError)
+ typeErrors foreach issue
setError(treeCopy.Apply(tree, fun, args))
}
@@ -4265,8 +4284,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
tryTypedApply(fun2, args)
else
doTypedApply(tree, fun2, args, mode, pt)
- case SilentTypeError(err) =>
- onError({ issue(err); setError(tree) })
+ case err: SilentTypeError =>
+ onError({
+ err.reportableErrors foreach issue
+ args foreach (arg => typed(arg, mode, ErrorType))
+ setError(tree)
+ })
}
}