Skip to content

2.12.2 "-Ywarn-unused:patvars" false report pattern vars #10394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
SattaiLanfear opened this issue Jun 30, 2017 · 11 comments
Closed

2.12.2 "-Ywarn-unused:patvars" false report pattern vars #10394

SattaiLanfear opened this issue Jun 30, 2017 · 11 comments
Assignees
Labels
Milestone

Comments

@SattaiLanfear
Copy link

The following code generates warnings under warn-unused:

import collection.immutable
class TestThing {
	def x: immutable.Seq[(Int, Int)] = {
		val s = immutable.Seq(4, 3, 2, 1).zipWithIndex

		val builder = immutable.Seq.newBuilder[(Int, Int)]
		for(oldPair@(v1, v2)  s) {
			val toAdd = if(v1 < v2) {
				(v2, v1)
			} else {
				oldPair
			}

			builder += toAdd
		}

		builder.result()
	}
}
TestThing.scala:12: pattern var oldPair in value $anonfun is never used; `oldPair@_' suppresses this warning
[error]                 for(oldPair@(v1, v2) ← s) {

Quite clearly within the block, oldPair is being used.

Full Scalac Options provided to SBT:

scalacOptions ++= Seq(
	"-deprecation:false", // Emit warning and location for usages of deprecated APIs.
	"-feature", // Emit warning and location for usages of features that should be imported explicitly.
	"-unchecked", // Enable additional warnings where generated code depends on assumptions.
	"-Xfatal-warnings", // Fail the compilation if there are any warnings.
	"-Xlint:-missing-interpolator", // Enable recommended additional warnings.
	"-Ywarn-adapted-args", // Warn if an argument list is modified to match the receiver.
	"-Ywarn-dead-code", // Warn when dead code is identified.
	"-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
	"-Ywarn-nullary-override", // Warn when non-nullary overrides nullary, e.g. def foo() over def foo.
	"-Ywarn-numeric-widen", // Warn when numerics are widened.
	"-Ywarn-unused"
)
@som-snytt
Copy link

som-snytt commented Jun 30, 2017

Thanks for the report.

The expansion:

        import scala.collection.immutable;
        class TestThing extends scala.AnyRef {
          def <init>(): TestThing = {
            TestThing.super.<init>();
            ()
          };
          def x: scala.collection.immutable.Seq[(Int, Int)] = {
            val s: scala.collection.immutable.Seq[(Int, Int)] = scala.collection.immutable.Seq.apply[Int](4, 3, 2, 1).zipWithIndex[Int, scala.collection.immutable.Seq[(Int, Int)]](immutable.this.Seq.canBuildFrom[(Int, Int)]);
            val builder: scala.collection.mutable.Builder[(Int, Int),scala.collection.immutable.Seq[(Int, Int)]] = scala.collection.immutable.Seq.newBuilder[(Int, Int)];
            s.withFilter(((check$ifrefutable$1: (Int, Int)) => (check$ifrefutable$1: (Int, Int) @unchecked) match {
  case (oldPair @ (_1: Int, _2: Int)(Int, Int)((v1 @ _), (v2 @ _))) => true
  case _ => false
})).foreach[scala.collection.mutable.Builder[(Int, Int),scala.collection.immutable.Seq[(Int, Int)]]](((x$1: (Int, Int)) => (x$1: (Int, Int) @unchecked) match {
              case (oldPair @ (_1: Int, _2: Int)(Int, Int)((v1 @ _), (v2 @ _))) => {
                val toAdd: (Int, Int) = if (v1.<(v2))
                  scala.Tuple2.apply[Int, Int](v2, v1)
                else
                  oldPair;
                builder.+=(toAdd)
              }
            }));
            builder.result()
          }
        }

Maybe this is a reduction (edited):

scala> List(1,2,3) withFilter { case x @ _ => true }
res3: scala.collection.generic.FilterMonadic[Int,List[Int]] = scala.collection.TraversableLike$WithFilter@54b2fc58

scala> List(1,2,3) withFilter { case x @ (_: Int) => true }
<console>:12: warning: pattern var x in value $anonfun is never used; `x@_' suppresses this warning
       List(1,2,3) withFilter { case x @ (_: Int) => true }
                                     ^
