diff options
| author | Michael Goulet <michael@errs.io> | 2024-03-21 14:38:01 -0400 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-03-25 19:39:45 -0400 |
| commit | 5fdc7555c1d6c80a51a3a88c494f255f719bdd35 (patch) | |
| tree | aa1bfca15d1bad7756cd896e7bb16ed37c523bf2 | |
| parent | b56279569be90758f1b53bb658ceace1527f5837 (diff) | |
| download | rust-5fdc7555c1d6c80a51a3a88c494f255f719bdd35.tar.gz rust-5fdc7555c1d6c80a51a3a88c494f255f719bdd35.zip | |
Require DerefMut if deref pattern has nested ref mut binding
| -rw-r--r-- | compiler/rustc_hir_typeck/src/pat.rs | 24 | ||||
| -rw-r--r-- | tests/ui/pattern/deref-patterns/ref-mut.rs | 17 | ||||
| -rw-r--r-- | tests/ui/pattern/deref-patterns/ref-mut.stderr | 20 |
3 files changed, 61 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 242523fb317..5f8b833b306 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2017,6 +2017,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 } diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs new file mode 100644 index 00000000000..1918008a761 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/ref-mut.rs @@ -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 + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr new file mode 100644 index 00000000000..41f1c3061ce --- /dev/null +++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr @@ -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`. |
