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

Compilation failure when using closure #41

Closed
bbdimitriu opened this issue Dec 28, 2017 · 11 comments · Fixed by #156
Closed

Compilation failure when using closure #41

bbdimitriu opened this issue Dec 28, 2017 · 11 comments · Fixed by #156

Comments

@bbdimitriu
Copy link

Using scala 2.12.4, JDK 8u141, Quicklens 1.4.11.
Using the following setup with an example from the documentation:

case class Street(name: String)
case class Address(street: Option[Street])
case class Person(addresses: List[Address])

val person = Person(List(
            Address(Some(Street("1 Functional Rd."))),
            Address(Some(Street("2 Imperative Dr.")))
))

Then this will work:

person
     .modify(_.addresses.each.street.eachWhere(_.name.startsWith("1")).name)
     .using(_.toUpperCase)

but this will fail with a compilation error:

val one = "1"
person
     .modify(_.addresses.each.street.eachWhere(_.name.startsWith(one)).name)
     .using(_.toUpperCase)

The exception is quite long, but it starts like this:

[error] java.lang.IllegalArgumentException: Could not find proxy for val one: String in List(value one, method $anonfun$new$1, value <local QuickLensIncidentTest>, class QuickLensIncidentTest, package <empty>, package <root>) (currentOwner= method $anonfun$new$9 )
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.searchIn$1(LambdaLift.scala:310)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.$anonfun$proxy$4(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.searchIn$1(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.$anonfun$proxy$4(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.searchIn$1(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.$anonfun$proxy$4(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.searchIn$1(LambdaLift.scala:315)
[error] 	at scala.tools.nsc.transform.LambdaLift$LambdaLifter.$anonfun$proxy$4(LambdaLift.scala:315)

So it looks like closures don't work.

@guyonvarch
Copy link

guyonvarch commented Jan 16, 2018

Hi,

Same problem, but with a NoSuchElementException instead of a IllegalArgumentException.

The following code is ok:

case class B(n: Int)

val xs = Seq(B(1), B(2), B(3), B(4))
val ys = xs.modify(_.eachWhere(_.n % 2 == 0).n).using(_ * 2)

But this one is not:

case class B(n: Int)

val xs = Seq(B(1), B(2), B(3), B(4))
val test = 0
val ys = xs.modify(_.eachWhere(_.n % 2 == test).n).using(_ * 2)

The error is:

java.util.NoSuchElementException: value test
	at scala.collection.mutable.AnyRefMap$ExceptionDefault.apply(AnyRefMap.scala:425)
	at scala.collection.mutable.AnyRefMap$ExceptionDefault.apply(AnyRefMap.scala:424)
	at scala.collection.mutable.AnyRefMap.apply(AnyRefMap.scala:180)
	at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder$locals$.load(BCodeSkelBuilder.scala:389)
	at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:354)
	at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.$anonfun$genLoadArguments$1(BCodeBodyBuilder.scala:935)
	at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadArguments(BCodeBodyBuilder.scala:935)

PS: scala 2.12.4 and quicklens 1.4.11.

@erikvanoosten
Copy link

erikvanoosten commented Feb 8, 2018

As a workaround, I found out that you can rewrite

val one = "1"
person
     .modify(_.addresses.each.street.eachWhere(_.name.startsWith(one)).name)
     .using(_.toUpperCase)

to

val one = "1"
val w: Street => Boolean = _.name.startsWith(one)   // also works when 'one' comes from elsewhere
person
     .modify(_.addresses.each.street.eachWhere(w).name)
     .using(_.toUpperCase)

Not as nice, but at least it compiles.

@mizerlou
Copy link

i ran into the same eachWhere issue with quicklens 1.4.11 and scala 2.12.7.

event match {
  case Bar(fooId, status) =>
    state.modify(_.bars.eachWhere(_.id == fooId).status).setTo(status)
}

however, i wasn't getting any exception; sbt simply failed with the cryptic:

[error] Error while emitting Foo.scala
[error] value fooId

@akahanek
Copy link

akahanek commented Jul 7, 2019

There is a workaround (see @erikvanoosten post):

event match {
  case Bar(fooId, status) =>
    val condition: Bar => Boolean = _.id == fooId
    state.modify(_.bars.eachWhere(condition).status).setTo(status)
}

I wish if the original eachWhere worked.

@pete-proton
Copy link

pete-proton commented Mar 29, 2022

we stumbled across this bug as well after switching to 2.12. took ages to understand this was due to this very bug, but better late than never. the workaround does work. please let me know if I could help, I am willing to spend time on this fixing it. But would need at least some guidance

@adamw
Copy link
Member

adamw commented Mar 29, 2022

@pete-proton I wish I could help you, but I'm not sure where to start as well :) Did you try on 2.13 - is the problem there as well? If not, this might indicate that this is some 2.12-compiler-specific hmm ... let's say "feature", that might be hard to overcome. If this happens also on 2.13, maybe we incorrectly use the tree api in the macro

@pete-proton
Copy link

@adamw I see, I will try with 2.13 and see how that goes. thanks for the quick response

@emersonmoura
Copy link

emersonmoura commented Mar 31, 2022

Hi there. Is there any idea about when it would be available?
@adamw I'm using the 2.13 version and I have the same problem.

@pete-proton
Copy link

@pete-proton I wish I could help you, but I'm not sure where to start as well :) Did you try on 2.13 - is the problem there as well? If not, this might indicate that this is some 2.12-compiler-specific hmm ... let's say "feature", that might be hard to overcome. If this happens also on 2.13, maybe we incorrectly use the tree api in the macro

@adamw thank you for the guidance. the issue seems to be reproducible using scala 2.13, see. If you could give directions on how to fix it, I would be very grateful. I just have not worked with macros before. thank you in advance.

@adamw
Copy link
Member

adamw commented May 6, 2022

@pete-proton If I only knew I would fix it :) I would start by looking at usages of FunctorPathElement in QuicklensMacros, but not sure if this will lead you anywhere ...

@pete-proton
Copy link

thank you, @adamw

KacperFKorban added a commit to KacperFKorban/quicklens that referenced this issue Apr 15, 2023
For Scala 2 untypecheck args to automatically rewrite owners of
functions.
For Scala 3 change owners of args manually.

closes softwaremill#41
closes softwaremill#60
closes softwaremill#86
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants