From a78e87329dbe66ad6cdfdb0d41e0abc18a0076ed Mon Sep 17 00:00:00 2001 From: Albab-Hasan Date: Sat, 14 Feb 2026 22:19:26 +0600 Subject: [PATCH] fix: handle `ref mut` bindings in `contains_explicit_ref_binding` the standalone `contains_explicit_ref_binding` function only checked for `BindingAnnotation::Ref`, missing `BindingAnnotation::RefMut`. this caused `let ref mut x = expr` to incorrectly take the coercion path instead of preserving the exact type of the rhs expression. the method version used for match arms already handles both `Ref` and `RefMut` correctly. --- crates/hir-ty/src/infer/pat.rs | 2 +- crates/hir-ty/src/tests/never_type.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 1b8ce5ceaf86..87fd0dace38f 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -673,7 +673,7 @@ impl<'db> InferenceContext<'_, 'db> { pub(super) fn contains_explicit_ref_binding(body: &Body, pat_id: PatId) -> bool { let mut res = false; body.walk_pats(pat_id, &mut |pat| { - res |= matches!(body[pat], Pat::Bind { id, .. } if body[id].mode == BindingAnnotation::Ref); + res |= matches!(body[pat], Pat::Bind { id, .. } if matches!(body[id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)); }); res } diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs index 4d68179a88b8..a89d97984dfe 100644 --- a/crates/hir-ty/src/tests/never_type.rs +++ b/crates/hir-ty/src/tests/never_type.rs @@ -760,6 +760,32 @@ fn coerce_ref_binding() -> ! { ) } +#[test] +fn diverging_place_match_ref_mut() { + check_infer_with_mismatches( + r#" +//- minicore: sized +fn coerce_ref_mut_binding() -> ! { + unsafe { + let x: *mut ! = 0 as _; + let ref mut _x: () = *x; + } +} +"#, + expect![[r#" + 33..120 '{ ... } }': ! + 39..118 'unsafe... }': ! + 60..61 'x': *mut ! + 72..73 '0': i32 + 72..78 '0 as _': *mut ! + 92..102 'ref mut _x': &'? mut () + 109..111 '*x': ! + 110..111 'x': *mut ! + 109..111: expected (), got ! + "#]], + ) +} + #[test] fn never_place_isnt_diverging() { check_infer_with_mismatches(