Add primitive documentation to libcore

This works by doing two things:
- Adding links that are specific to the crate. Since not all primitive
  items are defined in `core` (due to lang_items), these need to use
  relative links and not intra-doc links.
- Duplicating `primitive_docs` in both core and std. This allows not needing CARGO_PKG_NAME to build the standard library. It also adds a tidy check to make sure they stay the same.
This commit is contained in:
Joshua Nelson 2021-07-05 22:50:26 -04:00
parent 8c2b6ea37d
commit 69fe39e8a8
29 changed files with 1394 additions and 31 deletions

View file

@ -0,0 +1 @@
../std/boxed/struct.Box.html#method.into_raw

View file

@ -0,0 +1 @@
../std/fs/struct.File.html

View file

@ -0,0 +1 @@
../std/io/trait.BufRead.html

View file

@ -0,0 +1 @@
../std/io/trait.Read.html

View file

@ -0,0 +1 @@
../std/io/trait.Seek.html

View file

@ -0,0 +1 @@
../std/io/trait.Write.html

View file

@ -0,0 +1 @@
../std/net/trait.ToSocketAddrs.html

View file

@ -0,0 +1 @@
../std/process/fn.exit.html

View file

@ -0,0 +1 @@
../std/string/struct.String.html

View file

@ -2,7 +2,8 @@
#[lang = "bool"]
impl bool {
/// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
/// or `None` otherwise.
///
/// # Examples
///
@ -18,7 +19,8 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
if self { Some(t) } else { None }
}
/// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
/// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html),
/// or `None` otherwise.
///
/// # Examples
///

View file

