This is a known bug with lifetimes and operator overloading (Issue #32008). I'm not too familiar with how lifetimes interact with operator overloading and inference but the below is my understanding (someone please correct me if I'm wrong):
Your first implementation expands to
impl<'a> Add<&'a Foo> for &'a Foo so when your second implementation consumes Foo and creates a new reference, it doesn't have the
'a lifetime since it's in a difference scope.
Now, normally that's not a problem because when you call
self.add(&Foo), Rust can perform an implicit reborrow that casts the reference to
&'a Foo (as long as it's safe) but the compiler won't do that in operator overloading situations (or can't, due to ambiguity in type inference - I'm not sure). The lifetime error you are seeing has probably changed in the year since this issue was filed but the root cause is still the same. Operator overloading isn't a simple desugaring process of
a + b to
a.add(b) so type inference, especially with lifetimes, can behave unexpectedly.
With two lifetimes in the implementation, the ambiguity disappears since Rust can just generically plug any
'b, regardless of their relationship to each other and you don't have to rely on reborrowing to satisfy the single lifetime constraint.