diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala index 015ec917b65d..43d1f7c70732 100644 --- a/src/actors/scala/actors/Actor.scala +++ b/src/actors/scala/actors/Actor.scala @@ -11,6 +11,7 @@ package scala.actors import scala.compat.Platform +import scala.util.control.ControlException import java.util.{Timer, TimerTask} import java.util.concurrent.ExecutionException @@ -881,7 +882,7 @@ case class Exit(from: AbstractActor, reason: AnyRef) * @version 0.9.8 * @author Philipp Haller */ -private[actors] class SuspendActorException extends Throwable { +private[actors] class SuspendActorException extends Throwable with ControlException { /* * For efficiency reasons we do not fill in * the execution stack trace. diff --git a/src/actors/scala/actors/Reaction.scala b/src/actors/scala/actors/Reaction.scala index fee697b6cbc9..c8e19400eb5f 100644 --- a/src/actors/scala/actors/Reaction.scala +++ b/src/actors/scala/actors/Reaction.scala @@ -11,9 +11,10 @@ package scala.actors +import scala.util.control.ControlException import java.lang.{InterruptedException, Runnable} -private[actors] class KillActorException extends Throwable { +private[actors] class KillActorException extends Throwable with ControlException { /* * For efficiency reasons we do not fill in * the execution stack trace. diff --git a/src/actors/scala/actors/SchedulerService.scala b/src/actors/scala/actors/SchedulerService.scala index 1826a153da91..78abb97962e7 100644 --- a/src/actors/scala/actors/SchedulerService.scala +++ b/src/actors/scala/actors/SchedulerService.scala @@ -10,6 +10,7 @@ package scala.actors +import scala.util.control.ControlException import java.lang.{Runnable, Thread, InterruptedException} /** @@ -95,7 +96,7 @@ abstract class SchedulerService(daemon: Boolean) extends Thread with ActorGC { * @version 0.9.8 * @author Philipp Haller */ -private[actors] class QuitException extends Throwable { +private[actors] class QuitException extends Throwable with ControlException { /* For efficiency reasons we do not fill in the execution stack trace. diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index a8f685385342..d247134fd6fd 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -7,6 +7,7 @@ package scala.tools.nsc.ast.parser import scala.collection.mutable +import scala.util.control.ControlException import scala.tools.nsc.util.{Position,NoPosition,SourceFile,CharArrayReader} import scala.xml.{Text, TextBuffer} import SourceFile.{SU,LF} @@ -18,15 +19,15 @@ import scala.annotation.switch * @version 1.0 */ trait MarkupParsers {self: Parsers => - case object MissingEndTagException extends RuntimeException { + case object MissingEndTagException extends RuntimeException with ControlException { override def getMessage = "start tag was here: " } - case object ConfusedAboutBracesException extends RuntimeException { + case object ConfusedAboutBracesException extends RuntimeException with ControlException { override def getMessage = " I encountered a '}' where I didn't expect one, maybe this tag isn't closed <" } - case object TruncatedXML extends RuntimeException { + case object TruncatedXML extends RuntimeException with ControlException { override def getMessage = "input ended while parsing XML" } diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index d264632bd53a..0782639ac567 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -1,6 +1,7 @@ package scala.tools.nsc.interactive import scala.concurrent.SyncVar +import scala.util.control.ControlException import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.util.{SourceFile, Position, WorkScheduler} import scala.tools.nsc.symtab._ @@ -104,8 +105,8 @@ trait CompilerControl { self: Global => // ---------------- Interpreted exeptions ------------------- - class CancelActionReq extends Exception - class FreshRunReq extends Exception - class ShutdownReq extends Exception + class CancelActionReq extends Exception with ControlException + class FreshRunReq extends Exception with ControlException + class ShutdownReq extends Exception with ControlException } diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 51ba19951e3e..72415b5d7bd9 100755 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -4,6 +4,7 @@ import java.io.{ PrintWriter, StringWriter } import scala.collection.mutable.{LinkedHashMap, SynchronizedMap} import scala.concurrent.SyncVar +import scala.util.control.ControlException import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.util.{SourceFile, Position, RangePosition, OffsetPosition, NoPosition, WorkScheduler} import scala.tools.nsc.reporters._ @@ -77,11 +78,19 @@ self => throw new TyperResult(located) } val typerRun = currentTyperRun - pollForWork() - if (typerRun != currentTyperRun) { - integrateNew() - throw new FreshRunReq - } + + while(true) + try { + pollForWork() + if (typerRun == currentTyperRun) + return + + integrateNew() + throw new FreshRunReq + } catch { + case ex : ValidateError => // Ignore, this will have been reported elsewhere + case t : Throwable => throw t + } } } @@ -421,9 +430,8 @@ self => } } - class TyperResult(val tree: Tree) extends Exception + class TyperResult(val tree: Tree) extends Exception with ControlException assert(globalPhase.id == 0) - } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 7565b20c5697..ce16b5500198 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -7,6 +7,7 @@ package scala.tools.nsc.typechecker import scala.tools.nsc.util.{Position, NoPosition} import scala.collection.mutable.ListBuffer +import scala.util.control.ControlException import symtab.Flags._ /** This trait ... @@ -77,7 +78,7 @@ trait Infer { //todo: remove comments around following privates; right now they cause an IllegalAccess // error when built with scalac - /*private*/ class NoInstance(msg: String) extends RuntimeException(msg) + /*private*/ class NoInstance(msg: String) extends RuntimeException(msg) with ControlException /*private*/ class DeferredNoInstance(getmsg: () => String) extends NoInstance("") { override def getMessage(): String = getmsg() diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f576c17ad162..b1ed6da20895 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -11,7 +11,9 @@ package scala.tools.nsc.typechecker import scala.collection.mutable.{HashMap, ListBuffer} +import scala.util.control.ControlException import scala.compat.Platform.currentTime +import scala.tools.nsc.interactive.RangePositions import scala.tools.nsc.util.{HashSet, Position, Set, NoPosition, SourceFile} import symtab.Flags._ import util.HashSet @@ -3735,7 +3737,6 @@ trait Typers { self: Analyzer => * @return ... */ def typed(tree: Tree, mode: Int, pt: Type): Tree = { - import scala.tools.nsc.interactive.CompilerControl def dropExistential(tp: Type): Type = tp match { case ExistentialType(tparams, tpe) => @@ -3767,7 +3768,7 @@ trait Typers { self: Analyzer => if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, result) result } catch { - case ex: CompilerControl#FreshRunReq => throw ex + case ex: ControlException => throw ex case ex: TypeError => tree.tpe = null //Console.println("caught "+ex+" in typed");//DEBUG diff --git a/src/library/scala/runtime/NonLocalReturnException.scala b/src/library/scala/runtime/NonLocalReturnException.scala index 7bb7b9934111..2884a0ce9f43 100644 --- a/src/library/scala/runtime/NonLocalReturnException.scala +++ b/src/library/scala/runtime/NonLocalReturnException.scala @@ -13,8 +13,9 @@ package scala.runtime import Predef.RuntimeException +import scala.util.control.ControlException -class NonLocalReturnException[T](val key: AnyRef, val value: T) extends RuntimeException { +class NonLocalReturnException[T](val key: AnyRef, val value: T) extends RuntimeException with ControlException { /* * For efficiency reasons we do not fill in * the execution stack trace. diff --git a/src/library/scala/util/control/Breaks.scala b/src/library/scala/util/control/Breaks.scala index 3315140b6b44..25adf8057315 100755 --- a/src/library/scala/util/control/Breaks.scala +++ b/src/library/scala/util/control/Breaks.scala @@ -44,5 +44,5 @@ class Breaks { /** A singleton object providing the Break functionality */ object Breaks extends Breaks -private class BreakException extends RuntimeException +private class BreakException extends RuntimeException with ControlException diff --git a/src/library/scala/util/control/ControlException.scala b/src/library/scala/util/control/ControlException.scala new file mode 100644 index 000000000000..4ac7b0ceebad --- /dev/null +++ b/src/library/scala/util/control/ControlException.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.util.control + +/** + * A marker trait indicating that the Throwable it is mixed + * into is intended for flow control. + * + *

Note that Throwable subclasses which extend this trait + * may extend any other Throwable subclass (eg. + * RuntimeException) and are not required to extend + * Throwable directly.

+ * + *

Instances of Throwable subclasses marked in + * this way should not normally be caught. Where catch-all behaviour is + * required ControlExceptions should be propagated, for + * example,

+ * + *
+ *  import scala.util.control.ControlException
+ *
+ *  try {
+ *    // Body might throw arbitrarily
+ * } catch {
+ *   case ce : ControlException => throw ce // propagate
+ *   case t : Exception => log(t)           // log and suppress
+ * 
+ * + * @author Miles Sabin + */ +trait ControlException extends Throwable