Skip to content

Commit 16ddefa

Browse files
committed
Project pinned references to pinned fields
1 parent c9ca4f8 commit 16ddefa

File tree

81 files changed

+937
-764
lines changed

Some content is hidden

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

81 files changed

+937
-764
lines changed

compiler/rustc_ast/src/ast.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -719,14 +719,14 @@ pub struct PatField {
719719
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
720720
#[derive(Encodable, Decodable, HashStable_Generic)]
721721
pub enum ByRef {
722-
Yes(Mutability),
722+
Yes(Pinnedness, Mutability),
723723
No,
724724
}
725725

726726
impl ByRef {
727727
#[must_use]
728728
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
729-
if let ByRef::Yes(old_mutbl) = &mut self {
729+
if let ByRef::Yes(_, old_mutbl) = &mut self {
730730
*old_mutbl = cmp::min(*old_mutbl, mutbl);
731731
}
732732
self
@@ -744,20 +744,33 @@ pub struct BindingMode(pub ByRef, pub Mutability);
744744

745745
impl BindingMode {
746746
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
747-
pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not);
747+
pub const REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Not);
748+
pub const REF_PIN: Self =
749+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Not);
748750
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
749-
pub const REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Not);
750-
pub const MUT_REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Mut);
751-
pub const MUT_REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Mut);
751+
pub const REF_MUT: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Not);
752+
pub const REF_PIN_MUT: Self =
753+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Not);
754+
pub const MUT_REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Mut);
755+
pub const MUT_REF_PIN: Self =
756+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Mut);
757+
pub const MUT_REF_MUT: Self =
758+
Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Mut);
759+
pub const MUT_REF_PIN_MUT: Self =
760+
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Mut);
752761

753762
pub fn prefix_str(self) -> &'static str {
754763
match self {
755764
Self::NONE => "",
756765
Self::REF => "ref ",
766+
Self::REF_PIN => "ref pin const ",
757767
Self::MUT => "mut ",
758768
Self::REF_MUT => "ref mut ",
769+
Self::REF_PIN_MUT => "ref pin mut ",
759770
Self::MUT_REF => "mut ref ",
771+
Self::MUT_REF_PIN => "mut ref pin ",
760772
Self::MUT_REF_MUT => "mut ref mut ",
773+
Self::MUT_REF_PIN_MUT => "mut ref pin mut ",
761774
}
762775
}
763776
}

compiler/rustc_ast_ir/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,10 @@ pub enum Pinnedness {
101101
Not,
102102
Pinned,
103103
}
104+
105+
impl Pinnedness {
106+
/// Return `true` if self is pinned
107+
pub fn is_pinned(self) -> bool {
108+
matches!(self, Self::Pinned)
109+
}
110+
}

