Во-первых, решите проблему без макросов. Одним из решений является создание недокументированные частных функций, которые не смогут компиляции, если ваши условия не выполняются:
struct MyType {
age: i32,
name: String,
}
fn __assert_send()
where
MyType: Send,
{}
fn __assert_sync()
where
MyType: Sync,
{}
// RFC 2056
fn __assert_traits() {
__assert_send();
__assert_sync();
}
Затем изменить простое решение использовать макросы:
macro_rules! a {
($n:ident, $t:ty) => {
struct $n {
x: $t
}
impl $n {
fn __assert_add()
where
$t: std::ops::Add<$t, Output = $t>
{}
fn __assert_mul()
where
$t: std::ops::Mul<$t, Output = $t>
{}
// RFC 2056
fn __assert_traits() {
Self::__assert_add();
Self::__assert_mul();
}
}
}
}
a!(Moo, u8);
a!(Woof, bool);
fn main() {}
Я бы тогда верить в оптимизатор для удаления кода во время компиляции, поэтому я не ожидал бы дополнительного раздувания.
Главное спасибо до Chris Morgan за предоставление лучшей версии этого, которая поддерживает небезопасные свойства.
Стоит выделить RFC 2056, что позволит использовать «тривиальные» ограничения в тех случаях, когда предложения. После реализации положения, как это будет принято:
impl Foo for Bar
where
i32: Iterator,
{}
Это точное поведение изменилось несколько раз в течение истории Русте и RFC 2056 штырей его вниз. Чтобы сохранить нужное поведение в этом случае, нам нужно вызвать функции утверждения из другой функции, которая не имеет ограничений (и, следовательно, всегда должна быть истина).
Я отправился на 'fn _assert_add(), где Self: Добавить {} fn _verify_assertions() {Self :: _ assert_add()}', сам. Чуть более чистые сообщения об ошибках, на мой взгляд, и (что более важно) более общие, поскольку это не требует, чтобы этот признак был объектно-безопасным. –
@ChrisMorgan не будет 'Self' быть созданным типом, а не типом поля? – Shepmaster
О да, я не читал все это полностью. Но это не проблема - 'где $ t: Добавить <$ t, Output = $ t>' работает так же хорошо. Предложение 'where' может содержать материал для * любого * типа, а не только материал, связанный с' Self' или generics. –