Why need object safety?

⚓ Rust    📅 2025-07-14    👤 surdeus    👁️ 2      

surdeus

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Why need object safety?

If we use trait object only by generic function, it's always safe. For example, in below case, self_compare always compare two same type object.

trait Comparable {
    fn compare(&self, other: &Self) -> bool;
}

impl Comparable for i32 {
    fn compare(&self, other: &Self) -> bool {
        self == other
    }
}

fn self_compare<T: Comparable>(a: &T) -> bool {
    a.compare(a)
}

fn main() {
    let x = 42;

    println!("x == x: {}", self_compare(&x)); // true

    /* cannot compile, but it should be ok
    let a: &dyn Comparable = &x;
    self_compare(a);
    */
}

Also, we can compile it like below c code:

#include <stdio.h>
#include <stdbool.h>

typedef bool (*CompareFn)(const void* a, const void* b);

typedef struct {
    const void* obj;
    CompareFn compare;
} ComparableObject;

bool compare_i32(const void* a, const void* b) {
    return *(const int*)a == *(const int*)b;
}

bool self_compare(ComparableObject comp_obj) {
    return comp_obj.compare(comp_obj.obj, comp_obj.obj);
}

int main() {
    int x = 42;

    ComparableObject a = { &x, compare_i32 };
    printf("x == x: %s\n", self_compare(a) ? "true" : "false"); // true
    
    return 0;
}

What's more, for existential type ∃α.T(α)≡∀β.(∀α.T(α)→β)→β, that means, for a trait object, if we pass ∀β.(∀α.T(α)→β), we can get a β value. (∀α.T(α)→β) is just a generic function. Every such type generic function should be ok for trait object.
So, why Rust have object safety and forbidden such usage?

9 posts - 5 participants

Read full topic

🏷️ rust_feed