When looking into Higher-kinded types (HKTs), Generic associated types (GATs) constantly pop up as "the solution". They allow you to express things like this (which I think is really cool):
trait Foo {
type Bar<T>;
fn process<T>(&mut self, ctx: Self::Bar<T>);
}
I'm really excited about GATs being close to landing, but from what I understand it only enables HKTs for traits that use associated types. Or is there a way to express something like this too? (And if not, is there a feature flag or working issue for it?)
trait Foo<for<T> Bar> {
fn process<T>(&mut self, ctx: Self::Bar<T>);
}
Related
I know that str implements the trait Display. However, It is said that &str also implements this trait.
I wanna inspect the implementation detail of Display trait for &str, but I searched the resource code base of Rust and didn't find it. It doesn't exist in the std::str or the std::fmt::Display crates.
Maybe I had miss something I didn't realize. Can anyone give me some clue about where to find it?
First, str implements Display, i.e.: impl Display for str.
Second, there is a blanket implementation that implements Display for every reference type whose referent type also implements Display, i.e., impl<'_, T> Display for &'_ T where T: Display + ?Sized
Therefore, &str implements Display because its referent type, str, also does.
It is not implemented directly for &str. Rather, there is a blanket implementation impl<T: ?Sized + Display> Display for &'_ T.
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.
}
I have a type Foo that I want to be able to display to the end user as a string, is it more idiomatic to do this by implementing Display or by implementing ToString?
If Display is the way to go, how would I actually end up with a String? I suspect I need to make use of write!, but I'm not entirely sure how.
You should not implement ToString manually. The ToString trait is already implemented for all types which implement fmt::Display:
impl<T> ToString for T
where
T: Display + ?Sized,
{ /* ... */ }
If you implement Display, to_string() will be available on your type automatically.
fmt::Display is intended to be implemented manually for those select few types which should be displayed to the user, while fmt::Debug is expected to be implemented for all types in such a way that represents their internals most nicely (for most types this means that they should have #[derive(Debug)] on them).
In order to obtain the string representation of fmt::Debug output you need to use format!("{:?}", value), with {:?} being a placeholder for types which implement fmt::Debug.
RFC 565 defines guidelines for when to use fmt::Debug and fmt::Display.
I'm trying Rust and finding it hard to interpret what to do when my function signatures don't correspond to those expected by a trait. Example
impl std::fmt::Display for MyType {
// Not sure what to put here so I stub it and hope to get help from error
fn fmt() -> () { }
}
The compiler error message is
method `fmt` has a `&self` declaration in the trait, but not in the impl
What I was hoping to see was something helping me implement the method for example:
Incorrect method signature for `fmt`
Actual signature fn fmt() -> ()
Expected signature fn fmt(&self, &mut Formatter) -> Result<(), Error>
Is it possible to get signature help from the compiler like this? I'm usually very impressed by the very friendly and detailed compiler errors, so this one really surprised me. I'm using the rust playground (https://play.rust-lang.org/) but I don't think that makes any difference to compiler output.
No, it is not possible. If you think this is an important feature, you can always submit a feature request to Rust issue tracker.
Meanwhile, you can use docs generated by rustdoc, e.g. these for the standard library. They are usually pretty awesome, especially given that there is search function.
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.