diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0b44071496ea8..637282b0b8745 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1735,7 +1735,6 @@ symbols! {
         unsafe_cell,
         unsafe_cell_raw_get,
         unsafe_no_drop_flag,
-        unsafe_pin_internals,
         unsize,
         unsized_fn_params,
         unsized_locals,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 7d8c881eab809..a35db27149c59 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -407,14 +407,7 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
 #[repr(transparent)]
 #[derive(Copy, Clone)]
 pub struct Pin<P> {
-    // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
-    //   - deter downstream users from accessing it (which would be unsound!),
-    //   - let the `pin!` macro access it (such a macro requires using struct
-    //     literal syntax in order to benefit from lifetime extension).
-    // Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives.
-    #[unstable(feature = "unsafe_pin_internals", issue = "none")]
-    #[doc(hidden)]
-    pub pointer: P,
+    pointer: P,
 }
 
 // The following implementations aren't derived in order to avoid soundness
@@ -1173,8 +1166,6 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 ///
 /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
 #[stable(feature = "pin_macro", since = "1.68.0")]
-#[rustc_macro_transparency = "semitransparent"]
-#[allow_internal_unstable(unsafe_pin_internals)]
 pub macro pin($value:expr $(,)?) {
     // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
     // review such a hypothetical macro (that any user-code could define):
@@ -1246,5 +1237,16 @@ pub macro pin($value:expr $(,)?) {
     //
     // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
     // for more info.
-    $crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
+    //
+    // # Avoiding coercion
+    //
+    // We need to explicitly constrain the pointer type to avoid (unsound) coercion. Otherwise, you
+    // could write code like
+    // ```rust
+    // let rc = Rc::new(PhantomPinned);
+    // { let _pinned: Pin<&PhantomPinned> = pin!(rc.clone()); }
+    // let moved = Rc::into_inner(rc).unwrap();
+    // ```
+    // since the `&mut Rc` is coerced to a `&PhantomPinned`.
+    Pin::<&mut _> { pointer: &mut { $value } }
 }
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
index 6f617c8d0c297..ebebe387dff26 100644
--- a/library/core/tests/pin.rs
+++ b/library/core/tests/pin.rs
@@ -29,3 +29,14 @@ fn pin_const() {
 
     pin_mut_const();
 }
+
+#[test]
+fn dont_shadow() {
+    // test that the pointer field does not shadow fields of the pinned data.
+
+    struct Pinned {
+        pointer: i32,
+    }
+
+    let _: i32 = Pin::new(&mut Pinned { pointer: 0 }).pointer;
+}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
deleted file mode 100644
index 134ea25b75afb..0000000000000
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// edition:2018
-#![forbid(internal_features, unsafe_code)]
-#![feature(unsafe_pin_internals)]
-//~^ ERROR the feature `unsafe_pin_internals` is internal to the compiler or standard library
-
-use core::{marker::PhantomPinned, pin::Pin};
-
-/// The `unsafe_pin_internals` is indeed unsound.
-fn non_unsafe_pin_new_unchecked<T>(pointer: &mut T) -> Pin<&mut T> {
-    Pin { pointer }
-}
-
-fn main() {
-    let mut self_referential = PhantomPinned;
-    let _: Pin<&mut PhantomPinned> = non_unsafe_pin_new_unchecked(&mut self_referential);
-}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr
deleted file mode 100644
index fc9bcd90e52ee..0000000000000
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: the feature `unsafe_pin_internals` is internal to the compiler or standard library
-  --> $DIR/feature-gate-unsafe_pin_internals.rs:3:12
-   |
-LL | #![feature(unsafe_pin_internals)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: using it is strongly discouraged
-note: the lint level is defined here
-  --> $DIR/feature-gate-unsafe_pin_internals.rs:2:11
-   |
-LL | #![forbid(internal_features, unsafe_code)]
-   |           ^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs
index 5826a18b5718b..fbbaa5ccf6075 100644
--- a/tests/ui/pin-macro/cant_access_internals.rs
+++ b/tests/ui/pin-macro/cant_access_internals.rs
@@ -8,5 +8,5 @@ use core::{
 
 fn main() {
     let mut phantom_pinned = pin!(PhantomPinned);
-    mem::take(phantom_pinned.pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
+    mem::take(phantom_pinned.pointer); //~ ERROR field `pointer` of struct `Pin` is private
 }
diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr
index 9af1cd2a16c93..6f12b2c0a6126 100644
--- a/tests/ui/pin-macro/cant_access_internals.stderr
+++ b/tests/ui/pin-macro/cant_access_internals.stderr
@@ -1,11 +1,9 @@
-error[E0658]: use of unstable library feature 'unsafe_pin_internals'
-  --> $DIR/cant_access_internals.rs:11:15
+error[E0616]: field `pointer` of struct `Pin` is private
+  --> $DIR/cant_access_internals.rs:11:30
    |
 LL |     mem::take(phantom_pinned.pointer);
-   |               ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable
+   |                              ^^^^^^^ private field
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0616`.