Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1837,9 +1838,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
) -> Result<PlaceWithHirId<'tcx>, 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` ...
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -811,11 +811,11 @@ pub enum PatKind<'tcx> {
DerefPattern {
subpattern: Box<Pat<'tcx>>,
/// 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:
Expand Down Expand Up @@ -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)]
Expand Down
17 changes: 11 additions & 6 deletions compiler/rustc_middle/src/ty/typeck_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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,
Expand Down Expand Up @@ -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)
}
}

Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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() =>
{
Expand All @@ -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,
Expand All @@ -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?
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, *};
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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 }
}
Expand Down
30 changes: 11 additions & 19 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<PatMigration<'a>>,
rust_2024_migration: Option<PatMigration<'tcx>>,
}

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<Pat<'tcx>> {
let mut pcx = PatCtxt {
Expand All @@ -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<Pat<'tcx>> {
let adjustments: &[PatAdjustment<'tcx>] =
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
Expand Down Expand Up @@ -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 })
});
Expand Down Expand Up @@ -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) => {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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]
| ^^^^^^
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading