about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-22 01:42:25 +0000
committerbors <bors@rust-lang.org>2018-12-22 01:42:25 +0000
commitabaa9344d4c10a45d7725534145007a8284dabe8 (patch)
tree274fef4b6785a676159957406e2dac3d76cbfb36
parenta9ff13562f1e7f0543e3bdc3949e21cf88c7b0a9 (diff)
parent286503ace2fd1fc8ac8bf8aa10378fb93763d99f (diff)
downloadrust-abaa9344d4c10a45d7725534145007a8284dabe8.tar.gz
rust-abaa9344d4c10a45d7725534145007a8284dabe8.zip
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.
-rw-r--r--src/liballoc/boxed.rs7
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs5
-rw-r--r--src/liballoc/sync.rs5
-rw-r--r--src/libcore/ops/deref.rs16
-rw-r--r--src/libcore/ops/mod.rs3
-rw-r--r--src/libcore/pin.rs5
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc_typeck/check/wfcheck.rs164
-rw-r--r--src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs20
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr24
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr6
-rw-r--r--src/test/ui/privacy/privacy1.rs14
-rw-r--r--src/test/ui/privacy/privacy1.stderr34
-rw-r--r--src/test/ui/span/issue-27522.rs2
-rw-r--r--src/test/ui/span/issue-27522.stderr4
-rw-r--r--src/test/ui/ufcs/ufcs-explicit-self-bad.rs6
-rw-r--r--src/test/ui/ufcs/ufcs-explicit-self-bad.stderr12
20 files changed, 244 insertions, 100 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 83adcce5c74..f1581310b48 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -77,7 +77,9 @@ use core::iter::{Iterator, FromIterator, FusedIterator};
 use core::marker::{Unpin, Unsize};
 use core::mem;
 use core::pin::Pin;
-use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState};
+use core::ops::{
+    CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
+};
 use core::ptr::{self, NonNull, Unique};
 use core::task::{LocalWaker, Poll};
 
@@ -583,6 +585,9 @@ impl<T: ?Sized> DerefMut for Box<T> {
     }
 }
 
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<T: ?Sized> Receiver for Box<T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator + ?Sized> Iterator for Box<I> {
     type Item = I::Item;
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index abacc62c856..e00e430fab6 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -104,6 +104,7 @@
 #![feature(ptr_internals)]
 #![feature(ptr_offset_from)]
 #![feature(rustc_attrs)]
+#![feature(receiver_trait)]
 #![feature(specialization)]
 #![feature(split_ascii_whitespace)]
 #![feature(staged_api)]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 6769a70ddbe..3fc70f4ac37 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -253,7 +253,7 @@ use core::intrinsics::abort;
 use core::marker;
 use core::marker::{Unpin, Unsize, PhantomData};
 use core::mem::{self, align_of_val, forget, size_of_val};
-use core::ops::Deref;
+use core::ops::{Deref, Receiver};
 use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
@@ -813,6 +813,9 @@ impl<T: ?Sized> Deref for Rc<T> {
     }
 }
 
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<T: ?Sized> Receiver for Rc<T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
     /// Drops the `Rc`.
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index e596694fb9d..55737016608 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -24,7 +24,7 @@ use core::fmt;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
 use core::mem::{self, align_of_val, size_of_val};
-use core::ops::Deref;
+use core::ops::{Deref, Receiver};
 use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
