Skip to content

Commit 0e610bb

Browse files
committed
Document the unsafe keyword
1 parent 8e21bd0 commit 0e610bb

File tree

1 file changed

+181
-3
lines changed

1 file changed

+181
-3
lines changed

library/std/src/keyword_docs.rs

+181-3
Original file line numberDiff line numberDiff line change
@@ -1813,12 +1813,190 @@ mod type_keyword {}
18131813

18141814
#[doc(keyword = "unsafe")]
18151815
//
1816-
/// Code or interfaces whose [memory safety] cannot be verified by the type system.
1816+
/// Code or interfaces whose [memory safety] cannot be verified by the type
1817+
/// system.
1818+
///
1819+
/// The `unsafe` keyword has two uses: to declare the existence of contracts the
1820+
/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a
1821+
/// programmer has checked that these contracts have been upheld (`unsafe {}`
1822+
/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually
1823+
/// exclusive, as can be seen in `unsafe fn`.
1824+
///
1825+
/// # Unsafe abilities
1826+
///
1827+
/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is
1828+
/// referred to as [soundness]: a well-typed program actually has the desired
1829+
/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation
1830+
/// on the subject.
1831+
///
1832+
/// To ensure soundness, Safe Rust is restricted enough that it can be
1833+
/// automatically checked. Sometimes, however, it is necessary to write code
1834+
/// that is correct for reasons which are too clever for the compiler to
1835+
/// understand. In those cases, you need to use Unsafe Rust.
1836+
///
1837+
/// Here are the abilities Unsafe Rust has in addition to Safe Rust:
1838+
///
1839+
/// - Dereference [raw pointers]
1840+
/// - Implement `unsafe` [`trait`]s
1841+
/// - Call `unsafe` functions
1842+
/// - Mutate [`static`]s (including [`extern`]al ones)
1843+
/// - Access fields of [`union`]s
1844+
///
1845+
/// However, this extra power comes with extra responsibilities: it is now up to
1846+
/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the
1847+
/// pieces of code that need to worry about this.
1848+
///
1849+
/// ## The different meanings of `unsafe`
1850+
///
1851+
/// Not all uses of `unsafe` are equivalent: some are here to mark the existence
1852+
/// of a contract the programmer must check, others are to say "I have checked
1853+
/// the contract, go ahead and do this". The following
1854+
/// [discussion on Rust Internals] has more in-depth explanations about this but
1855+
/// here is a summary of the main points:
1856+
///
1857+
/// - `unsafe fn`: calling this function means abiding by a contract the
1858+
/// compiler cannot enforce.
1859+
/// - `unsafe trait`: implementing the [`trait`] means abiding by a
1860+
/// contract the compiler cannot enforce.
1861+
/// - `unsafe {}`: the contract necessary to call the operations inside the
1862+
/// block has been checked by the programmer and is guaranteed to be respected.
1863+
/// - `unsafe impl`: the contract necessary to implement the trait has been
1864+
/// checked by the programmer and is guaranteed to be respected.
1865+
///
1866+
/// `unsafe fn` also acts like an `unsafe {}` block
1867+
/// around the code inside the function. This means it is not just a signal to
1868+
/// the caller, but also promises that the preconditions for the operations
1869+
/// inside the function are upheld. Mixing these two meanings can be confusing
1870+
/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when
1871+
/// making `unsafe` operations.
1872+
///
1873+
/// See the [Rustnomicon] and the [Reference] for more informations.
18171874
///
1818-
/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
1875+
/// # Examples
1876+
///
1877+
/// ## Marking elements as `unsafe`
1878+
///
1879+
/// `unsafe` can be used on functions. Note that functions and statics declared
1880+
/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions
1881+
/// declared as `extern "something" fn ...`). Mutable statics are always unsafe,
1882+
/// wherever they are declared. Methods can also be declared as `unsafe`:
1883+
///
1884+
/// ```rust
1885+
/// # #![allow(dead_code)]
1886+
/// static mut FOO: &str = "hello";
1887+
///
1888+
/// unsafe fn unsafe_fn() {}
1889+
///
1890+
/// extern "C" {
1891+
/// fn unsafe_extern_fn();
1892+
/// static BAR: *mut u32;
1893+
/// }
1894+
///
1895+
/// trait SafeTraitWithUnsafeMethod {
1896+
/// unsafe fn unsafe_method(&self);
1897+
/// }
1898+
///
1899+
/// struct S;
1900+
///
1901+
/// impl S {
1902+
/// unsafe fn unsafe_method_on_struct() {}
1903+
/// }
1904+
/// ```
1905+
///
1906+
/// Traits can also be declared as `unsafe`:
1907+
///
1908+
/// ```rust
1909+
/// unsafe trait UnsafeTrait {}
1910+
/// ```
18191911
///
1912+
/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety
1913+
/// contract that the compiler cannot enforce, documenting it is important. The
1914+
/// standard library has many examples of this, like the following which is an
1915+
/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract
1916+
/// that must be fulfilled to safely call the function.
1917+
///
1918+
/// ```rust,ignore (stub-to-show-doc-example)
1919+
/// /// Forces the length of the vector to `new_len`.
1920+
/// ///
1921+
/// /// This is a low-level operation that maintains none of the normal
1922+
/// /// invariants of the type. Normally changing the length of a vector
1923+
/// /// is done using one of the safe operations instead, such as
1924+
/// /// `truncate`, `resize`, `extend`, or `clear`.
1925+
/// ///
1926+
/// /// # Safety
1927+
/// ///
1928+
/// /// - `new_len` must be less than or equal to `capacity()`.
1929+
/// /// - The elements at `old_len..new_len` must be initialized.
1930+
/// pub unsafe fn set_len(&mut self, new_len: usize)
1931+
/// ```
1932+
///
1933+
/// ## Using `unsafe {}` blocks and `impl`s
1934+
///
1935+
/// Performing `unsafe` operations requires an `unsafe {}` block:
1936+
///
1937+
/// ```rust
1938+
/// # #![allow(dead_code)]
1939+
/// /// Dereference the given pointer.
1940+
/// ///
1941+
/// /// # Safety
1942+
/// ///
1943+
/// /// `ptr` must be aligned and must not be dangling.
1944+
/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 {
1945+
/// *ptr
1946+
/// }
1947+
///
1948+
/// let a = 3;
1949+
/// let b = &a as *const _;
1950+
/// // SAFETY: `a` has not been dropped and references are always aligned,
1951+
/// // so `b` is a valid address.
1952+
/// unsafe { assert_eq!(*b, deref_unchecked(b)); };
1953+
/// ```
1954+
///
1955+
/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This
1956+
/// makes a guarantee to other `unsafe` code that the implementation satisfies
1957+
/// the trait's safety contract. The [Send] and [Sync] traits are examples of
1958+
/// this behaviour in the standard library.
1959+
///
1960+
/// ```rust
1961+
/// /// Implementors of this trait must guarantee an element is always
1962+
/// /// accessible with index 3.
1963+
/// unsafe trait ThreeIndexable<T> {
1964+
/// /// Returns a reference to the element with index 3 in `&self`.
1965+
/// fn three(&self) -> &T;
1966+
/// }
1967+
///
1968+
/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe`
1969+
/// // because the implementor must abide by a contract the compiler cannot
1970+
/// // check but as a programmer we know there will always be a valid element
1971+
/// // at index 3 to access.
1972+
/// unsafe impl<T> ThreeIndexable<T> for [T; 4] {
1973+
/// fn three(&self) -> &T {
1974+
/// // SAFETY: implementing the trait means there always is an element
1975+
/// // with index 3 accessible.
1976+
/// unsafe { self.get_unchecked(3) }
1977+
/// }
1978+
/// }
1979+
///
1980+
/// let a = [1, 2, 4, 8];
1981+
/// assert_eq!(a.three(), &8);
1982+
/// ```
1983+
///
1984+
/// [`extern`]: keyword.extern.html
1985+
/// [`trait`]: keyword.trait.html
1986+
/// [`static`]: keyword.static.html
1987+
/// [`union`]: keyword.union.html
1988+
/// [`impl`]: keyword.impl.html
1989+
/// [Send]: marker/trait.Send.html
1990+
/// [Sync]: marker/trait.Sync.html
1991+
/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len
1992+
/// [raw pointers]: ../reference/types/pointer.html
18201993
/// [memory safety]: ../book/ch19-01-unsafe-rust.html
1821-
/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
1994+
/// [Rustnomicon]: ../nomicon/index.html
1995+
/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
1996+
/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
1997+
/// [Reference]: ../reference/unsafety.html
1998+
/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585
1999+
/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696
18222000
mod unsafe_keyword {}
18232001

18242002
#[doc(keyword = "use")]

0 commit comments

Comments
 (0)