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

Unary function with argument of type Unit is not type-safe #12495

Closed
otto-dev opened this issue Nov 15, 2021 · 9 comments · Fixed by scala/scala#10150
Closed

Unary function with argument of type Unit is not type-safe #12495

otto-dev opened this issue Nov 15, 2021 · 9 comments · Fixed by scala/scala#10150

Comments

@otto-dev
Copy link

reproduction steps

using Scala 2.13.6,

scala> val f = (a: Unit) => println(s"Received $a")
val f: Unit => Unit = $Lambda$2279/411876574@4ee6291f

scala> f("foo", "bar", "baz")
Received ()

problem

The compiler should not allow the arguments ("foo", "bar", "baz") to be passed to a function that expects one Unit argument. This is particularly problematic for higher-order functions that may return a unary A => Unit function, with A being Unit in situations where the first function argument is irrelevant.

@otto-dev otto-dev changed the title Unit function arguments not type-safe Unary function with argument of type Unit is not type-safe Nov 15, 2021
@som-snytt
Copy link

scala> f(42, 17) // print
                                                                f.apply({
  scala.Tuple2.apply[Int, Int](42, 17);
  ()
}) // : Unit

@eed3si9n
Copy link
Member

As annoying and un-typesafe as it is, this is perfectly legal under the current specification. SLS 6.26.1 Value Conversions

Value Discarding

If 𝑒 has some value type and the expected type is Unit, 𝑒 is converted to the expected type by embedding it in the term { 𝑒; () }.

@dwijnand
Copy link
Member

dwijnand commented Nov 15, 2021

True, but this is under auto-tupling. I'm sure it's spec-legal to make this not compile, right?

@som-snytt
Copy link

➜  ~ scala -Werror -Wvalue-discard -Xlint
Welcome to Scala 2.13.7 (OpenJDK 64-Bit Server VM, Java 17).
Type in expressions for evaluation. Or try :help.

scala> val f = (u: Unit) => println(s"[$u]")
val f: Unit => Unit = $Lambda$1122/0x0000000801086220@203d1d93

scala> f(42, 17)
        ^
       warning: discarded non-Unit value
        ^
       warning: adapted the argument list to the expected 2-tuple: add additional parens instead
               signature: Function1.apply(v1: T1): R
         given arguments: 42, 17
        after adaptation: Function1((42, 17): Unit)
error: No warnings can be incurred under -Werror.

@SethTisue
Copy link
Member

SethTisue commented Nov 16, 2021

I had expected to label this "fixed in Scala 3", but I'm puzzled that Scala 3.1.0 doesn't complain, even under -source:future. I thought we'd agreed that adapted arguments were being phased out the language. Would someone like to dig around in the Scala 3 issue tracker and see if a bug ought to be opened?

Closing this ticket, since it's working as designed, even though we ended up regretting the design. fwiw, I'd never write a line of Scala 2 without -Xlint, not even in the REPL.

@som-snytt
Copy link

som-snytt commented Nov 16, 2021

@SethTisue I also tried it twice. The spec under autotupling links to the suspended PR 4311; see also https://docs.scala-lang.org/scala3/reference/overview.html#dropped-constructs Part of that pandemic saga was linting its sister wart, multi-arg infix. I get my zigs mixed up with my zags.

For this issue, perhaps a narrow lint is called for. Discarding args seems especially pernicious.

@SethTisue
Copy link
Member

SethTisue commented Nov 16, 2021

Okay, shall we reopen it as a "help wanted" enhancement ticket?

(I edited your comment slightly.)

@som-snytt
Copy link

som-snytt commented Nov 16, 2021

Thanks, I get my jigs mixed up with my jags. Oh, I had intentionally not linked the PR to avoid extra noise. Anyway, feel free to reopen. Perhaps someone will step up.

BTW the other nice link there is their refusal to consider the request for "autotuple Tuple1" feature.

@som-snytt
Copy link

In the linked PR, it warns under -Xlint, and -Wvalue-discard will also warn if specified.

The value discard is triggered first. I think the message is obscure, and the second message is informative.

test/files/neg/t12495.scala:4: warning: discarded non-Unit value of type (Int, Int)
  def g = f(42, 27)
           ^
test/files/neg/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)
           ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants