pin_ergonomics: allow reborrowing as Pin<&T>
This commit is contained in:
parent
92a5d21bc4
commit
a18800f807
5 changed files with 70 additions and 15 deletions
|
@ -798,9 +798,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
// Right now we can only reborrow if this is a `Pin<&mut T>`.
|
// Right now we can only reborrow if this is a `Pin<&mut T>`.
|
||||||
let extract_pin_mut = |ty: Ty<'tcx>| {
|
let extract_pin_mut = |ty: Ty<'tcx>| {
|
||||||
// Get the T out of Pin<T>
|
// Get the T out of Pin<T>
|
||||||
let ty = match ty.kind() {
|
let (pin, ty) = match ty.kind() {
|
||||||
ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => {
|
ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => {
|
||||||
args[0].expect_ty()
|
(*pin, args[0].expect_ty())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!("can't reborrow {:?} as pinned", ty);
|
debug!("can't reborrow {:?} as pinned", ty);
|
||||||
|
@ -809,7 +809,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
};
|
};
|
||||||
// Make sure the T is something we understand (just `&mut U` for now)
|
// Make sure the T is something we understand (just `&mut U` for now)
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Ref(region, ty, ty::Mutability::Mut) => Ok((*region, *ty)),
|
ty::Ref(region, ty, mutbl) => Ok((pin, *region, *ty, *mutbl)),
|
||||||
_ => {
|
_ => {
|
||||||
debug!("can't reborrow pin of inner type {:?}", ty);
|
debug!("can't reborrow pin of inner type {:?}", ty);
|
||||||
Err(TypeError::Mismatch)
|
Err(TypeError::Mismatch)
|
||||||
|
@ -817,16 +817,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, _a_ty) = extract_pin_mut(a)?;
|
let (pin, a_region, a_ty, mut_a) = extract_pin_mut(a)?;
|
||||||
let (b_region, _b_ty) = extract_pin_mut(b)?;
|
let (_, b_region, _b_ty, mut_b) = extract_pin_mut(b)?;
|
||||||
|
|
||||||
|
coerce_mutbls(mut_a, mut_b)?;
|
||||||
|
|
||||||
|
// update a with b's mutability since we'll be coercing mutability
|
||||||
|
let a = Ty::new_adt(
|
||||||
|
self.tcx,
|
||||||
|
pin,
|
||||||
|
self.tcx.mk_args(&[Ty::new_ref(self.tcx, a_region, a_ty, mut_b).into()]),
|
||||||
|
);
|
||||||
|
|
||||||
// To complete the reborrow, we need to make sure we can unify the inner types, and if so we
|
// To complete the reborrow, we need to make sure we can unify the inner types, and if so we
|
||||||
// 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(b_region, mut_b), target: b }]
|
||||||
kind: Adjust::ReborrowPin(b_region, hir::Mutability::Mut),
|
|
||||||
target: b,
|
|
||||||
}]
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,22 +181,25 @@ impl<'tcx> Cx<'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// expr = &mut target
|
// expr = &mut target
|
||||||
|
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, region, ptr_target_ty, mutbl);
|
||||||
let expr = self.thir.exprs.push(Expr {
|
let expr = self.thir.exprs.push(Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl),
|
ty: new_pin_target,
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow { borrow_kind, arg },
|
||||||
borrow_kind: BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
|
||||||
arg,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// kind = Pin { __pointer: pointer }
|
// kind = Pin { __pointer: pointer }
|
||||||
let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
|
let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
|
||||||
|
let args = self.tcx.mk_args(&[new_pin_target.into()]);
|
||||||
let kind = ExprKind::Adt(Box::new(AdtExpr {
|
let kind = ExprKind::Adt(Box::new(AdtExpr {
|
||||||
adt_def: self.tcx.adt_def(pin_did),
|
adt_def: self.tcx.adt_def(pin_did),
|
||||||
variant_index: FIRST_VARIANT,
|
variant_index: FIRST_VARIANT,
|
||||||
args: pin_ty_args,
|
args,
|
||||||
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
|
fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
base: None,
|
base: None,
|
||||||
|
|
|
@ -15,6 +15,9 @@ impl Foo {
|
||||||
fn foo(_: Pin<&mut Foo>) {
|
fn foo(_: Pin<&mut Foo>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn foo_const(_: Pin<&Foo>) {
|
||||||
|
}
|
||||||
|
|
||||||
fn bar(x: Pin<&mut Foo>) {
|
fn bar(x: Pin<&mut Foo>) {
|
||||||
foo(x);
|
foo(x);
|
||||||
foo(x); // for this to work we need to automatically reborrow,
|
foo(x); // for this to work we need to automatically reborrow,
|
||||||
|
@ -22,6 +25,12 @@ fn bar(x: Pin<&mut Foo>) {
|
||||||
|
|
||||||
Foo::baz(x);
|
Foo::baz(x);
|
||||||
Foo::baz(x);
|
Foo::baz(x);
|
||||||
|
|
||||||
|
foo_const(x); // make sure we can reborrow &mut as &.
|
||||||
|
|
||||||
|
let x: Pin<&Foo> = Pin::new(&Foo);
|
||||||
|
|
||||||
|
foo_const(x); // make sure reborrowing from & to & works.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
18
tests/ui/async-await/pin-reborrow-const-as-mut.rs
Normal file
18
tests/ui/async-await/pin-reborrow-const-as-mut.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#![feature(pin_ergonomics)]
|
||||||
|
#![allow(dead_code, incomplete_features)]
|
||||||
|
|
||||||
|
// make sure we can't accidentally reborrow Pin<&T> as Pin<&mut T>
|
||||||
|
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
fn foo(_: Pin<&mut Foo>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar(x: Pin<&Foo>) {
|
||||||
|
foo(x); //~ ERROR mismatched types
|
||||||
|
//| ERROR types differ in mutability
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
19
tests/ui/async-await/pin-reborrow-const-as-mut.stderr
Normal file
19
tests/ui/async-await/pin-reborrow-const-as-mut.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/pin-reborrow-const-as-mut.rs:14:9
|
||||||
|
|
|
||||||
|
LL | foo(x);
|
||||||
|
| --- ^ types differ in mutability
|
||||||
|
| |
|
||||||
|
| arguments to this function are incorrect
|
||||||
|
|
|
||||||
|
= note: expected struct `Pin<&mut Foo>`
|
||||||
|
found struct `Pin<&Foo>`
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/pin-reborrow-const-as-mut.rs:10:4
|
||||||
|
|
|
||||||
|
LL | fn foo(_: Pin<&mut Foo>) {
|
||||||
|
| ^^^ ----------------
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue