Is there a style guideline for writing impl X<'_> { fn f<'a>() -> X<'a> { ... } } versus impl X<'a> { fn f() -> Self { ... } } in Rust? Or is this more than a style choice — do they have different meanings?
Here is the code common to both of those two styles.
use std::borrow::Cow;
struct Response<'content> {
user: String,
content: Cow<'content, Content>,
}
#[derive(Clone)]
enum Content {
Cache(()),
Fetched(()),
}
fn main() {
let cache = Content::Cache(());
let _: Response<'_> = Response::new_with_content_ref("user".to_owned(), &cache);
let content = Content::Fetched(());
let _: Response<'static> = Response::new("user".to_owned(), content);
}
Style 1: Write functions with concrete lifetimes inside impl X<'_>.
They have different meanings, but it’s subtle. “Style 1” introduces two independent lifetime variables; you could in principle write Response::<'a>:: new_with_content_ref::<'b>(...), calling the new_with_content_ref function on an unrelated type.
It happens that, for an inherent constructor function, this never makes any difference because the lifetime variable on the type is not actually getting used, but in more complex situations it can matter, and in any case, you should refrain from introducing extra lifetimes that aren’t granting any useful flexibility but just making things more complicated. Write “Style 2” code and have your constructor functions always return -> Self.
This doesn’t necessarily mean you need to have three impl blocks, though; you can, if you choose, write all the functions in the impl<'content> Response<'content> { block. Yes, even the one that returns Cow::Owned, because 'static is one of the possible lifetimes that can fill that lifetime parameter. It’s debatable whether that’s good style, though, because it obscures the fact that Response<'static> is being offered as an option.
But, as a separate matter of pure style, I would say that you should not have both impl Response<'_> and impl<'content> Response<'content> unless you have some specific rationale for that. impl Response<'_> is just a shorthand for when the lifetime name is never needed anywhere in the body; you can and should put the “// other functions” that you have in impl Response<'_> into impl<'content> Response<'content>along with the functions that need 'content.