mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Support coercion between references and pinned references
This commit is contained in:
@@ -17,6 +17,8 @@ pub enum AutoderefKind {
|
||||
Builtin,
|
||||
/// A type which must dispatch to a `Deref` implementation.
|
||||
Overloaded,
|
||||
/// A pinned reference type, such as `Pin<&T>` and `Pin<&mut T>`.
|
||||
Pin,
|
||||
}
|
||||
struct AutoderefSnapshot<'tcx> {
|
||||
at_start: bool,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::PredicateObligations;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
@@ -62,6 +63,9 @@ pub(crate) fn adjust_steps_as_infer_ok(
|
||||
})
|
||||
.unwrap_or(DerefAdjustKind::Builtin)
|
||||
}
|
||||
AutoderefKind::Pin => {
|
||||
bug!("Pin autoderef kind should not be present in the steps")
|
||||
}
|
||||
AutoderefKind::Builtin => DerefAdjustKind::Builtin,
|
||||
})
|
||||
.zip_eq(targets)
|
||||
|
||||
@@ -269,12 +269,21 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||
return self.coerce_to_raw_ptr(a, b, b_mutbl);
|
||||
}
|
||||
ty::Ref(r_b, _, mutbl_b) => {
|
||||
if self.tcx.features().pin_ergonomics()
|
||||
&& a.pinned_ty().is_some_and(|ty| ty.is_ref())
|
||||
&& let Ok(coerce) = self.commit_if_ok(|_| self.coerce_maybe_pinned_ref(a, b))
|
||||
{
|
||||
return Ok(coerce);
|
||||
}
|
||||
return self.coerce_to_ref(a, b, r_b, mutbl_b);
|
||||
}
|
||||
ty::Adt(pin, _)
|
||||
if self.tcx.features().pin_ergonomics()
|
||||
&& self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
|
||||
{
|
||||
if a.is_ref() && b.pinned_ty().is_some_and(|ty| ty.is_ref()) {
|
||||
return self.coerce_maybe_pinned_ref(a, b);
|
||||
}
|
||||
let pin_coerce = self.commit_if_ok(|_| self.coerce_to_pin_ref(a, b));
|
||||
if pin_coerce.is_ok() {
|
||||
return pin_coerce;
|
||||
@@ -847,6 +856,62 @@ fn coerce_to_pin_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||
self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b), ForceLeakCheck::No)
|
||||
}
|
||||
|
||||
/// Coerce pinned reference to regular reference or vice versa
|
||||
///
|
||||
/// - `Pin<&mut T>` <-> `&mut T` when `T: Unpin`
|
||||
/// - `Pin<&T>` <-> `&T` when `T: Unpin`
|
||||
/// - `Pin<&mut T>` <-> `Pin<&T>` when `T: Unpin`
|
||||
#[instrument(skip(self), level = "trace")]
|
||||
fn coerce_maybe_pinned_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||
let span = self.cause.span;
|
||||
let Some((a_ty, a_pinnedness, a_mutbl, a_region)) = a.maybe_pinned_ref() else {
|
||||
span_bug!(span, "expect pinned reference or reference, found {:?}", a);
|
||||
};
|
||||
let Some((_b_ty, b_pinnedness, b_mutbl, _b_region)) = b.maybe_pinned_ref() else {
|
||||
span_bug!(span, "expect pinned reference or reference, found {:?}", b);
|
||||
};
|
||||
use ty::Pinnedness::*;
|
||||
if a_pinnedness == b_pinnedness {
|
||||
span_bug!(span, "expect different pinnedness, found {:?} and {:?}", a, b);
|
||||
}
|
||||
|
||||
coerce_mutbls(a_mutbl, b_mutbl)?;
|
||||
|
||||
let (deref, borrow) = match (a_pinnedness, b_pinnedness) {
|
||||
(Not, Not) | (Pinned, Pinned) => {
|
||||
span_bug!(span, "expect different pinnedness, found {:?} and {:?}", a, b)
|
||||
}
|
||||
(Pinned, Not) => {
|
||||
let mutbl = AutoBorrowMutability::new(b_mutbl, AllowTwoPhase::Yes);
|
||||
(DerefAdjustKind::Pin, AutoBorrow::Ref(mutbl))
|
||||
}
|
||||
(Not, Pinned) => (DerefAdjustKind::Builtin, AutoBorrow::Pin(b_mutbl)),
|
||||
};
|
||||
let mut coerce = self.unify_and(
|
||||
// update a with b's pinnedness and mutability since we'll be coercing pinnedness and mutability
|
||||
match b_pinnedness {
|
||||
Pinned => Ty::new_pinned_ref(self.tcx, a_region, a_ty, b_mutbl),
|
||||
Not => Ty::new_ref(self.tcx, a_region, a_ty, b_mutbl),
|
||||
},
|
||||
b,
|
||||
[Adjustment { kind: Adjust::Deref(deref), target: a_ty }],
|
||||
Adjust::Borrow(borrow),
|
||||
ForceLeakCheck::No,
|
||||
)?;
|
||||
|
||||
// Create an obligation for `a_ty: Unpin`.
|
||||
let cause =
|
||||
self.cause(self.cause.span, ObligationCauseCode::Coercion { source: a, target: b });
|
||||
let pred = ty::TraitRef::new(
|
||||
self.tcx,
|
||||
self.tcx.require_lang_item(hir::LangItem::Unpin, self.cause.span),
|
||||
[a_ty],
|
||||
);
|
||||
let obligation = Obligation::new(self.tcx, cause, self.fcx.param_env, pred);
|
||||
coerce.obligations.push(obligation);
|
||||
Ok(coerce)
|
||||
}
|
||||
|
||||
fn coerce_from_fn_pointer(
|
||||
&self,
|
||||
a: Ty<'tcx>,
|
||||
|
||||
@@ -736,7 +736,7 @@ fn walk_adjustment(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
|
||||
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
|
||||
}
|
||||
|
||||
adjustment::Adjust::Deref(DerefAdjustKind::Builtin) => {}
|
||||
adjustment::Adjust::Deref(DerefAdjustKind::Builtin | DerefAdjustKind::Pin) => {}
|
||||
|
||||
// Autoderefs for overloaded Deref calls in fact reference
|
||||
// their receiver. That is, if we have `(*x)` where `x`
|
||||
@@ -800,6 +800,16 @@ fn walk_autoref(
|
||||
ty::BorrowKind::from_mutbl(m),
|
||||
);
|
||||
}
|
||||
|
||||
adjustment::AutoBorrow::Pin(m) => {
|
||||
debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, base_place);
|
||||
|
||||
self.delegate.borrow_mut().borrow(
|
||||
base_place,
|
||||
base_place.hir_id,
|
||||
ty::BorrowKind::from_mutbl(m),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -331,6 +331,9 @@ pub(crate) fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec<Adjustment
|
||||
Adjust::Deref(DerefAdjustKind::Builtin) => {
|
||||
// FIXME(const_trait_impl): We *could* enforce `&T: [const] Deref` here.
|
||||
}
|
||||
Adjust::Deref(DerefAdjustKind::Pin) => {
|
||||
// FIXME(const_trait_impl): We *could* enforce `Pin<&T>: [const] Deref` here.
|
||||
}
|
||||
Adjust::Pointer(_pointer_coercion) => {
|
||||
// FIXME(const_trait_impl): We should probably enforce these.
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Muta
|
||||
Adjust::NeverToAny
|
||||
| Adjust::Pointer(..)
|
||||
| Adjust::ReborrowPin(..)
|
||||
| Adjust::Deref(DerefAdjustKind::Builtin)
|
||||
| Adjust::Borrow(AutoBorrow::RawPtr(..)) => None,
|
||||
| Adjust::Deref(DerefAdjustKind::Builtin | DerefAdjustKind::Pin)
|
||||
| Adjust::Borrow(AutoBorrow::RawPtr(..) | AutoBorrow::Pin(..)) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@ pub enum Adjust {
|
||||
Pointer(PointerCoercion),
|
||||
|
||||
/// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
|
||||
// FIXME(pin_ergonomics): This can be replaced with a `Deref(Pin)` followed by a `Borrow(Pin)`
|
||||
ReborrowPin(hir::Mutability),
|
||||
}
|
||||
|
||||
@@ -112,6 +113,7 @@ pub enum Adjust {
|
||||
pub enum DerefAdjustKind {
|
||||
Builtin,
|
||||
Overloaded(OverloadedDeref),
|
||||
Pin,
|
||||
}
|
||||
|
||||
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
|
||||
@@ -196,6 +198,9 @@ pub enum AutoBorrow {
|
||||
|
||||
/// Converts from T to *T.
|
||||
RawPtr(hir::Mutability),
|
||||
|
||||
/// Converts from T to Pin<&T>.
|
||||
Pin(hir::Mutability),
|
||||
}
|
||||
|
||||
/// Information for `CoerceUnsized` impls, storing information we
|
||||
|
||||
@@ -143,6 +143,19 @@ fn apply_adjustment(
|
||||
adjust_span(&mut expr);
|
||||
ExprKind::Deref { arg: self.thir.exprs.push(expr) }
|
||||
}
|
||||
Adjust::Deref(DerefAdjustKind::Pin) => {
|
||||
adjust_span(&mut expr);
|
||||
// pointer = ($expr).pointer
|
||||
let pin_ty = expr.ty.pinned_ty().expect("Deref(Pin) with non-Pin type");
|
||||
let pointer_target = ExprKind::Field {
|
||||
lhs: self.thir.exprs.push(expr),
|
||||
variant_index: FIRST_VARIANT,
|
||||
name: FieldIdx::ZERO,
|
||||
};
|
||||
let expr = Expr { temp_scope_id, ty: pin_ty, span, kind: pointer_target };
|
||||
// expr = *pointer
|
||||
ExprKind::Deref { arg: self.thir.exprs.push(expr) }
|
||||
}
|
||||
Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
|
||||
// We don't need to do call adjust_span here since
|
||||
// deref coercions always start with a built-in deref.
|
||||
@@ -177,6 +190,37 @@ fn apply_adjustment(
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
|
||||
}
|
||||
Adjust::Borrow(AutoBorrow::Pin(mutbl)) => {
|
||||
// expr = &pin (mut|const|) arget
|
||||
let borrow_kind = match mutbl {
|
||||
hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
||||
hir::Mutability::Not => BorrowKind::Shared,
|
||||
};
|
||||
let new_pin_target =
|
||||
Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, expr.ty, mutbl);
|
||||
let arg = self.thir.exprs.push(expr);
|
||||
let expr = self.thir.exprs.push(Expr {
|
||||
temp_scope_id,
|
||||
ty: new_pin_target,
|
||||
span,
|
||||
kind: ExprKind::Borrow { borrow_kind, arg },
|
||||
});
|
||||
|
||||
// kind = Pin { pointer }
|
||||
let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, span);
|
||||
let args = self.tcx.mk_args(&[new_pin_target.into()]);
|
||||
let kind = ExprKind::Adt(Box::new(AdtExpr {
|
||||
adt_def: self.tcx.adt_def(pin_did),
|
||||
variant_index: FIRST_VARIANT,
|
||||
args,
|
||||
fields: Box::new([FieldExpr { name: FieldIdx::ZERO, expr }]),
|
||||
user_ty: None,
|
||||
base: AdtExprBase::None,
|
||||
}));
|
||||
|
||||
debug!(?kind);
|
||||
kind
|
||||
}
|
||||
Adjust::ReborrowPin(mutbl) => {
|
||||
debug!("apply ReborrowPin adjustment");
|
||||
// Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:9:36
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &mut T { x.get_mut() };
|
||||
| ^^^^^^^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
note: required by a bound in `Pin::<&'a mut T>::get_mut`
|
||||
--> $SRC_DIR/core/src/pin.rs:LL:COL
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn get<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:18:34
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &mut T { x };
|
||||
| ------ ^ expected `&mut T`, found `Pin<&mut T>`
|
||||
| |
|
||||
| expected `&mut T` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut T`
|
||||
found struct `Pin<&mut T>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &mut T { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:21:30
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &T { x };
|
||||
| -- ^ expected `&T`, found `Pin<&mut T>`
|
||||
| |
|
||||
| expected `&T` because of return type
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found struct `Pin<&mut T>`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &T { &x };
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:24:26
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &T { x };
|
||||
| -- ^ expected `&T`, found `Pin<&T>`
|
||||
| |
|
||||
| expected `&T` because of return type
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found struct `Pin<&T>`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &T { &x };
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:27:30
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &mut T { x };
|
||||
| ------ ^ expected `&mut T`, found `Pin<&T>`
|
||||
| |
|
||||
| expected `&mut T` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut T`
|
||||
found struct `Pin<&T>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &mut T { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:31:34
|
||||
|
|
||||
LL | |x: Pin<&mut U>| -> &mut U { x };
|
||||
| ------ ^ expected `&mut U`, found `Pin<&mut U>`
|
||||
| |
|
||||
| expected `&mut U` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut U`
|
||||
found struct `Pin<&mut U>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&mut U>| -> &mut U { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:33:30
|
||||
|
|
||||
LL | |x: Pin<&mut U>| -> &U { x };
|
||||
| -- ^ expected `&U`, found `Pin<&mut U>`
|
||||
| |
|
||||
| expected `&U` because of return type
|
||||
|
|
||||
= note: expected reference `&U`
|
||||
found struct `Pin<&mut U>`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | |x: Pin<&mut U>| -> &U { &x };
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:35:26
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &U { x };
|
||||
| -- ^ expected `&U`, found `Pin<&U>`
|
||||
| |
|
||||
| expected `&U` because of return type
|
||||
|
|
||||
= note: expected reference `&U`
|
||||
found struct `Pin<&U>`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &U { &x };
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:37:30
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &mut U { x };
|
||||
| ------ ^ expected `&mut U`, found `Pin<&U>`
|
||||
| |
|
||||
| expected `&mut U` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut U`
|
||||
found struct `Pin<&U>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &mut U { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:43:34
|
||||
|
|
||||
LL | |x: &mut T| -> Pin<&mut T> { x };
|
||||
| ----------- ^ expected `Pin<&mut T>`, found `&mut T`
|
||||
| |
|
||||
| expected `Pin<&mut T>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut T>`
|
||||
found mutable reference `&mut T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:46:30
|
||||
|
|
||||
LL | |x: &mut T| -> Pin<&T> { x };
|
||||
| ------- ^ expected `Pin<&T>`, found `&mut T`
|
||||
| |
|
||||
| expected `Pin<&T>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&T>`
|
||||
found mutable reference `&mut T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:49:26
|
||||
|
|
||||
LL | |x: &T| -> Pin<&T> { x };
|
||||
| ------- ^ expected `Pin<&T>`, found `&T`
|
||||
| |
|
||||
| expected `Pin<&T>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&T>`
|
||||
found reference `&T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:52:30
|
||||
|
|
||||
LL | |x: &T| -> Pin<&mut T> { x };
|
||||
| ----------- ^ expected `Pin<&mut T>`, found `&T`
|
||||
| |
|
||||
| expected `Pin<&mut T>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut T>`
|
||||
found reference `&T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:56:34
|
||||
|
|
||||
LL | |x: &mut U| -> Pin<&mut U> { x };
|
||||
| ----------- ^ expected `Pin<&mut U>`, found `&mut U`
|
||||
| |
|
||||
| expected `Pin<&mut U>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut U>`
|
||||
found mutable reference `&mut U`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:58:30
|
||||
|
|
||||
LL | |x: &mut U| -> Pin<&U> { x };
|
||||
| ------- ^ expected `Pin<&U>`, found `&mut U`
|
||||
| |
|
||||
| expected `Pin<&U>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&U>`
|
||||
found mutable reference `&mut U`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:60:26
|
||||
|
|
||||
LL | |x: &U| -> Pin<&U> { x };
|
||||
| ------- ^ expected `Pin<&U>`, found `&U`
|
||||
| |
|
||||
| expected `Pin<&U>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&U>`
|
||||
found reference `&U`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:62:30
|
||||
|
|
||||
LL | |x: &U| -> Pin<&mut U> { x };
|
||||
| ----------- ^ expected `Pin<&mut U>`, found `&U`
|
||||
| |
|
||||
| expected `Pin<&mut U>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut U>`
|
||||
found reference `&U`
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
@@ -0,0 +1,155 @@
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:9:36
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &mut T { x.get_mut() };
|
||||
| ^^^^^^^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
note: required by a bound in `Pin::<&'a mut T>::get_mut`
|
||||
--> $SRC_DIR/core/src/pin.rs:LL:COL
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn get<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:18:34
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &mut T { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `Pin<&mut T>` to `&mut T`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:21:30
|
||||
|
|
||||
LL | |x: Pin<&mut T>| -> &T { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `Pin<&mut T>` to `&T`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:24:26
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &T { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `Pin<&T>` to `&T`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:27:30
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &mut T { x };
|
||||
| ------ ^ expected `&mut T`, found `Pin<&T>`
|
||||
| |
|
||||
| expected `&mut T` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut T`
|
||||
found struct `Pin<&T>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&T>| -> &mut T { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:37:30
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &mut U { x };
|
||||
| ------ ^ expected `&mut U`, found `Pin<&U>`
|
||||
| |
|
||||
| expected `&mut U` because of return type
|
||||
|
|
||||
= note: expected mutable reference `&mut U`
|
||||
found struct `Pin<&U>`
|
||||
help: consider mutably borrowing here
|
||||
|
|
||||
LL | |x: Pin<&U>| -> &mut U { &mut x };
|
||||
| ++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:43:34
|
||||
|
|
||||
LL | |x: &mut T| -> Pin<&mut T> { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `&mut T` to `Pin<&mut T>`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:46:30
|
||||
|
|
||||
LL | |x: &mut T| -> Pin<&T> { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `&mut T` to `Pin<&T>`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0277]: `T` cannot be unpinned
|
||||
--> $DIR/pin-coercion-check.rs:49:26
|
||||
|
|
||||
LL | |x: &T| -> Pin<&T> { x };
|
||||
| ^ the trait `Unpin` is not implemented for `T`
|
||||
|
|
||||
= note: consider using the `pin!` macro
|
||||
consider using `Box::pin` if you need to access the pinned value outside of the current scope
|
||||
= note: required for the cast from `&T` to `Pin<&T>`
|
||||
help: consider restricting type parameter `T` with trait `Unpin`
|
||||
|
|
||||
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:52:30
|
||||
|
|
||||
LL | |x: &T| -> Pin<&mut T> { x };
|
||||
| ----------- ^ types differ in mutability
|
||||
| |
|
||||
| expected `Pin<&mut T>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut T>`
|
||||
found reference `&T`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pin-coercion-check.rs:62:30
|
||||
|
|
||||
LL | |x: &U| -> Pin<&mut U> { x };
|
||||
| ----------- ^ types differ in mutability
|
||||
| |
|
||||
| expected `Pin<&mut U>` because of return type
|
||||
|
|
||||
= note: expected struct `Pin<&mut U>`
|
||||
found reference `&U`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
@@ -0,0 +1,66 @@
|
||||
//@ revisions: pin_ergonomics normal
|
||||
//@ edition:2024
|
||||
#![cfg_attr(pin_ergonomics, feature(pin_ergonomics))]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
fn get<T, U: Unpin>() {
|
||||
|x: Pin<&mut T>| -> &mut T { x.get_mut() }; //~ ERROR `T` cannot be unpinned
|
||||
|x: Pin<&T>| -> &T { x.get_ref() };
|
||||
|
||||
|x: Pin<&mut U>| -> &mut U { x.get_mut() };
|
||||
|x: Pin<&U>| -> &U { x.get_ref() };
|
||||
}
|
||||
|
||||
fn pin_to_ref<T, U: Unpin>() {
|
||||
// T: !Unpin
|
||||
|x: Pin<&mut T>| -> &mut T { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: Pin<&mut T>| -> &T { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: Pin<&T>| -> &T { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: Pin<&T>| -> &mut T { x };
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
// U: Unpin
|
||||
|x: Pin<&mut U>| -> &mut U { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: Pin<&mut U>| -> &U { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: Pin<&U>| -> &U { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: Pin<&U>| -> &mut U { x };
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn ref_to_pin<T, U: Unpin>() {
|
||||
// T: !Unpin
|
||||
|x: &mut T| -> Pin<&mut T> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: &mut T| -> Pin<&T> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: &T| -> Pin<&T> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR `T` cannot be unpinned
|
||||
|x: &T| -> Pin<&mut T> { x };
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
// U: Unpin
|
||||
|x: &mut U| -> Pin<&mut U> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: &mut U| -> Pin<&U> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: &U| -> Pin<&U> { x };
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|x: &U| -> Pin<&mut U> { x };
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,56 @@
|
||||
//@ run-pass
|
||||
//@ edition:2024
|
||||
#![feature(pin_ergonomics)]
|
||||
#![allow(incomplete_features)]
|
||||
#![deny(dead_code)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn coerce_mut_to_pin_mut<T: Unpin>(x: &mut T) -> &pin mut T {
|
||||
x
|
||||
}
|
||||
fn coerce_ref_to_pin_ref<T: Unpin>(x: &T) -> &pin const T {
|
||||
x
|
||||
}
|
||||
fn coerce_pin_mut_to_mut<T: Unpin>(x: &pin mut T) -> &mut T {
|
||||
x
|
||||
}
|
||||
fn coerce_pin_ref_to_ref<T: Unpin>(x: &pin const T) -> &T {
|
||||
x
|
||||
}
|
||||
|
||||
fn coerce_pin_mut_to_ref<T: Unpin>(x: &pin mut T) -> &T {
|
||||
x
|
||||
}
|
||||
fn coerce_mut_to_pin_ref<T: Unpin>(x: &mut T) -> &pin const T {
|
||||
x
|
||||
}
|
||||
|
||||
fn test(x: &mut RefCell<String>) {
|
||||
let mut x: &pin mut _ = coerce_mut_to_pin_mut(x);
|
||||
x.get_mut().get_mut().push_str("&mut T -> &pin mut T\n");
|
||||
let x_ref: &_ = coerce_pin_mut_to_ref(x.as_mut());
|
||||
x_ref.borrow_mut().push_str("&pin mut T -> &T\n");
|
||||
let x: &mut _ = coerce_pin_mut_to_mut(x);
|
||||
x.get_mut().push_str("&pin mut T -> &mut T\n");
|
||||
let x: &pin const _ = coerce_mut_to_pin_ref(x);
|
||||
x.borrow_mut().push_str("&mut T -> &pin const T\n");
|
||||
let x: &_ = coerce_pin_ref_to_ref(x);
|
||||
x.borrow_mut().push_str("&pin const T -> &T\n");
|
||||
let x: &pin const _ = coerce_ref_to_pin_ref(x);
|
||||
x.borrow_mut().push_str("&T -> &pin const T\n");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = RefCell::new(String::new());
|
||||
test(&mut x);
|
||||
assert_eq!(
|
||||
x.borrow().as_str(),
|
||||
"&mut T -> &pin mut T\n\
|
||||
&pin mut T -> &T\n\
|
||||
&pin mut T -> &mut T\n\
|
||||
&mut T -> &pin const T\n\
|
||||
&pin const T -> &T\n\
|
||||
&T -> &pin const T\n"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user