Object safety
- Rust course
- Advanced
- Lesson 57/81
- 4 min
Learn the object safety rules.
Object safety
For a trait to be used with dyn, it must be dyn compatible (formerly called object safe). Blocking cases: methods returning Self, methods taking generic type parameters, associated functions without self, and a Sized supertrait. Because these methods can't be called through a vtable without knowing the concrete type:
trait Kopyalanir {
fn kopya(&self) -> Self; // returns Self: not dyn compatible
}
// let x: Box<dyn Kopyalanir>; // E0038That's why Clone can't be used as a trait object.
where Self: Sized
To keep using the rest of the trait with dyn, separate the problematic method:
trait Sekil {
fn alan(&self) -> f64;
fn kopya(&self) -> Self
where
Self: Sized;
}
let k = Kare(3.0);
let k2 = k.kopya(); // works on the concrete type
let d: Box<dyn Sekil> = Box::new(k2); // dyn is possible too
// d.kopya(); // can't be called through dynThe common solution for a boxed copy is a separate method: fn kutulu_kopya(&self) -> Box<dyn Sekil>.
Practice A compatible shape trait
Write the Sekil trait above and implement it for #[derive(Clone)] struct Kare(f64); (kopya = self.clone()). Print the area of Kare(3.0).kopya() and, after putting it in a Box<dyn Sekil>, its area through dyn, separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
trait Sekil {
fn alan(&self) -> f64;
fn kopya(&self) -> Self
where
Self: Sized;
}
#[derive(Clone)]
struct Kare(f64);
impl Sekil for Kare {
fn alan(&self) -> f64 {
self.0 * self.0
}
fn kopya(&self) -> Self {
self.clone()
}
}
fn main() {
let k2 = Kare(3.0).kopya();
let a = k2.alan();
let d: Box<dyn Sekil> = Box::new(k2);
println!("{} {}", a, d.alan());
}Expected output
9 9
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 If a trait has a single non-dyn-compatible method, what can be done?
- Add where Self: Sized to that method to exclude it from trait objects Correct answer
- Delete the trait
- Use unsafe
- Nothing
Explanation: A method marked this way can be called on concrete types but not through dyn; the trait stays dyn compatible.
2 Exclude from dyn
fn kopya(&self) -> Self
where
Self: ____;
fn kopya(&self) -> Self
where
Self: Sized;
Explanation: where Self: Sized excludes the method from trait objects.
3 Method and dyn compatibility
| Term | Meaning |
|---|---|
fn alan(&self) -> f64 |
Compatible |
fn kopya(&self) -> Self |
Not compatible |
fn f<T>(&self, x: T) |
Not compatible (generic) |
.. where Self: Sized |
Excluded |