This is a subtle issue with type inference and automatic reborrowing.
The fetch_all
method in question takes some executor: E
argument where E: Executor<…>
, and that trait in turn is implemented for certain mutable references. But type inference works in such a way that if the type E
isn’t known a priori, then most possibilities for coercions of function arguments are eliminated to get rid of ambiguities. This way, once the compiler can deduce finally that E
has to be the exact type of conn
, a mutable-reference type in this case, (and this is just my intuition as a user; I don’t actually knowing anything about the relevant compiler internals at play here) it seems that by that point in some sense, the implicit reborrowing can’t be inserted anymore.
Implicit reborrowing? That’s if you pass some value x: &mut T
to a function f
that expects a &mut T
argument! In that case, even though the type &mut T
doesn’t implement Copy
, passing it like f(x)
doesn’t move the reference of x
, but instead creates a potentially-shorter-lived reborrow.
Making reborrowing explicit instead would look like f(&mut *x)
instead. Reborrowing is a fancy word for “taking a new reference to the target of another reference”, if you will.
And that’s what you can do to solve the issue here, too:
let rows1 = sqlx::query("select * from cheese").fetch_all(&mut *conn).await?;
like this it should work. Alternatively, you can give a (at least partial) type hint to take (some of the) type inference out of the equation: e.g. something like
let rows1 = sqlx::query("select * from cheese").fetch_all::<&mut _>(conn).await?;
should probably work, too.
A typical minimal example that shows the same kind of mechanism would be:
let x = &mut 42;
let y = x;
// use x
println!("{x}"); // error, use of moved value
vs
let x = &mut 42;
let y: &mut _ = x; // <- added a (partial) type hint
// use x
println!("{x}"); // this works now, x was only reborrowed