diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs index 933a9a5c3519..18509c52847f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs @@ -552,3 +552,58 @@ where "#]], ); } + +#[test] +fn regression_19957() { + // This test documents issue #19957: async-trait patterns incorrectly produce + // type mismatches between Pin> and Pin>. + check_no_mismatches( + r#" +//- minicore: future, pin, result, error, send, coerce_unsized, dispatch_from_dyn +use core::{future::Future, pin::Pin}; + +#[lang = "owned_box"] +pub struct Box { + inner: *mut T, +} + +impl Box { + fn pin(value: T) -> Pin> { + // Implementation details don't matter here for type checking + loop {} + } +} + +impl, U: ?Sized> core::ops::CoerceUnsized> for Box {} + +impl, U: ?Sized> core::ops::DispatchFromDyn> for Box {} + +pub struct ExampleData { + pub id: i32, +} + +// Simulates what #[async_trait] expands to +pub trait SimpleModel { + fn save<'life0, 'async_trait>( + &'life0 self, + ) -> Pin + Send + 'async_trait>> + where + 'life0: 'async_trait, + Self: 'async_trait; +} + +impl SimpleModel for ExampleData { + fn save<'life0, 'async_trait>( + &'life0 self, + ) -> Pin + Send + 'async_trait>> + where + 'life0: 'async_trait, + Self: 'async_trait, + { + // Body creates Pin>, which should coerce to Pin> + Box::pin(async move { self.id }) + } +} +"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index d5905afc3896..679fe420b05c 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -1518,6 +1518,12 @@ pub mod pin { { } // endregion:dispatch_from_dyn + // region:coerce_unsized + impl crate::ops::CoerceUnsized> for Pin where + Ptr: crate::ops::CoerceUnsized + { + } + // endregion:coerce_unsized } // endregion:pin