Skip to content

Commit abaa934

Browse files
committed
Auto merge of #56805 - mikeyhew:stabilize-pin-as-receiver, r=nikomatsakis
Stabilize `Rc`, `Arc` and `Pin` as method receivers Replaces #55880 Closes #55786 r? @nikomatsakis cc @withoutboats @cramertj This lets you write methods using `self: Rc<Self>`, `self: Arc<Self>`, `self: Pin<&mut Self>`, `self: Pin<Box<Self>`, and other combinations involving `Pin` and another stdlib receiver type, without needing the `arbitrary_self_types`. Other user-created receiver types can be used, but they still require the feature flag to use. This is implemented by introducing a new trait, `Receiver`, which the method receiver's type must implement if the `arbitrary_self_types` feature is not enabled. To keep composed receiver types such as `&Arc<Self>` unstable, the receiver type is also required to implement `Deref<Target=Self>` when the feature flag is not enabled. This lets you use `self: Rc<Self>` and `self: Arc<Self>` in stable Rust, which was not allowed previously. It was agreed that they would be stabilized in #55786. `self: Pin<&Self>` and other pinned receiver types do not require the `arbitrary_self_types` feature, but they cannot be used on stable because `Pin` still requires the `pin` feature.
2 parents a9ff135 + 286503a commit abaa934

20 files changed

+244
-100
lines changed

src/liballoc/boxed.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ use core::iter::{Iterator, FromIterator, FusedIterator};
7777
use core::marker::{Unpin, Unsize};
7878
use core::mem;
7979
use core::pin::Pin;
80-
use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState};
80+
use core::ops::{
81+
CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
82+
};
8183
use core::ptr::{self, NonNull, Unique};
8284
use core::task::{LocalWaker, Poll};
8385

@@ -583,6 +585,9 @@ impl<T: ?Sized> DerefMut for Box<T> {
583585
}
584586
}
585587

588+
#[unstable(feature = "receiver_trait", issue = "0")]
589+
impl<T: ?Sized> Receiver for Box<T> {}
590+
586591
#[stable(feature = "rust1", since = "1.0.0")]
587592
impl<I: Iterator + ?Sized> Iterator for Box<I> {
588593
type Item = I::Item;

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#![feature(ptr_internals)]
105105
#![feature(ptr_offset_from)]
106106
#![feature(rustc_attrs)]
107+
#![feature(receiver_trait)]
107108
#![feature(specialization)]
108109
#![feature(split_ascii_whitespace)]
109110
#![feature(staged_api)]

src/liballoc/rc.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ use core::intrinsics::abort;
253253
use core::marker;
254254
use core::marker::{Unpin, Unsize, PhantomData};
255255
use core::mem::{self, align_of_val, forget, size_of_val};
256-
use core::ops::Deref;
256+
use core::ops::{Deref, Receiver};
257257
use core::ops::{CoerceUnsized, DispatchFromDyn};
258258
use core::pin::Pin;
259259
use core::ptr::{self, NonNull};
@@ -813,6 +813,9 @@ impl<T: ?Sized> Deref for Rc<T> {
813813
}
814814
}
815815

816+
#[unstable(feature = "receiver_trait", issue = "0")]
817+
impl<T: ?Sized> Receiver for Rc<T> {}
818+
816819
#[stable(feature = "rust1", since = "1.0.0")]
817820
unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
818821
/// Drops the `Rc`.

src/liballoc/sync.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use core::fmt;
2424
use core::cmp::Ordering;
2525
use core::intrinsics::abort;
2626
use core::mem::{self, align_of_val, size_of_val};
27-
use core::ops::Deref;
27+
use core::ops::{Deref, Receiver};
2828
use core::ops::{CoerceUnsized, DispatchFromDyn};
2929
use core::pin::Pin;
3030
use core::ptr::{self, NonNull};
@@ -767,6 +767,9 @@ impl<T: ?Sized> Deref for Arc<T> {
767767
}
768768
}
769769

770+
#[unstable(feature = "receiver_trait", issue = "0")]
771+
impl<T: ?Sized> Receiver for Arc<T> {}
772+
770773
impl<T: Clone> Arc<T> {
771774
/// Makes a mutable reference into the given `Arc`.
772775
///

src/libcore/ops/deref.rs

+16
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,19 @@ pub trait DerefMut: Deref {
177177
impl<T: ?Sized> DerefMut for &mut T {
178178
fn deref_mut(&mut self) -> &mut T { *self }
179179
}
180+
181+
/// Indicates that a struct can be used as a method receiver, without the
182+
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
183+
/// `Rc<T>`, `&T`, and `Pin<P>`.
184+
#[cfg_attr(not(stage0), lang = "receiver")]
185+
#[unstable(feature = "receiver_trait", issue = "0")]
186+
#[doc(hidden)]
187+
pub trait Receiver {
188+
// Empty.
189+
}
190+
191+
#[unstable(feature = "receiver_trait", issue = "0")]
192+
impl<T: ?Sized> Receiver for &T {}
193+
194+
#[unstable(feature = "receiver_trait", issue = "0")]
195+
impl<T: ?Sized> Receiver for &mut T {}

src/libcore/ops/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig
178178
#[stable(feature = "rust1", since = "1.0.0")]
179179
pub use self::deref::{Deref, DerefMut};
180180

181+
#[unstable(feature = "receiver_trait", issue = "0")]
182+
pub use self::deref::Receiver;
183+
181184
#[stable(feature = "rust1", since = "1.0.0")]
182185
pub use self::drop::Drop;
183186

src/libcore/pin.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101

102102
use fmt;
103103
use marker::Sized;
104-
use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
104+
use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
105105

106106
#[doc(inline)]
107107
pub use marker::Unpin;
@@ -302,6 +302,9 @@ where
302302
}
303303
}
304304

305+
#[unstable(feature = "receiver_trait", issue = "0")]
306+
impl<P: Receiver> Receiver for Pin<P> {}
307+
305308
#[unstable(feature = "pin", issue = "49150")]
306309
impl<P: fmt::Debug> fmt::Debug for Pin<P> {
307310
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

src/librustc/middle/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ language_item_table! {
301301

302302
DerefTraitLangItem, "deref", deref_trait, Target::Trait;
303303
DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait;
304+
ReceiverTraitLangItem, "receiver", receiver_trait, Target::Trait;
304305

305306
FnTraitLangItem, "fn", fn_trait, Target::Trait;
306307
FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait;

src/librustc_typeck/check/wfcheck.rs

+120-44
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
1313

1414
use hir::def_id::DefId;
1515
use rustc::traits::{self, ObligationCauseCode};
16-
use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable};
16+
use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
1717
use rustc::ty::subst::{Subst, Substs};
18-
use rustc::ty::util::ExplicitSelf;
1918
use rustc::util::nodemap::{FxHashSet, FxHashMap};
2019
use rustc::middle::lang_items;
2120
use rustc::infer::opaque_types::may_define_existential_type;
@@ -749,72 +748,149 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
749748
&ty::Binder::bind(self_ty)
750749
);
751750

752-
let self_arg_ty = sig.inputs()[0];
751+
let receiver_ty = sig.inputs()[0];
753752

754-
let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
755-
let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
756-
let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
753+
let receiver_ty = fcx.normalize_associated_types_in(span, &receiver_ty);
754+
let receiver_ty = fcx.tcx.liberate_late_bound_regions(
757755
method.def_id,
758-
&ty::Binder::bind(self_arg_ty)
756+
&ty::Binder::bind(receiver_ty)
759757
);
760758

761-
let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
759+
if fcx.tcx.features().arbitrary_self_types {
760+
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
761+
// report error, arbitrary_self_types was enabled
762+
fcx.tcx.sess.diagnostic().mut_span_err(
763+
span, &format!("invalid method receiver type: {:?}", receiver_ty)
764+
).note("type of `self` must be `Self` or a type that dereferences to it")
765+
.help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
766+
.code(DiagnosticId::Error("E0307".into()))
767+
.emit();
768+
}
769+
} else {
770+
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
771+
if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
772+
// report error, would have worked with arbitrary_self_types
773+
feature_gate::feature_err(
774+
&fcx.tcx.sess.parse_sess,
775+
"arbitrary_self_types",
776+
span,
777+
GateIssue::Language,
778+
&format!(
779+
"`{}` cannot be used as the type of `self` without \
780+
the `arbitrary_self_types` feature",
781+
receiver_ty,
782+
),
783+
).help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
784+
.emit();
785+
} else {
786+
// report error, would not have worked with arbitrary_self_types
787+
fcx.tcx.sess.diagnostic().mut_span_err(
788+
span, &format!("invalid method receiver type: {:?}", receiver_ty)
789+
).note("type must be `Self` or a type that dereferences to it")
790+
.help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
791+
.code(DiagnosticId::Error("E0307".into()))
792+
.emit();
793+
}
794+
}
795+
}
796+
}
797+
798+
/// returns true if `receiver_ty` would be considered a valid receiver type for `self_ty`. If
799+
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
800+
/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
801+
/// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref<Target=self_ty>`.
802+
///
803+
/// NB: there are cases this function returns `true` but causes an error to be emitted,
804+
/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
805+
/// wrong lifetime. Be careful of this if you are calling this function speculatively.
806+
fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
807+
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
808+
span: Span,
809+
receiver_ty: Ty<'tcx>,
810+
self_ty: Ty<'tcx>,
811+
arbitrary_self_types_enabled: bool,
812+
) -> bool {
813+
let cause = fcx.cause(span, traits::ObligationCauseCode::MethodReceiver);
814+
815+
let can_eq_self = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
816+
817+
// `self: Self` is always valid
818+
if can_eq_self(receiver_ty) {
819+
if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, receiver_ty) {
820+
err.emit();
821+
}
822+
return true
823+
}
824+
825+
let mut autoderef = fcx.autoderef(span, receiver_ty);
826+
827+
// the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`
828+
if arbitrary_self_types_enabled {
829+
autoderef = autoderef.include_raw_pointers();
830+
}
831+
832+
// the first type is `receiver_ty`, which we know its not equal to `self_ty`. skip it.
833+
autoderef.next();
762834

835+
// keep dereferencing `receiver_ty` until we get to `self_ty`
763836
loop {
764837
if let Some((potential_self_ty, _)) = autoderef.next() {
765-
debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
838+
debug!("receiver_is_valid: potential self type `{:?}` to match `{:?}`",
766839
potential_self_ty, self_ty);
767840

768-
if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
841+
if can_eq_self(potential_self_ty) {
769842
autoderef.finalize(fcx);
843+
770844
if let Some(mut err) = fcx.demand_eqtype_with_origin(
771-
&cause, self_ty, potential_self_ty) {
845+
&cause, self_ty, potential_self_ty
846+
) {
772847
err.emit();
773848
}
849+
774850
break
775851
}
776852
} else {
777-
fcx.tcx.sess.diagnostic().mut_span_err(
778-
span, &format!("invalid `self` type: {:?}", self_arg_ty))
779-
.note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
780-
.help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
781-
.code(DiagnosticId::Error("E0307".into()))
782-
.emit();
783-
return
853+
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
854+
receiver_ty, self_ty);
855+
return false
856+
}
857+
858+
// without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
859+
// `self_ty`. Enforce this by only doing one iteration of the loop
860+
if !arbitrary_self_types_enabled {
861+
return false
784862
}
785863
}
786864

787-
let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
788-
let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
865+
// without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`
866+
if !arbitrary_self_types_enabled {
867+
let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
868+
Some(did) => did,
869+
None => {
870+
debug!("receiver_is_valid: missing Receiver trait");
871+
return false
872+
}
873+
};
789874

790-
if !fcx.tcx.features().arbitrary_self_types {
791-
match self_kind {
792-
ExplicitSelf::ByValue |
793-
ExplicitSelf::ByReference(_, _) |
794-
ExplicitSelf::ByBox => (),
875+
let trait_ref = ty::TraitRef{
876+
def_id: trait_def_id,
877+
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
878+
};
795879

796-
ExplicitSelf::ByRawPointer(_) => {
797-
feature_gate::feature_err(
798-
&fcx.tcx.sess.parse_sess,
799-
"arbitrary_self_types",
800-
span,
801-
GateIssue::Language,
802-
"raw pointer `self` is unstable")
803-
.help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
804-
.emit();
805-
}
880+
let obligation = traits::Obligation::new(
881+
cause.clone(),
882+
fcx.param_env,
883+
trait_ref.to_predicate()
884+
);
806885

807-
ExplicitSelf::Other => {
808-
feature_gate::feature_err(
809-
&fcx.tcx.sess.parse_sess,
810-
"arbitrary_self_types",
811-
span,
812-
GateIssue::Language,"arbitrary `self` types are unstable")
813-
.help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
814-
.emit();
815-
}
886+
if !fcx.predicate_must_hold(&obligation) {
887+
debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
888+
receiver_ty);
889+
return false
816890
}
817891
}
892+
893+
true
818894
}
819895

820896
fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![feature(arbitrary_self_types)]
1211
#![feature(pin)]
1312
#![feature(rustc_attrs)]
1413

@@ -23,6 +22,7 @@ trait Trait {
2322
fn by_arc(self: Arc<Self>) -> i64;
2423
fn by_pin_mut(self: Pin<&mut Self>) -> i64;
2524
fn by_pin_box(self: Pin<Box<Self>>) -> i64;
25+
fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64;
2626
}
2727

2828
impl Trait for i64 {
@@ -38,6 +38,9 @@ impl Trait for i64 {
3838
fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
3939
*self
4040
}
41+
fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64 {
42+
*self
43+
}
4144
}
4245

4346
fn main() {
@@ -53,4 +56,8 @@ fn main() {
5356

5457
let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
5558
assert_eq!(4, pin_box.by_pin_box());
59+
60+
let value = 5i64;
61+
let pin_pin_pin_ref = Pin::new(Pin::new(Pin::new(&value))) as Pin<Pin<Pin<&dyn Trait>>>;
62+
assert_eq!(5, pin_pin_pin_ref.by_pin_pin_pin_ref());
5663
}

src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,32 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::rc::Rc;
11+
use std::{
12+
ops::Deref,
13+
};
14+
15+
struct Ptr<T: ?Sized>(Box<T>);
16+
17+
impl<T: ?Sized> Deref for Ptr<T> {
18+
type Target = T;
19+
20+
fn deref(&self) -> &T {
21+
&*self.0
22+
}
23+
}
1224

1325
trait Foo {
14-
fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
26+
fn foo(self: Ptr<Self>); //~ ERROR `Ptr<Self>` cannot be used as the type of `self` without
1527
}
1628

1729
struct Bar;
1830

1931
impl Foo for Bar {
20-
fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
32+
fn foo(self: Ptr<Self>) {} //~ ERROR `Ptr<Bar>` cannot be used as the type of `self` without
2133
}
2234

2335
impl Bar {
24-
fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
36+
fn bar(self: Box<Ptr<Self>>) {} //~ ERROR `std::boxed::Box<Ptr<Bar>>` cannot be used as the
2537
}
2638

2739
fn main() {}

0 commit comments

Comments
 (0)