Add ObligationCauseCode::Coercion to the Unpin obligation

This commit is contained in:
Frank King
2026-03-02 15:25:14 +08:00
parent 7be286e5f0
commit d38c8c0ef5
2 changed files with 22 additions and 6 deletions
+16 -6
View File
@@ -807,17 +807,23 @@ fn coerce_unsized_old_solver(
Ok(())
}
/// Create an obligation for `ty: Unpin`.
fn unpin_obligation(&self, ty: Ty<'tcx>) -> PredicateObligation<'tcx> {
/// Create an obligation for `ty: Unpin`, where .
fn unpin_obligation(
&self,
source: Ty<'tcx>,
target: Ty<'tcx>,
ty: Ty<'tcx>,
) -> PredicateObligation<'tcx> {
let pred = ty::TraitRef::new(
self.tcx,
self.tcx.require_lang_item(hir::LangItem::Unpin, self.cause.span),
[ty],
);
PredicateObligation::new(self.tcx, self.cause.clone(), self.param_env, pred)
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
PredicateObligation::new(self.tcx, cause, self.param_env, pred)
}
/// Checks if the given types are compatible for coercion to a pinned reference.
/// Checks if the given types are compatible for coercion from a pinned reference to a normal reference.
fn maybe_pin_ref_to_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> Option<CoerceMaybePinnedRef<'tcx>> {
if !self.tcx.features().pin_ergonomics() {
return None;
@@ -847,6 +853,8 @@ fn coerce_pin_ref_to_ref(
coerce_mutbls(a_mut, b_mut)?;
let unpin_obligation = self.unpin_obligation(a, b, a_ty);
let a = Ty::new_ref(self.tcx, a_r, a_ty, b_mut);
let mut coerce = self.unify_and(
a,
@@ -855,7 +863,7 @@ fn coerce_pin_ref_to_ref(
Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(b_mut, self.allow_two_phase))),
ForceLeakCheck::No,
)?;
coerce.obligations.push(self.unpin_obligation(a_ty));
coerce.obligations.push(unpin_obligation);
Ok(coerce)
}
@@ -902,7 +910,9 @@ fn coerce_to_pin_ref(
// no `Unpin` required when reborrowing a pinned reference to a pinned reference
ty::Pinnedness::Pinned => (DerefAdjustKind::Pin, None),
// `Unpin` required when reborrowing a non-pinned reference to a pinned reference
ty::Pinnedness::Not => (DerefAdjustKind::Builtin, Some(self.unpin_obligation(a_ty))),
ty::Pinnedness::Not => {
(DerefAdjustKind::Builtin, Some(self.unpin_obligation(a, b, a_ty)))
}
};
coerce_mutbls(a_mut, b_mut)?;
@@ -21,6 +21,7 @@ LL | |x: Pin<&mut T>| -> &mut T { x };
|
= 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>() {
@@ -34,6 +35,7 @@ LL | |x: Pin<&mut T>| -> &T { x };
|
= 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>() {
@@ -47,6 +49,7 @@ LL | |x: Pin<&T>| -> &T { x };
|
= 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>() {
@@ -90,6 +93,7 @@ LL | |x: &mut T| -> Pin<&mut T> { x };
|
= 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>() {
@@ -103,6 +107,7 @@ LL | |x: &mut T| -> Pin<&T> { x };
|
= 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>() {
@@ -116,6 +121,7 @@ LL | |x: &T| -> Pin<&T> { x };
|
= 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>() {