Different parts of this proposal have distinct motivations. My feeling remains that it is important that we make the notation light but not too light, and this is reflected in the collection of proposals here. I guess that the meaning of light is obvious (less to type) but let me elaborate a bit on “not too light”.
I think it is really helpful to have a consistent, lightweight visual cue that indicates when lifetimes are present. I am not necessarily targeting “beginners” here (though I think it may help there); I am also thinking of advanced users. That is, I really appreciate being able to quickly scan type signatures and figure out which structs contain embedded references and which do not, as well as to identify when the return type may “extend” a borrow and when it will not.
I agree that people are not requesting Foo<'> in argument position (well, I don’t really know, but I can believe that). I do not necessarily think this means it would not be helpful to them. That is, I think that having a consistent visual cue could well help people to get a better understanding of how lifetimes work.
Note that it is easy to take this too far! As I’ve mentioned before, in Ye Olden Days of Rust, we allowed you to elide lifetimes everywhere. We even went so far as to infer whether a struct might have references in it globally. This was mega-confusing. You would get wacky errors and have to trace though layers of type definitions to figure out what was going on. The reaction to this was to make all lifetimes named and explicit. I see the elision proposal (and this one) as part of an ongoing effort to step back from that and figure out just the right places to make lifetimes explicit (or semi-explicit).
I agree it’s annoying to have to adjust trait signatures, but I am not convinced that the right solution is to allow you to obscure the fact that lifetimes are present. I do think there is a need to make it possible to code that is more tolerant of how many lifetimes are present. For example, one scenario that we don’t have a solution for just now is that sometimes I want to specify just some of the lifetimes on a type.
In the compiler, this often comes up when I want to specify 'tcx (the “big” lifetime that is often floating around) but I don’t care about the 'a (the “transient lifetime” that often shows up):
impl<'tcx> Foo<'tcx> {
fn bar<'a>(tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> { ... }
// ^^ ^^
// it is annoying that I have to give `'a` a name here
}
I think a good convention (which we have not consistently adopted in the compiler; I’ve debating about refactoring things so that we do) is to list lifetimes in “increasing” order. So e.g. it’d be TyCtxt<'a, 'tcx, 'gcx> ('a is transient, 'tcx is the current inference session, and 'gcx is the global compilation session). In that case, I think that you almost always just want to specify a suffix of the lifetimes. So you could imagine some scheme that lets you elide “leading” lifetimes. But it’s kind of … wacky. '_ helps here but I’m not keen on it otherwise.
Anyway, leaving all that aside, I feel like another potentially good solution to the problem of having to refactor types is that IDEs should be able to do this refactoring. I know that’s sort of dodging the question, but in my view there is a real readability tradeoff here. (Alternatively, of course, you could say that IDEs can add visual indicators when references might be present.)