From f672aff3f3b92506741b62d8f7eae6d1e0dc36a7 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 14 Sep 2016 23:55:16 -0700 Subject: 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. --- .../scala/tools/nsc/typechecker/TypeDiagnostics.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala') 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)) -- cgit v1.2.3