@@ -767,6 +767,9 @@ impl<T: ?Sized> Deref for Arc<T> {
     }
 }
 
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<T: ?Sized> Receiver for Arc<T> {}
+
 impl<T: Clone> Arc<T> {
     /// Makes a mutable reference into the given `Arc`.
     ///
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 91a3d77e8b2..ff836f4aa69 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -177,3 +177,19 @@ pub trait DerefMut: Deref {
 impl<T: ?Sized> DerefMut for &mut T {
     fn deref_mut(&mut self) -> &mut T { *self }
 }
+
+/// Indicates that a struct can be used as a method receiver, without the
+/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
+/// `Rc<T>`, `&T`, and `Pin<P>`.
+#[cfg_attr(not(stage0), lang = "receiver")]
+#[unstable(feature = "receiver_trait", issue = "0")]
+#[doc(hidden)]
+pub trait Receiver {
+    // Empty.
+}
+
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<T: ?Sized> Receiver for &T {}
+
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<T: ?Sized> Receiver for &mut T {}
diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs
index 785f0733df2..06740d2e4cd 100644
--- a/src/libcore/ops/mod.rs
+++ b/src/libcore/ops/mod.rs
@@ -178,6 +178,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::deref::{Deref, DerefMut};
 
+#[unstable(feature = "receiver_trait", issue = "0")]
+pub use self::deref::Receiver;
+
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::drop::Drop;
 
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 0ad6e8c7c1c..521ce9b5f6b 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -101,7 +101,7 @@
 
 use fmt;
 use marker::Sized;
-use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
+use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
 
 #[doc(inline)]
 pub use marker::Unpin;
@@ -302,6 +302,9 @@ where
     }
 }
 
+#[unstable(feature = "receiver_trait", issue = "0")]
+impl<P: Receiver> Receiver for Pin<P> {}
+
 #[unstable(feature = "pin", issue = "49150")]
 impl<P: fmt::Debug> fmt::Debug for Pin<P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 23ec24d71d2..cfcc7c83719 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -301,6 +301,7 @@ language_item_table! {
 
     DerefTraitLangItem,          "deref",              deref_trait,             Target::Trait;
     DerefMutTraitLangItem,       "deref_mut",          deref_mut_trait,         Target::Trait;
+    ReceiverTraitLangItem,       "receiver",           receiver_trait,          Target::Trait;
 
     FnTraitLangItem,             "fn",                 fn_trait,                Target::Trait;
     FnMutTraitLangItem,          "fn_mut",             fn_mut_trait,            Target::Trait;
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index e24548cfb23..e74b1ae47e3 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -13,9 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
 
 use hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable};
+use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, Substs};
-use rustc::ty::util::ExplicitSelf;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::middle::lang_items;
 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>,
         &ty::Binder::bind(self_ty)
     );
 
-    let self_arg_ty = sig.inputs()[0];
+    let receiver_ty = sig.inputs()[0];
 
-    let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-    let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
-    let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
+    let receiver_ty = fcx.normalize_associated_types_in(span, &receiver_ty);
+    let receiver_ty = fcx.tcx.liberate_late_bound_regions(
         method.def_id,
-        &ty::Binder::bind(self_arg_ty)
+        &ty::Binder::bind(receiver_ty)
     );
 
