So functions can create unbound lifetimes via generics. structs can no longer create them (because that’s an error, right?). What else can create them?
From a syntax::ast perspective, this would look like a Lifetime with a name other than 'static and an empty bounds Vec. Sure enough, when I put your fn foo definition through rustc -Z ast-json, I get (among a lot of other stuff):
"lifetimes": [
{
"lifetime": {
"span": 176093659175,
"name": {
"_field0": 63
},
"id": 31
},
"bounds": []
}
],
If this is it, we just identify where in the AST this can happen, and the rest is child’s play.
Edit: No, it’s not that easy: If I plug in a fn from_argument(a: &'a str) -> &'a str { a }, I get the same. The difference is that the function above defines the _field0 in its generics, while from_arguments has _field0 in an argument lifetime. So we’d need to create a set of valid argument lifetimes and compare the returned lifetime (if any) against that.