diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index 0140fb752bf92..e22a523dbc3ef 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -1,6 +1,6 @@
 //! The AST pointer.
 //!
-//! Provides `P<T>`, a frozen owned smart pointer.
+//! Provides [`P<T>`][struct@P], an owned smart pointer.
 //!
 //! # Motivations and benefits
 //!
@@ -8,18 +8,14 @@
 //!   passes (e.g., one may be able to bypass the borrow checker with a shared
 //!   `ExprKind::AddrOf` node taking a mutable borrow).
 //!
-//! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
-//!   (unless it contains an `Unsafe` interior, but that may be denied later).
-//!   This mainly prevents mistakes, but also enforces a kind of "purity".
-//!
 //! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
 //!   the latter even when the input and output types differ (as it would be the
 //!   case with arenas or a GADT AST using type parameters to toggle features).
 //!
-//! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
-//!   `and_then` and `map` - which can remain fully functional even if the
-//!   implementation changes (using a special thread-local heap, for example).
-//!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.
+//! * **Maintainability**: `P<T>` provides an interface, which can remain fully
+//!   functional even if the implementation changes (using a special thread-local
+//!   heap, for example). Moreover, a switch to, e.g., `P<'a, T>` would be easy
+//!   and mostly automated.
 
 use std::fmt::{self, Debug, Display};
 use std::ops::{Deref, DerefMut};
@@ -29,6 +25,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 /// An owned smart pointer.
+///
+/// See the [module level documentation][crate::ptr] for details.
 pub struct P<T: ?Sized> {
     ptr: Box<T>,
 }