@ -96,7 +96,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into
/// Converts a `u32` to a `char`.
///
/// Note that all `char`s are valid [`u32`]s, and can be cast to one with
/// [`as`](keyword.as.html):
/// [`as`](../std/keyword.as.html):
///
/// ```
/// let c = '💯';
@ -372,7 +372,7 @@ pub fn to_digit(self, radix: u32) -> Option<u32> {
/// println!("\\u{{2764}}");
/// ```
///
/// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
/// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
@ -448,7 +448,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
/// println!("\\n");
/// ```
///
/// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
/// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('\n'.escape_debug().to_string(), "\\n");
@ -502,7 +502,7 @@ pub fn escape_debug(self) -> EscapeDebug {
/// println!("\\\"");
/// ```
///
/// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
/// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('"'.escape_default().to_string(), "\\\"");
@ -937,7 +937,7 @@ pub fn is_numeric(self) -> bool {
/// println!("i\u{307}");
/// ```
///
/// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
/// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('C'.to_lowercase().to_string(), "c");
@ -1002,7 +1002,7 @@ pub fn to_lowercase(self) -> ToLowercase {
/// println!("SS");
/// ```
///
/// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
/// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
///
/// ```
/// assert_eq!('c'.to_uppercase().to_string(), "C");

View file

@ -130,6 +130,7 @@
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_notable_trait)]
#![feature(doc_primitive)]
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![feature(fundamental)]
@ -355,3 +356,5 @@ pub mod arch {
/* compiler built-in */
}
}
include!("primitive_docs.rs");

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
Box::into_raw

View file

@ -0,0 +1 @@
fs::File

View file

@ -0,0 +1 @@
io::BufRead

View file

@ -0,0 +1 @@
io::Read

View file

@ -0,0 +1 @@
io::Seek

View file

@ -0,0 +1 @@
io::Write

View file

@ -0,0 +1 @@
net::ToSocketAddrs

View file

@ -0,0 +1 @@
process::exit

View file

@ -0,0 +1 @@
string::String

View file

@ -1,3 +1,6 @@
// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
// These are different files so that relative links work properly without
// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
#[doc(primitive = "bool")]
#[doc(alias = "true")]
#[doc(alias = "false")]
@ -20,12 +23,12 @@
/// assert!(!bool_val);
/// ```
///
/// [`true`]: keyword.true.html
/// [`false`]: keyword.false.html
/// [`true`]: ../std/keyword.true.html
/// [`false`]: ../std/keyword.false.html
/// [`BitAnd`]: ops::BitAnd
/// [`BitOr`]: ops::BitOr
/// [`Not`]: ops::Not
/// [`if`]: keyword.if.html
/// [`if`]: ../std/keyword.if.html
///
/// # Examples
///
@ -103,7 +106,7 @@ mod prim_bool {}
/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
///
/// [`u32`]: prim@u32
/// [`exit`]: process::exit
#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
///
/// # `!` and generics
///
@ -188,7 +191,7 @@ mod prim_bool {}
/// because `!` coerces to `Result<!, ConnectionError>` automatically.
///
/// [`String::from_str`]: str::FromStr::from_str
/// [`String`]: string::String
#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
/// [`FromStr`]: str::FromStr
///
/// # `!` and traits
@ -264,7 +267,7 @@ mod prim_bool {}
/// `impl` for this which simply panics, but the same is true for any type (we could `impl
/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
///
/// [`File`]: fs::File
#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
/// [`Debug`]: fmt::Debug
/// [`default()`]: Default::default
///
@ -272,7 +275,6 @@ mod prim_bool {}
mod prim_never {}
#[doc(primitive = "char")]
//
/// A character type.
///
/// The `char` type represents a single character. More specifically, since
@ -304,7 +306,7 @@ mod prim_never {}
/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
/// ```
///
/// [`String`]: string/struct.String.html
#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
///
/// As always, remember that a human intuition for 'character' might not map to
/// Unicode's definitions. For example, despite looking similar, the 'é'
@ -499,7 +501,7 @@ mod prim_unit {}
/// [`null_mut`]: ptr::null_mut
/// [`is_null`]: pointer::is_null
/// [`offset`]: pointer::offset
/// [`into_raw`]: Box::into_raw
#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
/// [`drop`]: mem::drop
/// [`write`]: ptr::write
#[stable(feature = "rust1", since = "1.0.0")]
@ -581,9 +583,9 @@ mod prim_pointer {}
/// # Editions
///
/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old behavior
/// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
/// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition
/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old
/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition
/// might be made consistent to the behavior of later editions.
///
/// ```rust,edition2018
@ -1042,15 +1044,15 @@ mod prim_usize {}
/// References, both shared and mutable.
///
/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
/// operators on a value, or by using a [`ref`](keyword.ref.html) or
/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
/// <code>[ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html)</code> pattern.
///
/// For those familiar with pointers, a reference is just a pointer that is assumed to be
/// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
/// ([`true`](keyword.true.html)) or `0` ([`false`](keyword.false.html)), but creating a
/// <code>&[bool]</code> that points to an allocation containing the value `3` causes
/// undefined behaviour.
/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but
/// creating a <code>&[bool]</code> that points to an allocation containing
/// the value `3` causes undefined behaviour.
/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
///
@ -1117,6 +1119,7 @@ mod prim_usize {}
///
/// [`DerefMut`]: ops::DerefMut
/// [`BorrowMut`]: borrow::BorrowMut
/// [bool]: prim@bool
///
/// The following traits are implemented on `&T` references if the underlying `T` also implements
/// that trait:
@ -1134,7 +1137,7 @@ mod prim_usize {}
/// [`std::fmt`]: fmt
/// ['Pointer`]: fmt::Pointer
/// [`Hash`]: hash::Hash
/// [`ToSocketAddrs`]: net::ToSocketAddrs
#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
///
/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
/// implements that trait:
@ -1155,9 +1158,10 @@ mod prim_usize {}
///
/// [`FusedIterator`]: iter::FusedIterator
/// [`TrustedLen`]: iter::TrustedLen
/// [`Seek`]: io::Seek
/// [`BufRead`]: io::BufRead
/// [`Read`]: io::Read
#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
///
/// Note that due to method call deref coercion, simply calling a trait method will act like they
/// work on references as well as they do on owned values! The implementations described here are

View file

@ -1,5 +1,8 @@
// compile-flags: --crate-type lib --edition 2018
#![feature(no_core)]
#![no_core]
#[doc(primitive = "usize")]
/// This is the built-in type `usize`.
mod usize {

View file

@ -1,9 +1,11 @@
// aux-build:primitive-doc.rs
// compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
#![no_std]
#![feature(no_core)]
#![no_core]
extern crate primitive_doc;
// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize'
// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link'
/// [link](usize)
pub fn foo() -> usize { 0 }

View file

@ -0,0 +1,5 @@
#![no_std]
// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
// Link to [u8]
pub fn foo() -> u8 {}

View file

@ -46,6 +46,7 @@ macro_rules! tidy_error {
pub mod extdeps;
pub mod features;
pub mod pal;
pub mod primitive_docs;
pub mod style;
pub mod target_specific_tests;
pub mod ui_tests;

View file

@ -71,6 +71,7 @@ macro_rules! check {
// Checks that only make sense for the std libs.
check!(pal, &library_path);
check!(primitive_docs, &library_path);
// Checks that need to be done for both the compiler and std libraries.
check!(unit_tests, &src_path);

View file

@ -0,0 +1,17 @@
//! Tidy check to make sure `library/{std,core}/src/primitive_docs.rs` are the same file. These are
//! different files so that relative links work properly without having to have `CARGO_PKG_NAME`
//! set, but conceptually they should always be the same.
use std::path::Path;
pub fn check(library_path: &Path, bad: &mut bool) {
let std_name = "std/src/primitive_docs.rs";
let core_name = "core/src/primitive_docs.rs";
let std_contents = std::fs::read_to_string(library_path.join(std_name))
.unwrap_or_else(|e| panic!("failed to read library/{}: {}", std_name, e));
let core_contents = std::fs::read_to_string(library_path.join(core_name))
.unwrap_or_else(|e| panic!("failed to read library/{}: {}", core_name, e));
if std_contents != core_contents {
tidy_error!(bad, "library/{} and library/{} have different contents", core_name, std_name);
}
}