about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-01 08:23:41 +0000
committerbors <bors@rust-lang.org>2017-08-01 08:23:41 +0000
commit0bf018c58815eed79a279ee6fa98992b8a3639ef (patch)
tree856cffd54365d1a3aed113f76679dc6f38de7969 /src
parent6e8452ee4f66ef8b3b1f7a33d873e102bf8603d0 (diff)
parenta2d55146938972d7eecc19f9315f86d7ecb8f94b (diff)
downloadrust-0bf018c58815eed79a279ee6fa98992b8a3639ef.tar.gz
rust-0bf018c58815eed79a279ee6fa98992b8a3639ef.zip
Auto merge of #43560 - QuietMisdreavus:ref-docs, r=steveklabnik
add docs for references as a primitive

Just like #43529 did for function pointers, here is a new primitive page for references.

This PR will pull in impls on references if it's a reference to a generic type parameter. Initially i was only able to pull in impls that were re-exported from another crate; crate-local impls got a different representation in the AST, and i had to change how types were resolved when cleaning it. (This is the change at the bottom of `librustdoc/clean/mod.rs`, in `resolve_type`.) I'm unsure the full ramifications of the change, but from what it looks like, it shouldn't impact anything major. Likewise, references to generic type parameters also get the `&'a [mut]` linked to the new page.

cc @rust-lang/docs: Is this sufficient information? The listing of trait impls kinda feels redundant (especially if we can get the automated impl listing sorted again), but i still think it's useful to point out that you can use these in a generic context.

Fixes #15654
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/html/format.rs36
-rw-r--r--src/libstd/primitive_docs.rs117
3 files changed, 142 insertions, 19 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9d0b5b41a91..39258dd3a24 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1547,6 +1547,7 @@ pub enum PrimitiveType {
     Array,
     Tuple,
     RawPointer,
+    Reference,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1581,6 +1582,7 @@ impl Type {
             Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
             Tuple(..) => Some(PrimitiveType::Tuple),
             RawPointer(..) => Some(PrimitiveType::RawPointer),
+            BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
             _ => None,
         }
     }
@@ -1633,6 +1635,7 @@ impl PrimitiveType {
             "slice" => Some(PrimitiveType::Slice),
             "tuple" => Some(PrimitiveType::Tuple),
             "pointer" => Some(PrimitiveType::RawPointer),
+            "reference" => Some(PrimitiveType::Reference),
             _ => None,
         }
     }
@@ -1661,6 +1664,7 @@ impl PrimitiveType {
             Slice => "slice",
             Tuple => "tuple",
             RawPointer => "pointer",
+            Reference => "reference",
         }
     }
 
@@ -2556,6 +2560,7 @@ fn build_deref_target_impls(cx: &DocContext,
             Array => tcx.lang_items.slice_impl(),
             Tuple => None,
             RawPointer => tcx.lang_items.const_ptr_impl(),
+            Reference => None,
         };
         if let Some(did) = did {
             if !did.is_local() {
@@ -2777,6 +2782,9 @@ fn resolve_type(cx: &DocContext,
         Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(keywords::SelfType.name().to_string());
         }
+        Def::TyParam(..) if path.segments.len() == 1 => {
+            return Generic(format!("{:#}", path));
+        }
         Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
         _ => false,
     };
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 766e76137ca..33ab5cf47de 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -665,26 +665,29 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
                 _ => "".to_string(),
             };
             let m = MutableSpace(mutability);
+            let amp = if f.alternate() {
+                "&".to_string()
+            } else {
+                "&amp;".to_string()
+            };
             match **ty {
                 clean::Slice(ref bt) => { // BorrowedRef{ ... Slice(T) } is &[T]
                     match **bt {
                         clean::Generic(_) => {
                             if f.alternate() {
                                 primitive_link(f, PrimitiveType::Slice,
-                                    &format!("&{}{}[{:#}]", lt, m, **bt))
+                                    &format!("{}{}{}[{:#}]", amp, lt, m, **bt))
                             } else {
                                 primitive_link(f, PrimitiveType::Slice,
-                                    &format!("&amp;{}{}[{}]", lt, m, **bt))
+                                    &format!("{}{}{}[{}]", amp, lt, m, **bt))
                             }
                         }
                         _ => {
+                            primitive_link(f, PrimitiveType::Slice,
+                                           &format!("{}{}{}[", amp, lt, m))?;
                             if f.alternate() {
-                                primitive_link(f, PrimitiveType::Slice,
-                                               &format!("&{}{}[", lt, m))?;
                                 write!(f, "{:#}", **bt)?;
                             } else {
-                                primitive_link(f, PrimitiveType::Slice,
-                                               &format!("&amp;{}{}[", lt, m))?;
                                 write!(f, "{}", **bt)?;
                             }
                             primitive_link(f, PrimitiveType::Slice, "]")
@@ -692,23 +695,18 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
                     }
                 }
                 clean::ResolvedPath { typarams: Some(ref v), .. } if !v.is_empty() => {
-                    if f.alternate() {
-                        write!(f, "&{}{}", lt, m)?;
-                    } else {
-                        write!(f, "&amp;{}{}", lt, m)?;
-                    }
-                    write!(f, "(")?;
+                    write!(f, "{}{}{}(", amp, lt, m)?;
                     fmt_type(&ty, f, use_absolute)?;
                     write!(f, ")")
                 }
+                clean::Generic(..) => {
+                    primitive_link(f, PrimitiveType::Reference,
+                                   &format!("{}{}{}", amp, lt, m))?;
+                    fmt_type(&ty, f, use_absolute)
+                }
                 _ => {
-                    if f.alternate() {
-                        write!(f, "&{}{}", lt, m)?;
-                        fmt_type(&ty, f, use_absolute)
-                    } else {
-                        write!(f, "&amp;{}{}", lt, m)?;
-                        fmt_type(&ty, f, use_absolute)
-                    }
+                    write!(f, "{}{}{}", amp, lt, m)?;
+                    fmt_type(&ty, f, use_absolute)
                 }
             }
         }
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 869299e2144..84dba274a2e 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -722,3 +722,120 @@ mod prim_isize { }
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_usize { }
+
+#[doc(primitive = "reference")]
+//
+/// References, both shared and mutable.
+///
+/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
+/// operators on a value, or by using a `ref` or `ref mut` pattern.
+///
+/// For those familiar with pointers, a reference is just a pointer that is assumed to not be null.
+/// In fact, `Option<&T>` has the same memory representation as a nullable pointer, and can be
+/// passed across FFI boundaries as such.
+///
+/// In most cases, references can be used much like the original value. Field access, method
+/// calling, and indexing work the same (save for mutability rules, of course). In addition, the
+/// comparison operators transparently defer to the referent's implementation, allowing references
+/// to be compared the same as owned values.
+///
+/// References have a lifetime attached to them, which represents the scope for which the borrow is
+/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or
+/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the
+/// total life of the program. For example, string literals have a `'static` lifetime because the
+/// text data is embedded into the binary of the program, rather than in an allocation that needs
+/// to be dynamically managed.
+///
+/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
+/// references with longer lifetimes can be freely coerced into references with shorter ones.
+///
+/// For more information on how to use references, see [the book's section on "References and
+/// Borrowing"][book-refs].
+///
+/// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html
+///
+/// The following traits are implemented for all `&T`, regardless of the type of its referent:
+///
+/// * [`Copy`]
+/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!)
+/// * [`Deref`]
+/// * [`Borrow`]
+/// * [`Pointer`]
+///
+/// [`Copy`]: marker/trait.Copy.html
+/// [`Clone`]: clone/trait.Clone.html
+/// [`Deref`]: ops/trait.Deref.html
+/// [`Borrow`]: borrow/trait.Borrow.html
+/// [`Pointer`]: fmt/trait.Pointer.html
+///
+/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating
+/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its
+/// referent:
+///
+/// * [`DerefMut`]
+/// * [`BorrowMut`]
+///
+/// [`DerefMut`]: ops/trait.DerefMut.html
+/// [`BorrowMut`]: borrow/trait.BorrowMut.html
+///
+/// The following traits are implemented on `&T` references if the underlying `T` also implements
+/// that trait:
+///
+/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`AsRef`]
+/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`)
+/// * [`Hash`]
+/// * [`ToSocketAddrs`]
+///
+/// [`std::fmt`]: fmt/index.html
+/// [`fmt::Write`]: fmt/trait.Write.html
+/// [`PartialOrd`]: cmp/trait.PartialOrd.html
+/// [`Ord`]: cmp/trait.Ord.html
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+/// [`Eq`]: cmp/trait.Eq.html
+/// [`AsRef`]: convert/trait.AsRef.html
+/// [`Fn`]: ops/trait.Fn.html
+/// [`FnMut`]: ops/trait.FnMut.html
+/// [`FnOnce`]: ops/trait.FnOnce.html
+/// [`Hash`]: hash/trait.Hash.html
+/// [`ToSocketAddrs`]: net/trait.ToSocketAddrs.html
+///
+/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
+/// implements that trait:
+///
+/// * [`AsMut`]
+/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`)
+/// * [`fmt::Write`]
+/// * [`Iterator`]
+/// * [`DoubleEndedIterator`]
+/// * [`ExactSizeIterator`]
+/// * [`FusedIterator`]
+/// * [`TrustedLen`]
+/// * [`Send`] \(note that `&T` references only get `Send` if `T: Sync`)
+/// * [`io::Write`]
+/// * [`Read`]
+/// * [`Seek`]
+/// * [`BufRead`]
+///
+/// [`AsMut`]: convert/trait.AsMut.html
+/// [`Iterator`]: iter/trait.Iterator.html
+/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+/// [`ExactSizeIterator`]: iter/trait.ExactSizeIterator.html
+/// [`FusedIterator`]: iter/trait.FusedIterator.html
+/// [`TrustedLen`]: iter/trait.TrustedLen.html
+/// [`Send`]: marker/trait.Send.html
+/// [`io::Write`]: io/trait.Write.html
+/// [`Read`]: io/trait.Read.html
+/// [`Seek`]: io/trait.Seek.html
+/// [`BufRead`]: io/trait.BufRead.html
+///
+/// Note that due to method call deref coercion, simply calling a trait method will act like they
+/// work on references as well as they do on owned values! The implementations described here are
+/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
+/// locally known.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_ref { }