diff options
author | Paul Phillips <paulp@improving.org> | 2009-10-22 01:01:04 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-10-22 01:01:04 +0000 |
commit | 3bd3ae75dae560a307c818515d79a0a4ebe67d41 (patch) | |
tree | eb6e09c1eabf3feaf63c5490759798b3b6830515 | |
parent | dc64c686606f8dde6be4d5ff185806331c693842 (diff) | |
download | scala-3bd3ae75dae560a307c818515d79a0a4ebe67d41.tar.gz scala-3bd3ae75dae560a307c818515d79a0a4ebe67d41.tar.bz2 scala-3bd3ae75dae560a307c818515d79a0a4ebe67d41.zip |
Another warning for -Xstrict-warnings.
beloved try/catch blocks which swallow all comers. Realized that two
warnings are already one too many to combine under a single option, and
broke them out into individual options.
-rw-r--r-- | src/compiler/scala/tools/nsc/Settings.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 13 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 5 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 |
4 files changed, 30 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index c85242f937..ed7b745bef 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -761,7 +761,6 @@ trait ScalacSettings { val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options") val assemname = StringSetting ("-Xassem", "file", "Name of the output assembly (only relevant with -target:msil)", "").dependsOn(target, "msil") val assemrefs = StringSetting ("-Xassem-path", "path", "List of assemblies referenced by the program (only relevant with -target:msil)", ".").dependsOn(target, "msil") - val Xchecknull = BooleanSetting ("-Xcheck-null", "Emit warning on selection of nullable reference") val checkInit = BooleanSetting ("-Xcheckinit", "Add runtime checks on field accessors. Uninitialized accesses result in an exception being thrown.") val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions and assumptions") val elideLevel = IntSetting ("-Xelide-level", "Generate calls to @elidable-marked methods only method priority is greater than argument.", @@ -790,7 +789,6 @@ trait ScalacSettings { val Xshowobj = StringSetting ("-Xshow-object", "object", "Show object info", "") val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases") val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files", "scala.tools.nsc.io.SourceReader") - val Xwarninit = BooleanSetting ("-Xwarninit", "Warn about possible changes in initialization semantics") val newArrays = BooleanSetting ("-Ynewarrays", "Generate code for new array scheme") /** @@ -827,15 +825,24 @@ trait ScalacSettings { ChoiceSetting ("-Ystruct-dispatch", "Selects dispatch method for structural refinement method calls", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") . withHelpSyntax("-Ystruct-dispatch:<method>") - val Xwarndeadcode = BooleanSetting ("-Ywarn-dead-code", "Emit warnings for dead code") val specialize = BooleanSetting ("-Yspecialize", "Specialize generic code on types.") val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.") val Yidedebug = BooleanSetting ("-Yide-debug", "Generate, validate and output trees using the interactive compiler.") val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements") val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") - val Xwarnings = BooleanSetting ("-Xstrict-warnings", "Emit extra (usually spurious) warnings.") val Ytailrec = BooleanSetting ("-Ytailrecommend", "Alert methods which would be tail-recursive if private or final.") + // Warnings + val Xwarninit = BooleanSetting ("-Xwarninit", "Warn about possible changes in initialization semantics") + val Xchecknull = BooleanSetting ("-Xcheck-null", "Emit warning on selection of nullable reference") + val Xwarndeadcode = BooleanSetting ("-Ywarn-dead-code", "Emit warnings for dead code") + val YwarnShadow = BooleanSetting ("-Ywarn-shadowing", "Emit warnings about possible variable shadowing.") + val YwarnCatches = BooleanSetting ("-Ywarn-catches", "Emit warnings about catch blocks which catch everything.") + val Xwarnings = BooleanSetting ("-Xstrict-warnings", "Emit warnings about lots of things.") . + withPostSetHook(() => + List(YwarnShadow, YwarnCatches, Xwarndeadcode, Xwarninit) foreach (_.value = true) + ) + /** * -P "Plugin" settings */ diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 28fb914f11..6a8f653ac4 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -20,6 +20,7 @@ abstract class TreeInfo { val trees: SymbolTable import trees._ + import definitions.ThrowableClass def isTerm(tree: Tree): Boolean = tree.isTerm def isType(tree: Tree): Boolean = tree.isType @@ -238,6 +239,16 @@ abstract class TreeInfo { case _ => false } + /** Does this CaseDef catch Throwable? */ + def catchesThrowable(cdef: CaseDef) = catchesAllOf(cdef, ThrowableClass.tpe) + + /** Does this CaseDef catch everything of a certain Type? */ + def catchesAllOf(cdef: CaseDef, threshold: Type) = + isDefaultCase(cdef) || (cdef.guard.isEmpty && (unbind(cdef.pat) match { + case Typed(Ident(nme.WILDCARD), tpt) => (tpt.tpe != null) && (threshold <:< tpt.tpe) + case _ => false + })) + /** Is this pattern node a catch-all or type-test pattern? */ def isCatchCase(cdef: CaseDef) = cdef match { case CaseDef(Typed(Ident(nme.WILDCARD), tpt), EmptyTree, _) => @@ -251,7 +262,7 @@ abstract class TreeInfo { private def isSimpleThrowable(tp: Type): Boolean = tp match { case TypeRef(pre, sym, args) => (pre == NoPrefix || pre.widen.typeSymbol.isStatic) && - (sym isNonBottomSubClass definitions.ThrowableClass) && /* bq */ !sym.isTrait + (sym isNonBottomSubClass ThrowableClass) && /* bq */ !sym.isTrait case _ => false } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 24c5493858..96e40f1fe5 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -636,6 +636,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } treeCopy.DefDef(tree, mods, name, tparams, List(List.flatten(vparamss)), tpt, rhs1) case Try(body, catches, finalizer) => + // If warnings are enabled, alert about promiscuously catching cases. + if (settings.YwarnCatches.value) + for (cd <- catches find treeInfo.catchesThrowable) + unit.warning(cd.pos, "catch clause swallows everything: not advised.") + if (catches forall treeInfo.isCatchCase) tree else { val exname = unit.fresh.newName(tree.pos, "ex$") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b81c087901..269e9ca938 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1651,7 +1651,7 @@ trait Typers { self: Analyzer => // catches method parameters shadowing identifiers declared in the same file, so more // work is needed. Most of the code here is to filter out false positives. def isAuxConstructor(sym: Symbol) = sym.isConstructor && !sym.isPrimaryConstructor - if (settings.Xwarnings.value && !isAuxConstructor(ddef.symbol)) { + if (settings.YwarnShadow.value && !isAuxConstructor(ddef.symbol)) { for (v <- ddef.vparamss.flatten ; if v.symbol != null && !(v.symbol hasFlag SYNTHETIC)) checkShadowings(v, (sym => !sym.isDeferred && !sym.isMethod)) } @@ -1752,7 +1752,7 @@ trait Typers { self: Analyzer => while ((e ne null) && (e.sym ne stat.symbol)) e = e.tail if (e eq null) context.scope.enter(stat.symbol) } - if (settings.Xwarnings.value) checkShadowings(stat) + if (settings.YwarnShadow.value) checkShadowings(stat) enterLabelDef(stat) } val stats1 = typedStats(block.stats, context.owner) |