Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add documentation for function pointers as a primitive #43529

Merged
merged 1 commit into from
Aug 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,7 @@ pub enum PrimitiveType {
Tuple,
RawPointer,
Reference,
Fn,
}

#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
Expand Down Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -1636,6 +1638,7 @@ impl PrimitiveType {
"tuple" => Some(PrimitiveType::Tuple),
"pointer" => Some(PrimitiveType::RawPointer),
"reference" => Some(PrimitiveType::Reference),
"fn" => Some(PrimitiveType::Fn),
_ => None,
}
}
Expand Down Expand Up @@ -1665,6 +1668,7 @@ impl PrimitiveType {
Tuple => "tuple",
RawPointer => "pointer",
Reference => "reference",
Fn => "fn",
}
}

Expand Down Expand Up @@ -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() {
Expand Down
8 changes: 3 additions & 5 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
101 changes: 101 additions & 0 deletions src/libstd/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to mention here somewhere that function pointers are always assumed to be non-null.
This is a common mistake in FFI to use fn() in nullable callbacks when Option<fn()> need to be used instead.

/// 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 { }