Skip to content

Commit

Permalink
Require DerefMut if deref pattern has nested ref mut binding
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Mar 21, 2024
1 parent 32b0a42 commit ec9d26a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
24 changes: 24 additions & 0 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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
}

Expand Down
17 changes: 17 additions & 0 deletions tests/ui/pattern/deref-patterns/ref-mut.rs
Original file line number Diff line number Diff line change
@@ -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
_ => {}
}
}
20 changes: 20 additions & 0 deletions tests/ui/pattern/deref-patterns/ref-mut.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit ec9d26a

Please sign in to comment.