diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 12c4dd203203e..ad34994526ed9 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -21,6 +21,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, }; @@ -890,7 +891,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); @@ -1837,9 +1838,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 5913c05e2e747..6b4ba92434793 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}; @@ -287,8 +286,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() => { @@ -302,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, @@ -320,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/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 6316ccf1b8c5b..c3c4c455b9656 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -28,7 +28,7 @@ use crate::errors::{ PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern, }; -impl<'a, 'tcx> PatCtxt<'a, 'tcx> { +impl<'tcx> PatCtxt<'tcx> { /// Converts a constant to a pattern (if possible). /// This means aggregate values (like structs and enums) are converted /// to a pattern that matches the value (as if you'd compared via structural equality). @@ -64,7 +64,7 @@ struct ConstToPat<'tcx> { } impl<'tcx> ConstToPat<'tcx> { - fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self { + fn new(pat_ctxt: &PatCtxt<'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self { trace!(?pat_ctxt.typeck_results.hir_owner); ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 02e6f8d6ce717..3eac6ae344bb8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,12 +11,12 @@ 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; 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; @@ -30,19 +30,20 @@ pub(crate) use self::check_match::check_match; use self::migration::PatMigration; use crate::errors::*; -struct PatCtxt<'a, 'tcx> { +/// Context for lowering HIR patterns to THIR patterns. +struct PatCtxt<'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. - rust_2024_migration: Option>, + rust_2024_migration: Option>, } -pub(super) fn pat_from_hir<'a, 'tcx>( +pub(super) fn pat_from_hir<'tcx>( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { let mut pcx = PatCtxt { @@ -62,7 +63,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>( result } -impl<'a, 'tcx> PatCtxt<'a, 'tcx> { +impl<'tcx> PatCtxt<'tcx> { fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { let adjustments: &[PatAdjustment<'tcx>] = self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); @@ -114,16 +115,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 }) }); @@ -334,7 +326,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) => { diff --git a/tests/ui/eii/wrong_target.rs b/tests/ui/eii/attribute_targets.rs similarity index 100% rename from tests/ui/eii/wrong_target.rs rename to tests/ui/eii/attribute_targets.rs diff --git a/tests/ui/eii/wrong_target.stderr b/tests/ui/eii/attribute_targets.stderr similarity index 67% rename from tests/ui/eii/wrong_target.stderr rename to tests/ui/eii/attribute_targets.stderr index 9b27f49fb3026..bf04c323c95ca 100644 --- a/tests/ui/eii/wrong_target.stderr +++ b/tests/ui/eii/attribute_targets.stderr @@ -1,107 +1,107 @@ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:7:1 + --> $DIR/attribute_targets.rs:7:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:9:1 + --> $DIR/attribute_targets.rs:9:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:13:1 + --> $DIR/attribute_targets.rs:13:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:15:1 + --> $DIR/attribute_targets.rs:15:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:21:1 + --> $DIR/attribute_targets.rs:21:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:23:1 + --> $DIR/attribute_targets.rs:23:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:27:1 + --> $DIR/attribute_targets.rs:27:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:29:1 + --> $DIR/attribute_targets.rs:29:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:32:5 + --> $DIR/attribute_targets.rs:32:5 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:34:5 + --> $DIR/attribute_targets.rs:34:5 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:39:1 + --> $DIR/attribute_targets.rs:39:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:41:1 + --> $DIR/attribute_targets.rs:41:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:44:5 + --> $DIR/attribute_targets.rs:44:5 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:46:5 + --> $DIR/attribute_targets.rs:46:5 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:51:1 + --> $DIR/attribute_targets.rs:51:1 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:53:1 + --> $DIR/attribute_targets.rs:53:1 | LL | #[eii] | ^^^^^^ error: `#[foo]` is only valid on functions - --> $DIR/wrong_target.rs:56:5 + --> $DIR/attribute_targets.rs:56:5 | LL | #[foo] | ^^^^^^ error: `#[eii]` is only valid on functions - --> $DIR/wrong_target.rs:58:5 + --> $DIR/attribute_targets.rs:58:5 | LL | #[eii] | ^^^^^^ diff --git a/tests/ui/eii/subtype_1.rs b/tests/ui/eii/type_checking/subtype_1.rs similarity index 100% rename from tests/ui/eii/subtype_1.rs rename to tests/ui/eii/type_checking/subtype_1.rs diff --git a/tests/ui/eii/subtype_1.stderr b/tests/ui/eii/type_checking/subtype_1.stderr similarity index 100% rename from tests/ui/eii/subtype_1.stderr rename to tests/ui/eii/type_checking/subtype_1.stderr diff --git a/tests/ui/eii/subtype_2.rs b/tests/ui/eii/type_checking/subtype_2.rs similarity index 100% rename from tests/ui/eii/subtype_2.rs rename to tests/ui/eii/type_checking/subtype_2.rs diff --git a/tests/ui/eii/subtype_2.stderr b/tests/ui/eii/type_checking/subtype_2.stderr similarity index 100% rename from tests/ui/eii/subtype_2.stderr rename to tests/ui/eii/type_checking/subtype_2.stderr diff --git a/tests/ui/eii/subtype_3.rs b/tests/ui/eii/type_checking/subtype_3.rs similarity index 100% rename from tests/ui/eii/subtype_3.rs rename to tests/ui/eii/type_checking/subtype_3.rs diff --git a/tests/ui/eii/subtype_4.rs b/tests/ui/eii/type_checking/subtype_4.rs similarity index 100% rename from tests/ui/eii/subtype_4.rs rename to tests/ui/eii/type_checking/subtype_4.rs diff --git a/tests/ui/eii/wrong_ret_ty.rs b/tests/ui/eii/type_checking/wrong_ret_ty.rs similarity index 100% rename from tests/ui/eii/wrong_ret_ty.rs rename to tests/ui/eii/type_checking/wrong_ret_ty.rs diff --git a/tests/ui/eii/wrong_ret_ty.stderr b/tests/ui/eii/type_checking/wrong_ret_ty.stderr similarity index 100% rename from tests/ui/eii/wrong_ret_ty.stderr rename to tests/ui/eii/type_checking/wrong_ret_ty.stderr diff --git a/tests/ui/eii/wrong_ty.rs b/tests/ui/eii/type_checking/wrong_ty.rs similarity index 100% rename from tests/ui/eii/wrong_ty.rs rename to tests/ui/eii/type_checking/wrong_ty.rs diff --git a/tests/ui/eii/wrong_ty.stderr b/tests/ui/eii/type_checking/wrong_ty.stderr similarity index 100% rename from tests/ui/eii/wrong_ty.stderr rename to tests/ui/eii/type_checking/wrong_ty.stderr diff --git a/tests/ui/eii/wrong_ty_2.rs b/tests/ui/eii/type_checking/wrong_ty_2.rs similarity index 100% rename from tests/ui/eii/wrong_ty_2.rs rename to tests/ui/eii/type_checking/wrong_ty_2.rs diff --git a/tests/ui/eii/wrong_ty_2.stderr b/tests/ui/eii/type_checking/wrong_ty_2.stderr similarity index 100% rename from tests/ui/eii/wrong_ty_2.stderr rename to tests/ui/eii/type_checking/wrong_ty_2.stderr