summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2016-09-14 23:55:16 -0700
committerSom Snytt <som.snytt@gmail.com>2017-03-11 23:38:08 -0800
commitf672aff3f3b92506741b62d8f7eae6d1e0dc36a7 (patch)
tree7bfacf173c601643e83a91bb5eb53fce9e0caf5e /src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
parent9d9abffc94b28785e54bc2179b495d81f29b1e7f (diff)
downloadscala-f672aff3f3b92506741b62d8f7eae6d1e0dc36a7.tar.gz
scala-f672aff3f3b92506741b62d8f7eae6d1e0dc36a7.tar.bz2
scala-f672aff3f3b92506741b62d8f7eae6d1e0dc36a7.zip
SI-8040 Warn unused pattern vars
Warn for unused `case X(x) =>` but, as an escape hatch, not for `case X(x @ _) =>`. The latter form is deemed documentary. (Named args could serve a similar purpose, `case X(x = _) =>`.) An attachment is used to mark the bound var, and the symbol position is used to correlate the identifier with the variable that is introduced. This mechanism doesn't work yet when only a single var is defined.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 3cc896f3bd..f344364a75 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -33,7 +33,7 @@ import scala.annotation.tailrec
* @version 1.0
*/
trait TypeDiagnostics {
- self: Analyzer =>
+ self: Analyzer with StdAttachments =>
import global._
import definitions._
@@ -79,6 +79,8 @@ trait TypeDiagnostics {
prefix + name.decode
}
+ private def atBounded(t: Tree) = t.hasAttachment[AtBoundIdentifierAttachment.type]
+
/** Does the positioned line assigned to t1 precede that of t2?
*/
def posPrecedes(p1: Position, p2: Position) = p1.isDefined && p2.isDefined && p1.line < p2.line
@@ -473,6 +475,7 @@ trait TypeDiagnostics {
val targets = mutable.Set[Symbol]()
val setVars = mutable.Set[Symbol]()
val treeTypes = mutable.Set[Type]()
+ val atBounds = mutable.Set[Symbol]()
def defnSymbols = defnTrees.toList map (_.symbol)
def localVars = defnSymbols filter (t => t.isLocalToBlock && t.isVar)
@@ -496,6 +499,7 @@ trait TypeDiagnostics {
case t: MemberDef if qualifies(t.symbol) => defnTrees += t
case t: RefTree if t.symbol ne null => targets += t.symbol
case Assign(lhs, _) if lhs.symbol != null => setVars += lhs.symbol
+ case Bind(n, _) if atBounded(t) => atBounds += t.symbol
case _ =>
}
// Only record type references which don't originate within the
@@ -541,10 +545,13 @@ trait TypeDiagnostics {
def unusedTypes = defnTrees.toList filter (t => isUnusedType(t.symbol))
def unusedTerms = {
val all = defnTrees.toList.filter(v => isUnusedTerm(v.symbol))
- // filter out setters if already warning for getter, indicated by position
- if (all.exists(_.symbol.isSetter))
- all.filterNot(v => v.symbol.isSetter && all.exists(g => g.symbol.isGetter && g.symbol.pos.point == v.symbol.pos.point))
- else all
+
+ // filter out setters if already warning for getter, indicated by position.
+ // also documentary names in patterns.
+ all.filterNot(v =>
+ v.symbol.isSetter && all.exists(g => g.symbol.isGetter && g.symbol.pos.point == v.symbol.pos.point)
+ || atBounds.exists(x => v.symbol.pos.point == x.pos.point)
+ )
}
// local vars which are never set, except those already returned in unused
def unsetVars = localVars filter (v => !setVars(v) && !isUnusedTerm(v))