diff options
author | Paul Phillips <paulp@improving.org> | 2013-10-12 10:51:06 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-10-12 10:51:06 -0700 |
commit | 72736f7238616f4e56a0ee28e9d204d95e81107f (patch) | |
tree | 43e1bb16ed50dd42df67ee1300883a3f65959e5d /src/compiler | |
parent | ede4a958aa79aa07ed62283fc74314f2611d3dc4 (diff) | |
parent | 83feb8609161bf19247a8a310f8c5a9e3d8469f5 (diff) | |
download | scala-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/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 73 |
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) + }) } } |