How do I call a getter from another Substrate module? - rust

I have two modules, MyCore and Special. MyCore has a public getter:
pub fn get_core_account() -> Option<T::AccountId>
Which gets an accountId. If I call this from Special in a simple manner:
let core_account = MyCore::get_core_account();
then rustc complains that it can't infer the type, which is odd because the public setters don't need further info. So I make the type explicit
let core_account: Option<T::AccountId> = MyCore::get_core_account();
But this triggers demands for type specifiers on the call, so we elaborate:
let core_account: Option<T::AccountId> = MyCore::<T>::get_core_account();
At which point rust complains that it can't find get_core_account, because Special doesn't have a restriction to implement MyCore::Trait. But I don't want Special to implement MyCore::Trait! I want to call a getter!
Perhaps I'm missing something regarding the use of T here - in theory, Special is a trait templated over some T, which we can implement using a Test class if we implement the required types.
Does Special really need to implement MyCore::Trait?

What you want to do is possible, yet you are probably doing something wrong which is not clearly demonstrated in the question. Would be very helpful if you post the Trait definitions of both modules.
Does Special really need to implement MyCore::Trait?
No. You might have to make it a trait bound though.
Basically, you have two options in such cases:
If your Core is something that all other modules will depend on, similar to frame-system, you can explicitly depend on it. Note that this path should be taken with care and you don't want to create too big of a monolithic software with this mindset. Nonetheless, in that case, you can just do:
// in special.rs
// This is needed because then we can pass `T` into `mycore::Module<_>`.
pub trait Trait: mucore::Trait {
...
}
// and then later on you can call:
<mycore::Module<T>>:: get_core_account()
This seems like the approach that you wanted to take.
Alternatively, you can bind the two modules together without this explicit dependency. This is useful for when you want your Special to receive the getter eventually, but you don't really care who provides it. Or in other words, if multiple candidates can provide this getter and you want to be generic over it.
For this, you first need a common trait definition.
// in some common dependency
trait CoreGetterProvider<AccountId> {
fn getter() -> Option<AccountId>;
}
and your Special would express:
pub trait Trait {
// .. other stuff. Assuming that it has a common AccountId with Core.
type Getter: CoreGetterProvider<Self::AccountId>
}
And your Core implements it
// in Core.rs
impl<T: Trait> CoreGetterProvider<T::AccountId> for Module<T> { ... }
Finally, when building the runtime, you can pass the Core module to Special.
impl core::Trait for Runtime { ... }
impl special::Trait for Runtime {
type Getter = core::Module<Runtime> // or just `Core`. construct_runtime! creates this type alias.
}

Related

How can I split up a large impl over multiple files?

I really don't like monolithic implementations of the functions for a class (in C++ speak). In that language I can split things up as I like; in Rust there are strict rules about what goes in what files.
I have about 2000 lines (no comments/ docs) of impl for a struct. Logically they can be broken up into different sets; functions for managing aspect A, functions for managing aspect B, ... They all noodle on the struct's data big time, so chopping the struct up further wont help.
I saw in one answer that you can have
// in thing.rs
struct Thing{
.......
}
impl Thing{
fn1
fn2
}
// in more_thing.rs
use crate::thing::*;
impl Thing{
fn3,
fn4
}
// in lib.rs
mod thing;
mod more_thing;
This works, almost (I was surprised it worked at all). Its a kind of half way house. The problem is that for the methods in more_thing.rs I have to declare the fields of Thing all pub. Which is doable but not great. Are there any other options?
I know I can limit the pub scope but still it blows encapsulation.
All non-pub items in a module are still visible in its submodules. Just make more_thing a submodule of thing instead of a sibling. You can do this by putting it in a directory named thing, and putting the mod declaration inside thing.rs:
// thing.rs (or thing/mod.rs; see below)
pub struct Thing {
field: i32,
}
// Note the lack of `pub`: `more` is only an implementation detail
mod more;
// thing/more.rs
use super::Thing;
impl Thing {
// Although it is defined in a non-`pub` module, this method will be visible anywhere
// `Thing` is because it is marked `pub` and is a member of `Thing`. You can use
// `pub(crate)` or `pub(super)` instead to get different levels of visibility, or
// leave it private and it will only be available in the current module (thing::more)
pub fn field(&self) -> i32 {
// because more is a submodule of thing, non-`pub` members are visible here.
self.field
}
}
If you wish to keep all the Thing-related files in the thing directory, you can rename thing.rs to the special filename thing/mod.rs and it will work in exactly the same way.
All methods are private by default in Rust, which means they are only accessible in the scope of their containing module (which is never larger than a file), in this case thing.rs. thing.rs is just as remote to more_thing.rs as any libraries and external code; it may as well be a separate crate. In essence, you are trying to declare a private method on an external item, which of course fails.
However, this can be a bit confusing because when it comes to orphan rules, you can always implement traits for any item in the same crate, not just the same module. This is because trait implementations are always public (as long as you can access both the trait and the item implementing it; the actual orphan rules are a bit more complicated but this is the basic idea).
In essence: trait implementations are public, but method implementations are private by default. In order to implement public things you need at least public access, and in order to implement private things you need private access.
Instead, one solution is to simply declare a function that takes your item as an argument. For example, in more_thing.rs:
use super::thing::Thing;
fn foo(thing: &Thing) {
// ...
}
Why not put impl blocks in the same file?
in thing.rs
struct Thing {
.......
}
impl Thing {
fn1
fn2
}
impl Thing {
fn3
fn4
}
The methods are splited though there is still a large file.

