Allow shortening reborrows
Generating a call to `as_mut()` let to more restrictive borrows than what reborrowing usually gives us. Instead, we change the desugaring to reborrow the pin internals directly which makes things more expressive.
This commit is contained in:
parent
a73c8b1171
commit
b2b76fb706
@ -395,7 +395,6 @@ language_item_table! {
|
|||||||
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
|
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
|
||||||
|
|
||||||
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
||||||
PinAsMut, sym::pin_as_mut, as_mut_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
|
|
||||||
|
|
||||||
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
|
RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
|
RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
|
||||||
|
@ -824,10 +824,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
// add the adjustments.
|
// add the adjustments.
|
||||||
self.unify_and(a, b, |_inner_ty| {
|
self.unify_and(a, b, |_inner_ty| {
|
||||||
vec![Adjustment {
|
vec![Adjustment {
|
||||||
kind: Adjust::ReborrowPin(AutoBorrow::Ref(
|
kind: Adjust::ReborrowPin(b_region, hir::Mutability::Mut),
|
||||||
b_region,
|
|
||||||
AutoBorrowMutability::Mut { allow_two_phase_borrow: AllowTwoPhase::No },
|
|
||||||
)),
|
|
||||||
target: b,
|
target: b,
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
|
@ -781,14 +781,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||||||
self.walk_autoref(expr, &place_with_id, autoref);
|
self.walk_autoref(expr, &place_with_id, autoref);
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment::Adjust::ReborrowPin(ref autoref) => {
|
adjustment::Adjust::ReborrowPin(_, mutbl) => {
|
||||||
// Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
|
// Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
|
||||||
// both.
|
// both.
|
||||||
let bk = match autoref {
|
let bk = match mutbl {
|
||||||
adjustment::AutoBorrow::Ref(_, m) => {
|
ty::Mutability::Not => ty::BorrowKind::ImmBorrow,
|
||||||
ty::BorrowKind::from_mutbl((*m).into())
|
ty::Mutability::Mut => ty::BorrowKind::MutBorrow,
|
||||||
}
|
|
||||||
adjustment::AutoBorrow::RawPtr(m) => ty::BorrowKind::from_mutbl(*m),
|
|
||||||
};
|
};
|
||||||
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
|
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
|
||||||
}
|
}
|
||||||
@ -1296,7 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||||||
adjustment::Adjust::NeverToAny
|
adjustment::Adjust::NeverToAny
|
||||||
| adjustment::Adjust::Pointer(_)
|
| adjustment::Adjust::Pointer(_)
|
||||||
| adjustment::Adjust::Borrow(_)
|
| adjustment::Adjust::Borrow(_)
|
||||||
| adjustment::Adjust::ReborrowPin(_)
|
| adjustment::Adjust::ReborrowPin(..)
|
||||||
| adjustment::Adjust::DynStar => {
|
| adjustment::Adjust::DynStar => {
|
||||||
// Result is an rvalue.
|
// Result is an rvalue.
|
||||||
Ok(self.cat_rvalue(expr.hir_id, target))
|
Ok(self.cat_rvalue(expr.hir_id, target))
|
||||||
|
@ -105,9 +105,8 @@ pub enum Adjust<'tcx> {
|
|||||||
/// Cast into a dyn* object.
|
/// Cast into a dyn* object.
|
||||||
DynStar,
|
DynStar,
|
||||||
|
|
||||||
/// Take a `Pin<Ptr>` and call either `as_mut()` or `as_ref()` to get a `Pin<&mut T>` or
|
/// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
|
||||||
/// `Pin<&T>`.
|
ReborrowPin(ty::Region<'tcx>, hir::Mutability),
|
||||||
ReborrowPin(AutoBorrow<'tcx>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
|
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
|
||||||
|
@ -147,50 +147,64 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
|
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
|
||||||
}
|
}
|
||||||
Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
|
Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
|
||||||
Adjust::ReborrowPin(AutoBorrow::Ref(region, m)) => {
|
Adjust::ReborrowPin(region, mutbl) => {
|
||||||
debug!("apply ReborrowPin adjustment");
|
debug!("apply ReborrowPin adjustment");
|
||||||
match m {
|
// Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
|
||||||
AutoBorrowMutability::Mut { .. } => {
|
|
||||||
// Rewrite `$expr` as `Pin::as_mut(&mut $expr)`
|
// We'll need these types later on
|
||||||
let as_mut_method =
|
|
||||||
self.tcx().require_lang_item(rustc_hir::LangItem::PinAsMut, Some(span));
|
|
||||||
let pin_ty_args = match expr.ty.kind() {
|
let pin_ty_args = match expr.ty.kind() {
|
||||||
ty::Adt(_, args) => args,
|
ty::Adt(_, args) => args,
|
||||||
_ => bug!("ReborrowPin with non-Pin type"),
|
_ => bug!("ReborrowPin with non-Pin type"),
|
||||||
};
|
};
|
||||||
let as_mut_ty =
|
let pin_ty = pin_ty_args.iter().next().unwrap().expect_ty();
|
||||||
Ty::new_fn_def(self.tcx, as_mut_method, pin_ty_args.into_iter());
|
let ptr_target_ty = match pin_ty.kind() {
|
||||||
|
ty::Ref(_, ty, _) => *ty,
|
||||||
let ty = Ty::new_ref(self.tcx, region, expr.ty, ty::Mutability::Mut);
|
_ => bug!("ReborrowPin with non-Ref type"),
|
||||||
let arg = ExprKind::Borrow {
|
|
||||||
borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
|
||||||
arg: self.thir.exprs.push(expr),
|
|
||||||
};
|
};
|
||||||
debug!(?arg, "borrow arg");
|
|
||||||
let arg = self.thir.exprs.push(Expr { temp_lifetime, ty, span, kind: arg });
|
|
||||||
|
|
||||||
let kind = ExprKind::Call {
|
// pointer = ($expr).__pointer
|
||||||
ty: as_mut_ty,
|
let pointer_target = ExprKind::Field {
|
||||||
fun: self.thir.exprs.push(Expr {
|
lhs: self.thir.exprs.push(expr),
|
||||||
|
variant_index: FIRST_VARIANT,
|
||||||
|
name: FieldIdx::from(0u32),
|
||||||
|
};
|
||||||
|
let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target };
|
||||||
|
let arg = self.thir.exprs.push(arg);
|
||||||
|
|
||||||
|
// arg = *pointer
|
||||||
|
let expr = ExprKind::Deref { arg };
|
||||||
|
let arg = self.thir.exprs.push(Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: as_mut_ty,
|
ty: ptr_target_ty,
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::ZstLiteral { user_ty: None },
|
kind: expr,
|
||||||
}),
|
});
|
||||||
args: Box::new([arg]),
|
|
||||||
from_hir_call: true,
|
// expr = &mut target
|
||||||
fn_span: span,
|
let expr = self.thir.exprs.push(Expr {
|
||||||
};
|
temp_lifetime,
|
||||||
|
ty: Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl),
|
||||||
|
span,
|
||||||
|
kind: ExprKind::Borrow {
|
||||||
|
borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
||||||
|
arg,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// kind = Pin { __pointer: pointer }
|
||||||
|
let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
|
||||||
|
let kind = ExprKind::Adt(Box::new(AdtExpr {
|
||||||
|
adt_def: self.tcx.adt_def(pin_did),
|
||||||
|
variant_index: FIRST_VARIANT,
|
||||||
|
args: pin_ty_args,
|
||||||
|
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
|
||||||
|
user_ty: None,
|
||||||
|
base: None,
|
||||||
|
}));
|
||||||
|
|
||||||
debug!(?kind);
|
debug!(?kind);
|
||||||
kind
|
kind
|
||||||
}
|
}
|
||||||
AutoBorrowMutability::Not => {
|
|
||||||
// FIXME: We need to call Pin::as_ref on the expression
|
|
||||||
bug!("ReborrowPin with shared reference is not implemented yet")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Adjust::ReborrowPin(AutoBorrow::RawPtr(_)) => bug!("ReborrowPin with raw pointer"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Expr { temp_lifetime, ty: adjustment.target, span, kind }
|
Expr { temp_lifetime, ty: adjustment.target, span, kind }
|
||||||
@ -1059,7 +1073,7 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
|
|
||||||
// Reconstruct the output assuming it's a reference with the
|
// Reconstruct the output assuming it's a reference with the
|
||||||
// same region and mutability as the receiver. This holds for
|
// same region and mutability as the receiver. This holds for
|
||||||
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
// `Deref(Mut)::deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||||
let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
|
let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
|
||||||
span_bug!(span, "overloaded_place: receiver is not a reference");
|
span_bug!(span, "overloaded_place: receiver is not a reference");
|
||||||
};
|
};
|
||||||
|
@ -1418,7 +1418,6 @@ symbols! {
|
|||||||
pic,
|
pic,
|
||||||
pie,
|
pie,
|
||||||
pin,
|
pin,
|
||||||
pin_as_mut,
|
|
||||||
pin_ergonomics,
|
pin_ergonomics,
|
||||||
platform_intrinsics,
|
platform_intrinsics,
|
||||||
plugin,
|
plugin,
|
||||||
|
@ -1408,7 +1408,6 @@ impl<Ptr: DerefMut> Pin<Ptr> {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(not(bootstrap), lang = "pin_as_mut")]
|
|
||||||
#[stable(feature = "pin", since = "1.33.0")]
|
#[stable(feature = "pin", since = "1.33.0")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
|
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
|
||||||
|
14
tests/ui/async-await/pin-reborrow-shorter.rs
Normal file
14
tests/ui/async-await/pin-reborrow-shorter.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//@check-pass
|
||||||
|
|
||||||
|
#![feature(pin_ergonomics)]
|
||||||
|
#![allow(dead_code, incomplete_features)]
|
||||||
|
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
fn shorter<'b, T: 'b>(_: Pin<&'b mut T>) {}
|
||||||
|
|
||||||
|
fn test<'a: 'b, 'b, T: 'a>(x: Pin<&'a mut T>) {
|
||||||
|
shorter::<'b>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user