about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs84
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--src/tools/miri/tests/pass/dyn-arbitrary-self.rs2
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.rs2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr36
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr12
-rw-r--r--tests/ui/inference/auxiliary/inference_unstable_iterator.rs2
-rw-r--r--tests/ui/inference/auxiliary/inference_unstable_itertools.rs2
-rw-r--r--tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs2
-rw-r--r--tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs2
14 files changed, 134 insertions, 34 deletions
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 4524458023d..4197c89c011 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -348,8 +348,10 @@ declare_features! (
     (unstable, adt_const_params, "1.56.0", Some(95174)),
     /// Allows defining an `#[alloc_error_handler]`.
     (unstable, alloc_error_handler, "1.29.0", Some(51540)),
-    /// Allows trait methods with arbitrary self types.
+    /// Allows inherent and trait methods with arbitrary self types.
     (unstable, arbitrary_self_types, "1.23.0", Some(44874)),
+    /// Allows inherent and trait methods with arbitrary self types that are raw pointers.
+    (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)),
     /// Enables experimental inline assembly support for additional architectures.
     (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
     /// Allows using `label` operands in inline assembly.
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index fb9bcc113c6..2ed31d837a8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1651,6 +1651,14 @@ fn check_fn_or_method<'tcx>(
     }
 }
 
+/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.
+#[derive(Clone, Copy)]
+enum ArbitrarySelfTypesLevel {
+    None,                       // neither arbitrary_self_types nor arbitrary_self_types_pointers
+    ArbitrarySelfTypes,         // just arbitrary_self_types
+    ArbitrarySelfTypesPointers, // both arbitrary_self_types and arbitrary_self_types_pointers
+}
+
 #[instrument(level = "debug", skip(wfcx))]
 fn check_method_receiver<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
@@ -1683,14 +1691,28 @@ fn check_method_receiver<'tcx>(
         return Ok(());
     }
 
-    if tcx.features().arbitrary_self_types {
-        if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
-            // Report error; `arbitrary_self_types` was enabled.
-            return Err(tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }));
-        }
+    let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers {
+        ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers
+    } else if tcx.features().arbitrary_self_types {
+        ArbitrarySelfTypesLevel::ArbitrarySelfTypes
     } else {
-        if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
-            return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
+        ArbitrarySelfTypesLevel::None
+    };
+
+    if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
+        return Err(match arbitrary_self_types_level {
+            // Wherever possible, emit a message advising folks that the features
+            // `arbitrary_self_types` or `arbitrary_self_types_pointers` might
+            // have helped.
+            ArbitrarySelfTypesLevel::None
+                if receiver_is_valid(
+                    wfcx,
+                    span,
+                    receiver_ty,
+                    self_ty,
+                    ArbitrarySelfTypesLevel::ArbitrarySelfTypes,
+                ) =>
+            {
                 // Report error; would have worked with `arbitrary_self_types`.
                 feature_err(
                     &tcx.sess,
@@ -1698,25 +1720,49 @@ fn check_method_receiver<'tcx>(
                     span,
                     format!(
                         "`{receiver_ty}` cannot be used as the type of `self` without \
-                         the `arbitrary_self_types` feature",
+                            the `arbitrary_self_types` feature",
                     ),
                 )
                 .with_help(fluent::hir_analysis_invalid_receiver_ty_help)
                 .emit()
-            } else {
-                // Report error; would not have worked with `arbitrary_self_types`.
+            }
+            ArbitrarySelfTypesLevel::ArbitrarySelfTypes | ArbitrarySelfTypesLevel::None
+                if receiver_is_valid(
+                    wfcx,
+                    span,
+                    receiver_ty,
+                    self_ty,
+                    ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers,
+                ) =>
+            {
+                // Report error; would have worked with `arbitrary_self_types_pointers`.
+                feature_err(
+                    &tcx.sess,
+                    sym::arbitrary_self_types_pointers,
+                    span,
+                    format!(
+                        "`{receiver_ty}` cannot be used as the type of `self` without \
+                            the `arbitrary_self_types_pointers` feature",
+                    ),
+                )
+                .with_help(fluent::hir_analysis_invalid_receiver_ty_help)
+                .emit()
+            }
+            _ =>
+            // Report error; would not have worked with `arbitrary_self_types[_pointers]`.
+            {
                 tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
-            });
-        }
+            }
+        });
     }
     Ok(())
 }
 
 /// Returns whether `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>`.
+/// through a `*const/mut T` raw pointer if  `arbitrary_self_types_pointers` is also enabled.
+/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement
+/// `Receiver` and directly implement `Deref<Target = self_ty>`.
 ///
 /// N.B., 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
