Skip to content

By-name arguments do not behave as expected with right-associative operators #2808

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

Closed
smarter opened this issue Jun 25, 2017 · 3 comments
Closed

Comments

@smarter
Copy link
Member

smarter commented Jun 25, 2017

This is the same bug as scala/bug#1980:

class C {
  def m2_:(f: => Int) = ()
}

object Test {
  def foo() = { println("foo") ; 5 }

  def main(args: Array[String]): Unit = {
    val c = new C
    foo() m2_: c
  }
}

This should print nothing but ends up printing foo because we desugar:

foo() m2_: c

into:

val $1$: Int = Test.foo()
c.m2_:($1$)

In scalac this was basically unfixable because this desugaring is done during parsing, but in dotty we should have the type of m2_: during desugaring which tells us that its argument is by-name and thus we could simply do:

lazy val $1$: Int = Test.foo()
c.m2_:($1$)

Whether or not this is fixed might influence the design of the collection strawman: scala/collection-strawman#127

@smarter smarter changed the title by-name arguments do not work as expected with righ-associative operators By-name arguments do not behave as expected with right-associative operators Jun 25, 2017
@szeiger
Copy link
Contributor

szeiger commented Jun 30, 2017

While playing around with a possible solution for 2.13 I realized that lazy val may not be ideal in this case because it caches the result whereas a by-name parameter does not. For true by-name semantics we should translate a :: b where the parameter to b is by-name to b.::(a), i.e. the same as for left-associative operators, except for the reversed operands.

@szeiger
Copy link
Contributor

szeiger commented Jun 30, 2017

Here's my implementation of this scheme for 2.13: scala/scala#5969

@lrytz
Copy link
Member

lrytz commented Jul 3, 2017

I agree the transformation to b.::(a) is nice here. For names / defaults, we de-sugar to () => a:

scala> def f(x: => Int, y: Int) = 0
f: (x: => Int, y: Int)Int

scala> f(y = 1, x = { println(""); 2}) // print

{
  val x$1: Int = 1;
  val x$2: () => Int @scala.reflect.internal.annotations.uncheckedBounds = (() => {
    scala.Predef.println("");
    2
  });
  $line16.$read.$iw.$iw.f(x$2.apply(), x$1)
} // : Int

odersky added a commit to dotty-staging/dotty that referenced this issue Jan 15, 2018
Lift the left hand side of a right-associative infix operation
only if the operation takes a by-value argument.
odersky added a commit to dotty-staging/dotty that referenced this issue Feb 2, 2018
Lift the left hand side of a right-associative infix operation
only if the operation takes a by-value argument.
odersky added a commit to dotty-staging/dotty that referenced this issue Feb 2, 2018
Lift the left hand side of a right-associative infix operation
only if the operation takes a by-value argument.
@odersky odersky closed this as completed in 0124dca Feb 3, 2018
odersky added a commit that referenced this issue Feb 3, 2018
Fix #2808: Modify lifting of infix operations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants