The parameter to do_it is a reference to an object implementing Foo, but you reference it again when calling sub_do_it - in other words, you're trying to pass &&T to a function that expects &T. If you change sub_do_it(&foo) to sub_do_it(foo), your code compiles.
In your current situation, both Bar and & [mut] Bar implement Foo, but that does not mean that if T : Foo, then &T : Foo. Take, for instance, T = &Bar : does &T = &&Bar implement Foo ? It does not.
Oh - I think where I'm confusing myself is also a silly mistake...
thinking do_it(foo) moves foo, which of course it can't because it doesn't own foo - it only owns a reference to foo... and there's no such thing as moving a reference.
Both declaration lead to the same generic function, except for the fact that the second one can be explicitely monomorphised to a target type with turbofish notation:
let _: fn(& Bar) = do_it2::<Bar>;
let _: fn(& &Bar) = do_it2::<&Bar>;
This means that a call to do_it is equivalent to do_it2::<_>, i.e., we are letting Rust infer the type the generic function must be monomorphised to.
When using concrete types, either with an actual instance Bar, or by using turbofish, we can make Rust accept a &&Whatever where a &Whatever is expected, thanks to a Deref coercion that makes Rust implicitly dereference (use the * operator) on the reference to a reference, so that the types match.
But you cannot both let Rust infer a type and use a Deref coercion to make the current type, after dereference, match the inferred type. And this is what happened with sub_do_it. You can fix that by using turbofish to get rid of the type inference, or by manually dereferencing:
pub trait Trait {}
pub fn foo (_: &(impl Trait)) {}
pub fn foo_generic<T : Trait> (x: &T)
{
foo_generic::<T>(&x); // A - deref coercion
// real code: foo_generic::<T>(*&x);
/* fails */ foo_generic::<&T>(&x); // B - problem: &T may not impl Trait
/* fails */ foo_generic::<_>(&x); // type inference beats deref coercion, hence case B
/* fails */ foo(&x) // same as <_>
}