Require DerefMut if deref pattern has nested ref mut binding

This commit is contained in:
Michael Goulet 2024-03-21 14:38:01 -04:00
parent b56279569b
commit 5fdc7555c1
3 changed files with 61 additions and 0 deletions

View File

@ -2017,6 +2017,30 @@ fn check_pat_deref(
let ty = self.normalize(span, ty);
let ty = self.try_structurally_resolve_type(span, ty);
self.check_pat(inner, ty, pat_info);
// Check if the pattern has any `ref mut` bindings, which would require
// `DerefMut` to be emitted in MIR building instead of just `Deref`.
let mut needs_mut = false;
inner.walk(|pat| {
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
&& let Some(ty::BindByReference(ty::Mutability::Mut)) =
self.typeck_results.borrow().pat_binding_modes().get(id)
{
needs_mut = true;
// No need to continue recursing
false
} else {
true
}
});
if needs_mut {
self.register_bound(
expected,
tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
self.misc(span),
);
}
expected
}

View File

@ -0,0 +1,17 @@
#![feature(deref_patterns)]
//~^ WARN the feature `deref_patterns` is incomplete
use std::rc::Rc;
fn main() {
match &mut vec![1] {
deref!(x) => {}
_ => {}
}
match &mut Rc::new(1) {
deref!(x) => {}
//~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied
_ => {}
}
}

View File

@ -0,0 +1,20 @@
warning: the feature `deref_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/ref-mut.rs:1:12
|
LL | #![feature(deref_patterns)]
| ^^^^^^^^^^^^^^
|
= note: see issue #87121 <https://github.com/rust-lang/rust/issues/87121> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied
--> $DIR/ref-mut.rs:13:9
|
LL | deref!(x) => {}
| ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>`
|
= note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.