Моя цель состоит в том, чтобы скомпилировать последние 2 строки этого кода и передать последнее утверждение:
struct State {
string: String
}
impl State {
fn string<F: FnMut(String) -> String>(mut self, mut f: F) -> Self {
self.string = f(self.string);
self
}
}
fn main() {
let state = State { string: String::from("foo") };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
// let state = state.string(String::from("baz"));
// assert_eq!(state.string, "baz");
}
Я думал, что это будет возможно с особенностями и специализацией, но следующий код:
#![feature(specialization)]
trait Get<T> {
fn get(self, old: T) -> T;
}
impl<T> Get<T> for T {
default fn get(self, _: T) -> T {
self
}
}
impl<T, F> Get<T> for F where F: FnMut(T) -> T {
fn get(mut self, old: T) -> T {
self(old)
}
}
struct State {
string: String
}
impl State {
fn string<G: Get<String>>(mut self, g: G) -> Self {
self.string = g.get(self.string);
self
}
}
вызывает эту ошибку (live):
error[E0119]: conflicting implementations of trait `Get<_>`:
--> <anon>:13:1
|
13 | impl<T, F> Get<T> for F where F: FnMut(T) -> T {
| ^
|
note: conflicting implementation is here:
--> <anon>:7:1
|
7 | impl<T> Get<T> for T {
| ^
error: aborting due to previous error
Итак, мой вопрос: почему второй вариант Get не более "специфичен", чем первый, и есть ли какой-либо способ в текущей стабильной или ночной Rust, чтобы заставить мой исходный код работать?
Изменить: я знаю, что реализация признака только для одного типа будет работать, но я хочу использовать общее решение для любого типа, поскольку я хочу использовать его для любых произвольных полей структуры.