compiler/rustc_ast_pretty/src/pprust/state.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1624,10 +1624,15 @@ impl<'a> State<'a> {
16241624
if mutbl.is_mut() {
16251625
self.word_nbsp("mut");
16261626
}
1627-
if let ByRef::Yes(rmutbl) = by_ref {
1627+
if let ByRef::Yes(pinnedness, rmutbl) = by_ref {
16281628
self.word_nbsp("ref");
1629+
if pinnedness.is_pinned() {
1630+
self.word_nbsp("pin");
1631+
}
16291632
if rmutbl.is_mut() {
16301633
self.word_nbsp("mut");
1634+
} else if pinnedness.is_pinned() {
1635+
self.word_nbsp("const");
16311636
}
16321637
}
16331638
self.print_ident(*ident);

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12251225
}
12261226

12271227
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
1228-
binding_mode: BindingMode(ByRef::Yes(_), _),
1228+
binding_mode: BindingMode(ByRef::Yes(..), _),
12291229
..
12301230
})) => {
12311231
let pattern_span: Span = local_decl.source_info.span;
@@ -1588,7 +1588,7 @@ fn suggest_ampmut<'tcx>(
15881588
} else {
15891589
// otherwise, suggest that the user annotates the binding; we provide the
15901590
// type of the local.
1591-
let ty = decl_ty.builtin_deref(true, tcx).unwrap();
1591+
let ty = decl_ty.builtin_deref(true).unwrap();
15921592

15931593
Some(AmpMutSugg {
15941594
has_sugg: false,

compiler/rustc_borrowck/src/lib.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -2472,10 +2472,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
24722472

24732473
// Check the kind of deref to decide
24742474
match base_ty.kind() {
2475-
_ if let Some((_, _, _, mutbl)) =
2476-
base_ty.is_ref_or_pin_ref(self.infcx.tcx) =>
2477-
{
2478-
// FIXME(pin_ergonomics): handle `&pin mut|const T`
2475+
_ if let &ty::Ref(_, _, mutbl) = base_ty.kind() => {
24792476
match mutbl {
24802477
// Shared borrowed data is never mutable
24812478
hir::Mutability::Not => Err(place),
@@ -2516,6 +2513,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
25162513
_ => bug!("Deref of unexpected type: {:?}", base_ty),
25172514
}
25182515
}
2516+
// Check as the inner reference type if it is a field projection
2517+
// from the `&pin` pattern
2518+
ProjectionElem::Field(FieldIdx::ZERO, _)
2519+
if let Some(adt) =
2520+
place_base.ty(self.body(), self.infcx.tcx).ty.ty_adt_def()
2521+
&& adt.is_pin()
2522+
&& self.infcx.tcx.features().pin_ergonomics() =>
2523+
{
2524+
self.is_mutable(place_base, is_local_mutation_allowed)
2525+
}
25192526
// All other projections are owned by their base path, so mutable if
25202527
// base path is mutable
25212528
ProjectionElem::Field(..)

compiler/rustc_borrowck/src/type_check/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
17611761
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
17621762
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
17631763
let normalized_ty = self.normalize(unnormalized_ty, locations);
1764-
let literal_ty = constant.const_.ty().builtin_deref(true, tcx).unwrap();
1764+
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
17651765

17661766
if let Err(terr) =
17671767
self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
@@ -2360,9 +2360,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23602360

23612361
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
23622362
match base_ty.kind() {
2363-
_ if let Some((ref_region, _, _, mutbl)) =
2364-
base_ty.is_ref_or_pin_ref(tcx) =>
2365-
{
2363+
_ if let &ty::Ref(ref_region, _, mutbl) = base_ty.kind() => {
23662364
// FIXME(pin_ergonomics): handle `&pin mut|const T`
23672365
constraints.outlives_constraints.push(OutlivesConstraint {
23682366
sup: ref_region.as_var(),

compiler/rustc_codegen_llvm/src/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
626626
let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
627627
if element_type_index >= 0 {
628628
let arg_ty = self.args[element_type_index as usize].layout.ty;
629-
let pointee_ty = arg_ty.builtin_deref(true, bx.tcx).expect("Must be pointer argument");
629+
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
630630
let element_type_attr = unsafe {
631631
llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
632632
};

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2532,7 +2532,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
25322532

25332533
if name == sym::simd_arith_offset {
25342534
// This also checks that the first operand is a ptr type.
2535-
let pointee = in_elem.builtin_deref(true, bx.tcx).unwrap_or_else(|| {
2535+
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
25362536
span_bug!(span, "must be called with a vector of pointer types as first argument")
25372537
});
25382538
let layout = bx.layout_of(pointee);

compiler/rustc_codegen_ssa/src/mir/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11061106

11071107
// Make sure that we've actually unwrapped the rcvr down
11081108
// to a pointer or ref to `dyn* Trait`.
1109-
if !op.layout.ty.builtin_deref(true, bx.tcx()).unwrap().is_dyn_star() {
1109+
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
11101110
span_bug!(span, "can't codegen a virtual call on {:#?}", op);
11111111
}
11121112
let place = op.deref(bx.cx());

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
130130
{
131131
fn deref(&self, bx: &mut Bx) -> Self {
132132
bx.cx().layout_of(
133-
self.ty
134-
.builtin_deref(true, bx.tcx())
135-
.unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
133+
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
136134
)
137135
}
138136

compiler/rustc_codegen_ssa/src/mir/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
291291
let projected_ty = self
292292
.layout
293293
.ty
294-
.builtin_deref(true, cx.tcx())
294+
.builtin_deref(true)
295295
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));
296296

297297
let layout = cx.layout_of(projected_ty);
@@ -701,7 +701,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
701701
let unsized_ty = indirect_dest
702702
.layout
703703
.ty
704-
.builtin_deref(true, bx.tcx())
704+
.builtin_deref(true)
705705
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest));
706706

707707
let OperandValue::Ref(PlaceValue { llval: llptr, llextra: Some(llextra), .. }) = self

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
966966
mir::BinOp::BitXor => bx.xor(lhs, rhs),
967967
mir::BinOp::Offset => {
968968
let pointee_type = lhs_ty
969-
.builtin_deref(true, bx.tcx())
969+
.builtin_deref(true)
970970
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", lhs_ty));
971971
let pointee_layout = bx.cx().layout_of(pointee_type);
972972
if pointee_layout.is_zst() {

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub(super) fn op_to_const<'tcx>(
216216
// This codepath solely exists for `valtree_to_const_value` to not need to generate
217217
// a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
218218
// that case.
219-
let pointee_ty = imm.layout.ty.builtin_deref(false, *ecx.tcx).unwrap(); // `false` = no raw ptrs
219+
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
220220
debug_assert!(
221221
matches!(
222222
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
636636
nonoverlapping: bool,
637637
) -> InterpResult<'tcx> {
638638
let count = self.read_target_usize(count)?;
639-
let layout = self.layout_of(src.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;
639+
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?;
640640
let (size, align) = (layout.size, layout.align.abi);
641641

642642
let size = self.compute_size_in_bytes(size, count).ok_or_else(|| {
@@ -696,7 +696,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
696696
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
697697
name: &'static str,
698698
) -> InterpResult<'tcx> {
699-
let layout = self.layout_of(dst.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;
699+
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
700700

701701
let dst = self.read_pointer(dst)?;
702702
let byte = self.read_scalar(byte)?.to_u8()?;
@@ -735,7 +735,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
735735
lhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
736736
rhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
737737
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
738-
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;
738+
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
739739
assert!(layout.is_sized());
740740

741741
let get_bytes = |this: &InterpCx<'tcx, M>,

compiler/rustc_const_eval/src/interpret/operator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
313313
// Pointer ops that are always supported.
314314
Offset => {
315315
let ptr = left.to_scalar().to_pointer(self)?;
316-
let pointee_ty = left.layout.ty.builtin_deref(true, *self.tcx).unwrap();
316+
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
317317
let pointee_layout = self.layout_of(pointee_ty)?;
318318
assert!(pointee_layout.is_sized());
319319

compiler/rustc_const_eval/src/interpret/place.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,8 @@ where
419419
&self,
420420
val: &ImmTy<'tcx, M::Provenance>,
421421
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
422-
let pointee_type = val
423-
.layout
424-
.ty
425-
.builtin_deref(true, *self.tcx)
426-
.expect("`ref_to_mplace` called on non-ptr type");
422+
let pointee_type =
423+
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type");
427424
let layout = self.layout_of(pointee_type)?;
428425
let (ptr, meta) = val.to_scalar_and_meta();
429426

compiler/rustc_const_eval/src/util/check_validity_requirement.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ fn check_validity_requirement_lax<'tcx>(
126126
}
127127

128128
// Special magic check for references and boxes (i.e., special pointer types).
129-
if let Some(pointee) = this.ty.builtin_deref(false, cx.tcx()) {
129+
if let Some(pointee) = this.ty.builtin_deref(false) {
130130
let pointee = cx.layout_of(pointee)?;
131131
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
132132
if pointee.align.abi.bytes() > 1 {

compiler/rustc_hir/src/hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::{
1212
pub use rustc_ast::{
1313
AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
1414
BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
15-
MetaItemInner, MetaItemLit, Movability, Mutability, UnOp,
15+
MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, UnOp,
1616
};
1717
use rustc_attr_data_structures::AttributeKind;
1818
use rustc_data_structures::fingerprint::Fingerprint;

compiler/rustc_hir_analysis/src/autoderef.rs

+20-21
Original file line numberDiff line numberDiff line change
@@ -77,28 +77,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
7777
// be better to skip this clause and use the Overloaded case only, since &T
7878
// and &mut T implement Receiver. But built-in derefs apply equally to Receiver
7979
// and Deref, and this has benefits for const and the emitted MIR.
80-
let (kind, new_ty) = if let Some(ty) =
81-
self.state.cur_ty.builtin_deref(self.include_raw_pointers, self.infcx.tcx)
82-
{
83-
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
84-
// NOTE: we may still need to normalize the built-in deref in case
85-
// we have some type like `&<Ty as Trait>::Assoc`, since users of
86-
// autoderef expect this type to have been structurally normalized.
87-
if self.infcx.next_trait_solver()
88-
&& let ty::Alias(..) = ty.kind()
89-
{
90-
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
91-
self.state.obligations.extend(obligations);
92-
(AutoderefKind::Builtin, normalized_ty)
80+
let (kind, new_ty) =
81+
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
82+
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
83+
// NOTE: we may still need to normalize the built-in deref in case
84+
// we have some type like `&<Ty as Trait>::Assoc`, since users of
85+
// autoderef expect this type to have been structurally normalized.
86+
if self.infcx.next_trait_solver()
87+
&& let ty::Alias(..) = ty.kind()
88+
{
89+
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
90+
self.state.obligations.extend(obligations);
91+
(AutoderefKind::Builtin, normalized_ty)
92+
} else {
93+
(AutoderefKind::Builtin, ty)
94+
}
95+
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
96+
// The overloaded deref check already normalizes the pointee type.
97+
(AutoderefKind::Overloaded, ty)
9398
} else {
94-
(AutoderefKind::Builtin, ty)
95-
}
96-
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
97-
// The overloaded deref check already normalizes the pointee type.
98-
(AutoderefKind::Overloaded, ty)
99-
} else {
100-
return None;
101-
};
99+
return None;
100+
};
102101

103102
self.state.steps.push((self.state.cur_ty, kind));
104103
debug!(

compiler/rustc_hir_analysis/src/check/region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ fn resolve_local<'tcx>(
659659
// & expression, and its lifetime would be extended to the end of the block (due
660660
// to a different rule, not the below code).
661661
match pat.kind {
662-
PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(_), _), ..) => true,
662+
PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(..), _), ..) => true,
663663

664664
PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)),
665665

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,7 @@ fn check_method_receiver<'tcx>(
18081808
match receiver_validity_err {
18091809
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
18101810
let hint = match receiver_ty
1811-
.builtin_deref(false, tcx)
1811+
.builtin_deref(false)
18121812
.unwrap_or(receiver_ty)
18131813
.ty_adt_def()
18141814
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))

compiler/rustc_hir_pretty/src/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1882,10 +1882,15 @@ impl<'a> State<'a> {
18821882
if mutbl.is_mut() {
18831883
self.word_nbsp("mut");
18841884
}
1885-
if let ByRef::Yes(rmutbl) = by_ref {
1885+
if let ByRef::Yes(pinnedness, rmutbl) = by_ref {
18861886
self.word_nbsp("ref");
1887+
if pinnedness.is_pinned() {
1888+
self.word_nbsp("pin");
1889+
}
18871890
if rmutbl.is_mut() {
18881891
self.word_nbsp("mut");
1892+
} else if pinnedness.is_pinned() {
1893+
self.word_nbsp("const");
18891894
}
18901895
}
18911896
self.print_ident(ident);

0 commit comments

Comments
 (0)