summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-03-09 15:55:43 +0000
committerMartin Odersky <odersky@gmail.com>2007-03-09 15:55:43 +0000
commit87db2fe78421dd61d5b3955612e5b8dd0710cdbe (patch)
tree744145d1989716d9fdcbbf5efd393b4ac2359a00
parentab6384691801ae589265a0f4d15c79f11d7fc35c (diff)
downloadscala-87db2fe78421dd61d5b3955612e5b8dd0710cdbe.tar.gz
scala-87db2fe78421dd61d5b3955612e5b8dd0710cdbe.tar.bz2
scala-87db2fe78421dd61d5b3955612e5b8dd0710cdbe.zip
revised deadcode detection
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala32
4 files changed, 30 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 7054c695ea..3d9ed750e4 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -124,10 +124,8 @@ trait Trees requires Global {
val results = for (val i <- 0.until(this0.arity).toList) yield
equals0(this0.element(i), that0.element(i));
val b = results.foldLeft(true)((x,y) => x && y);
- if (!b) return false;
- return if (tpe == null || tpe == NoType) {
- that.tpe == null || that.tpe == NoType;
- } else tpe == that.tpe
+ b && (if (tpe == null || tpe == NoType) that.tpe == null || that.tpe == NoType
+ else tpe == that.tpe)
}
def duplicate: this.type =
(duplicator transform this).asInstanceOf[this.type]
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 6157e32aad..407c50caf1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -89,6 +89,7 @@ trait Contexts requires Analyzer {
var prefix: Type = NoPrefix
var inConstructorSuffix = false // are we in a secondary constructor
// after the this constructor call?
+ var returnsSeen = false // for method context: were returns encountered?
var reportAmbiguousErrors = false
var reportGeneralErrors = false
var implicitsEnabled = false
@@ -237,7 +238,7 @@ trait Contexts requires Analyzer {
c
}
- def error(pos: Int, err: Error): Unit = {
+ def error(pos: Int, err: Error) {
val msg = err.getMessage()
if (reportGeneralErrors)
unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
@@ -245,11 +246,16 @@ trait Contexts requires Analyzer {
throw err
}
- def error(pos: PositionType, msg: String): unit =
+ def error(pos: PositionType, msg: String) {
if (reportGeneralErrors)
unit.error(pos, if (checking) "**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
else
throw new TypeError(pos, msg)
+ }
+
+ def warning(pos: PositionType, msg: String) {
+ if (reportGeneralErrors) unit.warning(pos, msg)
+ }
/**
* @param pos ...
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ac8572c1d9..ed1e1a04d0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -942,6 +942,12 @@ trait Infer requires Analyzer {
protected def includeCondition(sym: Symbol): boolean = true
}
+ def checkDead(tree: Tree): Tree = {
+ if (settings.Xwarndeadcode.value && tree.tpe.symbol == AllClass)
+ context.warning (tree.pos, "dead code following this construct")
+ tree
+ }
+
/* -- Overload Resolution ---------------------------------------------- */
def checkNotShadowed(pos: PositionType, pre: Type, best: Symbol, eligible: List[Symbol]) =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 28431bf328..cfd18731b2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -625,9 +625,6 @@ trait Typers requires Analyzer {
} else if (!context.undetparams.isEmpty && (mode & POLYmode) == 0) { // (9)
instantiate(tree, mode, pt)
} else if (tree.tpe <:< pt) {
- if (settings.Xwarndeadcode.value &&
- tree.tpe.symbol == AllClass && pt != WildcardType && pt.symbol != AllClass)
- context.unit.warning (tree.pos, "dead code")
tree
} else {
if ((mode & PATTERNmode) != 0) {
@@ -997,7 +994,7 @@ trait Typers requires Analyzer {
} else {
newTyper(context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
}
- copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, rhs1) setType NoType
+ copy.ValDef(vdef, vdef.mods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
/** Enter all aliases of local parameter accessors.
@@ -1100,7 +1097,7 @@ trait Typers requires Analyzer {
typedType(ddef.tpt)))
checkNonCyclic(ddef, tpt1)
ddef.tpt.setType(tpt1.tpe)
- val rhs1 =
+ var rhs1 =
if (ddef.name == nme.CONSTRUCTOR) {
if (!meth.hasFlag(SYNTHETIC) &&
!(meth.owner.isClass ||
@@ -1124,6 +1121,7 @@ trait Typers requires Analyzer {
computeParamAliases(meth.owner, vparamss1, result)
result
} else transformedOrTyped(ddef.rhs, tpt1.tpe)
+ if (tpt1.tpe.symbol != AllClass && !context.returnsSeen) rhs1 = checkDead(rhs1)
copy.DefDef(ddef, ddef.mods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1339,10 +1337,7 @@ trait Typers requires Analyzer {
case _ =>
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
- val stat1 = localTyper.typed(stat)
- if (settings.Xwarndeadcode.value && stat1.tpe.symbol == AllClass)
- context.unit.warning(stat1.pos, "dead code")
- stat1
+ checkDead(localTyper.typed(stat))
}
}
def accesses(accessor: Symbol, accessed: Symbol) =
@@ -1371,7 +1366,7 @@ trait Typers requires Analyzer {
def typedArg(arg: Tree, mode: int, newmode: int, pt: Type): Tree = {
val argTyper = if ((mode & SCCmode) != 0) newTyper(context.makeConstructorContext)
else this
- argTyper.typed(arg, mode & stickyModes | newmode, pt)
+ checkDead(argTyper.typed(arg, mode & stickyModes | newmode, pt))
}
def typedArgs(args: List[Tree], mode: int) =
@@ -1618,7 +1613,7 @@ trait Typers requires Analyzer {
}
}
if (annType.symbol.hasFlag(JAVA) && settings.target.value == "jvm-1.4") {
- context.unit.warning (annot.constr.pos, "Java annotation will not be emitted in classfile unless you use the '-target:jvm-1.5' option")
+ context.warning (annot.constr.pos, "Java annotation will not be emitted in classfile unless you use the '-target:jvm-1.5' option")
}
if (attrError) AnnotationInfo(ErrorType, List(), List())
else AnnotationInfo(annType, constrArgs, nvPairs)
@@ -2042,7 +2037,7 @@ trait Typers requires Analyzer {
if (vble.name.toTermName != nme.WILDCARD) {
/*
if (namesSomeIdent(vble.name))
- context.unit.warning(tree.pos,
+ context.warning(tree.pos,
"pattern variable"+vble.name+" shadows a value visible in the environment;\n"+
"use backquotes `"+vble.name+"` if you mean to match against that value;\n" +
"or rename the variable or use an explicit bind "+vble.name+"@_ to avoid this warning.")
@@ -2091,14 +2086,14 @@ trait Typers requires Analyzer {
}
if ((varsym ne null) && (varsym.isVariable || varsym.isValue && phase.erasedTypes)) {
val rhs1 = typed(rhs, lhs1.tpe)
- copy.Assign(tree, lhs1, rhs1) setType UnitClass.tpe
+ copy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
} else {
if (!lhs1.tpe.isError) error(tree.pos, "assignment to non-variable ")
setError(tree)
}
case If(cond, thenp, elsep) =>
- val cond1 = typed(cond, BooleanClass.tpe)
+ val cond1 = checkDead(typed(cond, BooleanClass.tpe))
if (elsep.isEmpty) {
val thenp1 = typed(thenp, UnitClass.tpe)
copy.If(tree, cond1, thenp1, elsep) setType UnitClass.tpe
@@ -2109,7 +2104,7 @@ trait Typers requires Analyzer {
}
case Match(selector, cases) =>
- val selector1 = typed(selector)
+ val selector1 = checkDead(typed(selector))
val cases1 = typedCases(tree, cases, selector1.tpe.widen, pt)
copy.Match(tree, selector1, cases1) setType ptOrLub(cases1 map (.tpe))
@@ -2123,8 +2118,9 @@ trait Typers requires Analyzer {
errorTree(tree, "method " + enclMethod.owner +
" has return statement; needs result type")
} else {
+ context.enclMethod.returnsSeen = true
val expr1: Tree = typed(expr, restpt.tpe)
- copy.Return(tree, expr1) setSymbol enclMethod.owner setType AllClass.tpe
+ copy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType AllClass.tpe
}
}
@@ -2160,7 +2156,7 @@ trait Typers requires Analyzer {
copy.New(tree, tpt1).setType(tpt1.tpe)
case Typed(expr, Function(List(), EmptyTree)) =>
- val expr1 = typed1(expr, mode, pt)
+ val expr1 = checkDead(typed1(expr, mode, pt))
expr1.tpe match {
case TypeRef(_, sym, _) if (sym == ByNameParamClass) =>
val expr2 = Function(List(), expr1)
@@ -2323,7 +2319,7 @@ trait Typers requires Analyzer {
case Select(qual, name) =>
if (util.Statistics.enabled) selcnt = selcnt + 1
- var qual1 = typedQualifier(qual)
+ var qual1 = checkDead(typedQualifier(qual))
if (name.isTypeName) qual1 = checkStable(qual1)
val tree1 = typedSelect(qual1, name)
if (qual1.symbol == RootPackage) copy.Ident(tree1, name)