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.
This commit is contained in:
Albab-Hasan 2026-02-14 22:19:26 +06:00
parent b7d3e7bc4e
commit a78e87329d
2 changed files with 27 additions and 1 deletions

View File

@ -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
}

View File

@ -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(