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

lens-aeson examples throw IllegalStateExceptions #120

Closed
mmisamore opened this issue Oct 23, 2018 · 7 comments
Closed

lens-aeson examples throw IllegalStateExceptions #120

mmisamore opened this issue Oct 23, 2018 · 7 comments

Comments

@mmisamore
Copy link

mmisamore commented Oct 23, 2018

Description

lens-aeson examples are throwing runtime exceptions.

Steps to Reproduce

  1. Add build-depends for lens and lens-aeson to a new project .cabal file
  2. etlas repl
  3. import Control.Lens
  4. import Data.Aeson.Lens
  5. "[1, \"x\"]" ^? nth 0 . _Number
    or
    "42" ^? _Integer

Expected

Just 1.0
or
Just 42

Actual

Prelude Data.Aeson.Lens Control.Lens Main>  "[1, \"x\"]" ^? nth 0 . _Number
*** Exception: java.lang.RuntimeException: Failed during evalStmt of Eta REPL expression
	at eta.serv.REPLClassLoader.evalStmt(REPLClassLoader.java:253)
	at eta.serv.Utils.evalStmt(Utils.java:32)
	at main.eta.serv.Run$sat$21.applyV(Run.hs:61)
	at eta.runtime.exception.Exception.catch_(Exception.java:132)
	at main.eta.serv.Run$sat$20.applyV(Run.hs:181)
	at main.eta.serv.Run.$La4$1(Run.hs:166)
	at main.eta.serv.Run$sat$23.applyV(Run.hs)
	at eta.runtime.exception.Exception.unmaskAsyncExceptions(Exception.java:94)
	at main.eta.serv.Run$sat$19.applyV(Run.hs:125)
	at eta.runtime.exception.Exception.catch_(Exception.java:132)
	at main.eta.serv.Run$sat$18.applyV(Run.hs)
	at eta.runtime.stg.Closures$EvalLazyIO.enter(Closures.java:125)
	at eta.runtime.stg.Capability.schedule(Capability.java:254)
	at eta.runtime.concurrent.WorkerThread.run(WorkerThread.java:16)
Caused by: java.lang.RuntimeException: Failed during evalIOInternal of Eta REPL expression
	at eta.serv.REPLClassLoader.evalIOInternal(REPLClassLoader.java:381)
	at eta.serv.REPLClassLoader.evalStmt(REPLClassLoader.java:246)
	... 13 more
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at eta.serv.REPLClassLoader.evalIOInternal(REPLClassLoader.java:379)
	... 14 more
