rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.2k stars 1.59k forks source link

Type check error in sqlx chain #6833

Open neo-clon opened 3 years ago

neo-clon commented 3 years ago

Hi guys

I have an error with the type checker when use sqlx crate and try use query and query_as methods

Envioment:

image

I see that when use query or query_as methods ( no proc macros ), rust analayzer can show inlay Hint correctly, but if i try use the bind method, not appear on intellisense options despite of the impl over the struct

image

And if i set the method, my lib works but inlay hints no work more on the chain

image

This bug happen both in neovim and vscode

bmisiak commented 3 years ago

Oh yeah, just hit this. image vs image

Also seeing some fun output:

[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_as_with<'q, DB, O, A>(sql: &'q str, arguments: A) -> QueryAs<'q, DB, O, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
    O: for<'r> FromRow<'r, DB::Row>,
[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_with<'q, DB, A>(sql: &'q str, arguments: A) -> Query<'q, DB, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_scalar_with<'q, DB, O, A>(sql: &'q str, arguments: A) -> QueryScalar<'q, DB, O, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
    (O,): for<'r> FromRow<'r, DB::Row>,
[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_as_with<'q, DB, O, A>(sql: &'q str, arguments: A) -> QueryAs<'q, DB, O, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
    O: for<'r> FromRow<'r, DB::Row>,
[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_with<'q, DB, A>(sql: &'q str, arguments: A) -> Query<'q, DB, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
[ERROR rust_analyzer] assertion failed at crates/completion/src/item.rs:401:13: multiline detail: pub fn query_scalar_with<'q, DB, O, A>(sql: &'q str, arguments: A) -> QueryScalar<'q, DB, O, A>
where
    DB: Database,
    A: IntoArguments<'q, DB>,
    (O,): for<'r> FromRow<'r, DB::Row>,
lnicola commented 3 years ago

@bmisiak attribute proc macros are not supported.

flodiebold commented 3 years ago

@neo-clon @bmisiak can you provide a stand-alone, as small as possible reproduction?

bmisiak commented 3 years ago

Two repros:

The simplest one is this: https://github.com/bmisiak/repro-analyzer-sqlx/blob/master/src/main.rs It doesn't pass cargo check because sqlx needs a runtime, but it exhibits the inference problems just fine. If you need cargo check to work correctly, there is this slightly more complex branch with async-std: https://github.com/bmisiak/repro-analyzer-sqlx/blob/asyncstd/src/main.rs

Using sqlx::query_as (before getting to fetch_one) gives me the following hint: image Only after adding .fetch_one can rust-analyzer properly infer all types: image That is until I add a .bind: image

flodiebold commented 3 years ago

Thanks! The bind method is defined in:

impl<'q, DB: Database, O> QueryAs<'q, DB, O, <DB as HasArguments<'q>>::Arguments>

The <DB as HasArguments<'q>>::Arguments is the problem; I haven't looked into it in detail yet, but I guess our code for checking that the self type matches the impl doesn't deal with this correctly. It might not be trivial to handle this without some refactorings.

Dessix commented 3 years ago

Is there a known workaround for this, since it's been around for a while?

PorkSausages commented 2 years ago

Also interested in a workaround if there is one as this issue is still present

sanjeevprasad commented 2 years ago

Also interested in a workaround if there is one as this issue is still present

yes there is an ugly and stupid workaround that I am using.

let mut q = sqlx::query_as::<_, User>(&GET_USER_BY_ID);
q = q.bind(&id); // rust-analyzer still don't have any idea
let user = q.fetch_one(p).await.unwrap(); // but it is working here