Skip to content
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

Either lint unused or warn discarded or warn pure #10641

Merged
merged 1 commit into from
May 22, 2024

Conversation

som-snytt
Copy link
Contributor

@som-snytt som-snytt commented Dec 21, 2023

If they ask for -Wnonunit-statement, warn; otherwise, if they ask for -Wvalue-discard, warn for that.

If they don't ask, warn about pure expressions that aren't useful.

Move the value discard messaging to refchecks, in order to coordinate. Follow up to #8995.

Scala 3 won't mitigate warning value discard under expr: Unit syntax, so don't advertise it.

The mitigation is not removed, for convenience, and because no one writes normal code like that.

To see how to suppress warnings, use -Wconf:any:warning-verbose in Scala 2 and -Wconf:any:verbose in Scala 3.

Extracted from stalled #10476

@scala-jenkins scala-jenkins added this to the 2.13.14 milestone Dec 21, 2023
@SethTisue
Copy link
Member

Is there a different recommendation we could substitute?

@som-snytt
Copy link
Contributor Author

Every warning is nowarnable. Unfortunately, Scala 3 has different syntax and categories and messages, so there is no specific advice that cross-compiles.

@som-snytt som-snytt marked this pull request as ready for review January 27, 2024 21:46
@SethTisue SethTisue modified the milestones: 2.13.14, 2.13.13 Jan 30, 2024
@SethTisue
Copy link
Member

SethTisue commented Jan 30, 2024

What is the recommended mitigation in Scala 3?

I'm asking for a couple reasons, one is that I'd like the PR description to document the current situation for users, the other is that maybe we could do something on the Scala 3 side.

@som-snytt
Copy link
Contributor Author

scala -Wvalue-discard -Wnonunit-statement -Wconf:any:warning-verbose
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 21.0.2).
Type in expressions for evaluation. Or try :help.

scala> def f = 42
def f: Int

scala> def g: Unit = f
                     ^
       warning: discarded non-Unit value of type Int
       Applicable -Wconf / @nowarn filters for this warning: msg=<part of the message>, cat=w-flag-value-discard, site=g
                     ^
       warning: unused value of type Int (add `: Unit` to discard silently)
       Applicable -Wconf / @nowarn filters for this warning: msg=<part of the message>, cat=other-pure-statement, site=g
def g: Unit

scala>

and

scala -Wvalue-discard -Wnonunit-statement -Wconf:any:verbose
Welcome to Scala 3.3.1 (21.0.2, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> def f = 42
def f: Int

scala> def g: Unit = f
1 warning found
-- [E175] Potential Issue Warning: -------------------------------------------------------------------------------------
1 |def g: Unit = f
  |              ^
  |              discarded non-Unit value of type (f : => Int)
Matching filters for @nowarn or -Wconf:
  - id=E175
  - name=ValueDiscarding
def g: Unit

TIL dotty doesn't warn nonunit-statement for value discard. (The conversion moves a result expression to statement position, even the user did not "write it like that".)

@lrytz
Copy link
Member

lrytz commented Jan 31, 2024

Would be good if we could limit it to one warning. -Wvalue-discard is in typer, -Wnonunit-statement in refchecks. Every discarded value will lead to nonunit statement, or?

@som-snytt
Copy link
Contributor Author

Well, that may be true now. IIRC they used to have slightly different triggers.

scala -Wvalue-discard -Wnonunit-statement
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 21.0.2).
Type in expressions for evaluation. Or try :help.

scala> def f(): Unit = 42
                       ^
       warning: discarded non-Unit value of type Int(42)
                       ^
       warning: unused value of type Int(42) (add `: Unit` to discard silently)
def f(): Unit

scala> val b = collection.mutable.ListBuffer.empty[Int]
val b: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala> def f(): Unit = b += 42
def f(): Unit

scala>

@SethTisue SethTisue modified the milestones: 2.13.13, 2.13.14 Feb 6, 2024
@SethTisue
Copy link
Member

