Check if a trait is implemented at compile-time?

I'd like to ensure thread safety for types at compile-time. Because Send and Sync are "inherited" from what the type's contents are, it's easy to make inadvertent API changes if a struct's contents change.

I wanted to test for the Send and Sync traits in a way like this, but it uses non-existent language features.

fn is_send<T: Send>() -> bool { true }
fn is_send<T: !Send>() -> bool { false }

fn is_sync<T: Sync>() -> bool { true }
fn is_sync<T: !Sync>() -> bool { false }

#[test]
fn check_send_sync() {
    // Foo is Send, but not Sync.
    assert!(is_send::<Foo>());
    assert!(!is_sync::<Foo>());

    // checks for other types...
}

Testing for the negative (e.g. is not Send) is important as well. For some types, it's a hard requirement that that they do not move across threads.

Could this only be possible with specialization (which, from what I understand, isn't in the language yet)?

I needed it today, and it turned out to be possible:

#[test]
fn test() {
    fn is_sync<T: Sync>() {}
    is_sync::<u8>(); // compiles only if true
    // is_sync::<*mut u8>(); // won't compile; see compile_fail rustdoc feature
}
10 Likes