Traits and implementations in Rust - traits

I have the following types:
trait Monster {
fn attack(&self);
fn new(int) -> Self;
}
struct CookiesMonster {
cookies: int,
hungry_level: int,
}
impl Monster for CookiesMonster {
fn new(i: int) -> CookiesMonster {
CookiesMonster { cookies: i, hungry_level: i + 1 }
}
fn attack(&self) {
println!("I have {:d} cookies!!", self.cookies)
}
}
struct Dummy {
count: int
}
impl Dummy {
fn new(i: int) -> Dummy {
Dummy { count: i }
}
}
Now, this works:
let monster: CookiesMonster = Monster::new(10);
let dummy = Dummy::new(10);
But this doesn't:
let monster = CookiesMonster::new(10);
Why can't I call the new method directly on the CookiesMonster type?

Because that's how traits work at the moment. Static methods in traits must be called on the trait, and not on the implementor of the trait.

Note that calling the methods on the trait instead of on the type implementing the trait allows cases like this to be unambiguous: Consider if you added the following code to your example:
trait Newable {
fn new(int) -> Self;
}
impl Newable for CookiesMonster {
fn new(i: int) -> CookiesMonster {
CookiesMonster { cookies: i, hungry_level: 0 }
}
}
In this context, Monster::new still works, but CookiesMonster::new would be ambiguous.
(In this example, it figures how which implementation of the trait to use based on type inference. A generalized syntax such as Trait::<for Type>::static_method has been discussed as a way to explicitly write down one's intentions, but I am not sure how far along that is.)
Update circa 15 July 2014: the "Unified Function Call Syntax" proposal tracks the work alluded to in the previous paragraph. See Rust RFC PR 132. My understanding is that UFCS as described in that RFC would actually allow for you to write CookiesMonster::new when Monster is the only trait in scope that both (1.) provides the new method and (2.) is unambiguously implemented for CookiesMonster.

Related

OOP in Rust and shared/mutable references

In the context of a series of programming lessons, I have decided to use Rust instead of C++ as the support programming language.
One aspect of these lessons is dedicated to OOP (dynamic dispatch) relying on interfaces (dyn traits): composition of minimal interfaces instead of deep inheritance trees.
I know OOP does not fit well with modern languages and approaches, but the existing codebase and the habits of the teams since the 90s are still so present that the students must be at least aware of this paradigm (even if we don't encourage its usage for new developments).
In this playground is shown a minimal example inspired from an exercise formerly done in C++ (many other things exist around this excerpt).
At the abstract level, an Entity has an internal state (a position here, to keep it simple) and several dynamic components responsible for various behaviours (drawing, animation, reaction to events...).
These dynamic components implement some predefined interfaces (dyn traits) and can be freely defined at the application level (the abstract level does not have to know the details of these components).
Some of these components can have some internal data which could even be mutated.
For example, in this minimal code, a Shape component if mainly dedicated to drawing (no mutable operation is required for the entity or this component in general), but an Animator component can cause mutations on the entity (let's say its position), on the component itself and even on other components (change the color of the next drawing for example).
As requested in a comment, here is the code inline:
mod common {
pub trait Shape {
fn draw(
&self,
entity: &Entity,
);
fn change_color(
&mut self,
color: String,
);
}
pub trait Animator {
fn animate(
&mut self,
entity: &mut Entity,
);
}
#[derive(Debug)]
pub struct Pos {
pub x: f64,
pub y: f64,
}
pub struct Entity {
pos: Pos,
shape: Box<dyn Shape>,
animator: Box<dyn Animator>,
}
impl Entity {
pub fn new(
pos: Pos,
shape: Box<dyn Shape>,
animator: Box<dyn Animator>,
) -> Self {
Self {
pos,
shape,
animator,
}
}
pub fn pos(&self) -> &Pos {
&self.pos
}
pub fn pos_mut(&mut self) -> &mut Pos {
&mut self.pos
}
pub fn change_color(
&mut self,
color: String,
) {
self.shape.change_color(color);
}
pub fn draw(&self) {
self.shape.draw(self);
}
pub fn animate(&mut self) {
let anim = &mut self.animator;
anim.animate(self);
}
}
}
mod custom {
use super::common::{Animator, Entity, Shape};
pub struct MyShape {
color: String,
}
impl MyShape {
pub fn new(color: String) -> Self {
Self { color }
}
}
impl Shape for MyShape {
fn draw(
&self,
entity: &Entity,
) {
println!("draw at {:?} with {:?}", entity.pos(), self.color);
}
fn change_color(
&mut self,
color: String,
) {
self.color = color;
}
}
pub struct MyAnim {
count: i32,
}
impl MyAnim {
pub fn new() -> Self {
Self { count: 0 }
}
}
impl Animator for MyAnim {
fn animate(
&mut self,
entity: &mut Entity,
) {
let pos = entity.pos_mut();
if (self.count % 2) == 0 {
pos.x += 0.1;
pos.y += 0.2;
} else {
pos.x += 0.2;
pos.y += 0.1;
}
self.count += 1;
if self.count >= 3 {
entity.change_color("red".to_owned());
}
}
}
}
fn main() {
use common::{Entity, Pos};
use custom::{MyAnim, MyShape};
let mut entity = Entity::new(
Pos { x: 0.0, y: 0.0 },
Box::new(MyShape::new("green".to_owned())),
Box::new(MyAnim::new()),
);
entity.draw();
for _ in 0..5 {
entity.animate();
entity.draw();
}
}
As you can see, the provided code cannot be compiled since, at line 66, anim is a mutable reference to the Animator component responsible for the dynamic dispatch but the parameter of the method is also a mutable reference to the Entity as a whole which contains the previous Animator.
This parameter is needed if we want the Animator to be able to make changes on the entity.
I'm stuck with this situation and I can only think about workarounds that look quite ugly to me:
don't pass the entity as a parameter but each of its field (except the animator) as many parameters: what's the point of defining structs then? (if an entity is made of twelve fields, should I pass eleven parameters every time I would act on this entity?)
embed each field of an entity in a RefCell and pretend every parameter of every function is a non-mutable reference, then borrow_mut() everywhere we want to and hope it won't panic: for me, it's like giving-up the idea that function prototypes tell and enforce the intent of the code (let's add some Rc everywhere in order to totally forget who owns what, and we obtain Java ;^)
I'm certain I did some bad choices about what deserves to be exclusive (&mut) or shared (&), but I can't see a reasonable limit.
In my opinion, when an entity has to be animated, it's its own concern: there is nothing to be shared, except looking at the state of the surrounding environment (but not changing it).
If we share everything and rely on interior-mutability in order to enable safe mutations at run-time (thanks to the ref-count) it sounds to me like: «let's drive like crazy, as if there were no traffic regulations, as long as no one complains (try_borrow()/try_borrow_mut()) and we don't have any accident (panic!())».
Could anyone suggest a better organisation of my structs/functions in order to enable the intended behaviour: an entity made of a few dynamic (as in OOP) components responsible for the details of the actions on the concerned entity?

Designing a UI element tree structure in Rust

I've stumbled upon a somewhat quirky situation due to lack of inheritance in Rust.
I'm designing an element structure where all elements have some common behaviour (e.g. having children) and need to propagate function calls down the tree.
My current design is to have a View trait and a ViewInner struct that encapsulates all common behaviour. However it appears that doing so would spawn tons of boilerplate code that forwards calls from View to its ViewInner. And as it appears, adding another level of encapsulation (e.g. AutoLayoutView) would triple the call depth.
Here's a short example:
// "Base" view trait
pub trait View {
fn render(&self, ...);
fn handle_events(&self, ...);
}
// View internals
pub struct ViewInner {
children: Vec<Box<View>>
}
impl ViewInner {
...
pub fn add_child(...);
pub fn layout(...);
}
// Forwarded calls
impl View for ViewInner {
fn render(&self, ...) {
for child in self.children.iter() {
child.render(...);
}
}
fn handle_events(&self, ...) {
for child in self.children.iter() {
child.handle_events(...);
}
}
}
// Actual entity
pub struct SomeView {
inner: ViewInner,
...
}
impl SomeView {
pub fn new() -> Self {
return Self {
inner: ViewInner::new()
}
}
}
impl View for SomeView {
// Forwarding all over again
fn render(&self, ...) {
self.inner.render(...)
}
fn handle_events(&self, ...) {
self.inner.handle_events(...)
}
}
What would be a more optimal way to structure this and minimize boilerplate in the future (in case of more tree-crawling calls and View variations)?
For the generic cases where the calls will be forwarded without any added logic you can write a custom derive macro for the View trait.
With it you just need to write:
#[derive(View)]
pub struct ViewInner {
...
}
and the View trait will be automatically implemented for the struct.

How do I use a trait object in a BinaryHeap? [duplicate]

Editor's note: This code example is from a version of Rust prior to 1.0 and is not syntactically valid Rust 1.0 code. Updated versions of this code produce different errors, but the answers still contain valuable information.
It seems like we cannot test for equality in the following case. Why is this? Is there a workaround? (I am using Rust 0.11).
trait A: PartialEq {}
#[deriving(PartialEq)]
enum T {Ta, Tb}
impl A for T {}
fn main() {
assert!(Ta == Ta);
assert!(Ta != Tb);
assert!(some_fn(&Ta, &Ta));
assert!(!some_fn(&Ta, &Tb));
}
fn some_fn(an_a: &A, another_a: &A) -> bool {
an_a == another_a
// ERROR ^~~~~~~~~~~~ binary operation `==` cannot be applied to type `&A`
}
fn another_fn(an_a: &A + PartialEq, another_a: &A + PartialEq) -> bool {
// ERROR: ^~~~~~~~~ only the builtin traits can be used as closure or object bounds
an_a == another_a
}
With help from Vladimir Matveev, I figured out how to use Any to downcast my trait to a concrete type and test the resulting value for equality:
// `Any` allows us to do dynamic typecasting.
use std::any::Any;
trait A {
// An &Any can be cast to a reference to a concrete type.
fn as_any(&self) -> &dyn Any;
// Perform the test.
fn equals_a(&self, _: &dyn A) -> bool;
}
#[derive(Debug, PartialEq)]
enum T {
Ta,
Tb,
}
// Implement A for all 'static types implementing PartialEq.
impl<S: 'static + PartialEq> A for S {
fn as_any(&self) -> &dyn Any {
self
}
fn equals_a(&self, other: &dyn A) -> bool {
// Do a type-safe casting. If the types are different,
// return false, otherwise test the values for equality.
other
.as_any()
.downcast_ref::<S>()
.map_or(false, |a| self == a)
}
}
fn main() {
assert_eq!(T::Ta, T::Ta);
assert_ne!(T::Ta, T::Tb);
assert!(some_fn(&T::Ta, &T::Ta));
assert!(!some_fn(&T::Ta, &T::Tb));
}
fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {
// It works!
an_a.equals_a(another_a)
}
Here is the definition of the PartialEq trait:
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
Note the Self parameter type. This means that eq() and ne() methods accept a parameter of the same type as implementor. For example:
impl PartialEq for i32 {
fn eq(&self, other: &i32) -> bool { ... }
}
impl PartialEq for String {
fn eq(&self, other: &String) -> bool { ... }
}
Note how type of other changes to reflect the type PartialEq is implemented for.
This is the problem. In trait objects, the actual type is erased and unavailable at runtime. This means that it is impossible to obtain a reference to a concrete type from a trait object; in particular, you can't go from &A to &T in your example.
This means that it is impossible to call methods accepting or returning the Self type on trait objects. Indeed, these methods always require a concrete type, but if you have only a trait object, there is no concrete type, and there is no way such method could work in any sensible way.
In certain cases of trait objects, you wish to compare them based on some properties exposed via the trait. You can achieve this by implementing methods on the trait type itself:
trait A {
fn id(&self) -> i32;
}
impl PartialEq for dyn A + '_ {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for dyn A + '_ {}
fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {
an_a == another_a
}
This doesn't directly address the original case which wants to delegate back to the implementation of PartialEq of the underlying type, but you can combine the existing solution:
impl PartialEq for dyn A + '_ {
fn eq(&self, other: &Self) -> bool {
self.equals_a(other)
}
}
See also:
Why would I implement methods on a trait instead of as part of the trait?

Rust: Create an Iterator out of Default and Succ?

I have the following code in a repo:
impl<Id> IdAllocator<Id> where
Id : Clone + Default + Add<u32, Id>,
{
pub fn new() -> IdAllocator<Id> {
IdAllocator {
next: Default::default()
}
}
// Produce an Id that hasn't been produced yet by this object.
pub fn allocate(&mut self) -> Id {
let ret = self.next.clone();
self.next = self.next + 1;
ret
}
}
But it seems a little clumsy, especially since the Add instance is only used as a succ function (generating the next value in sequence). Is there some Succ class I can use? And if so, is there already some Iterator construction somewhere in the standard library that already does this Default+Succ pattern?
Thanks!
No, unfortunately, there is no Succ-like thing in the standard library. The closest thing you can find is range() family of iterators, however, it uses Add and One numeric traits to generate items. You can do it this way (the idea is basically the same as yours, but this version is slightly more generic due to One trait usage):
use std::num::One;
use std::default::Default;
struct IdAllocator<T> {
current: T
}
impl<T: Default> IdAllocator<T> {
#[inline]
pub fn new() -> IdAllocator<T> {
IdAllocator {
current: Default::default()
}
}
}
impl<T: Add<T, T>+One+Clone> Iterator<T> for IdAllocator<T> {
fn next(&mut self) -> Option<T> {
let next = self.current + One::one();
self.current = next.clone();
Some(next)
}
}
fn main() {
let a = IdAllocator::<uint>::new();
for i in a.take(10) {
println!("{}", i);
}
}
(try it here)

Objects and classes in Rust

I am fiddling around with Rust, going by the examples, trying to make a class. I have been looking at the example of StatusLineText
It keeps raising the errors:
error: `self` is not available in a static method. Maybe a `self` argument is missing? [E0424]
self.id + self.extra
^~~~
error: no method named `get_total` found for type `main::Thing` in the current scope
println!("the thing's total is {}", my_thing.get_total());
^~~~~~~~~
My code is rather simple:
fn main() {
struct Thing {
id: i8,
extra: i8,
}
impl Thing {
pub fn new() -> Thing {
Thing { id: 3, extra: 2 }
}
pub fn get_total() -> i8 {
self.id + self.extra
}
}
let my_thing = Thing::new();
println!("the thing's total is {}", my_thing.get_total());
}
You need to add an explicit self parameter to make methods:
fn get_total(&self) -> i8 {
self.id + self.extra
}
Functions without the explicit self parameter are considered associated functions, which can be called without a specific instance.