@@ -1726,7 +1772,7 @@ fn receiver_is_valid<'tcx>(
     span: Span,
     receiver_ty: Ty<'tcx>,
     self_ty: Ty<'tcx>,
-    arbitrary_self_types_enabled: bool,
+    arbitrary_self_types_enabled: ArbitrarySelfTypesLevel,
 ) -> bool {
     let infcx = wfcx.infcx;
     let tcx = wfcx.tcx();
@@ -1744,8 +1790,8 @@ fn receiver_is_valid<'tcx>(
 
     let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
 
-    // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
-    if arbitrary_self_types_enabled {
+    // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
+    if matches!(arbitrary_self_types_enabled, ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers) {
         autoderef = autoderef.include_raw_pointers();
     }
 
@@ -1771,7 +1817,7 @@ fn receiver_is_valid<'tcx>(
 
         // Without `feature(arbitrary_self_types)`, we require that each step in the
         // deref chain implement `receiver`.
-        if !arbitrary_self_types_enabled {
+        if matches!(arbitrary_self_types_enabled, ArbitrarySelfTypesLevel::None) {
             if !receiver_is_implemented(
                 wfcx,
                 receiver_trait_def_id,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 28f537c87c4..e557cbf1701 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     mode,
                 }));
             } else if bad_ty.reached_raw_pointer
-                && !self.tcx.features().arbitrary_self_types
+                && !self.tcx.features().arbitrary_self_types_pointers
                 && !self.tcx.sess.at_least_rust_2018()
             {
                 // this case used to be allowed by the compiler,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2957105288b..84c87b62262 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -406,6 +406,7 @@ symbols! {
         append_const_msg,
         arbitrary_enum_discriminant,
         arbitrary_self_types,
+        arbitrary_self_types_pointers,
         args,
         arith_offset,
         arm,
diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
index 6be13b155f4..dc2b9e4491b 100644
--- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
+++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
@@ -1,6 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
+#![feature(arbitrary_self_types_pointers, unsize, coerce_unsized, dispatch_from_dyn)]
 #![feature(rustc_attrs)]
 
 fn pin_box_dyn() {
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs
index 4bb3b4cade5..1ddb8b71a5a 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.rs
+++ b/tests/mir-opt/building/receiver_ptr_mutability.rs
@@ -1,7 +1,7 @@
 // skip-filecheck
 // EMIT_MIR receiver_ptr_mutability.main.built.after.mir
 
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 struct Test {}
 
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs
index 96345de01c9..be2b89aab08 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs
@@ -2,7 +2,7 @@
 //
 // issue: <https://github.com/rust-lang/rust/issues/120217>
 
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 trait Static<'a> {
     fn proof(self: *const Self, s: &'a str) -> &'static str;
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs
new file mode 100644
index 00000000000..79ceb05662b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs
@@ -0,0 +1,15 @@
+trait Foo {
+    fn foo(self: *const Self); //~ ERROR `*const Self` cannot be used as the type of `self`
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(self: *const Self) {} //~ ERROR `*const Bar` cannot be used as the type of `self`
+}
+
+impl Bar {
+    fn bar(self: *mut Self) {} //~ ERROR `*mut Bar` cannot be used as the type of `self`
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
new file mode 100644
index 00000000000..3bb93cf2ea0
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
@@ -0,0 +1,36 @@
+error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:8:18
+   |
+LL |     fn foo(self: *const Self) {}
+   |                  ^^^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18
+   |
+LL |     fn bar(self: *mut Self) {}
+   |                  ^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18
+   |
+LL |     fn foo(self: *const Self);
+   |                  ^^^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
index 711025ff93b..856e0595331 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr
@@ -1,33 +1,33 @@
-error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18
    |
 LL |     fn foo(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
-   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18
    |
 LL |     fn bar(self: *const Self) {}
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
-   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
   --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18
    |
 LL |     fn bar(self: *const Self);
    |                  ^^^^^^^^^^^
    |
    = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
-   = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
diff --git a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs
index 04bc0b1a8ac..8ba6fc89f16 100644
--- a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs
+++ b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs
@@ -1,5 +1,5 @@
 #![feature(staged_api)]
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 #![stable(feature = "ipu_iterator", since = "1.0.0")]
 
diff --git a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs
index fa1efbcfefc..32ca3a45119 100644
--- a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs
+++ b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs
@@ -1,4 +1,4 @@
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 pub trait IpuItertools {
     fn ipu_flatten(&self) -> u32 {
diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs
index 1f45d91847f..7f76ed7fd2a 100644
--- a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs
+++ b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 use std::rc::Rc;
 
diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs
index 43f596659b9..6f34c9281b0 100644
--- a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs
+++ b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-#![feature(arbitrary_self_types)]
+#![feature(arbitrary_self_types_pointers)]
 
 use std::ptr;