Description
I encountered a persistent type mismatch error when using async-trait that only appeared in rust-analyzer but not during compilation. After several hours of troubleshooting, I discovered that the issue was caused by having rust-analyzer.diagnostics.enableExperimental set to true in my workspace settings.
Setting enableExperimental to false completely resolves the issue, while cargo check and cargo build work correctly regardless of this setting.
Impact:
This appears to be a bug in rust-analyzer's experimental diagnostics when processing async-trait macro expansions. The experimental feature incorrectly reports type mismatches between Pin<Box> and Pin<Box> for async trait implementations.
Reproduction:
The issue can be reproduced by:
Setting "rust-analyzer.diagnostics.enableExperimental": true in VS Code settings
Using #[async_trait] with async methods in trait definitions and implementations
Observing the false positive type mismatch errors in the IDE
Workaround:
Setting "rust-analyzer.diagnostics.enableExperimental": false eliminates the issue entirely.
I'm reporting this to help improve the experimental diagnostics feature and assist other developers who may encounter the same issue.
Description:
rust-analyzer shows a type mismatch error for async trait implementations using the async-trait crate when vscode has "rust-analyzer.diagnostics.enableExperimental": true:
error[E0308]: mismatched types
expected Pin<Box<dyn Future<Output = Result<SimpleResult, Box<dyn Error + Send + Sync + 'static, Global>>> + Send + 'async_trait, Global>>
found Pin<Box<impl Future<Output = Result<SimpleResult, Box<dyn Error + Send + Sync + 'static, Global>>>, Global>>
code snippet to reproduce:
use async_trait::async_trait;
use std::error::Error;
#[derive(Debug, PartialEq)]
pub enum SimpleResult {
Ok,
Error,
}
pub struct ExampleData {
pub id: i32,
pub name: String,
}
#[async_trait]
pub trait SimpleModel {
async fn save(&self) -> Result<SimpleResult, Box<dyn Error + Send + Sync + 'static>>;
}
#[async_trait]
impl SimpleModel for ExampleData {
async fn save(&self) -> Result<SimpleResult, Box<dyn Error + Send + Sync + 'static>> {
if self.id > 0 {
Ok(SimpleResult::Ok)
} else {
Ok(SimpleResult::Error)
}
}
}
vscode workspace file settings:
{
"folders": [
{
"path": "."
}
],
"settings": {
// Rust Configuration
"rust-analyzer.showUnlinkedFileNotification": false,
"rust-analyzer.check.command": "clippy",
"rust-analyzer.check.allTargets": false,
"rust-analyzer.diagnostics.enable": true,
"rust-analyzer.diagnostics.enableExperimental": true,
"rust-analyzer.completion.autoimport.enable": true,
"rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.prefix": "crate",
"rust-analyzer.rustfmt.extraArgs": ["+stable"],
},
}
Expected behavior:
No error should be shown, as the #[async_trait] macro should transform the async fn into the correct Pin<Box> type.
Actual behavior:
rust-analyzer shows a type mismatch between Pin<Box> and Pin<Box>, suggesting it's not correctly processing the async-trait macro expansion.
Additional context:
- cargo check and cargo build complete successfully with no errors
- The error only appears in the IDE, not during compilation
- The error occurs specifically when combining #[async_trait] with async fn methods
- Non-async trait methods work fine
- Issue persists after cache clearing, rust-analyzer restarts, and ensuring single async-trait version
Dependencies:
[dependencies]
async-trait = "0.1.88"
This appears to be a rust-analyzer issue with macro expansion for the async-trait crate, where the IDE incorrectly analyzes the return type of async trait methods.
rust-analyzer version: 0.4.2488-standalone (6acff6c 2025-06-06) [/Users/henryverlin/.vscode/extensions/rust-lang.rust-analyzer-0.4.2488-darwin-arm64/server/rust-analyzer]
rustc version: rustc 1.87.0 (17067e9ac 2025-05-09)
editor or extension: VSCode with rust-analyzer extension version 0.4.2488
relevant settings: Default settings, workspace with Cargo.toml at root defining fetcher as member
repository link (if public, optional): N/A