-
Notifications
You must be signed in to change notification settings - Fork 21
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
spurious "a pure expression does nothing" warning (awkward to suppress in 2.12, prone to occur in sbt builds) #12112
Comments
Could someone let twitter know
but
+1 for adding a rule to Probably the compiler should get out of the warnings business, except for migration warnings. Also, instead of "error", for "that which has erred," it should just output "WRONG", with a caret at the position. It could expose a code for other tools. For some conditions, it might output, "Obviously WRONG". |
I'll repeat what I wrote here - scala/scala#6218 (comment) Between val _ = compile.value
val _ = copyResources.value
So if we're going to backport something to 2.12, maybe scala/scala#6218 is better, at least the less controversial part ( |
fwiw, I agree with Eugene that |
re: Pure Expression line of greeting cards, I used to send stickers with hand-written notes https://twitter.com/hochgi/status/961521854409256960 |
The problem here is that the warning is considering the path as pure even though it contains a lazy val. This should be fixed
|
Similar discussion where selection from object warns as pure scala/scala#9161 (comment) The subsequent comment says the warning is "reasonable", presumably because nobody writes Selection |
Thanks, @som-snytt
Right, I agree with that in fact. |
Sorry, but let's not let the reproduction confuse the original issue (though fixing the lazy value thing might be useful to do anyways). The real world equivalent of the reproduction def use() =
try {
task1.value
task2.value
()
} catch {
case _: Throwable => ()
} is actually: FullInstance.app[[T0[x]](T0[Int], T0[Int]), Unit](scala.Tuple2(task2, task1), (($p$macro$3: (Int, Int)) => {
<synthetic> val $q$macro$2: Int = $p$macro$3._1;
<synthetic> val $q$macro$1: Int = $p$macro$3._2;
{
($q$macro$1: Int);
($q$macro$2: Int);
()
}
}))(AList.tuple2[Int, Int]) Which has nothing to do with initialising/paths, it's just literally pointless statements, because the resulting value isn't needed, only the side-effect that happened to produce it. Talking about this with Jason, it turns out Eugene had identified what had caused it from the get-go:
|
Yeah, so here I stand by my position that this should be fixed on sbt's side. The easiest way out might be |
Ref scala/bug#12112 Current app transformation macro creates a tree that looks like: ```scala FullInstance.app[[T0[x]](T0[Int], T0[Int]), Unit](scala.Tuple2(task2, task1), (($p$macro$3: (Int, Int)) => { <synthetic> val $q$macro$2: Int = $p$macro$3._1; <synthetic> val $q$macro$1: Int = $p$macro$3._2; { ($q$macro$1: Int); ($q$macro$2: Int); () } }))(AList.tuple2[Int, Int]) ``` Starting Scala 2.12.12 the compiler's "pure expression does nothing" has become more enthusiastic/accurate in its reach, and it started warning about the naked reference to `$q$macro$1` that appears to do nothing, even though in reality it would trigger the tasks and do something in the context of sbt. It's just _that_ particular line ends up macroed away into a pure expression. A somewhat bizarre workaround is to make a fake call to a method just to satisfy this warning. I've chosen `scala.Predef.identity` here so it can be composed together with the existing expression nesting when they exist.
Ref scala/bug#12112 Current app transformation macro creates a tree that looks like: ```scala FullInstance.app[[T0[x]](T0[Int], T0[Int]), Unit](scala.Tuple2(task2, task1), (($p$macro$3: (Int, Int)) => { <synthetic> val $q$macro$2: Int = $p$macro$3._1; <synthetic> val $q$macro$1: Int = $p$macro$3._2; { ($q$macro$1: Int); ($q$macro$2: Int); () } }))(AList.tuple2[Int, Int]) ``` Starting Scala 2.12.12 the compiler's "pure expression does nothing" has become more enthusiastic/accurate in its reach, and it started warning about the naked reference to `$q$macro$1` that appears to do nothing, even though in reality it would trigger the tasks and do something in the context of sbt. It's just _that_ particular line ends up macroed away into a pure expression. A somewhat bizarre workaround is to make a fake call to a method just to satisfy this warning. I've chosen `scala.Predef.identity` here so it can be composed together with the existing expression nesting when they exist.
sbt 1.4.1 (released today) includes a workaround: sbt/sbt#5981 |
Yea, I tried but it doesn't feel right. With sbt's macro, <synthetic> val $q$macro$2: Int = $p$macro$3._1;
<synthetic> val $q$macro$1: Int = $p$macro$3._2; The safest thing to maintain the original The workaround I got it to pass the tests handles only the |
Trying to guess what code is pure after the macro expansion is done has proven to be very precarious. There's a regression discovered by @julienrf sbt/sbt#6126 that sbt 1.4.3 does not evaluate the body of a pure function, and @eatkins has identified the source to be the combination of sbt/sbt@b62ddaa, sbt/sbt@a44aee9 and sbt/sbt@3a1463b where I'm trying to strip out pure expressions. |
In sbt#5981 I tried to work around the spruious post-macro "a pure expression does nothing" warning (scala/bug#12112) by trying to remove some pure-looking expressions out of the tree. This quickly backfired when it was reported that sbt 1.4.3 was not evaluating some code. This backs out the macro-level manipulation, and instead try to silence the warning at the reporter level. This feels safer, and it seems to work just as well.
In sbt#5981 I tried to work around the spruious post-macro "a pure expression does nothing" warning (scala/bug#12112) by trying to remove some pure-looking expressions out of the tree. This quickly backfired when it was reported that sbt 1.4.3 was not evaluating some code. This backs out the macro-level manipulation, and instead try to silence the warning at the reporter level. This feels safer, and it seems to work just as well.
In sbt#5981 I tried to work around the spruious post-macro "a pure expression does nothing" warning (scala/bug#12112) by trying to remove some pure-looking expressions out of the tree. This quickly backfired when it was reported that sbt 1.4.3 was not evaluating some code. This backs out the macro-level manipulation, and instead try to silence the warning at the reporter level. This feels safer, and it seems to work just as well.
We get hit by the same issue on mill: |
Fixes sbt#6161 Ref scala/bug#12112 This uses the configurable warning backported to Scala 2.12.
Seems better in sbt 1.5.5, although still reproducible with conditional tasks: foo := {
if (!(Compile / publish / skip).value) {
bar.value // a pure expression does nothing in statement position...
}
} |
Also present in |
Somewhere, I noted that If one were inclined or motivated to tweak this warning, which apparently one is not, one could attempt such a mitigation. |
reproduction steps
Scala 2.13.3 or 2.12.12 with fatal warnings.
The following code emulates
build.sbt
, but I'm seeing it in sbt code really sbt/sbt#5743, and I'm afraid others will run into this if we upgrade to Scala 2.12.12.problem
expectations
task1.value
may look pure-looking from the compiler's point of view, but it's actually a macro, and it's not.The reproduction above exploits a bug that @som-snytt pointed out that it's not checking full path for laziness, but I'm not sure if fixing that alone would fix the situation with sbt.
Maybe it would be better to put this warning behind a flag as an opt-in or turn it into Scalafix rule instead?
notes
In the recent releases of Scala, "a pure expression does nothing in statement position" has become more enthusiastic/accurate in its reach. Maybe because it moved to RefCheck in scala/scala#8995?
This seems to be a common occurrence since there are multiple PRs related to this:
Unit
scala#7563People have suggested various creative solutions in reply to https://twitter.com/eed3si9n/status/1293272725415505921.
https://github.com/AVSystem/scala-commons/blob/87c92cfcf5cbbd183fe5d77a841352b4e58ece39/commons-core/src/main/scala/com/avsystem/commons/SharedExtensions.scala#L81
The text was updated successfully, but these errors were encountered: