That's a good question. A couple of things:
- Making every function generic that way is bad for compile times. That's because instead of compiling them once in the library, they have to be monomorphized on use in the application. You can refactor everything to be outlined to limit that, but it's questionable whether that's worth the effort.
- Making everything generic means that you can't use anything dependent on inference context when calling it. For example,
foo(s.parse()) won't work with the
impl trick (those two specific examples might not make sense for your case, but they're the easiest ones to explain).
- Making the
String allocation invisible tends to lead to "pervasive pessimization": something that's not really bad, but you lose the opportunity for the weak push to "did you maybe want a variable to not do that repeatedly?"
I agree. So what I would say is that the
From impls are still good (as well another for
From<String> probably), it's just the invisible calling of them that I suggest avoiding.
That means that you can always just do
operate_on("hello".into()), which is fairly minor overhead. And if you're going to call multiple things with the same id, it encourages
let id = "hello".into(); foo(&id); bar(&id);.
Oh, that's another good point: most of these should probably be taking
&Identifier, since you don't need to consume the
String every time. And
operate_on(&"hello".into()); will work, but
impl Into<&Identifier> isn't going to because there's nowhere to borrow it from.
TL/DR: Keep the
Froms, just have the caller do the
.into() instead of
impl Into<_>ing everything.