Caused by: java.lang.IllegalStateException: The trampoline function expects a thunk and not a function [class aeson.data.aeson.types.internal.datacons.Success extends class aeson.data.aeson.types.internal.tycons.Result]
	at eta.runtime.stg.Stg.trampoline(Stg.java:87)
	at lens_aeson.data.aeson.Lens.$fAsNumber_ByteString3(Lens.hs:386)
	at lens_aeson.data.aeson.Lens$$fAsNumber_ByteString3.apply1(Lens.hs)
	at profunctors.data.profunctor.Unsafe$sat$1.thunkEnter(Unsafe.hs:169)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at base.data.Either.$fFunctor_Either_$cfmap(Either.hs:130)
	at base.data.Either$$fFunctor_Either_$cfmap.apply2(Either.hs:130)
	at eta.runtime.apply.PAP1_1.apply1(PAP1_1.java:62)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe$sat.thunkEnter(Unsafe.hs:169)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at lens_aeson.data.aeson.Lens$sat$261.apply1(Lens.hs)
	at profunctors.data.profunctor.Unsafe.$fProfunctor_ZLzmzgZR_$cdimap(Unsafe.hs:169)
	at profunctors.data.profunctor.Unsafe$$fProfunctor_ZLzmzgZR_$cdimap.apply4(Unsafe.hs:169)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:53)
	at eta.runtime.apply.PAPSlow.apply1(PAPSlow.java:179)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe$sat.thunkEnter(Unsafe.hs:169)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at eta.runtime.stg.Closure.evaluateTail(Closure.java:33)
	at base.data.functor.Const.$fFunctor_Const2(Const.hs:66)
	at base.data.functor.Const$$fFunctor_Const2.apply2(Const.hs)
	at eta.runtime.apply.PAP1_1.apply1(PAP1_1.java:62)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe.$fProfunctor_ZLzmzgZR_$cdimap(Unsafe.hs:169)
	at profunctors.data.profunctor.Unsafe$$fProfunctor_ZLzmzgZR_$cdimap.apply4(Unsafe.hs:169)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:53)
	at eta.runtime.apply.PAPSlow.apply1(PAPSlow.java:179)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe$sat.thunkEnter(Unsafe.hs:169)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at eta.runtime.stg.Closure.evaluateTail(Closure.java:33)
	at base.data.functor.Const.$fFunctor_Const2(Const.hs:66)
	at base.data.functor.Const$$fFunctor_Const2.apply2(Const.hs)
	at eta.runtime.apply.PAP1_1.apply1(PAP1_1.java:62)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe.$fProfunctor_ZLzmzgZR_$cdimap(Unsafe.hs:169)
	at profunctors.data.profunctor.Unsafe$$fProfunctor_ZLzmzgZR_$cdimap.apply4(Unsafe.hs:169)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:53)
	at eta.runtime.apply.PAPSlow.apply1(PAPSlow.java:179)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe$sat.thunkEnter(Unsafe.hs:169)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at eta.runtime.stg.Closure.evaluateTail(Closure.java:33)
	at base.data.functor.Const.$fFunctor_Const2(Const.hs:66)
	at base.data.functor.Const$$fFunctor_Const2.apply2(Const.hs)
	at eta.runtime.apply.PAP1_1.apply1(PAP1_1.java:62)
	at eta.runtime.thunk.Thunk.apply1(Thunk.java:151)
	at profunctors.data.profunctor.Unsafe.$fProfunctor_ZLzmzgZR_$cdimap(Unsafe.hs:169)
	at profunctors.data.profunctor.Unsafe$$fProfunctor_ZLzmzgZR_$cdimap.apply4(Unsafe.hs:169)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:53)
	at eta.runtime.apply.PAPSlow.apply1(PAPSlow.java:179)
	at eta.runtime.apply.PAPSlow.apply2(PAPSlow.java:212)
	at eta.runtime.thunk.Thunk.apply2(Thunk.java:161)
	at lens.control.lens.Fold.$La12$1(Fold.hs:1266)
	at lens.control.lens.Fold.zcz3fU(Fold.hs:1266)
	at lens.control.lens.Fold$zcz3fU.apply2(Fold.hs:1266)
	at interactive.EtaRepl1_3$it0.thunkEnter(Interactive.hs)
	at eta.runtime.thunk.UpdatableThunk.evaluate(UpdatableThunk.java:19)
	at base.ghc.Show.$fShow_Maybe_$cshow(Show.hs:190)
	at base.ghc.Show$sat$492.apply1(Show.hs)
	at base.system.IO$sat.thunkEnter(IO.hs:279)
	at eta.runtime.thunk.SingleEntryThunk.evaluate(SingleEntryThunk.java:20)
	at base.ghc.io.handle.Text.hPutStr3(Text.hs:558)
	at base.ghc.io.handle.Text.hPutStr2(Text.hs:550)
	at base.system.IO.print1(IO.hs:265)
	at base.system.IO.print(IO.hs:279)
	at base.system.IO$print.apply2V(IO.hs:279)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:71)
	at eta.runtime.apply.PAPSlow.applyV(PAPSlow.java:119)
	at eta.runtime.thunk.Thunk.applyV(Thunk.java:121)
	at base.ghc.Base.thenIO1(Base.hs:1335)
	at base.ghc.Base.thenIO(Base.hs:1335)
	at base.ghc.Base$thenIO.apply2V(Base.hs:1335)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:71)
	at eta.runtime.apply.PAPSlow.applyV(PAPSlow.java:119)
	at eta.runtime.thunk.Thunk.applyV(Thunk.java:121)
	at eta.runtime.exception.Exception.unmaskAsyncExceptions(Exception.java:94)
	at base.control.exception.Base$sat$25.applyV(Base.hs)
	at eta.runtime.exception.Exception.catch_(Exception.java:132)
	at base.control.exception.Base$sat$22.applyV(Base.hs:226)
	at eta.runtime.exception.Exception.maskAsyncExceptions(Exception.java:45)
	at base.control.exception.Base.bracket1(Base.hs:228)
	at base.system.Environment.withArgs1(Environment.hs:156)
	at base.system.Environment.withArgs(Environment.hs:153)
	at base.system.Environment$withArgs.apply2V(Environment.hs:153)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:71)
	at eta.runtime.apply.PAPSlow.applyV(PAPSlow.java:119)
	at eta.runtime.thunk.Thunk.applyV(Thunk.java:121)
	at eta.runtime.exception.Exception.unmaskAsyncExceptions(Exception.java:94)
	at base.control.exception.Base$sat$25.applyV(Base.hs)
	at eta.runtime.exception.Exception.catch_(Exception.java:132)
	at base.control.exception.Base$sat$22.applyV(Base.hs:226)
	at eta.runtime.exception.Exception.maskAsyncExceptions(Exception.java:45)
	at base.control.exception.Base.bracket1(Base.hs:228)
	at base.system.Environment.withProgName1(Environment.hs:170)
	at base.system.Environment.withProgName(Environment.hs:168)
	at base.system.Environment$withProgName.apply2V(Environment.hs:168)
	at eta.runtime.apply.PAPSlow.apply(PAPSlow.java:71)
	at eta.runtime.apply.PAPSlow.applyV(PAPSlow.java:119)
	at eta.runtime.stg.Closures$EvalIO.enter(Closures.java:150)
	at eta.runtime.stg.Capability.schedule(Capability.java:254)
	at eta.runtime.stg.Capability.scheduleClosure(Capability.java:210)
	at eta.runtime.Runtime.evalIO(Runtime.java:380)
	... 19 more

