2
struct Foo;

#[derive(Clone)]
struct Bar {
    f: Foo,
}

fn main() {}

Playground

This results in

error[E0277]: the trait bound `Foo: std::clone::Clone` is not satisfied
 --> <anon>:5:5
  |
5 |     f: Foo,
  |     ^^^^^^ the trait `std::clone::Clone` is not implemented for `Foo`
  |
  = note: required by `std::clone::Clone::clone`

It is only possible to derive Clone if all the types of the fields implement clone. I would like to do the same thing.

Field does not seem to expose which traits it implements. How would I check if a Type implements a specific trait? Is this currently not possible?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Maik Klein
  • 15,548
  • 27
  • 101
  • 197

1 Answers1

3

Take a look at the expanded version of your code:

#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
struct Foo;

struct Bar {
    f: Foo,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::clone::Clone for Bar {
    #[inline]
    fn clone(&self) -> Bar {
        match *self {
            Bar { f: ref __self_0_0 } => Bar { f: ::std::clone::Clone::clone(&(*__self_0_0)) },
        }
    }
}

fn main() {}

All it does is call a function that has a trait bound, passing in the arguments. This is useful because clone needs to be called recursively anyway. This gets you the check "for free".

If you don't need to call the trait in question, you can still do something similar to enforce that an argument implements a trait at compile time. Eq does this by implementing a hidden function on the trait. You could also generate one-off functions that express your trait bound.

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366