From 7733f65ff9fbd5b033e5ad012250f0fc4bee44ad Mon Sep 17 00:00:00 2001 From: Albab-Hasan Date: Sun, 15 Feb 2026 17:37:51 +0600 Subject: [PATCH] fix: use `ExprIsRead::Yes` for rhs of ordinary assignments the rhs of an ordinary assignment `x = *never_ptr` was inferred with `ExprIsRead::No`, which prevented `NeverToAny` coercion for place expressions of type `!`. this caused false type mismatches and missing divergence detection. the destructuring assignment path and let binding path both correctly use `ExprIsRead::Yes` for the rhs value, since the value is always consumed (read). this makes the ordinary assignment path consistent with both. --- .../crates/hir-ty/src/infer/expr.rs | 2 +- .../crates/hir-ty/src/tests/never_type.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 9f2d9d25b957..16e7d51e8734 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -751,7 +751,7 @@ impl<'db> InferenceContext<'_, 'db> { if let Some(lhs_ty) = lhs_ty { self.write_pat_ty(target, lhs_ty); - self.infer_expr_coerce(value, &Expectation::has_type(lhs_ty), ExprIsRead::No); + self.infer_expr_coerce(value, &Expectation::has_type(lhs_ty), ExprIsRead::Yes); } else { let rhs_ty = self.infer_expr(value, &Expectation::none(), ExprIsRead::Yes); let resolver_guard = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs index a89d97984dfe..e4e7b4cc3885 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs @@ -786,6 +786,22 @@ fn coerce_ref_mut_binding() -> ! { ) } +#[test] +fn assign_never_place_no_mismatch() { + check_no_mismatches( + r#" +//- minicore: sized +fn foo() { + unsafe { + let p: *mut ! = 0 as _; + let mut x: () = (); + x = *p; + } +} +"#, + ); +} + #[test] fn never_place_isnt_diverging() { check_infer_with_mismatches(