SethTisue commented Feb 7, 2024

I don't mean to be difficult, but I don't feel comfortable merging this unless we can, at the same time, provide users extremely clear guidance about how to proceed, including in cross-built projects. Changing the behavior without providing that seems like churn to me.

@som-snytt
Copy link
Contributor Author

@SethTisue they will have to supply version-specific -Wconf as shown above. But that is already true now.

This PR doesn't change behavior, only the "advice".

@SethTisue SethTisue modified the milestones: 2.13.14, 2.13.15 Mar 13, 2024
@som-snytt
Copy link
Contributor Author

som-snytt commented May 16, 2024

Relatedly, proposal to try -Wnonunit-statement then -Wvalue-discard then "pure expr in statement position" on dotty at scala/scala3#20408.

That behavior is adopted in refchecks, per Lukas's review comment above.

The previous message for the case of "discarded pure expression" is amended. It used to be a separate warning, but after the move from typer to refchecks, appears in the wrong order (because top-down traversal).

@som-snytt som-snytt force-pushed the tweak/remove-ad-for-mitigation branch from dab82c6 to 1b33c8a Compare May 17, 2024 04:34
@som-snytt som-snytt changed the title Remove deprecated advice Either lint unused or warn discarded or warn pure May 17, 2024
@som-snytt som-snytt changed the title Either lint unused or warn discarded or warn pure Either lint unused or warn discarded or warn pure! May 17, 2024
@som-snytt som-snytt force-pushed the tweak/remove-ad-for-mitigation branch from 1b33c8a to 2daadc5 Compare May 17, 2024 15:26
@som-snytt
Copy link
Contributor Author

TIL I also need to partest --srcpath async --update-check.

Copy link
Member

@lrytz lrytz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM otherwise, thank you!

@@ -1908,6 +1908,13 @@ abstract class RefChecks extends Transform {
&& !treeInfo.hasExplicitUnit(t) // suppressed by explicit expr: Unit
&& !isJavaApplication(t) // Java methods are inherently side-effecting
)
def checkDiscardValue(t: Tree): Boolean =
t.hasAttachment[DiscardedValue.type] && {
t.removeAttachment[DiscardedValue.type]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's getAndRemoveAttachment[DiscardedValue.type].exists

Copy link
Contributor Author

@som-snytt som-snytt May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was avoiding Option. This corner of the API is bothersome. Edit: but I would welcome guidance or reassurance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, retronym had already tired of the API, so I will use his improvement. getAndRemove isn't very efficient, aside from allocating. It would be nice to have remove(element): Boolean with just an indicator that it was removed. I did not touch the calls to update, which remove before adding (presumably to ensure only one attachment of a given type).

val discard = if (adapted) "; a value can be silently discarded when Unit is expected" else ""
val msg =
if (t.hasAttachment[DiscardedExpr.type]) {
t.removeAttachment[DiscardedExpr.type]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also getAndRemoveAttachment

@som-snytt som-snytt force-pushed the tweak/remove-ad-for-mitigation branch from 2daadc5 to 8be2220 Compare May 21, 2024 15:09
@som-snytt som-snytt changed the title Either lint unused or warn discarded or warn pure! Either lint unused or warn discarded or warn pure May 21, 2024
@som-snytt
Copy link
Contributor Author

som-snytt commented May 21, 2024

Squashed, rebased, used retronym API for getAndRemove.

Also realized I don't have a workflow for removing ! syntax from my title, which winds up in the merge commit.

@som-snytt som-snytt requested a review from lrytz May 21, 2024 15:16
Copy link
Member

@lrytz lrytz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 maybe we can improve the attachments API so that the convenient thing doesn't come with caveats

@lrytz lrytz merged commit 0d8f4ca into scala:2.13.x May 22, 2024
3 checks passed
@som-snytt som-snytt deleted the tweak/remove-ad-for-mitigation branch May 22, 2024 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants