My goal is to make the last 2 lines of this code compile and the last assertion to pass:
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");
}
I thought this would be possible with traits and specialization, but the following code:
#![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
}
}
throws this error (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
So my question is, why is the second impl of Get not more "specific" than the first one, and is there any way in current stable or nightly Rust to get my original code to work?
Edit: I know implementing a trait for just one type would work, but I want a generic solution for any type as I want to be able to use this for any arbitrary fields of a struct.
T
implementsFnMut(T) -> T
? – CodesInChaosFnMut(T) -> T
implementation but I'll be happy with either one as I'm not going to be using it with a type of that kind. – Dogbert