-
Notifications
You must be signed in to change notification settings - Fork 259
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
Proposal: return Result from contract rather than panicking #574
Comments
Thanks for opening this! I've been thinking a lot about this and would like to add support for it, but it's hard to make a change that works well in a backwards-compatible way. The main issue is just that The other consideration is that for those who want to minimize contract sizes, My intuition is that the bounds for the error type might be constrained by a new trait that has auto impl from |
Hm I see. Code size matters a lot, so maybe try replacing Regarding the serialized result, yeah that’s definitely a strange pattern, but it would introduce a breaking change. There would probably need to be some sort of backward compatibility for the old behavior, which would cause returning a Result not to panic implicitly. I could imagine adding an attribute to the function like |
No this would be fine, but it may create some overhead still for types that don't need to be heap-allocated to a
Yeah, this or just recommend just using a nested If you or anyone reading would like to take this on, more than welcome to PR and I'm happy to help however I can. Other than this, not sure how soon we will have the bandwidth to support this, but it's high on my wants personally :) |
My proposal for 4.x:
In 5.x we get rid of the marker annotation and make the new behaviour the default one. I think this would provide the smoothest migration experience for everyone.
By "auto impl" are you referring to auto traits or something different? |
Keep in mind that this requires us to maintain the Returning a result and using that serialized data is an extremely uncommon pattern (I've only seen it once) so I don't think there is a large cost to switching this behaviour given it's coming with a major version bump as long as it's documented well.
Just referring to something like: impl SdkFunctionError for T where T: std::error::Error { ... } I guess a more accurate term would be generic implementation |
Why wouldn't we be able to deprecate/remove it in 5.x? Is there some technical problem with this as I think we follow semver and make breaking changes in major versions?
Right, I was just trying to put myself in the place of a user and I must admit that I rarely fully read changelogs when I upgrade a major version of a library I am using unless I see some kind of a compilation error/warning :) But if you think it is okay to do it this way I am not against it either.
Ah, I see. I have a naive implementation ready, just playing with different error contraints right now to see what makes the most amount of sense. |
We can only remove it, which is fine, I'm just indicating that this will be an abrupt change when it comes and people have to think about yet another custom annotation during
This is a very good point, and I think your plan of adding the annotation for 4.0 and changing default behaviour/removing the annotation in 5.0 makes sense. Just in the same pattern as above, just trying to make sure we consider all drawbacks :) |
I have looked into the ways to invoke It does not seem like it is possible to come up with a trait that has a generic implementation from Some alternatives I have considered up to now:
To me it seems like 3 is the most robust choice, but in the end it is also going to be the most awkward to use. Would love to hear your guys' thoughts on this before I proceed with the final implementation. |
One other benefit about 3 is that it allows specific customization of how an error would be printed out, instead of having to do things like overriding the Also, instead of using a function-like macro to implement this, can just do a derive macro to make it cleaner to implement. My intuition is similar to yours where 3 seems like the best path given our constraints/goals |
Hey!
I am still fairly new to writing Smart Contracts in Rust, but one thing that makes me feel really uncomfortable is the panicking.
I don’t feel like this is a very “rusty” way. In idiomatic Rust, I would rather expect to return a
Result<T, std::error::Error + Display>
and I don’t see a downside here, except that it needs to be supported by the SDK.Returning a
Result
:?
operatorDisplay
trait for returning the error messageThe text was updated successfully, but these errors were encountered: