From ead115949017533de244049c58f4b6886243eda7 Mon Sep 17 00:00:00 2001 From: Stephane Raux Date: Mon, 9 Dec 2019 22:49:59 -0800 Subject: [PATCH] Use Niko's wording --- src/liballoc/boxed.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index a502a5b0a0b..a7e09d72b4a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -63,14 +63,25 @@ //! T` obtained from `Box::::into_raw` may be deallocated using the //! [`Global`] allocator with `Layout::for_value(&*value)`. //! -//! `Box` has the same ABI as `&mut T`. In particular, when `T: Sized`, -//! this allows using `Box` in FFI: +//! So long as `T: Sized`, a `Box` is guaranteed to be represented as a +//! single pointer and is also ABI-compatible with C pointers (i.e. the C type +//! `T*`). This means that you have Rust code which passes ownership of a +//! `Box` to C code by using `Box` as the type on the Rust side, and +//! `T*` as the corresponding type on the C side. As an example, consider this +//! C header which declares functions that create and destroy some kind of +//! `Foo` value: //! //! ```c //! /* C header */ //! struct Foo* foo_new(void); /* Returns ownership to the caller */ //! void foo_delete(struct Foo*); /* Takes ownership from the caller */ //! ``` +//! +//! These two functions might be implemented in Rust as follows. Here, the +//! `struct Foo*` type from C is translated to `Box`, which captures +//! the ownership constraints. Note also that the nullable argument to +//! `foo_delete` is represented in Rust as `Option>`, since `Box` +//! cannot be null. //! //! ``` //! #[repr(C)] @@ -84,6 +95,14 @@ //! #[no_mangle] //! pub extern "C" fn foo_delete(_: Option>) {} //! ``` +//! +//! Even though `Box` has the same representation and C ABI as a C pointer, +//! this does not mean that you can convert an arbitrary `T*` into a `Box` +//! and expect things to work. `Box` values will always be fully aligned, +//! non-null pointers. Moreover, the destructor for `Box` will attempt to +//! free the value with the global allocator. In general, the best practice +//! is to only use `Box` for pointers that originated from the global +//! allocator. //! //! [dereferencing]: ../../std/ops/trait.Deref.html //! [`Box`]: struct.Box.html