Skip to content

Commit d38c8c0

Browse files
committed
Add ObligationCauseCode::Coercion to the Unpin obligation
1 parent 7be286e commit d38c8c0

2 files changed

Lines changed: 22 additions & 6 deletions

File tree

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -807,17 +807,23 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
807807
Ok(())
808808
}
809809

810-
/// Create an obligation for `ty: Unpin`.
811-
fn unpin_obligation(&self, ty: Ty<'tcx>) -> PredicateObligation<'tcx> {
810+
/// Create an obligation for `ty: Unpin`, where .
811+
fn unpin_obligation(
812+
&self,
813+
source: Ty<'tcx>,
814+
target: Ty<'tcx>,
815+
ty: Ty<'tcx>,
816+
) -> PredicateObligation<'tcx> {
812817
let pred = ty::TraitRef::new(
813818
self.tcx,
814819
self.tcx.require_lang_item(hir::LangItem::Unpin, self.cause.span),
815820
[ty],
816821
);
817-
PredicateObligation::new(self.tcx, self.cause.clone(), self.param_env, pred)
822+
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
823+
PredicateObligation::new(self.tcx, cause, self.param_env, pred)
818824
}
819825

820-
/// Checks if the given types are compatible for coercion to a pinned reference.
826+
/// Checks if the given types are compatible for coercion from a pinned reference to a normal reference.
821827
fn maybe_pin_ref_to_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> Option<CoerceMaybePinnedRef<'tcx>> {
822828
if !self.tcx.features().pin_ergonomics() {
823829
return None;
@@ -847,6 +853,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
847853

848854
coerce_mutbls(a_mut, b_mut)?;
849855

856+
let unpin_obligation = self.unpin_obligation(a, b, a_ty);
857+
850858
let a = Ty::new_ref(self.tcx, a_r, a_ty, b_mut);
851859
let mut coerce = self.unify_and(
852860
a,
@@ -855,7 +863,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
855863
Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(b_mut, self.allow_two_phase))),
856864
ForceLeakCheck::No,
857865
)?;
858-
coerce.obligations.push(self.unpin_obligation(a_ty));
866+
coerce.obligations.push(unpin_obligation);
859867
Ok(coerce)
860868
}
861869

@@ -902,7 +910,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
902910
// no `Unpin` required when reborrowing a pinned reference to a pinned reference
903911
ty::Pinnedness::Pinned => (DerefAdjustKind::Pin, None),
904912
// `Unpin` required when reborrowing a non-pinned reference to a pinned reference
905-
ty::Pinnedness::Not => (DerefAdjustKind::Builtin, Some(self.unpin_obligation(a_ty))),
913+
ty::Pinnedness::Not => {
914+
(DerefAdjustKind::Builtin, Some(self.unpin_obligation(a, b, a_ty)))
915+
}
906916
};
907917

908918
coerce_mutbls(a_mut, b_mut)?;

tests/ui/pin-ergonomics/pin-coercion-check.pin_ergonomics.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ LL | |x: Pin<&mut T>| -> &mut T { x };
2121
|
2222
= note: consider using the `pin!` macro
2323
consider using `Box::pin` if you need to access the pinned value outside of the current scope
24+
= note: required for the cast from `Pin<&mut T>` to `&mut T`
2425
help: consider restricting type parameter `T` with trait `Unpin`
2526
|
2627
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
@@ -34,6 +35,7 @@ LL | |x: Pin<&mut T>| -> &T { x };
3435
|
3536
= note: consider using the `pin!` macro
3637
consider using `Box::pin` if you need to access the pinned value outside of the current scope
38+
= note: required for the cast from `Pin<&mut T>` to `&T`
3739
help: consider restricting type parameter `T` with trait `Unpin`
3840
|
3941
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
@@ -47,6 +49,7 @@ LL | |x: Pin<&T>| -> &T { x };
4749
|
4850
= note: consider using the `pin!` macro
4951
consider using `Box::pin` if you need to access the pinned value outside of the current scope
52+
= note: required for the cast from `Pin<&T>` to `&T`
5053
help: consider restricting type parameter `T` with trait `Unpin`
5154
|
5255
LL | fn pin_to_ref<T: std::marker::Unpin, U: Unpin>() {
@@ -90,6 +93,7 @@ LL | |x: &mut T| -> Pin<&mut T> { x };
9093
|
9194
= note: consider using the `pin!` macro
9295
consider using `Box::pin` if you need to access the pinned value outside of the current scope
96+
= note: required for the cast from `&mut T` to `Pin<&mut T>`
9397
help: consider restricting type parameter `T` with trait `Unpin`
9498
|
9599
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {
@@ -103,6 +107,7 @@ LL | |x: &mut T| -> Pin<&T> { x };
103107
|
104108
= note: consider using the `pin!` macro
105109
consider using `Box::pin` if you need to access the pinned value outside of the current scope
110+
= note: required for the cast from `&mut T` to `Pin<&T>`
106111
help: consider restricting type parameter `T` with trait `Unpin`
107112
|
108113
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {
@@ -116,6 +121,7 @@ LL | |x: &T| -> Pin<&T> { x };
116121
|
117122
= note: consider using the `pin!` macro
118123
consider using `Box::pin` if you need to access the pinned value outside of the current scope
124+
= note: required for the cast from `&T` to `Pin<&T>`
119125
help: consider restricting type parameter `T` with trait `Unpin`
120126
|
121127
LL | fn ref_to_pin<T: std::marker::Unpin, U: Unpin>() {

0 commit comments

Comments
 (0)