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

fix(macro): use FQDNs when calling contract methods #1186

Merged
merged 3 commits into from
Jun 1, 2024

Conversation

mitinarseny
Copy link
Contributor

@mitinarseny mitinarseny commented May 30, 2024

Hey Team!

I've noticed a small inconsistency while working on #[access_control] from near-plugins, which uses #[near-sdk::near] macro internally.

The inconsistency itself can be described as follows:

The generated code by #[near_bindgen] assumes that all necessary traits were imported into current scope.

To simplify the issue, consider the following example:

use near_sdk::near;

pub mod other {
    pub trait SomeTrait {
        fn method(&self);
    }
}

#[near(contract_state)]
struct Contract {
    // ..
}

#[near]
impl other::SomeTrait for Contract {
    fn method(&self) {
        // ...
    }
}

When you compile it with cargo build --target wasm32-unknown-unknown, you get the following error:

error[E0599]: no method named `method` found for struct `Contract` in the current scope
  --> controller/src/lib.rs:17:8
   |
5  |         fn method(&self);
   |            ------ the method is available for `Contract` here
...
11 | struct Contract {
   | --------------- method `method` not found for this struct
...
17 |     fn method(&self) {
   |        ^^^^^^ method not found in `Contract`
   |
   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
1  + use crate::other::SomeTrait;
   |

For more information about this error, try `rustc --explain E0599`.
error: could not compile `defuse-controller-contract` (lib) due to previous error

This happens due to method is not implemented on Contract itself but is a part of impl other::SomeTrait for Contract, so it's not visible in the current scope.
Of course, It can be fixed by adding use other::SomeTrait at top of your module, but it's better to avoid it, so it can just work.

The current version of near-sdk 5.1.0 generates following code:

#[cfg(target_arch = "wasm32")]
#[no_mangle]
pub extern "C" fn method() {
    ::near_sdk::env::setup_panic_hook();
    let contract: Contract = ::near_sdk::env::state_read().unwrap_or_default();
    contract.method();
}

This PR introduces a fix for that by using fully qualified syntax for calling methods that are part of trait implementation.

Here is the code that this PR generates:

#[cfg(target_arch = "wasm32")]
#[no_mangle]
pub extern "C" fn method() {
    ::near_sdk::env::setup_panic_hook();
    let contract: Contract = ::near_sdk::env::state_read().unwrap_or_default();
    <Contract as other::SomeTrait>::method(&contract);
}

@frol
Copy link
Collaborator

frol commented Jun 1, 2024

@mitinarseny Great job! Thank you for your contribution! It seems to resolve #1084

@frol frol merged commit 8a908c3 into near:master Jun 1, 2024
15 checks passed
This was referenced Jun 1, 2024
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.

2 participants