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

feat: add an optional way to handle contract errors with Result #745

Merged
merged 6 commits into from
Mar 10, 2022

Conversation

itegulov
Copy link
Contributor

@itegulov itegulov commented Mar 8, 2022

Fixes #574

This PR provides an opt-in way to treat Result function return types as an error-handling mechanism. Meaning that only the underlying Ok values are serialized while the Err values result in panic. To do this, FunctionError must be implemented by the Errtype (there are default implementations for types that have Borrow<str> and a derivation macro that generates a ToString-powered implementation).

The legacy behavior still works by default (Result is treated as a normal value and goes through full serialization), but it is supposed to generate compilation warnings (I am still trying to figure out a proper way to do this ascompile_warning! seems to be missing rn, any suggestions are welcome). The user will have to mark the function with #[return_result] to opt-in for the new behavior.

Copy link
Contributor

@austinabell austinabell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! Perhaps would be worthwhile to add this pattern to any examples where it would cleanup code, but lets do this in a follow up PR :)

near-sdk/src/types/error.rs Outdated Show resolved Hide resolved
near-sdk/src/types/error.rs Outdated Show resolved Hide resolved
near-sdk-macros/src/lib.rs Outdated Show resolved Hide resolved
@@ -19,4 +19,5 @@ fn compilation_tests() {
t.pass("compilation_tests/cond_compilation.rs");
t.compile_fail("compilation_tests/payable_view.rs");
t.pass("compilation_tests/borsh_storage_key.rs");
t.pass("compilation_tests/function_error.rs");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is awesome, perhaps it's worth adding a test with invalid format(s) to assert it fails consistently and with a valid error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so, I have spent half a day trying to figure out why a negative test I wrote was not failing at compile-time and finally realized that we are compiling all these files with the host target rather than wasm32-unknown-unknown, so none of the wasm-specific code we generate is tested here. I have tried making trybuild use a target different to the one we compile near-sdk crate with, but it does not seem like it is possible? I am a bit stumped here as to how to proceed. Maybe moving compilation tests into a different crate would help, but then we would still have to compile trybuild with wasm target and I do not know if it will play out well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so, I have spent half a day trying to figure out why a negative test I wrote was not failing at compile-time and finally realized that we are compiling all these files with the host target rather than wasm32-unknown-unknown, so none of the wasm-specific code we generate is tested here. I have tried making trybuild use a target different to the one we compile near-sdk crate with, but it does not seem like it is possible? I am a bit stumped here as to how to proceed. Maybe moving compilation tests into a different crate would help, but then we would still have to compile trybuild with wasm target and I do not know if it will play out well.

Oh, interesting. Yeah I wasn't aware of this. Yeah I’d say just leave it and we can create an issue and tackle it separately not to block this one.

@itegulov
Copy link
Contributor Author

itegulov commented Mar 8, 2022

Perhaps would be worthwhile to add this pattern to any examples where it would cleanup code, but lets do this in a follow up PR :)

Yeah,lockable-fungible-token seems like a good candidate.

Also, not related to this PR in particular, but I don't think it makes sense that our only integration tests are essentially examples. I have had a few occasions where I wanted to add an e2e test but didn't want anyone to treat it as an example to follow.

@austinabell
Copy link
Contributor

Perhaps would be worthwhile to add this pattern to any examples where it would cleanup code, but lets do this in a follow up PR :)

Yeah,lockable-fungible-token seems like a good candidate.

Also, not related to this PR in particular, but I don't think it makes sense that our only integration tests are essentially examples. I have had a few occasions where I wanted to add an e2e test but didn't want anyone to treat it as an example to follow.

Absolutely, this is a good idea to build out this scaffolding. I just suggested in examples since we do want to indicate to users that this pattern exists

@austinabell
Copy link
Contributor

Oh also a changelog entry would be awesome, but nbd it can come after

Copy link
Member

@ChaoticTempest ChaoticTempest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

{
let value_ser = match result_serializer {
SerializerType::JSON => quote! {
let result = near_sdk::serde_json::to_vec(&result).expect("Failed to serialize the return value using JSON.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we're making similar calls to expect in a couple places, but @austinabell do we want to eventually get rid of these expect calls since they should be bringing the formatting mechanism. Or is there some reason we're keeping them?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc this expect doesn't embed file-specific data in the error message when used in a proc macro, but I could be remembering wrong why I didn't switch these.

Might be worth opening an issue and double-checking before next release, but wouldn't be a breaking change to come in after anyway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ticket: #746

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 this pull request may close these issues.

Proposal: return Result from contract rather than panicking
3 participants