d-unsed / ruru

Native Ruby extensions written in Rust
MIT License
832 stars 40 forks source link

RFC: default Ruby return behavior as `Result<AnyObject, AnyException>` #91

Open danielpclark opened 6 years ago

danielpclark commented 6 years ago

I've put comments through numerous issues on this and it doesn't make sense to me to leave any of this discussion so scattered so I'm opening this issue to discuss the merits of designing the default behavior where ever AnyObject would return to be Result<AnyObject, AnyException>.

Pros

Cons

Exceptions to the Rule

Some scenarios won't “ever” *cough* *cough* call for an exception to be raised like when doing equality checks. Equality checks simply make sense to return the bool type for convenience. Although any method that can be monkey-patched and rewritten may raise exceptions in which case that should use protect. The choice for design and usage would then come down to how strict to adhere to The Rust Way pattern in case of risk, or provide the end user more of a choice. My thoughts on this point is to be more relaxed on enforcing the return type and trust the developers to understand the risks and choose there own implementation decisions.

Alternatives

Looking at a Helix PR with_protect example gave me the idea to have an impl WithProtect on FnOnce() trait. It's just a rough idea but it would be something like lazily produce a FnOnce() closure and have that take &self for the method definition in the WithProtect trait to route the code through something like my protect_send method (https://github.com/d-unseductable/ruru/pull/88). So we could do my_closure.with_protect() to run it.

Strictness

If the need for safety comes first and we choose a relaxed stance on enforcing Result return types then it would come down to where we choose to draw the line. Like, for example, when instantiating a new object both new and initialize methods are highly likely to raise an exception if the startup standards for that object are not met. However the alternative method allocate is nearly guaranteed to never do anything that would raise an exception so this would be one method not needing the Result return type.

Choosing a form of this as a relaxed standard will require a more case by case decision on implementing it. That would likely be the sole choice of the author of this project on his beliefs and weighting on the likeliness of any particular method to raise an exception.

My Stance

I'm not too picky about this change being implemented. With protect_send #88 and eval #79 developers should have enough to take the risk out of most scenarios. But this will require programmers to be more defensive and more on guard with their code when working with ruru. Perhaps the easiest solution would be the alternative I've proposed here above.

I leave this RFC here open for discussion.

danielpclark commented 6 years ago

It's come to my attention upon further thinking on this subject that there is two contexts to deal with here. One is a Rust program taking advantage of Ruby and the other is a Ruby program taking advantage of Rust.

I believe there is a need for the Error kind which is currently in Rust/ruru for the Rust program side. But I do also believe we need an Exception/AnyException type for dealing with Ruby centric programs. In my minds eye I see this full implemented as AnyException being the core type used everywhere and the Error type as a wrapper to contain behavior on Rust side for Rust applications.