-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Implement -Wvalue-discard warning #15975
Conversation
Warn when an expression `e` with non-Unit type is adapted by embedding it into a block `{ e; () }` because the expected type is Unit.
It's documented somewhere, but Scala 2 avoids warning for methods that return
The user can "annotate" that discarding is desired:
That convention was devised before I'd suggest not supporting ancient compiler option aliases (the original If they want to support |
This is a fine line to walk since lots of parts of the Scala library do return something that can safely be ignored. For instance To make the test bullet-proof it would need to be augmented with effect checking. It makes indeed no sense to discard the value of a pure expression, but for side-effecting expressions it's common practice. |
Note that in Scala 2 these warnings aren't enabled by default, and they aren't enabled by
I agree with Som that these are important to exempt. |
Relatedly, My recent interaction with |
Apologies for rekindling this discussion, but I am currently finishing writing a Scala 3 book focused on purely functional programming, and I was wondering if there were any plans for Scala 3 to add support for I've been following the work on #16157, but it seems this work is out of scope. Then Chris made me aware of this draft PR. I've also been pointed to the zerowaste plugin, I've been told this feature is planned to be implemented after 3.3, but I couldn't find any discussion about it. Is there any link related to this I can refer to in my book? This flag is a must-have for production systems, and I believe it currently is the biggest blocker to Scala 3 adoption in FP shops. |
I copied all the relevant code over from `scala/scala:2.13.x`, so the behaviour should be equivalent to Scala 2.13.
I've ported over from Scala 2 the special-case handling of functions that return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested the PR and it seems to work as expected (the same as in Scala 2). Added some suggestions/questions about the code.
* * targs = Nil | ||
* * argss = List(List(arg11, arg12...), List(arg21, arg22, ...)) | ||
*/ | ||
final class Applied(val tree: Tree) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we possibly reuse some of the existing utility methods e.g. allArguments
, methPart
, stripApply
, etc.?
Or else make those methods top-level? (Some of them seem unnecessary for this case)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointer. When I was copying swathes of code from Scala 2, I didn't noticed those almost-identical methods already existed. I've refactored Applied
to make use of them.
TreeInfo already provided helpers that were almost identical to some of the methods in `Applied` that I copied over from Scala 2. Refactored `Applied` to make use of the existing methods. Moved `termArgss` from `TypedTreeInfo` up to `TreeInfo` so I could make use of it in `Applied`. Also moved `typeArgss`, just for consistency.
/** Applications in Scala can have one of the following shapes: | ||
* | ||
* 1) naked core: Ident(_) or Select(_, _) or basically anything else | ||
* 2) naked core with targs: TypeApply(core, targs) or AppliedTypeTree(core, targs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Scala 3 a TypeApply
can also wrap an Apply
because of how extension methods are desugared and soon because of #14019
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(And an AppliedTypeTree can wrap another AppliedTypeTree, e.g. type Foo[X] = [Y] =>> Y; val x: Foo[Int][String] = ""
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I was planning to address that comment but it was gradually moving further down my todo list 😄 so I'm happy for you to take over from here. |
Warn when an expression
e
with non-Unit type is adapted by embedding it into a block{ e; () }
because the expected type is Unit.In Scala 2.13 (relevant code in Typers.scala) there are two special cases:
: Unit
.@nowarn
. It's just as easy to annotate with@nowarn
as with: Unit
.this.type
, because this is a very common operation when using mutable collections.warn-value-discard.scala
test for some examples.2.13.x
branch in scala/scala, so the behaviour should be equivalent to Scala 2.13.