Skip to content

Commit 2b3c0f3

Browse files
Auto merge of #139751 - frank-king:feature/pin-project, r=<try>
Implement pin-project in pattern matching for `&pin mut|const T`
2 parents 2aaa62b + 7533f2d commit 2b3c0f3

File tree

60 files changed

+2449
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2449
-118
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -789,14 +789,14 @@ pub struct PatField {
789789
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
790790
#[derive(Encodable, Decodable, HashStable_Generic, Walkable)]
791791
pub enum ByRef {
792-
Yes(Mutability),
792+
Yes(Pinnedness, Mutability),
793793
No,
794794
}
795795

796796
impl ByRef {
797797
#[must_use]
798798
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
799-
if let ByRef::Yes(old_mutbl) = &mut self {
799+
if let ByRef::Yes(_, old_mutbl) = &mut self {
800800
*old_mutbl = cmp::min(*old_mutbl, mutbl);
801801
}
802802
self
@@ -814,20 +814,33 @@ pub struct BindingMode(pub ByRef, pub Mutability);
814814

815815
impl BindingMode {
816816
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
817-
pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not);
817+
pub const REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Not);
818+
pub const REF_PIN: Self =
819+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Not);
818820
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
819-
pub const REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Not);
820-
pub const MUT_REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Mut);
821-
pub const MUT_REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Mut);
821+
pub const REF_MUT: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Not);
822+
pub const REF_PIN_MUT: Self =
823+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Not);
824+
pub const MUT_REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Mut);
825+
pub const MUT_REF_PIN: Self =
826+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Mut);
827+
pub const MUT_REF_MUT: Self =
828+
Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Mut);
829+
pub const MUT_REF_PIN_MUT: Self =
830+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Mut);
822831

823832
pub fn prefix_str(self) -> &'static str {
824833
match self {
825834
Self::NONE => "",
826835
Self::REF => "ref ",
836+
Self::REF_PIN => "ref pin const ",
827837
Self::MUT => "mut ",
828838
Self::REF_MUT => "ref mut ",
839+
Self::REF_PIN_MUT => "ref pin mut ",
829840
Self::MUT_REF => "mut ref ",
841+
Self::MUT_REF_PIN => "mut ref pin ",
830842
Self::MUT_REF_MUT => "mut ref mut ",
843+
Self::MUT_REF_PIN_MUT => "mut ref pin mut ",
831844
}
832845
}
833846
}

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ macro_rules! common_visitor_and_walkers {
368368
crate::tokenstream::TokenStream,
369369
Movability,
370370
Mutability,
371+
Pinnedness,
371372
Result<(), rustc_span::ErrorGuaranteed>,
372373
rustc_data_structures::fx::FxHashMap<Symbol, usize>,
373374
rustc_span::ErrorGuaranteed,

compiler/rustc_ast_ir/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,10 @@ pub enum Pinnedness {
311311
Not,
312312
Pinned,
313313
}
314+
315+
impl Pinnedness {
316+
/// Return `true` if self is pinned
317+
pub fn is_pinned(self) -> bool {
318+
matches!(self, Self::Pinned)
319+
}
320+
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,10 +1712,15 @@ impl<'a> State<'a> {
17121712
if mutbl.is_mut() {
17131713
self.word_nbsp("mut");
17141714
}
1715-
if let ByRef::Yes(rmutbl) = by_ref {
1715+
if let ByRef::Yes(pinnedness, rmutbl) = by_ref {
17161716
self.word_nbsp("ref");
1717+
if pinnedness.is_pinned() {
1718+
self.word_nbsp("pin");
1719+
}
17171720
if rmutbl.is_mut() {
17181721
self.word_nbsp("mut");
1722+
} else if pinnedness.is_pinned() {
1723+
self.word_nbsp("const");
17191724
}
17201725
}
17211726
self.print_ident(*ident);

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub(crate) mod must_use;
4848
pub(crate) mod no_implicit_prelude;
4949
pub(crate) mod non_exhaustive;
5050
pub(crate) mod path;
51+
pub(crate) mod pin_v2;
5152
pub(crate) mod proc_macro_attrs;
5253
pub(crate) mod prototype;
5354
pub(crate) mod repr;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use rustc_hir::Target;
2+
use rustc_hir::attrs::AttributeKind;
3+
use rustc_span::{Span, Symbol, sym};
4+
5+
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
6+
use crate::context::Stage;
7+
use crate::target_checking::AllowedTargets;
8+
use crate::target_checking::Policy::Allow;
9+
10+
pub(crate) struct PinV2Parser;
11+
12+
impl<S: Stage> NoArgsAttributeParser<S> for PinV2Parser {
13+
const PATH: &[Symbol] = &[sym::pin_v2];
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
15+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
16+
Allow(Target::Enum),
17+
Allow(Target::Struct),
18+
Allow(Target::Union),
19+
]);
20+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PinV2;
21+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use crate::attributes::must_use::MustUseParser;
4747
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
4848
use crate::attributes::non_exhaustive::NonExhaustiveParser;
4949
use crate::attributes::path::PathParser as PathAttributeParser;
50+
use crate::attributes::pin_v2::PinV2Parser;
5051
use crate::attributes::proc_macro_attrs::{
5152
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
5253
};
@@ -233,6 +234,7 @@ attribute_parsers!(
233234
Single<WithoutArgs<NonExhaustiveParser>>,
234235
Single<WithoutArgs<ParenSugarParser>>,
235236
Single<WithoutArgs<PassByValueParser>>,
237+
Single<WithoutArgs<PinV2Parser>>,
236238
Single<WithoutArgs<PointeeParser>>,
237239
Single<WithoutArgs<ProcMacroAttributeParser>>,
238240
Single<WithoutArgs<ProcMacroParser>>,

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
11881188
}
11891189

11901190
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
1191-
binding_mode: BindingMode(ByRef::Yes(_), _),
1191+
binding_mode: BindingMode(ByRef::Yes(..), _),
11921192
..
11931193
})) => {
11941194
let pattern_span: Span = local_decl.source_info.span;

compiler/rustc_borrowck/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,6 +2584,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
25842584
_ => bug!("Deref of unexpected type: {:?}", base_ty),
25852585
}
25862586
}
2587+
// Check as the inner reference type if it is a field projection
2588+
// from the `&pin` pattern
2589+
ProjectionElem::Field(FieldIdx::ZERO, _)
2590+
if let Some(adt) =
2591+
place_base.ty(self.body(), self.infcx.tcx).ty.ty_adt_def()
2592+
&& adt.is_pin()
2593+
&& self.infcx.tcx.features().pin_ergonomics() =>
2594+
{
2595+
self.is_mutable(place_base, is_local_mutation_allowed)
2596+
}
25872597
// All other projections are owned by their base path, so mutable if
25882598
// base path is mutable
25892599
ProjectionElem::Field(..)

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,15 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
888888
EncodeCrossCrate::No, loop_match, experimental!(loop_match)
889889
),
890890

891+
// The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment
892+
// that allows structurally pinning, tracked in:
893+
//
894+
// - https://github.com/rust-lang/rust/issues/130494
895+
gated!(
896+
pin_v2, Normal, template!(Word), ErrorFollowing,
897+
EncodeCrossCrate::Yes, pin_ergonomics, experimental!(pin_v2),
898+
),
899+
891900
// ==========================================================================
892901
// Internal attributes: Stability, deprecation, and unsafe:
893902
// ==========================================================================

0 commit comments

Comments
 (0)