-    let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
+    if fcx.tcx.features().arbitrary_self_types {
+        if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
+            // report error, arbitrary_self_types was enabled
+            fcx.tcx.sess.diagnostic().mut_span_err(
+                span, &format!("invalid method receiver type: {:?}", receiver_ty)
+            ).note("type of `self` must be `Self` or a type that dereferences to it")
+            .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+            .code(DiagnosticId::Error("E0307".into()))
+            .emit();
+        }
+    } else {
+        if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
+            if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
+                // report error, would have worked with arbitrary_self_types
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,
+                    &format!(
+                        "`{}` cannot be used as the type of `self` without \
+                            the `arbitrary_self_types` feature",
+                        receiver_ty,
+                    ),
+                ).help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
+            } else {
+                // report error, would not have worked with arbitrary_self_types
+                fcx.tcx.sess.diagnostic().mut_span_err(
+                    span, &format!("invalid method receiver type: {:?}", receiver_ty)
+                ).note("type must be `Self` or a type that dereferences to it")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .code(DiagnosticId::Error("E0307".into()))
+                .emit();
+            }
+        }
+    }
+}
+
+/// returns true if `receiver_ty` would be considered a valid receiver type for `self_ty`. If
+/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
+/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
+/// strict: `receiver_ty` must implement `Receiver` and directly implement `Deref<Target=self_ty>`.
+///
+/// NB: there are cases this function returns `true` but causes an error to be emitted,
+/// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the
+/// wrong lifetime. Be careful of this if you are calling this function speculatively.
+fn receiver_is_valid<'fcx, 'tcx, 'gcx>(
+    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+    span: Span,
+    receiver_ty: Ty<'tcx>,
+    self_ty: Ty<'tcx>,
+    arbitrary_self_types_enabled: bool,
+) -> bool {
+    let cause = fcx.cause(span, traits::ObligationCauseCode::MethodReceiver);
+
+    let can_eq_self = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
+
+    // `self: Self` is always valid
+    if can_eq_self(receiver_ty) {
+        if let Some(mut err) = fcx.demand_eqtype_with_origin(&cause, self_ty, receiver_ty) {
+            err.emit();
+        }
+        return true
+    }
+
+    let mut autoderef = fcx.autoderef(span, receiver_ty);
+
+    // the `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`
+    if arbitrary_self_types_enabled {
+        autoderef = autoderef.include_raw_pointers();
+    }
+
+    // the first type is `receiver_ty`, which we know its not equal to `self_ty`. skip it.
+    autoderef.next();
 
+    // keep dereferencing `receiver_ty` until we get to `self_ty`
     loop {
         if let Some((potential_self_ty, _)) = autoderef.next() {
-            debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
+            debug!("receiver_is_valid: potential self type `{:?}` to match `{:?}`",
                 potential_self_ty, self_ty);
 
-            if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
+            if can_eq_self(potential_self_ty) {
                 autoderef.finalize(fcx);
+
                 if let Some(mut err) = fcx.demand_eqtype_with_origin(
-                    &cause, self_ty, potential_self_ty) {
+                    &cause, self_ty, potential_self_ty
+                ) {
                     err.emit();
                 }
+
                 break
             }
         } else {
-            fcx.tcx.sess.diagnostic().mut_span_err(
-                span, &format!("invalid `self` type: {:?}", self_arg_ty))
-            .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
-            .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-            .code(DiagnosticId::Error("E0307".into()))
-            .emit();
-            return
+            debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
+                receiver_ty, self_ty);
+            return false
+        }
+
+        // without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
+        // `self_ty`. Enforce this by only doing one iteration of the loop
+        if !arbitrary_self_types_enabled {
+            return false
         }
     }
 
-    let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
-    let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
+    // without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`
+    if !arbitrary_self_types_enabled {
+        let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
+            Some(did) => did,
+            None => {
+                debug!("receiver_is_valid: missing Receiver trait");
+                return false
+            }
+        };
 
-    if !fcx.tcx.features().arbitrary_self_types {
-        match self_kind {
-            ExplicitSelf::ByValue |
-            ExplicitSelf::ByReference(_, _) |
-            ExplicitSelf::ByBox => (),
+        let trait_ref = ty::TraitRef{
+            def_id: trait_def_id,
+            substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
+        };
 
-            ExplicitSelf::ByRawPointer(_) => {
-                feature_gate::feature_err(
-                    &fcx.tcx.sess.parse_sess,
-                    "arbitrary_self_types",
-                    span,
-                    GateIssue::Language,
-                    "raw pointer `self` is unstable")
-                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                .emit();
-            }
+        let obligation = traits::Obligation::new(
+            cause.clone(),
+            fcx.param_env,
+            trait_ref.to_predicate()
+        );
 
-            ExplicitSelf::Other => {
-                feature_gate::feature_err(
-                    &fcx.tcx.sess.parse_sess,
-                    "arbitrary_self_types",
-                    span,
-                    GateIssue::Language,"arbitrary `self` types are unstable")
-                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                .emit();
-            }
+        if !fcx.predicate_must_hold(&obligation) {
+            debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
+                receiver_ty);
+            return false
         }
     }
+
+    true
 }
 
 fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
index 80a7ce96911..6ec70bb8c09 100644
--- a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
+++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(arbitrary_self_types)]
 #![feature(pin)]
 #![feature(rustc_attrs)]
 
