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

Lint if args adapted to Unit and discarded #10150

Merged
merged 1 commit into from Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/compiler/scala/tools/nsc/settings/Warnings.scala
Expand Up @@ -213,6 +213,7 @@ trait Warnings {
val MultiargInfix = LintWarning("multiarg-infix", "Infix operator was defined or used with multiarg operand.")
val ImplicitRecursion = LintWarning("implicit-recursion", "Implicit resolves to an enclosing definition.")
val UniversalMethods = LintWarning("universal-methods", "Require arg to is/asInstanceOf.")
val ArgDiscard = LintWarning("arg-discard", "-Wvalue-discard for adapted arguments.")

def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
Expand Down Expand Up @@ -246,6 +247,7 @@ trait Warnings {
def multiargInfix = lint contains MultiargInfix
def lintImplicitRecursion = lint.contains(ImplicitRecursion) || (warnSelfImplicit.value: @nowarn("cat=deprecation"))
def lintUniversalMethods = lint.contains(UniversalMethods)
def lintArgDiscard = lint.contains(ArgDiscard)

// The Xlint warning group.
val lint = MultiChoiceSetting(
Expand Down
16 changes: 12 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
Expand Up @@ -77,20 +77,28 @@ trait Adaptations {
)
}
@inline def msg(what: String): String = s"adaptation of an empty argument list by inserting () $what"
@inline def noAdaptation = {
@inline def noAdaptation: false = {
context.error(t.pos, adaptWarningMessage(msg("has been removed"), showAdaptation = false))
false // drop adaptation
}
@inline def deprecatedAdaptation = {
@inline def deprecatedAdaptation: true = {
val twist =
if (isLeakyTarget) "leaky (Object-receiving) target makes this especially dangerous"
else "this is unlikely to be what you want"
val text = s"${msg("is deprecated")}: ${twist}"
context.deprecationWarning(t.pos, t.symbol, adaptWarningMessage(text), "2.11.0")
true // keep adaptation
}
@inline def warnAdaptation = {
if (settings.warnAdaptedArgs && !isInfix) context.warning(t.pos, adaptWarningMessage(
@inline def warnAdaptation: true = {
def discardedArgs = t match {
case Apply(_, stat @ Block(Apply(TypeApply(Select(adapter, _), _), adapted) :: Nil, expr) :: Nil) =>
isTupleSymbol(adapter.symbol.companion) && expr.tpe == UnitTpe && adapted == args
case _ => false
}
if (settings.lintArgDiscard && discardedArgs) context.warning(t.pos, adaptWarningMessage(
s"adapted the argument list to expected Unit type: arguments will be discarded"),
WarningCategory.LintAdaptedArgs)
else if (settings.warnAdaptedArgs && !isInfix) context.warning(t.pos, adaptWarningMessage(
s"adapted the argument list to the expected ${args.size}-tuple: add additional parens instead"),
WarningCategory.LintAdaptedArgs)
true // keep adaptation
Expand Down
12 changes: 12 additions & 0 deletions test/files/neg/t12495.check
@@ -0,0 +1,12 @@
t12495.scala:4: warning: discarded non-Unit value of type (Int, Int)
def g = f(42, 27)
^
t12495.scala:4: warning: adapted the argument list to expected Unit type: arguments will be discarded
signature: Function1.apply(v1: T1): R
given arguments: 42, 27
after adaptation: Function1((42, 27): Unit)
def g = f(42, 27)
^
error: No warnings can be incurred under -Werror.
2 warnings
1 error
5 changes: 5 additions & 0 deletions test/files/neg/t12495.scala
@@ -0,0 +1,5 @@
// scalac: -Werror -Xlint:arg-discard,adapted-args -Wvalue-discard
class C {
val f = (u: Unit) => println(s"[$u]")
def g = f(42, 27)
}