Say I have two datatypes, A and B, which can be converted from one into another. It also so happens that they don't share internal representation at all, so that, if I implement conversion manually, I'd go with
impl A {
// Note the reference
fn to_b(&self) -> B { ... }
}
Should I implement From<A> for B, or for<'a> From<&'a A> for B or both?
Probably it is a matter of usage, but that's my personal opinion:
Implement From<A> for B because, in any case, it should be possible to consume the original object. In the end, the user is unaware of the internal representation, and the opportunity to consume should be given.
Implement for<'a> From<&'a A> for B if A is not Copy-able. Since the original object cannot be cheaply copied, the user would like to create B without having to do something let b: B = a.clone().into(). If the internal representation is different, this is also important to avoid useless copies around.
As said, this is merely my opinion, and probably macros helps quite a lot to avoid boilerplate code.
I'd tend to follow the standard library on this. For instance, String implements From<&str>, and PathBuf implements a rather complicated-looking but convenient From which uses AsRef to simultaneously handle a lot of possible inputs. In general, there are an awful lot of From implementations, and that is great. So in your case, from a reference sounds great.
Note that standard library does not have a similar &OwnedA -> OwnedB conversion. In all of the case where stdlib's From is parametrized by lifetimes, its either that lhs is naturally parametrized by a lifetime (like From<Cow<'a, Path>> for PathBuf), or rhs has a lifetime (like From<&'a PathBuf> for Cow<'a, Path>).
The impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf impl is the first-case, due to T: ?Sized.
In general, there are an awful lot of From implementations, and that is great.
More doesn't mean better. In general, if From<A> for B reuses all allocations, adding From<&A> for B would be a bad idea, because it might lead to unnecessary copies. Similarly, if you don't reuse any allocations, From<A> for B seems less than ideal, because it forces a needless .clone .