summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala6
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala6
6 files changed, 33 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 0cdba861a5..dabce69b2f 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1957,7 +1957,14 @@ self =>
pattern3()
case Ident(name) =>
in.nextToken()
- atPos(p.pos.start) { Bind(name, pattern3()) }
+ val body = pattern3()
+ atPos(p.pos.start, p.pos.start, body.pos.end) {
+ val t = Bind(name, body)
+ body match {
+ case Ident(nme.WILDCARD) => t updateAttachment AtBoundIdentifierAttachment
+ case _ => t
+ }
+ }
case _ => p
}
}
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))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 8333d5d295..b0a8b5d4c6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4266,7 +4266,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val name = tree.name
val body = tree.body
name match {
- case name: TypeName => assert(body == EmptyTree, context.unit + " typedBind: " + name.debugString + " " + body + " " + body.getClass)
+ case name: TypeName =>
+ assert(body == EmptyTree, s"${context.unit} typedBind: ${name.debugString} ${body} ${body.getClass}")
val sym =
if (tree.symbol != NoSymbol) tree.symbol
else {
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index fc49de1cf6..f72c1eb1b3 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -57,6 +57,12 @@ trait StdAttachments {
*/
case object BackquotedIdentifierAttachment extends PlainAttachment
+ /** Indicates that the host `Ident` has been created from a pattern2 binding, `case x @ p`.
+ * In the absence of named parameters in patterns, allows nuanced warnings for unused variables.
+ * Hence, `case X(x = _) =>` would not warn; for now, `case X(x @ _) =>` is documentary if x is unused.
+ */
+ case object AtBoundIdentifierAttachment extends PlainAttachment
+
/** Identifies trees are either result or intermediate value of for loop desugaring.
*/
case object ForAttachment extends PlainAttachment
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 72e21f67fe..7aa3b113dd 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -40,6 +40,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.SAMFunction
this.DelambdafyTarget
this.BackquotedIdentifierAttachment
+ this.AtBoundIdentifierAttachment
this.ForAttachment
this.SyntheticUnitAttachment
this.SubpatternsAttachment
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 9635f320fe..cd263a26f6 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -958,17 +958,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
def withSuppressedSettings[A](body: => A): A = {
val ss = this.settings
import ss._
- val noisy = List(Xprint, Ytyperdebug)
+ val noisy = List(Xprint, Ytyperdebug, browse)
val noisesome = noisy.exists(!_.isDefault)
- val current = (Xprint.value, Ytyperdebug.value)
+ val current = (Xprint.value, Ytyperdebug.value, browse.value)
if (isReplDebug || !noisesome) body
else {
this.settings.Xprint.value = List.empty
+ this.settings.browse.value = List.empty
this.settings.Ytyperdebug.value = false
try body
finally {
Xprint.value = current._1
Ytyperdebug.value = current._2
+ browse.value = current._3
intp.global.printTypings = current._2
}
}