summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2016-09-15 12:58:21 -0700
committerSom Snytt <som.snytt@gmail.com>2017-03-11 23:38:08 -0800
commitbd280077d04a3ac84ca48f549faaa8915d46ef2e (patch)
treea7c8b244ef84b44df201c88b4233d17bcec306d1
parent1b415c904bece230a706c0d19462345fc87abf67 (diff)
downloadscala-bd280077d04a3ac84ca48f549faaa8915d46ef2e.tar.gz
scala-bd280077d04a3ac84ca48f549faaa8915d46ef2e.tar.bz2
scala-bd280077d04a3ac84ca48f549faaa8915d46ef2e.zip
SI-9158 No warn for comprehension patvars
Midstream assignments should not cause unused warnings. Currently the encoding doesn't pass them along, but passes the value from which they were destructured. For for-comprehensions only, the patvar transform tags the binds so that they are not warned if they turn up in a valdef and are unused. Extractors are invoked multiple times if the patvar is used later, as noted on the ticket. In a yield, the valdef is emitted only if the patvar is referenced (possibly saving the extra extraction), so there is no warning there currently.
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala17
-rw-r--r--test/files/neg/warn-unused-privates.check4
-rw-r--r--test/files/neg/warn-unused-privates.scala21
3 files changed, 33 insertions, 9 deletions
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 4fecaf70df..373758d0a5 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -797,7 +797,7 @@ abstract class TreeGen {
/** Create tree for for-comprehension generator <val pat0 <- rhs0> */
def mkGenerator(pos: Position, pat: Tree, valeq: Boolean, rhs: Tree)(implicit fresh: FreshNameCreator): Tree = {
- val pat1 = patvarTransformer.transform(pat)
+ val pat1 = patvarTransformerForFor.transform(pat)
if (valeq) ValEq(pat1, rhs).setPos(pos)
else ValFrom(pat1, mkCheckIfRefutable(pat1, rhs)).setPos(pos)
}
@@ -894,11 +894,15 @@ abstract class TreeGen {
* x becomes x @ _
* x: T becomes x @ (_: T)
*/
- object patvarTransformer extends Transformer {
+ class PatvarTransformer(forFor: Boolean) extends Transformer {
override def transform(tree: Tree): Tree = tree match {
- case Ident(name) if (treeInfo.isVarPattern(tree) && name != nme.WILDCARD) =>
- atPos(tree.pos)(Bind(name, atPos(tree.pos.focus) (Ident(nme.WILDCARD))))
- case Typed(id @ Ident(name), tpt) if (treeInfo.isVarPattern(id) && name != nme.WILDCARD) =>
+ case Ident(name) if treeInfo.isVarPattern(tree) && name != nme.WILDCARD =>
+ atPos(tree.pos) {
+ val b = Bind(name, atPos(tree.pos.focus) (Ident(nme.WILDCARD)))
+ if (forFor) b updateAttachment AtBoundIdentifierAttachment
+ else b
+ }
+ case Typed(id @ Ident(name), tpt) if treeInfo.isVarPattern(id) && name != nme.WILDCARD =>
atPos(tree.pos.withPoint(id.pos.point)) {
Bind(name, atPos(tree.pos.withStart(tree.pos.point)) {
Typed(Ident(nme.WILDCARD), tpt)
@@ -918,6 +922,9 @@ abstract class TreeGen {
tree
}
}
+ object patvarTransformer extends PatvarTransformer(forFor = false)
+ /** Tag pat vars in for comprehensions. */
+ object patvarTransformerForFor extends PatvarTransformer(forFor = true)
// annotate the expression with @unchecked
def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) {
diff --git a/test/files/neg/warn-unused-privates.check b/test/files/neg/warn-unused-privates.check
index d273aa40f4..c77fcff420 100644
--- a/test/files/neg/warn-unused-privates.check
+++ b/test/files/neg/warn-unused-privates.check
@@ -71,13 +71,13 @@ warn-unused-privates.scala:153: warning: local val z in method f is never used
val C(x, y, Some(z)) = c // warn
^
warn-unused-privates.scala:161: warning: local val z in method h is never used
- val C(x @ _, y @ _, z @ Some(_)) = c // warn?
+ val C(x @ _, y @ _, z @ Some(_)) = c // warn for z?
^
warn-unused-privates.scala:166: warning: local val x in method v is never used
val D(x) = d // warn
^
warn-unused-privates.scala:170: warning: local val x in method w is never used
- val D(x @ _) = d // fixme
+ val D(x @ _) = d // warn, fixme (valdef pos is different)
^
warn-unused-privates.scala:97: warning: local var x in method f2 is never set - it could be a val
var x = 100 // warn about it being a var
diff --git a/test/files/neg/warn-unused-privates.scala b/test/files/neg/warn-unused-privates.scala
index 1b702c7555..bc2799067e 100644
--- a/test/files/neg/warn-unused-privates.scala
+++ b/test/files/neg/warn-unused-privates.scala
@@ -158,7 +158,7 @@ trait Boundings {
17
}
def h() = {
- val C(x @ _, y @ _, z @ Some(_)) = c // warn?
+ val C(x @ _, y @ _, z @ Some(_)) = c // warn for z?
17
}
@@ -167,8 +167,25 @@ trait Boundings {
17
}
def w() = {
- val D(x @ _) = d // fixme
+ val D(x @ _) = d // warn, fixme (valdef pos is different)
17
}
}
+
+trait Forever {
+ def f = {
+ val t = Option((17, 42))
+ for {
+ ns <- t
+ (i, j) = ns // no warn
+ } yield (i + j)
+ }
+ def g = {
+ val t = Option((17, 42))
+ for {
+ ns <- t
+ (i, j) = ns // warn, fixme
+ } yield 42 // val emitted only if needed, hence nothing unused
+ }
+}