Environment

  1. etlas --version
    etlas version 1.5.0.0
    compiled using version 2.1.0.0 of the etlas-cabal library
  2. The Eta Programming Language Compiler, Version 0.8.6b2, Git Revision e42f73dcfa407c0f80394240911a488d85c7199a
  3. Mac OS X: Darwin Michaels-MacBook-Pro.local 17.2.0 Darwin Kernel Version 17.2.0: Fri Sep 29 18:27:05 PDT 2017; root:xnu-4570.20.62~3/RELEASE_X86_64 x86_64
@rahulmutt
Copy link
Member

rahulmutt commented Oct 24, 2018

We wanted to improve the user experience for the trampoline function by giving the user hints when you're trampolining the wrong expression in your code. Turns out it's not a good idea according to this bug report.

If you would like a contribution opportunity, the fix to this is just removing the following lines in the runtime system:
https://github.com/typelead/eta/blob/master/rts/src/main/java/eta/runtime/stg/Stg.java#L82-L88

If not, we'll get around to fixing this by the next release.

@mmisamore
Copy link
Author

Thanks @rahulmutt! I see that it is trying to trampoline via an Eta Hackage patch here, but I'm not sure why it would fail in this specific case: https://github.com/typelead/eta-hackage/blob/master/patches/aeson-1.2.4.0.patch. As you said, maybe the aeson patch is trampolining on the wrong expression.

I'll pull down the eta compiler repo and see if I can get it to compile, because this looks like it would be educational.

@jneira
Copy link
Collaborator

jneira commented Oct 24, 2018

If i remember correctly i got that error when using trampoline in a class instance method impl, so it seems internally it is not represented by a Thunk like normal functions

@rahulmutt
Copy link
Member

rahulmutt commented Oct 25, 2018

@mmisamore Actually, the aeson package is trampolining on the right expression, it's that the change in the trampolining implementation that I highlighted thinks that it's a wrong expression. That change was added very recently and I think we didn't test against an example like lens-aeson. We should probably add this example to the test suite to catch future regressions.

The if condition that determines whether an exception should be thrown was added because of what @jneira mentioned - if you use the trampoline function wrong (try to trampoline a function directly that's not a thunk), it can throw really nasty exceptions that are less readable than the one you got.

The basic hierarchy for Eta values:

  • eta.runtime.stg.Closure - The superclass of all Eta values
    • eta.runtime.thunk.Thunk - The superclass of all yet-to-be evaluated expressions.
    • eta.runtime.stg.Value - The superclass of all thunks that have been evaluated to Weak Head Normal Form
      • eta.runtime.stg.DataCon - The superclass of all ADTs
      • eta.runtime.apply.Function - The superclass of all functions
      • eta.runtime.apply.PAP - Stores "pending arguments" for curried functions and can be thought of as a function itself, though the hierarchy doesn't reflect it (yet).

The trampoline function calls the enter method of the Closure that is passed to it. The enter method for subclasses of Value other than Function and PAP simply returns itself because they don't have any code attached to them. For Function and PAP, enter will execute the code of the respective function and retrieves the argument(s) from the ubiquitous StgContext object (the object that stores the runtime state for the particular thread of execution).

The problem here is that trampoline does not pass any arguments! So when you try to trampoline against a function directly and not a thunk that evaluates a function, it will cause nasty errors that @jneira mentioned.

So I think the true fix has to be a better if condition. Perhaps if (!(closure instanceof Thunk) && !(closure instanceof DataCon)).

@mmisamore
Copy link
Author

mmisamore commented Oct 25, 2018 via email

@rahulmutt
Copy link
Member

Great. Btw, if you have successfully source installed the master version of Eta, a fast way to test changes to the runtime can be done with:

stack exec eta-build -- rts-clean

All future Eta project compilations will use the new version of the runtime with your changes (unless you're using Gradle to compile your Eta projects, in which case you should wipe out ~/.gradle/caches/etlas before doing that step).

@rahulmutt
Copy link
Member

Should be resolved after typelead/eta#896 submitted by the OP.

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

No branches or pull requests

3 participants