[][src]Macro static_assertions::assert_obj_safe

macro_rules! assert_obj_safe {
    ($($xs:tt)+) => { ... };
}

Asserts that the traits are object-safe.

This is useful for when changes are made to a trait that accidentally prevent it from being used as an object. Such a case would be adding a generic method and forgetting to add where Self: Sized after it. If left unnoticed, that mistake will affect crate users and break both forward and backward compatibility.

Examples

When exposing a public API, it's important that traits that could previously use dynamic dispatch can still do so in future compatible crate versions.

// Requires a unique label in module scope
assert_obj_safe!(basic; Send, Sync, AsRef<str>);

mod inner {
    // Works with traits that are not in the calling module
    pub trait BasicTrait {
        fn foo(&self);
    }
}

trait MySafeTrait {
    fn bar(&self) -> u32;
}

fn main() {
    assert_obj_safe!(MySafeTrait);
    assert_obj_safe!(inner::BasicTrait);
}

The labeling limitation is not necessary if compiling on nightly Rust with the nightly feature enabled:

This example is not tested
#![feature(underscore_const_names)]

use std::fmt;

assert_obj_safe!(fmt::Write);

fn main() {
    assert_obj_safe!(fmt::Debug);
}

Raw pointers cannot be sent between threads safely:

This example deliberately fails to compile
assert_impl!(*const u8, Send);

Generics without where Self: Sized are not allowed in object-safe trait methods:

This example deliberately fails to compile
trait MyUnsafeTrait {
    fn baz<T>(&self) -> T;
}

assert_obj_safe!(MyUnsafeTrait);