From 0383197fbe1d293c1b10e05f463b00075e7f1320 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 17 Dec 2025 21:10:03 +1100 Subject: [PATCH 1/2] Don't use `thir::PatKind::DerefPattern` for implicit pin-patterns --- .../src/builder/matches/match_pair.rs | 3 ++- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 13 ++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index dc1545c9278a9..e08ef0d267480 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -287,8 +287,9 @@ impl<'tcx> MatchPairTree<'tcx> { None } + // FIXME: Pin-patterns should probably have their own pattern kind, + // instead of overloading `PatKind::Deref` via the pattern type. PatKind::Deref { ref subpattern } - | PatKind::DerefPattern { ref subpattern, borrow: ByRef::Yes(Pinnedness::Pinned, _) } if let Some(ref_ty) = pattern.ty.pinned_ty() && ref_ty.is_ref() => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 02e6f8d6ce717..a13536559527a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer}; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, ByRef, LangItem, Mutability, Pinnedness, RangeEnd}; +use rustc_hir::{self as hir, LangItem, RangeEnd}; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::LitToConstInput; @@ -114,16 +114,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat); PatKind::DerefPattern { subpattern: thir_pat, borrow } } - PatAdjust::PinDeref => { - let mutable = self.typeck_results.pat_has_ref_mut_binding(pat); - PatKind::DerefPattern { - subpattern: thir_pat, - borrow: ByRef::Yes( - Pinnedness::Pinned, - if mutable { Mutability::Mut } else { Mutability::Not }, - ), - } - } + PatAdjust::PinDeref => PatKind::Deref { subpattern: thir_pat }, }; Box::new(Pat { span, ty: adjust.source, kind }) }); From 1ae96045d255ebda6ae9bb4a3b578f47ec24f6e7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 17 Dec 2025 21:24:26 +1100 Subject: [PATCH 2/2] Don't use `ByRef` for the `thir::PatKind::DerefPattern` borrow mode This avoids having to awkwardly ignore the `Pinnedness` field. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 7 ++++--- compiler/rustc_middle/src/thir.rs | 12 +++++++++--- compiler/rustc_middle/src/ty/typeck_results.rs | 17 +++++++++++------ .../src/builder/matches/match_pair.rs | 11 +++-------- .../rustc_mir_build/src/builder/matches/mod.rs | 8 ++------ .../rustc_mir_build/src/thir/pattern/mod.rs | 4 ++-- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 27b66d07f98e4..be4fdb5240c7e 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -23,6 +23,7 @@ use rustc_middle::hir::place::ProjectionKind; // Export these here so that Clippy can use them. pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; +use rustc_middle::thir::DerefPatBorrowMode; use rustc_middle::ty::{ self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; @@ -1004,7 +1005,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // Deref patterns on boxes don't borrow, so we ignore them here. // HACK: this could be a fake pattern corresponding to a deref inserted by match // ergonomics, in which case `pat.hir_id` will be the id of the subpattern. - if let hir::ByRef::Yes(_, mutability) = + if let DerefPatBorrowMode::Borrow(mutability) = self.cx.typeck_results().deref_pat_borrow_mode(place.place.ty(), subpattern) { let bk = ty::BorrowKind::from_mutbl(mutability); @@ -1891,9 +1892,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx ) -> Result, Cx::Error> { match self.cx.typeck_results().deref_pat_borrow_mode(base_place.place.ty(), inner) { // Deref patterns on boxes are lowered using a built-in deref. - hir::ByRef::No => self.cat_deref(hir_id, base_place), + DerefPatBorrowMode::Box => self.cat_deref(hir_id, base_place), // For other types, we create a temporary to match on. - hir::ByRef::Yes(_, mutability) => { + DerefPatBorrowMode::Borrow(mutability) => { let re_erased = self.cx.tcx().lifetimes.re_erased; let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability); // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ... diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index edbb736128cf9..3d893bf75e0b6 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -14,7 +14,7 @@ use std::ops::Index; use std::sync::Arc; use rustc_abi::{FieldIdx, Integer, Size, VariantIdx}; -use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece, Mutability}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; @@ -811,11 +811,11 @@ pub enum PatKind<'tcx> { DerefPattern { subpattern: Box>, /// Whether the pattern scrutinee needs to be borrowed in order to call `Deref::deref` or - /// `DerefMut::deref_mut`, and if so, which. This is `ByRef::No` for deref patterns on + /// `DerefMut::deref_mut`, and if so, which. This is `DerefPatBorrowMode::Box` for deref patterns on /// boxes; they are lowered using a built-in deref rather than a method call, thus they /// don't borrow the scrutinee. #[type_visitable(ignore)] - borrow: ByRef, + borrow: DerefPatBorrowMode, }, /// One of the following: @@ -879,6 +879,12 @@ pub enum PatKind<'tcx> { Error(ErrorGuaranteed), } +#[derive(Copy, Clone, Debug, HashStable)] +pub enum DerefPatBorrowMode { + Borrow(Mutability), + Box, +} + /// A range pattern. /// The boundaries must be of the same type and that type must be numeric. #[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index a3353661d9dd9..2c5e4957d0aed 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -11,7 +11,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::hir_id::OwnerId; use rustc_hir::{ self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability, - Pinnedness, }; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; @@ -21,6 +20,7 @@ use rustc_span::Span; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::Canonical; use crate::mir::FakeReadCause; +use crate::thir::DerefPatBorrowMode; use crate::traits::ObligationCause; use crate::ty::{ self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs, @@ -491,13 +491,18 @@ impl<'tcx> TypeckResults<'tcx> { /// In most cases, if the pattern recursively contains a `ref mut` binding, we find the inner /// pattern's scrutinee by calling `DerefMut::deref_mut`, and otherwise we call `Deref::deref`. /// However, for boxes we can use a built-in deref instead, which doesn't borrow the scrutinee; - /// in this case, we return `ByRef::No`. - pub fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: &hir::Pat<'_>) -> ByRef { + /// in this case, we return `DerefPatBorrowMode::Box`. + pub fn deref_pat_borrow_mode( + &self, + pointer_ty: Ty<'_>, + inner: &hir::Pat<'_>, + ) -> DerefPatBorrowMode { if pointer_ty.is_box() { - ByRef::No + DerefPatBorrowMode::Box } else { - let mutable = self.pat_has_ref_mut_binding(inner); - ByRef::Yes(Pinnedness::Not, if mutable { Mutability::Mut } else { Mutability::Not }) + let mutability = + if self.pat_has_ref_mut_binding(inner) { Mutability::Mut } else { Mutability::Not }; + DerefPatBorrowMode::Borrow(mutability) } } diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index e08ef0d267480..8d612b8c5efe5 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,10 +1,9 @@ use std::sync::Arc; use rustc_abi::FieldIdx; -use rustc_hir::ByRef; use rustc_middle::mir::*; use rustc_middle::thir::*; -use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use crate::builder::Builder; use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder}; @@ -303,12 +302,8 @@ impl<'tcx> MatchPairTree<'tcx> { None } - PatKind::DerefPattern { borrow: ByRef::Yes(Pinnedness::Pinned, _), .. } => { - rustc_middle::bug!("RefPin pattern on non-`Pin` type {:?}", pattern.ty) - } - PatKind::Deref { ref subpattern } - | PatKind::DerefPattern { ref subpattern, borrow: ByRef::No } => { + | PatKind::DerefPattern { ref subpattern, borrow: DerefPatBorrowMode::Box } => { MatchPairTree::for_pattern( place_builder.deref(), subpattern, @@ -321,7 +316,7 @@ impl<'tcx> MatchPairTree<'tcx> { PatKind::DerefPattern { ref subpattern, - borrow: ByRef::Yes(Pinnedness::Not, mutability), + borrow: DerefPatBorrowMode::Borrow(mutability), } => { // Create a new temporary for each deref pattern. // FIXME(deref_patterns): dedup temporaries to avoid multiple `deref()` calls? diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index ecdc3842a9b86..66e36a99d3c4e 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -11,10 +11,10 @@ use std::mem; use std::sync::Arc; use itertools::{Itertools, Position}; -use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_abi::{FIRST_VARIANT, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir::{BindingMode, ByRef, LangItem, LetStmt, LocalSource, Node, Pinnedness}; +use rustc_hir::{BindingMode, ByRef, LangItem, LetStmt, LocalSource, Node}; use rustc_middle::middle::region::{self, TempLifetime}; use rustc_middle::mir::*; use rustc_middle::thir::{self, *}; @@ -920,10 +920,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { visit_subpat(self, subpattern, &user_tys.deref(), f); } - PatKind::DerefPattern { ref subpattern, borrow: ByRef::Yes(Pinnedness::Pinned, _) } => { - visit_subpat(self, subpattern, &user_tys.leaf(FieldIdx::ZERO).deref(), f); - } - PatKind::DerefPattern { ref subpattern, .. } => { visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index a13536559527a..891a7df7d2357 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -16,7 +16,7 @@ use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ - Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, + Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment}; use rustc_middle::ty::layout::IntegerExt; @@ -325,7 +325,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Box(subpattern) => PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), - borrow: hir::ByRef::No, + borrow: DerefPatBorrowMode::Box, }, hir::PatKind::Slice(prefix, slice, suffix) => {