better-monadic-for
better-monadic-for copied to clipboard
Unused warning on scala 2.13.5
Given build.sbt
scalaVersion := "2.13.5"
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")
scalacOptions += "-Ywarn-unused"
And main
object Main extends App {
for {
implicit0(i: Int) <- Option(1)
} yield println(i)
}
I get warning
[warn] /dev/foo/src/main/scala/Main.scala:3:23: local val i$implicit$1 in value $anonfun is never used
[warn] implicit0(i: Int) <- Option(1)
[warn] ^
[warn] one warning found
I do not get this on 2.13.4. It still works and can be passed as an implicit, its just a bad warning produced.
I tried with https://github.com/sirthias/macrolizer I modified the code to make sure that the value is required implicitly, like:
object Main extends App {
macrolizer.show {
for {
implicit0(i: Int) <- Option(1)
} yield p("i")
}
def p(prefix: String)(implicit i: Int): Unit =
println(s"$prefix: $i")
}
generated expanded code for both versions:
[info] scala.Option
[info] .apply[Int](1)
[info] .map[Unit](
[info] (
[info] (x$1: Int) =>
[info] x$1 match {
[info] case (i @ _) =>
[info] implicit val i$implicit$1: scala.Int = i;
[info] X.this.p("i")(i$implicit$1)
[info] },
[info] ),
[info] )
The i$implicit$1
gets passed explicitly, and it seems that in 2.13.5 the validation rules were changed to warn about such implicitly explicit usage.
From Scala 2.13.5 release notes:
Add linting of unused context bounds (via -Wunused:synthetics or -Wunused:params) (#9346) — thank you @som-snytt!
Yeah I'd have to look for a new workaround for that warning. The linter has always produced bogus warnings in that scenario, but I was able to silence it using a synthetic flag previously.
Given that dotty is around the corner and it's gonna break all plugins and such anyways I'm not going to look deeply into that for now. Since plugin consistently uses that $implicit$
part in a val name, my personal workaround for now is to use Scala's warning suppression:
scalacOptions += "-Wconf:msg=\\$implicit\\$:s"
Warning for synthetic param is under -Wunused:synthetics
. It's not enabled under -Xlint:unused
.
The buffet menu is -Wunused:help
. Also depending on how a macro expands, -Wmacros:after
might help.
-Wmacros:after
fails in my case, but "-Wconf:msg=\\$implicit\\$:s"
works like a charm.
I am using sbt-scalac-opts-plugin, with which "-Wunused:params"
gets added and triggers (according to changes in Scala 2.13.5).
I see it can be selectively disabled (if your build.sbt is simple, I guess):
➜ skala -Wunused:params -Wunused:-synthetics
Welcome to Scala 2.13.5-20210301-002240-d4a711b (OpenJDK 64-Bit Server VM, Java 15).
Type in expressions for evaluation. Or try :help.
scala> def f[A: Ordered] = 42
def f[A](implicit evidence$1: Ordered[A]): Int
scala>
I'm glad -Wconf
serves people well. I'm almost due for my -Wconf
refresher course, I got behind during the pandemic.
@som-snytt and @oleg-py, thank you!
as I understood, usage of -Wunused:-synthetics
could disable check for all unused context bounds too, thus "-Wconf:msg=\\$implicit\\$:s"
looks to be safer fine-grained workaround.
The i$implicit$1 gets passed explicitly, and it seems that in 2.13.5 the validation rules were changed to warn about such implicitly explicit usage.
Oh by the way, bm4 doesn't do explicit implicits itself. Macros and implicit resolution run during typer phase, and, afaik, the unused lint does as well. My speculation is that they aren't deterministically ordered between themselves, causing warnings before the implicits are fully resolved to be needed.
The lint is done at the end of typer; during typer, trees are typechecked both before and after macro expansion, and both typechecks will do implicit resolution as needed.
The lint looks at either or both of the unexpanded and expanded trees, depending on -Wmacros
. The missing mode, however, is to let only the unexpanded tree (which the user wrote) introduce symbols to check, but let either tree mark them used.