about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-01 19:59:53 +0000
committerbors <bors@rust-lang.org>2017-08-01 19:59:53 +0000
commitdd53dd5f9e21dce1fbc06b7f9f451d1009bdcfd8 (patch)
tree7361d01fc125c95abb8dd112a2879c984f1cab0f /src
parente772c28d2e1a6eb5e4b13980255300b0ee4d774f (diff)
parent71751db49150b89b917130a68db0d1baef43af33 (diff)
downloadrust-dd53dd5f9e21dce1fbc06b7f9f451d1009bdcfd8.tar.gz
rust-dd53dd5f9e21dce1fbc06b7f9f451d1009bdcfd8.zip
Auto merge of #43529 - QuietMisdreavus:fn-docs, r=steveklabnik
add documentation for function pointers as a primitive

This PR adds a new kind of primitive to the standard library documentation: Function pointers. It's useful to be able to discuss them separately from closure-trait-objects, and to have something to point to when discussing function pointers as a *type* and not a *trait*.

Fixes #17104
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/librustdoc/html/format.rs8
-rw-r--r--src/libstd/primitive_docs.rs101
3 files changed, 109 insertions, 5 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 39258dd3a24..a9636c7e2fd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1548,6 +1548,7 @@ pub enum PrimitiveType {
     Tuple,
     RawPointer,
     Reference,
+    Fn,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1583,6 +1584,7 @@ impl Type {
             Tuple(..) => Some(PrimitiveType::Tuple),
             RawPointer(..) => Some(PrimitiveType::RawPointer),
             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
+            BareFunction(..) => Some(PrimitiveType::Fn),
             _ => None,
         }
     }
@@ -1636,6 +1638,7 @@ impl PrimitiveType {
             "tuple" => Some(PrimitiveType::Tuple),
             "pointer" => Some(PrimitiveType::RawPointer),
             "reference" => Some(PrimitiveType::Reference),
+            "fn" => Some(PrimitiveType::Fn),
             _ => None,
         }
     }
@@ -1665,6 +1668,7 @@ impl PrimitiveType {
             Tuple => "tuple",
             RawPointer => "pointer",
             Reference => "reference",
+            Fn => "fn",
         }
     }
 
@@ -2561,6 +2565,7 @@ fn build_deref_target_impls(cx: &DocContext,
             Tuple => None,
             RawPointer => tcx.lang_items.const_ptr_impl(),
             Reference => None,
+            Fn => None,
         };
         if let Some(did) = did {
             if !did.is_local() {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 33ab5cf47de..988890ffedc 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -607,11 +607,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
                        decl.generics,
                        decl.decl)
             } else {
-                write!(f, "{}{}fn{}{}",
-                       UnsafetySpace(decl.unsafety),
-                       AbiSpace(decl.abi),
-                       decl.generics,
-                       decl.decl)
+                write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?;
+                primitive_link(f, PrimitiveType::Fn, "fn")?;
+                write!(f, "{}{}", decl.generics, decl.decl)
             }
         }
         clean::Tuple(ref typs) => {
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 84dba274a2e..7be319d1954 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -839,3 +839,104 @@ mod prim_usize { }
 /// locally known.
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_ref { }
+
+#[doc(primitive = "fn")]
+//
+/// Function pointers, like `fn(usize) -> bool`.
+///
+/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].*
+///
+/// [`Fn`]: ops/trait.Fn.html
+/// [`FnMut`]: ops/trait.FnMut.html
+/// [`FnOnce`]: ops/trait.FnOnce.html
+///
+/// Plain function pointers are obtained by casting either plain functions, or closures that don't
+/// capture an environment:
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let ptr: fn(usize) -> usize = add_one;
+/// assert_eq!(ptr(5), 6);
+///
+/// let clos: fn(usize) -> usize = |x| x + 5;
+/// assert_eq!(clos(5), 10);
+/// ```
+///
+/// In addition to varying based on their signature, function pointers come in two flavors: safe
+/// and unsafe. Plain `fn()` function pointers can only point to safe functions,
+/// while `unsafe fn()` function pointers can point to safe or unsafe functions.
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// unsafe fn add_one_unsafely(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let safe_ptr: fn(usize) -> usize = add_one;
+///
+/// //ERROR: mismatched types: expected normal fn, found unsafe fn
+/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely;
+///
+/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
+/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
+/// ```
+///
+/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
+/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
+/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
+/// fn()`, and so on for the various ABIs that Rust supports.  Non-`extern` functions have an ABI
+/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
+/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
+///
+/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+///
+/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
+/// to be called with a variable number of arguments. Normal rust functions, even those with an
+/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
+/// variadic functions][nomicon-variadic].
+///
+/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
+///
+/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
+///
+/// Like references in rust, function pointers are assumed to not be null, so if you want to pass a
+/// function pointer over FFI and be able to accomodate null pointers, make your type
+/// `Option<fn()>` with your required signature.
+///
+/// Function pointers implement the following traits:
+///
+/// * [`Clone`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Hash`]
+/// * [`Pointer`]
+/// * [`Debug`]
+///
+/// [`Clone`]: clone/trait.Clone.html
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+/// [`Eq`]: cmp/trait.Eq.html
+/// [`PartialOrd`]: cmp/trait.PartialOrd.html
+/// [`Ord`]: cmp/trait.Ord.html
+/// [`Hash`]: hash/trait.Hash.html
+/// [`Pointer`]: fmt/trait.Pointer.html
+/// [`Debug`]: fmt/trait.Debug.html
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change.
+///
+/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
+/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
+/// are specially known to the compiler.
+///
+/// [`Copy`]: marker/trait.Copy.html
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_fn { }