@@ -23,6 +22,7 @@ trait Trait {
     fn by_arc(self: Arc<Self>) -> i64;
     fn by_pin_mut(self: Pin<&mut Self>) -> i64;
     fn by_pin_box(self: Pin<Box<Self>>) -> i64;
+    fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64;
 }
 
 impl Trait for i64 {
@@ -38,6 +38,9 @@ impl Trait for i64 {
     fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
         *self
     }
+    fn by_pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> i64 {
+        *self
+    }
 }
 
 fn main() {
@@ -53,4 +56,8 @@ fn main() {
 
     let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
     assert_eq!(4, pin_box.by_pin_box());
+
+    let value = 5i64;
+    let pin_pin_pin_ref = Pin::new(Pin::new(Pin::new(&value))) as Pin<Pin<Pin<&dyn Trait>>>;
+    assert_eq!(5, pin_pin_pin_ref.by_pin_pin_pin_ref());
 }
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs
index ff0306f1993..84cd5c2bffa 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.rs
@@ -8,20 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rc::Rc;
+use std::{
+    ops::Deref,
+};
+
+struct Ptr<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized> Deref for Ptr<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.0
+    }
+}
 
 trait Foo {
-    fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
+    fn foo(self: Ptr<Self>); //~ ERROR `Ptr<Self>` cannot be used as the type of `self` without
 }
 
 struct Bar;
 
 impl Foo for Bar {
-    fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+    fn foo(self: Ptr<Self>) {} //~ ERROR `Ptr<Bar>` cannot be used as the type of `self` without
 }
 
 impl Bar {
-    fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+    fn bar(self: Box<Ptr<Self>>) {} //~ ERROR `std::boxed::Box<Ptr<Bar>>` cannot be used as the
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
index ea259aa22ad..c70774b3710 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary-self-types.stderr
@@ -1,26 +1,26 @@
-error[E0658]: arbitrary `self` types are unstable (see issue #44874)
-  --> $DIR/feature-gate-arbitrary-self-types.rs:14:18
+error[E0658]: `Ptr<Self>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:26:18
    |
-LL |     fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
-   |                  ^^^^^^^^^^^^^
+LL |     fn foo(self: Ptr<Self>); //~ ERROR `Ptr<Self>` cannot be used as the type of `self` without
+   |                  ^^^^^^^^^
    |
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: arbitrary `self` types are unstable (see issue #44874)
-  --> $DIR/feature-gate-arbitrary-self-types.rs:20:18
+error[E0658]: `Ptr<Bar>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:32:18
    |
-LL |     fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
-   |                  ^^^^^^^^^^^^^
+LL |     fn foo(self: Ptr<Self>) {} //~ ERROR `Ptr<Bar>` cannot be used as the type of `self` without
+   |                  ^^^^^^^^^
    |
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: arbitrary `self` types are unstable (see issue #44874)
-  --> $DIR/feature-gate-arbitrary-self-types.rs:24:18
+error[E0658]: `std::boxed::Box<Ptr<Bar>>` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:36:18
    |
-LL |     fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
-   |                  ^^^^^^^^^^^^^
+LL |     fn bar(self: Box<Ptr<Self>>) {} //~ ERROR `std::boxed::Box<Ptr<Bar>>` cannot be used as the
+   |                  ^^^^^^^^^^^^^^
    |
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs
index 29e51727edc..6d42460ba56 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs
@@ -12,17 +12,17 @@ struct Foo;
 
 impl Foo {
     fn foo(self: *const Self) {}
-    //~^ ERROR raw pointer `self` is unstable
+    //~^ ERROR `*const Foo` cannot be used as the type of `self` without
 }
 
 trait Bar {
     fn bar(self: *const Self);
-    //~^ ERROR raw pointer `self` is unstable
+    //~^ ERROR `*const Self` cannot be used as the type of `self` without
 }
 
 impl Bar for () {
     fn bar(self: *const Self) {}
-    //~^ ERROR raw pointer `self` is unstable
+    //~^ ERROR `*const ()` cannot be used as the type of `self` without
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index 5ed9a0f4ed0..b8cc7dee986 100644
--- a/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/src/test/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -1,4 +1,4 @@
-error[E0658]: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:19:18
    |
 LL |     fn bar(self: *const Self);
@@ -7,7 +7,7 @@ LL |     fn bar(self: *const Self);
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
    |
 LL |     fn foo(self: *const Self) {}
@@ -16,7 +16,7 @@ LL |     fn foo(self: *const Self) {}
    = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0658]: raw pointer `self` is unstable (see issue #44874)
+error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature (see issue #44874)
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:24:18
    |
 LL |     fn bar(self: *const Self) {}
diff --git a/src/test/ui/privacy/privacy1.rs b/src/test/ui/privacy/privacy1.rs
index 9aff4bbc41c..c336cc6299e 100644
--- a/src/test/ui/privacy/privacy1.rs
+++ b/src/test/ui/privacy/privacy1.rs
@@ -17,6 +17,20 @@ pub trait Sized {}
 #[lang="copy"]
 pub trait Copy {}
 
+#[lang="deref"]
+pub trait Deref {
+    type Target;
+}
+
+#[lang="receiver"]
+pub trait Receiver: Deref {}
+
+impl<'a, T> Deref for &'a T {
+    type Target = T;
+}
+
+impl<'a, T> Receiver for &'a T {}
+
 mod bar {
     // shouldn't bring in too much
     pub use self::glob::*;
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
index d6197575447..54e01cca6c4 100644
--- a/src/test/ui/privacy/privacy1.stderr
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -1,101 +1,101 @@
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:128:18
+  --> $DIR/privacy1.rs:142:18
    |
 LL |         use bar::baz::{foo, bar};
    |                  ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:136:18
+  --> $DIR/privacy1.rs:150:18
    |
 LL |         use bar::baz;
    |                  ^^^
 
 error[E0603]: module `i` is private
-  --> $DIR/privacy1.rs:160:20
+  --> $DIR/privacy1.rs:174:20
    |
 LL |     use self::foo::i::A; //~ ERROR: module `i` is private
    |                    ^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:100:16
+  --> $DIR/privacy1.rs:114:16
    |
 LL |         ::bar::baz::A::foo();   //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:101:16
+  --> $DIR/privacy1.rs:115:16
    |
 LL |         ::bar::baz::A::bar();   //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:103:16
+  --> $DIR/privacy1.rs:117:16
    |
 LL |         ::bar::baz::A.foo2();   //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:104:16
+  --> $DIR/privacy1.rs:118:16
    |
 LL |         ::bar::baz::A.bar2();   //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: trait `B` is private
-  --> $DIR/privacy1.rs:108:16
+  --> $DIR/privacy1.rs:122:16
    |
 LL |         ::bar::B::foo();        //~ ERROR: trait `B` is private
    |                ^
 
 error[E0603]: function `epriv` is private
-  --> $DIR/privacy1.rs:114:20
+  --> $DIR/privacy1.rs:128:20
    |
 LL |             ::bar::epriv(); //~ ERROR: function `epriv` is private
    |                    ^^^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:123:16
+  --> $DIR/privacy1.rs:137:16
    |
 LL |         ::bar::baz::foo(); //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: module `baz` is private
-  --> $DIR/privacy1.rs:124:16
+  --> $DIR/privacy1.rs:138:16
    |
 LL |         ::bar::baz::bar(); //~ ERROR: module `baz` is private
    |                ^^^
 
 error[E0603]: trait `B` is private
-  --> $DIR/privacy1.rs:152:17
+  --> $DIR/privacy1.rs:166:17
    |
 LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
    |                 ^
 
 error[E0624]: method `bar` is private
-  --> $DIR/privacy1.rs:73:9
+  --> $DIR/privacy1.rs:87:9
    |
 LL |         self::baz::A::bar(); //~ ERROR: method `bar` is private
    |         ^^^^^^^^^^^^^^^^^
 
 error[E0624]: method `bar` is private
-  --> $DIR/privacy1.rs:91:5
+  --> $DIR/privacy1.rs:105:5
    |
 LL |     bar::A::bar(); //~ ERROR: method `bar` is private
    |     ^^^^^^^^^^^
 
 error[E0624]: method `bar` is private
-  --> $DIR/privacy1.rs:98:9
+  --> $DIR/privacy1.rs:112:9
    |
 LL |         ::bar::A::bar();        //~ ERROR: method `bar` is private
    |         ^^^^^^^^^^^^^
 
 error[E0624]: method `bar` is private
-  --> $DIR/privacy1.rs:101:9
+  --> $DIR/privacy1.rs:115:9
    |
 LL |         ::bar::baz::A::bar();   //~ ERROR: module `baz` is private
    |         ^^^^^^^^^^^^^^^^^^
 
 error[E0624]: method `bar2` is private
-  --> $DIR/privacy1.rs:104:23
+  --> $DIR/privacy1.rs:118:23
    |
 LL |         ::bar::baz::A.bar2();   //~ ERROR: module `baz` is private
    |                       ^^^^
diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs
index 1e3eba4bf36..11c90833e71 100644
--- a/src/test/ui/span/issue-27522.rs
+++ b/src/test/ui/span/issue-27522.rs
@@ -13,7 +13,7 @@
 struct SomeType {}
 
 trait Foo {
-    fn handler(self: &SomeType); //~ ERROR invalid `self` type
+    fn handler(self: &SomeType); //~ ERROR invalid method receiver type
 }
 
 fn main() {}
diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr
index 9b61ecae651..767b99a92cb 100644
--- a/src/test/ui/span/issue-27522.stderr
+++ b/src/test/ui/span/issue-27522.stderr
@@ -1,7 +1,7 @@
-error[E0307]: invalid `self` type: &SomeType
+error[E0307]: invalid method receiver type: &SomeType
   --> $DIR/issue-27522.rs:16:22
    |
-LL |     fn handler(self: &SomeType); //~ ERROR invalid `self` type
+LL |     fn handler(self: &SomeType); //~ ERROR invalid method receiver type
    |                      ^^^^^^^^^
    |
    = note: type must be `Self` or a type that dereferences to it
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
index a0d1f2dc331..f87541b56ac 100644
--- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs
@@ -16,7 +16,7 @@ struct Foo {
 
 impl Foo {
     fn foo(self: isize, x: isize) -> isize {
-        //~^ ERROR invalid `self` type
+        //~^ ERROR invalid method receiver type
         self.f + x
     }
 }
@@ -27,11 +27,11 @@ struct Bar<T> {
 
 impl<T> Bar<T> {
     fn foo(self: Bar<isize>, x: isize) -> isize {
-        //~^ ERROR invalid `self` type
+        //~^ ERROR invalid method receiver type
         x
     }
     fn bar(self: &Bar<usize>, x: isize) -> isize {
-        //~^ ERROR invalid `self` type
+        //~^ ERROR invalid method receiver type
         x
     }
 }
diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
index fce74605cad..a229dabcce4 100644
--- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -1,28 +1,28 @@
-error[E0307]: invalid `self` type: isize
+error[E0307]: invalid method receiver type: isize
   --> $DIR/ufcs-explicit-self-bad.rs:18:18
    |
 LL |     fn foo(self: isize, x: isize) -> isize {
    |                  ^^^^^
    |
-   = note: type must be `Foo` or a type that dereferences to it
+   = note: type must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0307]: invalid `self` type: Bar<isize>
+error[E0307]: invalid method receiver type: Bar<isize>
   --> $DIR/ufcs-explicit-self-bad.rs:29:18
    |
 LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
    |                  ^^^^^^^^^^
    |
-   = note: type must be `Bar<T>` or a type that dereferences to it
+   = note: type must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
-error[E0307]: invalid `self` type: &Bar<usize>
+error[E0307]: invalid method receiver type: &Bar<usize>
   --> $DIR/ufcs-explicit-self-bad.rs:33:18
    |
 LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
    |                  ^^^^^^^^^^^
    |
-   = note: type must be `Bar<T>` or a type that dereferences to it
+   = note: type must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
 
 error[E0308]: mismatched method receiver