about summary refs log tree commit diff
diff options
context:
space:
mode:
authordianne <diannes.gm@gmail.com>2025-01-01 15:19:11 -0800
committerdianne <diannes.gm@gmail.com>2025-01-07 23:15:42 -0800
commite2f3ce956809dd98adf271afe0b024c7febdf47f (patch)
tree9201d8842eab14b1bb67959b415556240bd8abbd
parentff165d54cbfc4734ae889e861ef9fd94ecfc5375 (diff)
downloadrust-e2f3ce956809dd98adf271afe0b024c7febdf47f.tar.gz
rust-e2f3ce956809dd98adf271afe0b024c7febdf47f.zip
always track patterns' `MutblCap`
If Rules 3 or 5 are adopted in any edition, we'll need to track the
`MutblCap` in all editions for macro hygiene purposes. Previously, the
check for whether to track it was conflated with the checks for whether
to apply Rules 3 and 5, so to make it a bit clearer, this always tracks
the `MutblCap`. If needed, we could check if Rules 3 or 5 are present in
any edition before tracking the `MutblCap`, but since it's not that much
more expensive to always track it, I've figured that's simplest.

My main concern with removing the checks is that it may not be clear
that the `MutblCap` is tracked for those specific purposes. To try and
mitigate this, I've made its doc comment a bit more precise regarding
the extent of how and why it's used.

This leaves the condition untouched on the `cap_to_weakly_not` call
needed for Rule 5, since it's only needed for that and it can affect
diagnostics.
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs25
1 files changed, 13 insertions, 12 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 5e6cca51c92..391acce97bd 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -168,15 +168,16 @@ enum AdjustMode {
     Pass,
 }
 
-/// `ref mut` patterns (explicit or match-ergonomics)
-/// are not allowed behind an `&` reference.
+/// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference.
+/// Normally, the borrow checker enforces this, but for (currently experimental) match ergonomics,
+/// we track this when typing patterns for two purposes:
 ///
-/// This includes explicit `ref mut` behind `&` patterns
-/// that match against `&mut` references,
-/// where the code would have compiled
-/// had the pattern been written as `&mut`.
-/// However, the borrow checker will not catch
-/// this last case, so we need to throw an error ourselves.
+/// - For RFC 3627's Rule 3, when this would prevent us from binding with `ref mut`, we limit the
+///   default binding mode to be by shared `ref` when it would otherwise be `ref mut`.
+///
+/// - For RFC 3627's Rule 5, we allow `&` patterns to match against `&mut` references, treating them
+///   as if they were shared references. Since the scrutinee is mutable in this case, the borrow
+///   checker won't catch if we bind with `ref mut`, so we need to throw an error ourselves.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum MutblCap {
     /// Mutability restricted to immutable.
@@ -477,9 +478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if features.ref_pat_eat_one_layer_2024() || features.ref_pat_eat_one_layer_2024_structural()
         {
             def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
-            if def_br == ByRef::Yes(Mutability::Not) {
-                max_ref_mutbl = MutblCap::Not;
-            }
+        }
+        if def_br == ByRef::Yes(Mutability::Not) {
+            max_ref_mutbl = MutblCap::Not;
         }
 
         if !pat_adjustments.is_empty() {
@@ -2292,7 +2293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if (no_ref_mut_behind_and && r_mutbl >= pat_mutbl)
                             || r_mutbl == pat_mutbl =>
                     {
-                        if no_ref_mut_behind_and && r_mutbl == Mutability::Not {
+                        if r_mutbl == Mutability::Not {
                             pat_info.max_ref_mutbl = MutblCap::Not;
                         }