Is it possible to iterate over an external struct's members in a macro? [duplicate]

I'm interested in using wasm-bindgen via rust-webpack-template to compile Rust code to WebAssembly. However, I'd like to avoid directly wrapping my code with the #[wasm_bindgen] attribute macro directly so that I can separate out the function logic from the generated WebAssembly interface to better organize my project. Instead, I would prefer to have binding generation be in a separate file, for example:
mod my_code;
use my_code::my_function;
#[wasm_bindgen]
my_function; // I want to do something like this!
I understand that #[wasm_bindgen] is a macro attribute that operates on the AST of the function definition that usually follows, but is there an approach for applying that macro to code defined elsewhere?
As far as I know, there's no way to do this. Macros operate on the AST of the code they are attached to, and there's no code to be attached to here.
If you really need this, you'll have to copy-and-paste the signature of your function:
mod my_code {
pub fn my_function(_: i32) -> String {
unimplemented!()
}
}
#[wasm_bindgen]
fn my_function(a: i32) -> String {
my_code::my_function(a)
}
It's possible you could write a macro to make the wrapping slightly less tedious, but you'll still need to replicate the function name, argument types, and return type.

What is the difference between using a type as a different name and a type alias?

What is the difference between
use hyper::status::StatusCode as Error;
and
type Error = hyper::status::StatusCode;
Are the any more differences between them except that type can be also pub type? What are the benefits between using one or another?
In case of simple types, like in your example, there doesn't seem to be any semantic difference. Moreover, there is a direct analogue with use to pub type, it's pub use:
// will be available to other modules
pub use hyper::status::StatusCode as Error;
However, there are differences in more complex cases. For example, you can define generic type aliases or aliases for specialized generic types:
type Result<T> = ::std::result::Result<T, MyError>;
type OptionI32 = Option<i32>;
The general idea is that you usually use type aliases because they are more powerful and suggest the intent more clearly, like with Result, and you use use .. as .. when you only want to import that specific name but it conflicts with something which is already in the current namespace:
use std::io::Read as StdRead;
trait Read: StdRead { ... }
Note that using path-qualified identifiers should be preferred to use renaming. The above is better written as
use std::io;
trait Read: io::Read { ... }
(unless Read methods are used for some concrete type in the same file, of course).
Using use .. as .. as a substitute for type (in case where it is possible) is uncommon and I think it should be avoided.

Optional function argument that is specified as a trait instead of a concrete type

I have been watching Rust for the past few months but I just started into an actual project. I am not sure if the terminology in the title is correct. Please let me know how it can be corrected.
I am writing a rust wrapper around the ENet library (http://enet.bespin.org). My goal is to keep the rust API as similar to the C API as possible except to refactor functions that take C style handle pointers into member functions of structure objects. I want to keep the API similar so that the official C documentation will apply equally well to the rust wrapper.
ENet exposes a single function to create either a client host or a server host. When creating a server you pass a pointer to an IP Address structure to the function. When creating a client you pass NULL.
I am trying to emulate that behavior using the ToSocketAddr trait and Option but I am running into problems using them in conjunction.
This is a reduced example of what I am trying to do:
use std::io::net::ip::ToSocketAddr;
fn create_host<A: ToSocketAddr>(addr: Option<A>) {
match addr {
Some(a) => println!("Address is {}. Return a server host object.",a.to_socket_addr()),
None => println!("no address... Return a client.")
};
}
fn main() {
create_host(Some("localhost:12345"));
create_host(None);
}
The first call to create_host() works like a charm. The second call however will not compile.
Rustc returns
error: unable to infer enough type information about `_`; type annotations required
I am guessing that error is occurring because None doesn't provide any resolution to the generic A. I tried the following but this doesn't work either because ToSocketAddr does not implement the trait core::kinds::Sized.
fn create_host(addr: Option<ToSocketAddr>) {
...
}
Is there a way I can do this or do I need to take a different approach?
fn main() {
create_host(Some("localhost:12345"));
create_host(None::<&str>);
}
I've chosen &str here as it is the same type as on the first call, so that the compiler wouldn't generate another monomorphized version of the generic function. You could choose any type that implements ToSocketAddr.

Function behaviour depending on whether a trait is implemented

Given a situation like this one :
trait Basic {
// Some functions
}
trait Derived : Basic {
// some other functions
}
fn do_someting<T : Basic>(target: &mut T) {
// do stuff
}
Is it possible to have the do_something function behave differently depending on whether target implements the trait Derived or not (the information being known at compilation time) ?
I guess something similar could be achieved in C++ using template specialization, but I don't see a Rust equivalent.
AFAIK this is not currently possible. Defining fn do_something<T : Derived> alongside your existing function leads to compilation error:
error: duplicate definition of value `do_someting`
because both versions can be used for Basic.
There are some proposals to allow explicit bounds like <T: Basic + !Derived> that will allow you to resolve this conflict.
But I personally hope that impl overloading/specialization will be possible some day after 1.0 version is released.

Resources