res4: scala.collection.generic.FilterMonadic[Int,List[Int]] = scala.collection.TraversableLike$WithFilter@45d56062

The wildcard pattern is the escape hatch.

@pathikrit
Copy link

@som-snytt som-snytt changed the title 2.12.2 "-Ywarn-unused" false report pattern vars 2.12.2 "-Ywarn-unused:patvars" false report pattern vars Dec 1, 2017
@som-snytt
Copy link

Worth documenting that -Xlint:unused enables the friendlier unused warnings. The others are -Ywarn-unused:patvars,explicits where explicits means explicit parameters as opposed to implicits.

@lewis6991
Copy link

Is there any workaround? This is currently giving me issues.

@som-snytt
Copy link

@lewis6991 The workaround is to avoid a refutable pattern in the for comprehension, or turn off the warning, -Ywarn-unused:-patvars,_, or prefer -Xlint:unused.

Another footnote: it looks like tuple destructuring doesn't warn at all, even if the tuple vars are unused.

@lewis6991
Copy link

Ok, thanks for the reply.
Is it possible suppress the warning as the error message suggests?

`oldPair@_' suppresses this warning

Though I don't exactly understand how you would apply this for the given error.

@som-snytt
Copy link

I don't see a syntax to help you.

The reason tuples don't warn is that they are rewritten syntactically to the escape hatch. It's the case P(x) => true part that produced the warning. A better fix there would be for that rewrite to replace vars with underscore.

$ scala -Ywarn-unused:patvars
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144).
Type in expressions for evaluation. Or try :help.

scala> for ((x,y) <- List((2,3))) yield x
res0: List[Int] = List(2)

scala> for ((x,y) <- List((2,3))) yield x  //print

scala.collection.immutable.List.apply[(Int, Int)](scala.Tuple2.apply[Int, Int](2, 3)).withFilter(((check$ifrefutable$1: (Int, Int)) => (check$ifrefutable$1: @scala.unchecked) match {
  case scala.Tuple2((x @ _), (y @ _)) => true
  case _ => false
})).map[Int, List[Int]](((x$1: (Int, Int)) => (x$1: @scala.unchecked) match {
  case scala.Tuple2((x @ _), (y @ _)) => x
}))(scala.collection.immutable.List.canBuildFrom[Int]) // : List[Int]

scala> for (z@(x,y) <- List((2,3))) yield z  //print

scala.collection.immutable.List.apply[(Int, Int)](scala.Tuple2.apply[Int, Int](2, 3)).withFilter(((check$ifrefutable$1: (Int, Int)) => (check$ifrefutable$1: @scala.unchecked) match {
  case (z @ scala.Tuple2((x @ _), (y @ _))) => true
  case _ => false
})).map[(Int, Int), List[(Int, Int)]](((x$1: (Int, Int)) => (x$1: @scala.unchecked) match {
  case (z @ scala.Tuple2((x @ _), (y @ _))) => z
}))(scala.collection.immutable.List.canBuildFrom[(Int, Int)]) // : List[(Int, Int)]

scala> for (z@(x,y) <- List((2,3))) yield z  //print
<console>:12: warning: pattern var z in value $anonfun is never used; `z@_' suppresses this warning
       for (z@(x,y) <- List((2,3))) yield z  //print
            ^
res1: List[(Int, Int)] = List((2,3))

@SethTisue SethTisue added this to the 2.12.5 milestone Feb 16, 2018
@lrytz
Copy link
Member

lrytz commented Feb 22, 2018

scala/scala#6190

@lrytz lrytz closed this as completed Feb 22, 2018
@lewis6991
Copy link

This is still causing an issue for me (2.12.5). Here is a simplified test case.

object ErroneousPatVarWarning {
  case class A()
  case class B(b: A)

  def main(args: Array[String]) {
    for(B(a@A()) <- Nil: List[B])
      println(a)
  }
}
[error] /Users/lewrus01/sbt_helloworld/hw.scala:6:11: pattern var a in value $anonfun is never used; `a@_' suppresses this warning
[error]     for(B(a@A()) <- Nil: List[B])
[error]           ^

@som-snytt
Copy link

@lewis6991 Thanks. scala/scala#6473

@SethTisue
Copy link
Member

Som's followup fix has been merged for 2.12.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants