How to call a trait method without a struct instance? - rust

If I have a struct with a method that doesn't have self as an argument, I can call the method via SomeStruct::method(). I can't seem to do the same with a method that's defined from a trait. For example:
trait SomeTrait {
fn one_trait() -> uint;
}
struct SomeStruct;
impl SomeStruct {
fn one_notrait() -> uint {
1u
}
}
impl SomeTrait for SomeStruct {
fn one_trait() -> uint {
1u
}
}
#[test]
fn testing() {
SomeStruct::one_trait(); // doesn't compile
SomeStruct::one_notrait(); // compiles
}
The compiler gives the error "unresolved name 'SomeStruct::one_trait.'"
How can I call a struct's implementation of a trait method directly?

trait Animal {
fn baby_name() -> String;
}
struct Dog;
impl Dog {
fn baby_name() -> String {
String::from("Spot")
}
}
impl Animal for Dog {
fn baby_name() -> String {
String::from("puppy")
}
}
fn main() {
println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
}
From Advanced Trait

I believe this is currently not possible. The problem is that you cannot explicitly specify the Self type. But there is an active RFC in the pipeline which should allow this when implemented.
In the meantime, you could work around it like this:
trait SomeTrait {
fn one_trait(&self) -> uint;
}
struct Static<T>;
struct SomeStruct;
impl SomeTrait for Static<SomeStruct> {
fn one_trait(&self) -> uint { 1 }
}
fn main() {
let type_to_uint = Static::<SomeStruct>.one_trait();
println!("{}", type_to_uint);
}
This is how I map a type to an integer (if that's what you're after). It's done without having a value of type T. The dummy value, Static<T>, has a size of zero.

Related

How to avoid orphan rules for repr transparent wrappers

My problem is I want to have a transparent wrapper and implemented Into<underlying> for it. Unfortunately, rust's orphan rules forbid it. Here is a simple example:
#[repr(transparent)]
pub struct MyWrapper<T>(pub T);
impl<T> Into<T> for MyWrapper<T> {
fn into(self) -> T {
self.0
}
}
The question is is there any way I can implement it? I'm using macro to generate impl for all types I'm currently using but it looks very awkward and dirty.
You can implement the Deref trait instead. The Deref docs contain the following example which is almost identical to your code:
use std::ops::Deref;
struct DerefExample<T> {
value: T
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}
You can implement it in a regular impl block:
#[repr(transparent)]
pub struct MyWrapper<T>(pub T);
impl<T> MyWrapper<T> {
pub fn into(self) -> T {
self.0
}
}
fn main() {
let wrapped : MyWrapper<f32> = MyWrapper::<f32>(3.4f32);
let unwrapped : f32 = wrapped.into();
println!("{}", unwrapped);
}

Trait as generic parameter to struct object intialization

I have this struct:
use sp_runtime::traits::Block;
struct Bar<T: Block> {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar { e1: Vec::new() }
}
}
Where Block is from the sp_runtime crate.
In main:
fn main() {
let var_1 = Bar::<Block>::new();
}
Full Code
This code throws compilation error that trait can't be made into an object. I'm new to Rust, much of online solution haven't addressed this issue. Kindly let me know how to get around initialization of bar object.
Your confusion likely stems from the fact that the sp_runtime crate has two items called Block. One is the trait sp_runtime::traits::Block and the other is a struct, sp_runtime::generic::Block, which implements that trait.
Traits can be used as a constraint on a type parameter, but they cannot be used as a type argument.
So, in your definition of Bar<T>, you can constrain T with sp_runtime::traits::Block, but when you construct an instance of Bar<T>, T needs to be the struct instead.
use sp_runtime::traits::Block;
struct<T: Block> Bar {
e1: Vec<T>,
}
impl<T: Block> Bar<T> {
pub fn new() -> Self {
Bar {
e1: Vec::new(),
}
}
}
fn main() {
use sp_runtime::generic::Block;
let var_1 = Bar::<Block>::new();
}
However, given that this is the only implementation of the trait in the crate, you can just avoid mentioning the trait altogether and use the concrete struct type (unless you plan on implementing it yourself or depending on implementations from other crates):
use sp_runtime::generic::Block;
struct Bar{
e1 : Vec<Block>,
}
impl Bar {
pub fn new() -> Self{
Bar {
e1: Vec::new(),
}
}
}
fn main() {
let var_1 = Bar::new();
}

Is it possible to use `impl Trait` as a function's return type in a trait definition?

Is it at all possible to define functions inside of traits as having impl Trait return types? I want to create a trait that can be implemented by multiple structs so that the new() functions of all of them returns an object that they can all be used in the same way without having to write code specific to each one.
trait A {
fn new() -> impl A;
}
However, I get the following error:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:2:17
|
2 | fn new() -> impl A;
| ^^^^^^
Is this a limitation of the current implementation of impl Trait or am I using it wrong?
As trentcl mentions, you cannot currently place impl Trait in the return position of a trait method.
From RFC 1522:
impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.
Eventually, we will want to allow the feature to be used within traits [...]
For now, you must use a boxed trait object:
trait A {
fn new() -> Box<dyn A>;
}
See also:
Is it possible to have a constructor function in a trait?
Why can a trait not construct itself?
How do I return an instance of a trait from a method?
Nightly only
If you wish to use unstable nightly features, you can use existential types (RFC 2071):
// 1.67.0-nightly (2022-11-13 e631891f7ad40eac3ef5)
#![feature(type_alias_impl_trait)]
#![feature(return_position_impl_trait_in_trait)]
trait FromTheFuture {
type Iter: Iterator<Item = u8>;
fn returns_associated_type(&self) -> Self::Iter;
// Needs `return_position_impl_trait_in_trait`
fn returns_impl_trait(&self) -> impl Iterator<Item = u16>;
}
impl FromTheFuture for u8 {
// Needs `type_alias_impl_trait`
type Iter = impl Iterator<Item = u8>;
fn returns_associated_type(&self) -> Self::Iter {
std::iter::repeat(*self).take(*self as usize)
}
fn returns_impl_trait(&self) -> impl Iterator<Item = u16> {
Some((*self).into()).into_iter()
}
}
fn main() {
for v in 7.returns_associated_type() {
println!("type_alias_impl_trait: {v}");
}
for v in 7.returns_impl_trait() {
println!("return_position_impl_trait_in_trait: {v}");
}
}
If you only need to return the specific type for which the trait is currently being implemented, you may be looking for Self.
trait A {
fn new() -> Self;
}
For example, this will compile:
trait A {
fn new() -> Self;
}
struct Person;
impl A for Person {
fn new() -> Person {
Person
}
}
Or, a fuller example, demonstrating using the trait:
trait A {
fn new<S: Into<String>>(name: S) -> Self;
fn get_name(&self) -> String;
}
struct Person {
name: String
}
impl A for Person {
fn new<S: Into<String>>(name: S) -> Person {
Person { name: name.into() }
}
fn get_name(&self) -> String {
self.name.clone()
}
}
struct Pet {
name: String
}
impl A for Pet {
fn new<S: Into<String>>(name: S) -> Pet {
Pet { name: name.into() }
}
fn get_name(&self) -> String {
self.name.clone()
}
}
fn main() {
let person = Person::new("Simon");
let pet = Pet::new("Buddy");
println!("{}'s pets name is {}", get_name(&person), get_name(&pet));
}
fn get_name<T: A>(a: &T) -> String {
a.get_name()
}
Playground
As a side note.. I have used String here in favor of &str references.. to reduce the need for explicit lifetimes and potentially a loss of focus on the question at hand. I believe it's generally the convention to return a &str reference when borrowing the content and that seems appropriate here.. however I didn't want to distract from the actual example too much.
You can get something similar even in the case where it's not returning Self by using an associated type and explicitly naming the return type:
trait B {}
struct C;
impl B for C {}
trait A {
type FReturn: B;
fn f() -> Self::FReturn;
}
struct Person;
impl A for Person {
type FReturn = C;
fn f() -> C {
C
}
}
Fairly new to Rust, so may need checking.
You could parametrise over the return type. This has limits, but they're less restrictive than simply returning Self.
trait A<T> where T: A<T> {
fn new() -> T;
}
// return a Self type
struct St1;
impl A<St1> for St1 {
fn new() -> St1 { St1 }
}
// return a different type
struct St2;
impl A<St1> for St2 {
fn new() -> St1 { St1 }
}
// won't compile as u32 doesn't implement A<u32>
struct St3;
impl A<u32> for St3 {
fn new() -> u32 { 0 }
}
The limit in this case is that you can only return a type T that implements A<T>. Here, St1 implements A<St1>, so it's OK for St2 to impl A<St2>. However, it wouldn't work with, for example,
impl A<St1> for St2 ...
impl A<St2> for St1 ...
For that you'd need to restrict the types further, with e.g.
trait A<T, U> where U: A<T, U>, T: A<U, T> {
fn new() -> T;
}
but I'm struggling to get my head round this last one.

How can I expose a safe wrapper around an owned pointer?

I'm wrapping a C library that has two structs: one has a pointer to the other.
struct StructA {
void * some_mem;
};
struct StructB {
void * some_mem;
struct StructA * some_struct;
};
Both of these structs own memory, so my wrapper has constructors and destructors for both of them.
struct StructA(*mut c_void);
impl StructA {
fn new() -> Self {
StructA(c_constructor())
}
}
impl Drop for StructA {
fn drop(&mut self) {
let StructA(ptr) = self;
c_destructor(ptr);
}
}
There's also a function that takes a pointer to StructB and returns its pointer to StructA:
const struct StructA * get_struct(const struct StructB * obj);
The user of this function should not free the returned pointer, since it will be freed when the user frees obj.
How can I wrap this function? The problem is that the destructor for StructB frees all its memory, including the one for StructA. So if my wrapping of get_struct returns an object, then the wrapped StructA will be freed twice (right?). It could instead return a reference to an object, but where would that object live?
I could have separate structs for StructA based on whether it's standalone and needs to be freed or if it's a reference, but I'm hoping that's unnecessary.
I could have separate structs for StructA based on whether it's standalone and needs to be freed or if it's a reference, but I'm hoping that's unnecessary.
It's necessary. The difference between an owned StructA * and a borrowed StructA * is precisely the same as the difference between a Box<T> and a &T. They're both "just a pointer", but the semantics are completely different.
Something along these lines is probably what you want:
use std::marker::PhantomData;
struct OwnedA(*mut c_void);
impl Drop for OwnedA {
fn drop(&mut self) { }
}
impl OwnedA {
fn deref(&self) -> RefA { RefA(self.0, PhantomData) }
}
struct RefA<'a>(*mut c_void, PhantomData<&'a u8>);
struct OwnedB(*mut c_void);
impl Drop for OwnedB {
fn drop(&mut self) { }
}
impl OwnedB {
fn get_a(&self) -> RefA { RefA(get_struct(self.0), PhantomData) }
}
In particular, it's worth noting that lifetime parameter on RefA lets the compiler make sure you don't use a RefA after the backing structure has been freed.
I could have separate structs for StructA based on whether it's standalone and needs to be freed or if it's a reference, but I'm hoping that's unnecessary.
I believe this would be the accepted pattern. For backup, I'd point to the fact that this is a normal pattern in the Rust library. &str and String, &[T] and Vec<T>, Path and PathBuf, and probably lots of others I can't think of.
The good news is that you can use similar patterns as these pairs, leveraging Deref or DerefMut to call down to shared implementation:
use std::ops::{Deref, DerefMut};
enum RawFoo {}
fn c_foo_new() -> *const RawFoo { std::ptr::null() }
fn c_foo_free(_f: *const RawFoo) {}
fn c_foo_count(_f: *const RawFoo) -> u8 { 42 }
fn c_foo_make_awesome(_f: *const RawFoo, _v: bool) { }
struct OwnedFoo(Foo);
impl OwnedFoo {
fn new() -> OwnedFoo {
OwnedFoo(Foo(c_foo_new()))
}
}
impl Drop for OwnedFoo {
fn drop(&mut self) { c_foo_free((self.0).0) }
}
impl Deref for OwnedFoo {
type Target = Foo;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for OwnedFoo {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
struct Foo(*const RawFoo);
impl Foo {
fn count(&self) -> u8 { c_foo_count(self.0) }
fn make_awesome(&mut self, v: bool) { c_foo_make_awesome(self.0, v) }
}
fn main() {
let mut f = OwnedFoo::new();
println!("{}", f.count());
f.make_awesome(true);
}
Then, when you get a borrowed pointer from your other object, just wrap it up in a &Foo:
use std::mem;
fn c_bar_foo_ref() -> *const RawFoo { std::ptr::null() }
// Ignoring boilerplate for wrapping the raw Bar pointer
struct Bar;
impl Bar {
fn new() -> Bar { Bar }
fn foo(&self) -> &Foo {
unsafe { mem::transmute(c_bar_foo_ref()) }
}
fn foo_mut(&mut self) -> &mut Foo {
unsafe { mem::transmute(c_bar_foo_ref()) }
}
}
fn main() {
let mut b = Bar::new();
println!("{}", b.foo().count());
b.foo_mut().make_awesome(true);
// Doesn't work - lifetime constrained to Bar
// let nope = Bar::new().foo();
}

Implementing Rust traits cause struct to not be found

When I implement a trait on a struct in Rust it's causing the struct type not to be found. First, the working code:
trait SomeTrait {
fn new() -> Box<SomeTrait>;
fn get_some_value(&self) -> int;
}
struct SomeStruct {
value: int
}
impl SomeStruct {
fn new() -> Box<SomeStruct> {
return box SomeStruct { value: 3 };
}
fn get_some_value(&self) -> int {
return self.value;
}
}
fn main() {
let obj = SomeStruct::new();
println!("{}", obj.get_some_value());
}
Here the SomeTrait trait isn't being used. Everything works. If I now change the impl of SomeStruct to implement SomeTrait:
trait SomeTrait {
fn new() -> Box<SomeTrait>;
fn get_some_value(&self) -> int;
}
struct SomeStruct {
value: int
}
impl SomeTrait for SomeStruct {
fn new() -> Box<SomeTrait> {
return box SomeStruct { value: 3 };
}
fn get_some_value(&self) -> int {
return self.value;
}
}
fn main() {
let obj = SomeStruct::new();
println!("{}", obj.get_some_value());
}
I get the error:
trait.rs:21:13: 21:28 error: failed to resolve. Use of undeclared module `SomeStruct`
trait.rs:21 let obj = SomeStruct::new();
^~~~~~~~~~~~~~~
trait.rs:21:13: 21:28 error: unresolved name `SomeStruct::new`.
trait.rs:21 let obj = SomeStruct::new();
What am I doing wrong? Why is SomeStruct suddenly missing? Thanks!
At the moment, associated functions (non-method functions) in traits are called via the trait, i.e. SomeTrait::new(). However, if you just write this, the compiler cannot work out which impl you're using, as there's no way to specify the SomeStruct information (it only works if the special Self type is mentioned in the signature somewhere). That is, the compiler needs to be able to work out which version of new should be called. (And this is required; they could have very different behaviour:
struct Foo;
impl SomeTrait for Foo {
fn new() -> Box<SomeTrait> { box Foo as Box<SomeTrait> }
}
struct Bar;
impl SomeTrait for Bar {
fn new() -> Box<SomeTrait> {
println!("hello")
box Bar as Box<SomeTrait>
}
}
Or something more dramatic than just printing.)
This is a language hole that will be filled by UFCS. For the moment, you need to use the dummy-Self trick:
trait SomeTrait {
fn new(_dummy: Option<Self>) -> Box<SomeTrait>;
...
}
which is then called like SomeTrait::new(None::<SomeStruct>).
However, I question why you are returning a boxed object from a constructor. This is rarely a good idea, it's normally better to just return the plain type directly, and the user can box it if necessary, that is,
trait SomeTrait {
fn new() -> Self;
...
}
(NB. this signature mentions Self and thus the Option trick above isn't required.)
Sidenote: the error message is rather bad, but it just reflects how these methods are implemented; an associated function in an impl Foo is very similar to writing mod Foo { fn ... }. You can see it differ by forcing the compiler to create that module:
struct Foo;
impl Foo {
fn bar() {}
}
fn main() {
Foo::baz();
}
prints just
<anon>:7:5: 7:13 error: unresolved name `Foo::baz`.
<anon>:7 Foo::baz();
^~~~~~~~
i.e. the Foo "module" exists.

Resources