Skip to content

Commit dd53dd5

Browse files
committed
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
2 parents e772c28 + 71751db commit dd53dd5

File tree

3 files changed

+109
-5
lines changed

3 files changed

+109
-5
lines changed

src/librustdoc/clean/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,7 @@ pub enum PrimitiveType {
15481548
Tuple,
15491549
RawPointer,
15501550
Reference,
1551+
Fn,
15511552
}
15521553

15531554
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1583,6 +1584,7 @@ impl Type {
15831584
Tuple(..) => Some(PrimitiveType::Tuple),
15841585
RawPointer(..) => Some(PrimitiveType::RawPointer),
15851586
BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
1587+
BareFunction(..) => Some(PrimitiveType::Fn),
15861588
_ => None,
15871589
}
15881590
}
@@ -1636,6 +1638,7 @@ impl PrimitiveType {
16361638
"tuple" => Some(PrimitiveType::Tuple),
16371639
"pointer" => Some(PrimitiveType::RawPointer),
16381640
"reference" => Some(PrimitiveType::Reference),
1641+
"fn" => Some(PrimitiveType::Fn),
16391642
_ => None,
16401643
}
16411644
}
@@ -1665,6 +1668,7 @@ impl PrimitiveType {
16651668
Tuple => "tuple",
16661669
RawPointer => "pointer",
16671670
Reference => "reference",
1671+
Fn => "fn",
16681672
}
16691673
}
16701674

@@ -2561,6 +2565,7 @@ fn build_deref_target_impls(cx: &DocContext,
25612565
Tuple => None,
25622566
RawPointer => tcx.lang_items.const_ptr_impl(),
25632567
Reference => None,
2568+
Fn => None,
25642569
};
25652570
if let Some(did) = did {
25662571
if !did.is_local() {

src/librustdoc/html/format.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -607,11 +607,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
607607
decl.generics,
608608
decl.decl)
609609
} else {
610-
write!(f, "{}{}fn{}{}",
611-
UnsafetySpace(decl.unsafety),
612-
AbiSpace(decl.abi),
613-
decl.generics,
614-
decl.decl)
610+
write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?;
611+
primitive_link(f, PrimitiveType::Fn, "fn")?;
612+
write!(f, "{}{}", decl.generics, decl.decl)
615613
}
616614
}
617615
clean::Tuple(ref typs) => {

src/libstd/primitive_docs.rs

+101
Original file line numberDiff line numberDiff line change
@@ -839,3 +839,104 @@ mod prim_usize { }
839839
/// locally known.
840840
#[stable(feature = "rust1", since = "1.0.0")]
841841
mod prim_ref { }
842+
843+
#[doc(primitive = "fn")]
844+
//
845+
/// Function pointers, like `fn(usize) -> bool`.
846+
///
847+
/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].*
848+
///
849+
/// [`Fn`]: ops/trait.Fn.html
850+
/// [`FnMut`]: ops/trait.FnMut.html
851+
/// [`FnOnce`]: ops/trait.FnOnce.html
852+
///
853+
/// Plain function pointers are obtained by casting either plain functions, or closures that don't
854+
/// capture an environment:
855+
///
856+
/// ```
857+
/// fn add_one(x: usize) -> usize {
858+
/// x + 1
859+
/// }
860+
///
861+
/// let ptr: fn(usize) -> usize = add_one;
862+
/// assert_eq!(ptr(5), 6);
863+
///
864+
/// let clos: fn(usize) -> usize = |x| x + 5;
865+
/// assert_eq!(clos(5), 10);
866+
/// ```
867+
///
868+
/// In addition to varying based on their signature, function pointers come in two flavors: safe
869+
/// and unsafe. Plain `fn()` function pointers can only point to safe functions,
870+
/// while `unsafe fn()` function pointers can point to safe or unsafe functions.
871+
///
872+
/// ```
873+
/// fn add_one(x: usize) -> usize {
874+
/// x + 1
875+
/// }
876+
///
877+
/// unsafe fn add_one_unsafely(x: usize) -> usize {
878+
/// x + 1
879+
/// }
880+
///
881+
/// let safe_ptr: fn(usize) -> usize = add_one;
882+
///
883+
/// //ERROR: mismatched types: expected normal fn, found unsafe fn
884+
/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely;
885+
///
886+
/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
887+
/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
888+
/// ```
889+
///
890+
/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
891+
/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
892+
/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
893+
/// fn()`, and so on for the various ABIs that Rust supports. Non-`extern` functions have an ABI
894+
/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
895+
/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
896+
///
897+
/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
898+
///
899+
/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
900+
/// to be called with a variable number of arguments. Normal rust functions, even those with an
901+
/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
902+
/// variadic functions][nomicon-variadic].
903+
///
904+
/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
905+
///
906+
/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
907+
///
908+
/// Like references in rust, function pointers are assumed to not be null, so if you want to pass a
909+
/// function pointer over FFI and be able to accomodate null pointers, make your type
910+
/// `Option<fn()>` with your required signature.
911+
///
912+
/// Function pointers implement the following traits:
913+
///
914+
/// * [`Clone`]
915+
/// * [`PartialEq`]
916+
/// * [`Eq`]
917+
/// * [`PartialOrd`]
918+
/// * [`Ord`]
919+
/// * [`Hash`]
920+
/// * [`Pointer`]
921+
/// * [`Debug`]
922+
///
923+
/// [`Clone`]: clone/trait.Clone.html
924+
/// [`PartialEq`]: cmp/trait.PartialEq.html
925+
/// [`Eq`]: cmp/trait.Eq.html
926+
/// [`PartialOrd`]: cmp/trait.PartialOrd.html
927+
/// [`Ord`]: cmp/trait.Ord.html
928+
/// [`Hash`]: hash/trait.Hash.html
929+
/// [`Pointer`]: fmt/trait.Pointer.html
930+
/// [`Debug`]: fmt/trait.Debug.html
931+
///
932+
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
933+
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
934+
/// may change.
935+
///
936+
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
937+
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
938+
/// are specially known to the compiler.
939+
///
940+
/// [`Copy`]: marker/trait.Copy.html
941+
#[stable(feature = "rust1", since = "1.0.0")]
942+
mod prim_fn { }

0 commit comments

Comments
 (0)