Rainer Stropek | @rstropek
Let's build a (slightly over-engineered 😜) TicTacToe game and learn about traits
on the way.
Sample code is available on GitHub
pub trait Computer {
fn get_answer(&self) -> u8;
}
pub struct DeepThought;
impl Computer for DeepThought {
fn get_answer(&self) -> u8 {
42
}
}
fn main() {
let c = DeepThought {};
let _result = c.get_answer();
}<playground::DeepThought as playground::Computer>::get_answer:
pushq %rax
movq %rdi, (%rsp)
movb $42, %al
popq %rcx
retq
playground::main:
pushq %rax
movq %rsp, %rdi
callq <playground::DeepThought as playground::Computer>::get_answer
movb %al, 7(%rsp)
popq %rax
retquse std::io::*;
pub trait Animal {
fn make_sound(&self) -> &'static str;
}
pub struct Cat;
pub struct Dog;
impl Animal for Cat {
fn make_sound(&self) -> &'static str {
"Miau\n"
}
}
impl Animal for Dog {
fn make_sound(&self) -> &'static str {
"Wuff\n"
}
}
fn print_sound(animal: &impl Animal) {
stdout().write(animal.make_sound().as_bytes()).unwrap();
}
fn main() {
// Static dispatching
let a = Cat {};
print_sound(&a);
let a = Dog {};
print_sound(&a);
}<playground::Cat as playground::Animal>::make_sound:
...
leaq .L__unnamed_4(%rip), %rax ; Miau
...
retq
<playground::Dog as playground::Animal>::make_sound:
...
leaq .L__unnamed_5(%rip), %rax ; Wuff
...
retq
playground::print_sound:
...
callq *std::io::stdio::stdout@GOTPCREL(%rip)
...
callq <playground::Dog as playground::Animal>::make_sound
...
callq *<std::io::stdio::Stdout as std::io::Write>::write@GOTPCREL(%rip)
...
retq
playground::print_sound:
...
callq *std::io::stdio::stdout@GOTPCREL(%rip)
...
callq <playground::Cat as playground::Animal>::make_sound
...
callq *<std::io::stdio::Stdout as std::io::Write>::write@GOTPCREL(%rip)
...
retq
playground::main:
subq $24, %rsp
leaq 8(%rsp), %rdi
callq playground::print_sound ; Cat
leaq 16(%rsp), %rdi
callq playground::print_sound ; Dog
addq $24, %rsp
retqDirect function calls
use std::io::*;
pub trait Animal {
fn make_sound(&self) -> &'static str;
}
pub struct Cat;
pub struct Dog;
impl Animal for Cat {
fn make_sound(&self) -> &'static str {
"Miau\n"
}
}
impl Animal for Dog {
fn make_sound(&self) -> &'static str {
"Wuff\n"
}
}
fn print_sound(animal: &dyn Animal) {
stdout().write(animal.make_sound().as_bytes()).unwrap();
}
fn main() {
let da: &dyn Animal = &Cat {};
print_sound(da);
let da: &dyn Animal = &Dog {};
print_sound(da);
}playground::print_sound:
...
movq %rax, 80(%rsp)
movq 48(%rsp), %rax
movq 40(%rsp), %rdi
callq *24(%rax)
...
retq
playground::main:
...
leaq .L__unnamed_3(%rip), %rax
movq %rax, 16(%rsp)
leaq .L__unnamed_9(%rip), %rdi
leaq .L__unnamed_3(%rip), %rsi
callq playground::print_sound
...
leaq .L__unnamed_4(%rip), %rax
movq %rax, 32(%rsp)
leaq .L__unnamed_9(%rip), %rdi
leaq .L__unnamed_4(%rip), %rsi
callq playground::print_sound
addq $40, %rsp
retq
...
.L__unnamed_3:
.quad core::ptr::drop_in_place<playground::Cat>
.quad 0
.quad 1
.quad <playground::Cat as playground::Animal>::make_sound
.L__unnamed_4:
.quad core::ptr::drop_in_place<playground::Dog>
.quad 0
.quad 1
.quad <playground::Dog as playground::Animal>::make_sound
Indirect function call
Rainer Stropek | @rstropek