-
Notifications
You must be signed in to change notification settings - Fork 440
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
Fold restriction not allowing any Function<*> to be returned is too strict #3391
Comments
@nomisRev just adding you to see this issue quickly... ;-) |
To make the same code work with Arrow 1.2.3 it is necessary to give up the
This will circumvent the error thrown by |
Use |
Hm. I really do not like to use functions called The problem with the error is: |
Another catch people will stumble upon is: |
...just realizing, in my case, as I am using |
I played around with it and I do understand what you wanted to achieve with this error. Alas, I am not convinced this is the right way to go forward, as this change breaks compatibility for users like me in an unintended way, whereas the old error was clearly an error provoked by abuse of the nested raises. This code failed at runtime with Arrow 1.2.1 - and it should. The inner function returned has nothing to do with the outer scope at its creation time and as such must not call raise.
In Arrow 1.2.3 this correctly throws an error - sadly at runtime, which is not good enough as this is a static problem. Because of today's limitations you cannot tackle this correctly at compile time, and as such the addition to disallow any functional or closure type as a return type was added. But this is, IMHO, not a good idea, it even looks awkward as you have to specify explicitly some types you had thought of today: I would argue this change is a little too far fetching and does not help as abuse has also been detected at runtime before, so there is no difference at all - other than punishing the correct use of fold and all derived methods. |
I see your point! Would you be satisfied if it was changed to an |
If there's any way to make it more subtle, that would be a good way. I know it's a very tricky situation to work around, as basically you need the compiler to "know" not to make the raise context part of the closure created in the returned function. If that can be done with the said annotation, fine. Otherwise, I personally would go back to 1.2.1 behaviour. If a user really does that, it breaks, but it should. Then, telling in the exception what was done wrong is best you can do. |
Please don’t do that. You’re still replacing a system that threw runtime exceptions when used improperly with a system that throws runtime exceptions even when used properly, just that this alternative will “only” break unit tests. I agree with Zordid. If you can make it work correctly and at compile time, that’s good, but if that’s not possible, I’d rather have no checks than bad checks. And in the future, I’d appreciate you not making breaking changes that produce runtime exceptions in patch releases. 😅 |
@kageru I'm so sorry about that 😓 😭That was never our intention! I think part of our rationale was here that we imagined almost no1 doing this, and we were afraid people were having subtle bugs right now. Clearly some of you really now what you're doing here 😁 So this is what is actually problematic: val x = either<String, () -> Int> {
{ raise("Hello") }
}
x.getOrElse { fail("Boom!") }
.invoke() // RaiseLeakedException That's happening here:
So it's already kind-of covered, but we were still wondering if we should be more strict. Which resulted in this change in the patch, we incorrectly figured all cases of this would been subtle bugs (the thought of introducing subtle/hard to find bugs keeps me up at night 😓). So I guess what I am looking for is feedback, it seems it's hindering at least a couple of people and perhaps we can/should figure out a better default for 2.0.0. cc\ @wfhartford you also raised this topic on Slack so including you here 😉 |
I second @kageru's opinion. Don't exchange a system that breaks when not used correctly with a system that breaks when used correctly. ;-) I now had to work my way around a correct solution by either either replacing the use of the So, this should be enough to not leave the |
I totally agree. Shouldn't have happened.
Very good point. I'm open to revert it, and publish another patch or do it directly in 2.x.x. |
Thanks for copying me here Simon. I don't have much to add that hasn't been brought up by others. My use case was validating user input to produce an instance of a sealed class extending |
I think so, but only using a compiler plugin I am afraid. So I guess we cannot count that as a solution. @kyay10 experimented with special overloading syntax, to detect when a DSL returns |
Has this really been an issue for anyone? I mean, yes, it breaks at runtime when you use the Raise context during the computation at a later time - but hey, yes, that hurts. If we cannot tell this at compile time though, we should not make good code break to protect people who did not understand. |
This thread definitely gives enough reasons to revert the change. I think we should do a 1.2.4 bug fix release, given that we haven’t completely moved main to 2.0 yet. |
Yes, I was thinking the same @serras 👍 If we want to switch 2.0 to main we can, we can just make a new branch from the latest commit before doing that and release 1.2.4 from there. So doesn't have to be blocking, but let's plan some dates anyway! |
This problem is fixed as per this commit. Version 1.2.4 is on its way to Maven Central. |
Hi there!
Coming from Arrow 1.2.1, I was quite surprised to get some exceptions in my unit tests like this:
In my case, my code creates a "Validator", which happens to be a just a function signature.
I do not leak anything from within, I simply need error detection when creating my independent validator.
I think I understand what you want to prevent, but simply disallowing return values to be a
Function<*>
is too much.I will now rework my interface to not be a functional interface, but a normal one - just to circumvent this error.
This worked fine with 1.2.1:
The creation of a validator could have a logical error if the given threshold is not greater than 0. If it is, you get a proper validator that validates any int agains the threshold.
There is nothing wrong with the code, nothing can and will ever leak. It is just a double-stacked validation.
Outputs:
Going from Arrow 1.2.1 to 1.2.3 makes this code throw the error on the first line of main - in a very bad way, as the error is a runtime error and not a compile time error. I would strongly advise not to create runtime errors...
The text was updated successfully, but these errors were encountered: