Skip to content

query!() is evaluated incorrectly/inconsistently with rust-analyser because of static caching #3738

Closed
@zkrising

Description

@zkrising

I have found these related issues/pull requests

Not related to any other issue on this repo - sort of related to #121, but not really

Description

This issue happens in workspaces with sqlx, and does not happen in cargo check, but does affect rust-analyser.

You need two crates in your workspace, and those crates need to use a different database. For example:

crates/
  postgres_red/
    .env (DATABASE_URL=postgres://blah/red_database)
  postgres_yellow/
    .env (DATABASE_URL=postgres://blah/yellow_database)

Rust-Analyser will incorrectly evaluate query!() executions against the wrong database, the right database, or both databases.

According to the rust-analyser devs (where this was originally reported), this is the issue:
rust-lang/rust-analyzer#18533 (comment)

Thanks for the repro, that made me reinvestigate and I just noticed the issue.

Well the lookup happens here launchbadge/sqlx@4590b9c/sqlx-macros-core/src/query/mod.rs#L109-L118
So I am stumped as to what's happening here as your cargo invocation isn't really special in that regard then

I completely missed this when looking into this the last time, this static caching is the culprit. rust-analyzer does not unload proc-macros unlike rustc, so that lazy static is going to be initialized with the first expansion and as such any other expansion in differing crates will observe the Metadata for the first crate.

So unfortunately that's a wontfix from our side, we are required to cache proc-macro expansions for implementation results (I am not going into detail here as we have this discussion before and there is no budging on that stance at this point) and we can't unload proc-macro dylibs either. That needs changing in sqlx, ideally by not using a lazy static that depends on the environment in the first place or replace it with a thread local as right now we spawn a new thread per expansion to clear such context.

Reproduction steps

This repository will reproduce the issue: https://github.com/zkrising/ra-sqlx-repro

A reproduction is available here: https://github.com/zkrising/ra-sqlx-repro

Note that cargo check et. al. report no issues, but rust-analyser will. You might have to edit and save the main.rs files just to get rust-analyser to trip up, but I've found doing that pretty reliably gives you an error that shouldn't exist.

The gist of the repro is that there's sqlite_red which queries red_things and sqlite_yellow which queries yellow_things. Despite the crates working and compiling, rust-analyser will seemingly manifest an error that the table does not exist.

SQLx version

0.8

Enabled SQLx features

runtime-tokio, sqlite, but any driver has this issue

Database server and version

sqlite 3.48.0, but any works

Operating system

Linux

Rust version

rustc 1.83.0-nightly (55a22d2a6 2024-10-06)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions