From c956fe5cea5c2221e54a98b6f83214b08eb5ce24 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 3 Mar 2022 19:45:53 -0500 Subject: [PATCH 01/15] Document new recommended use of method --- library/core/src/iter/traits/collect.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 637d7bc44885e..9af3c0d48092b 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -4,9 +4,11 @@ /// created from an iterator. This is common for types which describe a /// collection of some kind. /// -/// [`FromIterator::from_iter()`] is rarely called explicitly, and is instead -/// used through [`Iterator::collect()`] method. See [`Iterator::collect()`]'s -/// documentation for more examples. +/// If you want to create a collection from the contents of an iterator, the +/// [`Iterator::collect()`] method is preferred. However, the compiler is +/// sometimes unable to infer the full type of the collection. In these cases, +/// [`FromIterator::from_iter()`] can be more concise and readable. See the +/// [`Iterator::collect()`] documentation for more examples of its use. /// /// See also: [`IntoIterator`]. /// @@ -32,6 +34,17 @@ /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` /// +/// Using [`FromIterator::from_iter()`] as a more readable alternative to +/// [`Iterator::collect()`]: +/// +/// ``` +/// # use std::collections::VecDeque; +/// let first = (0..10).collect::>(); +/// let second = VecDeque::from_iter(0..10); +/// +/// assert_eq!(first, second); +/// ``` +/// /// Implementing `FromIterator` for your type: /// /// ``` From 5f34c04de66c9ec98dd4f6f6d88bb6c10d21b9fb Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 4 Mar 2022 09:45:18 -0500 Subject: [PATCH 02/15] Make use statement visible --- library/core/src/iter/traits/collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 9af3c0d48092b..28ae227725281 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -38,7 +38,7 @@ /// [`Iterator::collect()`]: /// /// ``` -/// # use std::collections::VecDeque; +/// use std::collections::VecDeque; /// let first = (0..10).collect::>(); /// let second = VecDeque::from_iter(0..10); /// From b363f130698dbc55fe594155bcb4df826ffad71e Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 4 Mar 2022 09:48:51 -0500 Subject: [PATCH 03/15] Add suggested changes to the docs --- library/core/src/iter/traits/collect.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 28ae227725281..dee66e6e07283 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -5,9 +5,9 @@ /// collection of some kind. /// /// If you want to create a collection from the contents of an iterator, the -/// [`Iterator::collect()`] method is preferred. However, the compiler is -/// sometimes unable to infer the full type of the collection. In these cases, -/// [`FromIterator::from_iter()`] can be more concise and readable. See the +/// [`Iterator::collect()`] method is preferred. However, when you need to +/// specify the container type, [`FromIterator::from_iter()`] can be more +/// readable than using a turbofish (e.g. `::>()`). See the /// [`Iterator::collect()`] documentation for more examples of its use. /// /// See also: [`IntoIterator`]. From a5216cf67d93de97091b41ecba85de2e08f39863 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Mar 2022 17:40:24 +0100 Subject: [PATCH 04/15] Unify inherent impl blocks by wrapping them into a div --- src/librustdoc/html/markdown.rs | 1 + src/librustdoc/html/render/mod.rs | 16 ++++++++++------ src/librustdoc/html/static/js/main.js | 2 +- src/test/rustdoc/duplicate_impls/issue-33054.rs | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 7061a9674e4fb..f2856690d257a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1460,6 +1460,7 @@ fn init_id_map() -> FxHashMap { map.insert("provided-methods".to_owned(), 1); map.insert("implementors".to_owned(), 1); map.insert("synthetic-implementors".to_owned(), 1); + map.insert("implementations-list".to_owned(), 1); map.insert("trait-implementations-list".to_owned(), 1); map.insert("synthetic-implementations-list".to_owned(), 1); map.insert("blanket-implementations-list".to_owned(), 1); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 558dbb3b3965a..26f29a3524b00 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1065,14 +1065,15 @@ fn render_assoc_items_inner( let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let mut tmp_buf = Buffer::empty_from(w); - let render_mode = match what { + let (render_mode, id) = match what { AssocItemRender::All => { tmp_buf.write_str( "

\ - Implementations\ -

", + Implementations\ + \ + ", ); - RenderMode::Normal + (RenderMode::Normal, "implementations-list".to_owned()) } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { let id = @@ -1090,7 +1091,7 @@ fn render_assoc_items_inner( trait_ = trait_.print(cx), type_ = type_.print(cx), ); - RenderMode::ForDeref { mut_: deref_mut_ } + (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } }; let mut impls_buf = Buffer::empty_from(w); @@ -1115,7 +1116,9 @@ fn render_assoc_items_inner( } if !impls_buf.is_empty() { w.push_buffer(tmp_buf); + write!(w, "
", id); w.push_buffer(impls_buf); + w.write_str("
"); } } @@ -1146,7 +1149,8 @@ fn render_assoc_items_inner( write!( w, "

\ - Trait Implementations\ + Trait Implementations\ + \

\
{}
", impls diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 8e1919f75d671..90592335d5ddf 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -741,7 +741,7 @@ function hideThemeButtonState() { } else { addClass(innerToggle, "will-expand"); onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) { - if (e.parentNode.id !== MAIN_ID || + if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle"))) { diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index b018dd6cda58a..3f9a476d96e23 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -2,7 +2,7 @@ // @has - '//h3[@class="code-header in-band"]' 'impl Foo' // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 -// @count - '//*[@id="main-content"]/details/summary/*[@class="impl has-srclink"]' 1 +// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1 // @has issue_33054/impls/bar/trait.Bar.html // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 From fbd9c284d7f018db07da8aa6e03cffdf0ce1786b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Mar 2022 18:11:29 +0100 Subject: [PATCH 05/15] Update GUI tests for impl blocks path changes --- src/test/rustdoc-gui/docblock-table-overflow.goml | 8 ++++---- src/test/rustdoc-gui/hash-item-expansion.goml | 4 ++-- src/test/rustdoc-gui/impl-default-expansion.goml | 2 +- src/test/rustdoc-gui/toggle-docs-mobile.goml | 2 +- src/test/rustdoc-gui/toggle-docs.goml | 2 +- src/test/rustdoc/duplicate_impls/issue-33054.rs | 2 ++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml index a9af88189a67d..af76d2ea42760 100644 --- a/src/test/rustdoc-gui/docblock-table-overflow.goml +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -12,10 +12,10 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"}) // Logically, the ".docblock" and the "

" should have the same scroll width. compare-elements-property: ( - "#implementations + details .docblock", - "#implementations + details .docblock > p", + "#implementations-list > details .docblock", + "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations + details .docblock", {"scrollWidth": "801"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"}) // However, since there is overflow in the , its scroll width is bigger. -assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"}) +assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1573"}) diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml index a680635ef8ae4..861f6928362c2 100644 --- a/src/test/rustdoc-gui/hash-item-expansion.goml +++ b/src/test/rustdoc-gui/hash-item-expansion.goml @@ -3,9 +3,9 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow // In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)". assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""}) // We first check that the impl block is open by default. -assert-attribute: ("#implementations + details", {"open": ""}) +assert-attribute: ("#implementations-list details", {"open": ""}) // To ensure that we will click on the currently hidden method. assert-text: (".sidebar-elems section .block li > a", "must_use") click: ".sidebar-elems section .block li > a" // We check that the impl block was opened as expected so that we can see the method. -assert-attribute: ("#implementations + details", {"open": ""}) +assert-attribute: ("#implementations-list > details", {"open": ""}) diff --git a/src/test/rustdoc-gui/impl-default-expansion.goml b/src/test/rustdoc-gui/impl-default-expansion.goml index 7c4496dc0cabc..6df2661e6c2bb 100644 --- a/src/test/rustdoc-gui/impl-default-expansion.goml +++ b/src/test/rustdoc-gui/impl-default-expansion.goml @@ -1,3 +1,3 @@ // This test ensures that the impl blocks are open by default. goto: file://|DOC_PATH|/test_docs/struct.Foo.html -assert-attribute: ("#main-content > details.implementors-toggle", {"open": ""}) +assert-attribute: ("#implementations-list details.implementors-toggle", {"open": ""}) diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml index b502692300113..ee6bc3cf7675c 100644 --- a/src/test/rustdoc-gui/toggle-docs-mobile.goml +++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml @@ -14,7 +14,7 @@ assert-attribute: (".top-doc", {"open": ""}) // Assert the position of the toggle on the top doc block. assert-position: (".top-doc summary::before", {"x": 4}) // Assert the position of the toggle on the impl block. -assert-position: ("#implementations + details > summary::before", {"x": 4}) +assert-position: ("#implementations-list > details > summary::before", {"x": 4}) // Assert the position of the toggle on a method. assert-position: ( "#trait-implementations-list .impl-items .method-toggle > summary::before", diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index 477105193d3ee..f98111484f315 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -24,7 +24,7 @@ wait-for: 50 assert-text: ("#toggle-all-docs", "[+]") // We check that all
are collapsed (except for the impl block ones). assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL) -assert-attribute: ("details.rustdoc-toggle.implementors-toggle", {"open": ""}) +assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""}) // We now check that the other impl blocks are collapsed. assert-attribute-false: ( "#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle", diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 3f9a476d96e23..84c9e4ac0cd84 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // @has issue_33054/impls/struct.Foo.html // @has - '//h3[@class="code-header in-band"]' 'impl Foo' // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' From 4e067e80ebb60022d6446335b0721feed73483b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Tue, 8 Mar 2022 23:11:37 +0100 Subject: [PATCH 06/15] Improve rustdoc book --- src/doc/rustdoc/book.toml | 4 ++ src/doc/rustdoc/src/SUMMARY.md | 15 +++--- src/doc/rustdoc/src/advanced-features.md | 22 ++++++++ src/doc/rustdoc/src/command-line-arguments.md | 30 ++--------- .../src/{passes.md => deprecated-features.md} | 4 +- src/doc/rustdoc/src/how-to-read-rustdoc.md | 4 +- src/doc/rustdoc/src/lints.md | 24 ++++----- src/doc/rustdoc/src/unstable-features.md | 51 +++++++++++++++++-- src/doc/rustdoc/src/website-features.md | 25 --------- .../documentation-tests.md | 2 +- .../linking-to-items-by-name.md | 2 +- .../the-doc-attribute.md | 4 +- .../what-to-include.md | 2 +- 13 files changed, 106 insertions(+), 83 deletions(-) rename src/doc/rustdoc/src/{passes.md => deprecated-features.md} (94%) delete mode 100644 src/doc/rustdoc/src/website-features.md rename src/doc/rustdoc/src/{ => write-documentation}/documentation-tests.md (99%) rename src/doc/rustdoc/src/{ => write-documentation}/linking-to-items-by-name.md (98%) rename src/doc/rustdoc/src/{ => write-documentation}/the-doc-attribute.md (98%) rename src/doc/rustdoc/src/{ => write-documentation}/what-to-include.md (99%) diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index 97e08416d7686..45405a11765cc 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -4,3 +4,7 @@ title = "The rustdoc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" + +[output.html.redirect] +"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html" +"/documentation-tests.html" = "write-documentation/documentation-tests.html" diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index eb18185945387..d627f5b0389f3 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,16 +1,15 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [Command-line arguments](command-line-arguments.md) - [How to read rustdoc output](how-to-read-rustdoc.md) - [How to write documentation](how-to-write-documentation.md) -- [What to include (and exclude)](what-to-include.md) -- [Command-line arguments](command-line-arguments.md) -- [The `#[doc]` attribute](the-doc-attribute.md) -- [Documentation tests](documentation-tests.md) -- [Linking to items by name](linking-to-items-by-name.md) -- [Lints](lints.md) + - [What to include (and exclude)](write-documentation/what-to-include.md) + - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md) + - [Linking to items by name](write-documentation/linking-to-items-by-name.md) + - [Documentation tests](write-documentation/documentation-tests.md) +- [Rustdoc-specific lints](lints.md) - [Advanced features](advanced-features.md) - [Unstable features](unstable-features.md) -- [Website features](website-features.md) -- [Passes](passes.md) +- [Deprecated features](deprecated-features.md) - [References](references.md) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index 6147bd0a97a96..dbf0baec04c03 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -88,3 +88,25 @@ You can add multiple aliases at the same time by using a list: #[doc(alias("x", "big"))] pub struct BigX; ``` + +## Custom search engines + +If you find yourself often referencing online Rust docs you might enjoy using a custom search +engine. This allows you to use the navigation bar directly to search a `rustdoc` website. +Most browsers support this feature by letting you define a URL template containing `%s` +which will be substituted for the search term. As an example, for the standard library you could use +this template: + +```text +https://doc.rust-lang.org/stable/std/?search=%s +``` + +Note that this will take you to a results page listing all matches. If you want to navigate to the first +result right away (which is often the best match) use the following instead: + +```text +https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true +``` + +This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL +to automatically go to the first result. diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 3ce57f88938f7..2a2e51b2f6331 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -177,7 +177,7 @@ $ rustdoc src/lib.rs --test ``` This flag will run your code examples as tests. For more, see [the chapter -on documentation tests](documentation-tests.md). +on documentation tests](write-documentation/documentation-tests.md). See also `--test-args`. @@ -190,7 +190,7 @@ $ rustdoc src/lib.rs --test --test-args ignored ``` This flag will pass options to the test runner when running documentation tests. -For more, see [the chapter on documentation tests](documentation-tests.md). +For more, see [the chapter on documentation tests](write-documentation/documentation-tests.md). See also `--test`. @@ -336,7 +336,7 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses when compiling your code. -### `--edition`: control the edition of docs and doctests +## `--edition`: control the edition of docs and doctests Using this flag looks like this: @@ -403,12 +403,12 @@ encoded as UTF-8. ## `--passes`: add more rustdoc passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `--no-defaults`: don't run default passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `-r`/`--input-format`: input format @@ -417,23 +417,3 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. - -# Unstable command line arguments - -## `--nocapture` - -When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be -captured by rustdoc. Instead, the output will be directed to your terminal, -as if you had run the test executable manually. This is especially useful -for debugging your tests! - -## `--check` - -When this flag is supplied, rustdoc will type check and lint your code, but will not generate any -documentation or run your doctests. - -Using this flag looks like: - -```bash -rustdoc -Z unstable-options --check src/lib.rs -``` diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/deprecated-features.md similarity index 94% rename from src/doc/rustdoc/src/passes.md rename to src/doc/rustdoc/src/deprecated-features.md index c3c3fd3068ec4..2bc6e8fc8ae4d 100644 --- a/src/doc/rustdoc/src/passes.md +++ b/src/doc/rustdoc/src/deprecated-features.md @@ -1,4 +1,6 @@ -# Passes +# Deprecated features + +## Passes Rustdoc has a concept called "passes". These are transformations that `rustdoc` runs on your documentation before producing its final output. diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 99724d859ee75..098bc1879b56f 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -26,7 +26,7 @@ At the top is some at-a-glance info and controls: - a button to collapse or expand the top-level documentation for that item (`[+]` or `[-]`), - a link to the source code (`[src]`), - if [configured](the-doc-attribute.html#html_no_source), + if [configured](write-documentation/the-doc-attribute.html#html_no_source), and present (the source may not be available if the documentation was created with `cargo doc --no-deps`), - and the version in which the item became stable, @@ -52,7 +52,7 @@ For example, when looking at documentation for the crate root, it shows all the crates documented in the documentation bundle, and quick links to the modules, structs, traits, functions, and macros available from the current crate. -At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url) +At the top, it displays a [configurable logo](write-documentation/the-doc-attribute.html#html_logo_url) alongside the current crate's name and version, or the current item whose documentation is being displayed. diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 1773c15464a94..bff01d7cb7c14 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -13,11 +13,11 @@ Note that, except for `missing_docs`, these lints are only available when runnin Here is the list of the lints provided by `rustdoc`: -## broken_intra_doc_links +## `broken_intra_doc_links` This lint **warns by default**. This lint detects when an [intra-doc link] fails to be resolved. For example: -[intra-doc link]: linking-to-items-by-name.md +[intra-doc link]: write-documentation/linking-to-items-by-name.md ```rust /// I want to link to [`Nonexistent`] but it doesn't exist! @@ -64,7 +64,7 @@ help: to link to the function, add parentheses ``` -## private_intra_doc_links +## `private_intra_doc_links` This lint **warns by default**. This lint detects when [intra-doc links] from public to private items. For example: @@ -104,9 +104,9 @@ warning: public documentation for `public` links to private item `private` = note: this link resolves only because you passed `--document-private-items`, but will break without ``` -[intra-doc links]: linking-to-items-by-name.html +[intra-doc links]: write-documentation/linking-to-items-by-name.md -## missing_docs +## `missing_docs` This lint is **allowed by default**. It detects items missing documentation. For example: @@ -130,7 +130,7 @@ warning: missing documentation for a function Note that unlike other rustdoc lints, this lint is also available from `rustc` directly. -## missing_crate_level_docs +## `missing_crate_level_docs` This lint is **allowed by default**. It detects if there is no documentation at the crate root. For example: @@ -154,7 +154,7 @@ warning in the future. This is intended as a means to introduce new users on get started, without providing overwhelming warnings like `missing_docs` might. -## missing_doc_code_examples +## `missing_doc_code_examples` This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block is missing a code example. For example: @@ -190,7 +190,7 @@ To fix the lint, you need to add a code example into the documentation block: pub fn no_code_example() {} ``` -## private_doc_tests +## `private_doc_tests` This lint is **allowed by default**. It detects documentation tests when they are on a private item. For example: @@ -223,7 +223,7 @@ warning: Documentation test in private item | |___________^ ``` -## invalid_codeblock_attributes +## `invalid_codeblock_attributes` This lint **warns by default**. It detects code block attributes in documentation examples that have potentially mis-typed values. For example: @@ -259,7 +259,7 @@ warning: unknown attribute `should-panic`. Did you mean `should_panic`? In the example above, the correct form is `should_panic`. This helps detect typo mistakes for some common attributes. -## invalid_html_tags +## `invalid_html_tags` This lint is **allowed by default** and is **nightly-only**. It detects unclosed or invalid HTML tags. For example: @@ -298,7 +298,7 @@ warning: unclosed HTML tag `h1` warning: 2 warnings emitted ``` -## invalid_rust_codeblocks +## `invalid_rust_codeblocks` This lint **warns by default**. It detects Rust code blocks in documentation examples that are invalid (e.g. empty, not parsable as Rust). For example: @@ -342,7 +342,7 @@ warning: could not parse code block as Rust code = note: error from rustc: unterminated character literal ``` -## bare_urls +## `bare_urls` This lint is **warn-by-default**. It detects URLs which are not links. For example: diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 141d5d2d2b2d0..537ab48bbfc12 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -22,7 +22,7 @@ As detailed in [the chapter on documentation tests][doctest-attributes], you can nightly, you can optionally add an error number to state that a doctest should emit a specific error number: -[doctest-attributes]: documentation-tests.html#attributes +[doctest-attributes]: write-documentation/documentation-tests.html#attributes ``````markdown ```compile_fail,E0044 @@ -45,6 +45,8 @@ and enabled with a `#![feature(...)]` attribute in your crate. ### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on. This has two effects: @@ -86,6 +88,8 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. ### `doc_auto_cfg`: Automatically generate `#[doc(cfg)]` + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + `doc_auto_cfg` is an extension to the `#[doc(cfg)]` feature. With it, you don't need to add `#[doc(cfg(...)]` anymore unless you want to override the default behaviour. So if we take the previous source code: @@ -123,6 +127,8 @@ And `doc` won't show up anymore! ### Adding your trait to the "Notable traits" dialog + * Tracking issue: [#45040](https://github.com/rust-lang/rust/issues/45040) + Rustdoc keeps a list of a few traits that are believed to be "fundamental" to types that implement them. These traits are intended to be the primary interface for their implementers, and are often most of the API available to be documented @@ -146,6 +152,8 @@ and [its tracking issue][issue-notable_trait]. ### Exclude certain dependencies from documentation + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + The standard library uses several dependencies which, in turn, use several types and traits from the standard library. In addition, there are several compiler-internal crates that are not considered to be part of the official standard library, and thus would be a distraction to include in @@ -164,8 +172,7 @@ Book][unstable-masked] and [its tracking issue][issue-masked]. [unstable-masked]: ../unstable-book/language-features/doc-masked.html [issue-masked]: https://github.com/rust-lang/rust/issues/44027 - -## Document primitives +### Document primitives This is for Rust compiler internal use only. @@ -174,7 +181,7 @@ attributes. The `#[doc(primitive)]` attribute is used by the standard library to to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to enable. -## Document keywords +### Document keywords This is for Rust compiler internal use only. @@ -199,6 +206,8 @@ the flag in question to Rustdoc on the command-line. To do this from Cargo, you ### `--markdown-before-content`: include rendered Markdown before the content + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + Using this flag looks like this: ```bash @@ -241,7 +250,7 @@ attribute][doc-playground]. Please be aware that the official Rust Playground at https://play.rust-lang.org does not have every crate available, so if your examples require your crate, make sure the playground you provide has your crate available. -[doc-playground]: the-doc-attribute.html#html_playground_url +[doc-playground]: write-documentation/the-doc-attribute.html#html_playground_url If both `--playground-url` and `--markdown-playground-url` are present when rendering a standalone Markdown file, the URL given to `--markdown-playground-url` will take precedence. If both @@ -279,6 +288,8 @@ between compilations. ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs + * Tracking issue: [#54765](https://github.com/rust-lang/rust/issues/54765) + Using this flag looks like this: ```bash @@ -331,6 +342,24 @@ Using `index-page` option enables `enable-index-page` option as well. This feature allows the generation of a default index-page which lists the generated crates. +### `--nocapture`: disable output capture for test + +When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be +captured by rustdoc. Instead, the output will be directed to your terminal, +as if you had run the test executable manually. This is especially useful +for debugging your tests! + +### `--check`: only checks the documentation + +When this flag is supplied, rustdoc will type check and lint your code, but will not generate any +documentation or run your doctests. + +Using this flag looks like: + +```bash +rustdoc -Z unstable-options --check src/lib.rs +``` + ### `--static-root-path`: control how static files are loaded in HTML output Using this flag looks like this: @@ -348,6 +377,8 @@ renamed with `--resource-suffix` will load from the given path. ### `--persist-doctests`: persist doctest executables after running + * Tracking issue: [#56925](https://github.com/rust-lang/rust/issues/56925) + Using this flag looks like this: ```bash @@ -360,6 +391,8 @@ with this option, you can keep those binaries around for farther testing. ### `--show-coverage`: calculate the percentage of items with documentation + * Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154) + Using this flag looks like this: ```bash @@ -438,6 +471,8 @@ information. ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using this flag looks like this: ```bash @@ -471,6 +506,8 @@ override `ignore`. ### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using these options looks like this: ```bash @@ -488,6 +525,8 @@ Another use case would be to run a test inside an emulator, or through a Virtual ### `--with-examples`: include examples of uses of items as documentation + * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) + This option, combined with `--scrape-examples-target-crate` and `--scrape-examples-output-path`, is used to implement the functionality in [RFC #3123](https://github.com/rust-lang/rfcs/pull/3123). Uses of an item (currently @@ -515,6 +554,8 @@ add the `--scrape-tests` flag. ### `--check-cfg`: check configuration flags + * Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450) + This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags. Using this flag looks like this: diff --git a/src/doc/rustdoc/src/website-features.md b/src/doc/rustdoc/src/website-features.md deleted file mode 100644 index 5fade4e84a992..0000000000000 --- a/src/doc/rustdoc/src/website-features.md +++ /dev/null @@ -1,25 +0,0 @@ -# Website features - -These features are about using the website generated by `rustdoc`. - -## Custom search engines - -If you find yourself often referencing online Rust docs you might enjoy using a custom search -engine. This allows you to use the navigation bar directly to search a `rustdoc` website. -Most browsers support this feature by letting you define a URL template containing `%s` -which will be substituted for the search term. As an example, for the standard library you could use -this template: - -```text -https://doc.rust-lang.org/stable/std/?search=%s -``` - -Note that this will take you to a results page listing all matches. If you want to navigate to the first -result right away (which is often the best match) use the following instead: - -```text -https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true -``` - -This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL -to automatically go to the first result. diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md similarity index 99% rename from src/doc/rustdoc/src/documentation-tests.md rename to src/doc/rustdoc/src/write-documentation/documentation-tests.md index 534fd19b52eb2..1cb5b049df404 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -269,7 +269,7 @@ By default, this will still hide `unused` warnings, since so many examples use p you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. -[test-attr]: ./the-doc-attribute.md#testattr +[test-attr]: the-doc-attribute.md#testattr ## Documenting macros diff --git a/src/doc/rustdoc/src/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md similarity index 98% rename from src/doc/rustdoc/src/linking-to-items-by-name.md rename to src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md index 6ca1d1153b494..36bc312b9c99a 100644 --- a/src/doc/rustdoc/src/linking-to-items-by-name.md +++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md @@ -35,7 +35,7 @@ link to `Option`. You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and `crate`. Associated items (functions, types, and constants) are supported, but [not for blanket trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in -[the standard library documentation](../std/index.html#primitives). +[the standard library documentation](../../std/index.html#primitives). [#79682]: https://github.com/rust-lang/rust/pull/79682 diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md similarity index 98% rename from src/doc/rustdoc/src/the-doc-attribute.md rename to src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index c5cc84022e389..25ef8b5bb9141 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -38,7 +38,7 @@ but given that docs are rendered via Markdown, it will remove these newlines. Another use case is for including external files as documentation: ```rust,no_run -#[doc = include_str!("../README.md")] +#[doc = include_str!("../../README.md")] # fn f() {} ``` @@ -73,7 +73,7 @@ left hand side of the docs. #![doc(html_logo_url = "https://example.com/logo.jpg")] ``` -This will put `logo` into +This will put `logo` into your docs, where the string for the attribute goes into the `{}`. If you don't use this attribute, there will be no logo. diff --git a/src/doc/rustdoc/src/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md similarity index 99% rename from src/doc/rustdoc/src/what-to-include.md rename to src/doc/rustdoc/src/write-documentation/what-to-include.md index 2a6b62ebfd552..35e6ccbc38807 100644 --- a/src/doc/rustdoc/src/what-to-include.md +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -122,4 +122,4 @@ Here is an example of a new theme, [Ayu]. [API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden [Documentation tests]: documentation-tests.md [on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme -[rustdoc-lints]: lints.md +[rustdoc-lints]: ../lints.md From 5226395d6faef77a5f1dadb6235bcd99352e1843 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 5 Mar 2022 17:19:04 +0100 Subject: [PATCH 07/15] Fix soundness issue in scoped threads. --- library/std/src/thread/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 5ffc86b4560fc..56baa7e445588 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1293,6 +1293,23 @@ impl<'scope, T> Drop for Packet<'scope, T> { // panicked, and nobody consumed the panic payload, we make sure // the scope function will panic. let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result before decrementing the number of running + // threads, because the Drop implementation might still use things + // it borrowed from 'scope. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this drop panics, that just results in an abort, because + // we're outside of the outermost `catch_unwind` of our thread. + // The same happens for detached non-scoped threads when dropping + // their ignored return value (or panic payload) panics, so + // there's no need to try to do anything better. + // (And even if we tried to handle it, we'd also need to handle + // the case where the panic payload we get out of it also panics + // on drop, and so on. See issue #86027.) + *self.result.get_mut() = None; + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. scope.decrement_num_running_threads(unhandled_panic); } } From 7a481ff8a412121b0a52c51c086ae22ed7e96ab5 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 5 Mar 2022 18:07:20 +0100 Subject: [PATCH 08/15] Properly abort when thread result panics on drop. --- library/std/src/lib.rs | 10 ++++----- library/std/src/thread/mod.rs | 40 ++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c35389d44f9fc..232b66230782f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -363,6 +363,11 @@ extern crate std as realstd; #[macro_use] mod macros; +// The runtime entry point and a few unstable public functions used by the +// compiler +#[macro_use] +pub mod rt; + // The Rust prelude pub mod prelude; @@ -547,11 +552,6 @@ pub mod arch { #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; -// The runtime entry point and a few unstable public functions used by the -// compiler -#[macro_use] -pub mod rt; - // Platform-abstraction modules mod sys; mod sys_common; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 56baa7e445588..74b29454b94a4 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1287,29 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {} impl<'scope, T> Drop for Packet<'scope, T> { fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } // Book-keeping so the scope knows when it's done. if let Some(scope) = self.scope { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result before decrementing the number of running - // threads, because the Drop implementation might still use things - // it borrowed from 'scope. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this drop panics, that just results in an abort, because - // we're outside of the outermost `catch_unwind` of our thread. - // The same happens for detached non-scoped threads when dropping - // their ignored return value (or panic payload) panics, so - // there's no need to try to do anything better. - // (And even if we tried to handle it, we'd also need to handle - // the case where the panic payload we get out of it also panics - // on drop, and so on. See issue #86027.) - *self.result.get_mut() = None; // Now that there will be no more user code running on this thread // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. scope.decrement_num_running_threads(unhandled_panic); } } From 1c06eb7c1f416055d7ede098f35bcf22cf85b7f8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Mar 2022 11:47:46 +0100 Subject: [PATCH 09/15] Remove outdated comment. --- library/std/src/thread/tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 3323ba36bf310..27eebd0ddf4ec 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -293,5 +293,3 @@ fn test_thread_id_not_equal() { assert!(thread::current().id() != spawned_id); } -// NOTE: the corresponding test for stderr is in ui/thread-stderr, due -// to the test harness apparently interfering with stderr configuration. From b97d87518d19e418220f726e774ffceadb4d33b9 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Mar 2022 11:47:53 +0100 Subject: [PATCH 10/15] Add soundness test for dropping scoped thread results before joining. --- library/std/src/thread/tests.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 27eebd0ddf4ec..7386fe1c442ab 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -4,10 +4,11 @@ use crate::mem; use crate::panic::panic_any; use crate::result; use crate::sync::{ + atomic::{AtomicBool, Ordering}, mpsc::{channel, Sender}, Arc, Barrier, }; -use crate::thread::{self, ThreadId}; +use crate::thread::{self, Scope, ThreadId}; use crate::time::Duration; use crate::time::Instant; @@ -293,3 +294,25 @@ fn test_thread_id_not_equal() { assert!(thread::current().id() != spawned_id); } +#[test] +fn test_scoped_threads_drop_result_before_join() { + let actually_finished = &AtomicBool::new(false); + struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool); + impl Drop for X<'_, '_> { + fn drop(&mut self) { + thread::sleep(Duration::from_millis(20)); + let actually_finished = self.1; + self.0.spawn(move || { + thread::sleep(Duration::from_millis(20)); + actually_finished.store(true, Ordering::Relaxed); + }); + } + } + thread::scope(|s| { + s.spawn(move || { + thread::sleep(Duration::from_millis(20)); + X(s, actually_finished) + }); + }); + assert!(actually_finished.load(Ordering::Relaxed)); +} From e346920907d1dec22d2dcc19b0dc483b9a94810b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Wed, 9 Mar 2022 11:18:28 +0100 Subject: [PATCH 11/15] Also take in account mdbook redirect in linkchecker --- src/tools/linkchecker/main.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 46daaf42883f0..c9b1649200d9c 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -489,16 +489,22 @@ fn is_exception(file: &Path, link: &str) -> bool { /// If the given HTML file contents is an HTML redirect, this returns the /// destination path given in the redirect. fn maybe_redirect(source: &str) -> Option { - const REDIRECT: &str = "

Redirecting to Redirecting to Redirecting to... (source: &str, attr: &str, mut f: F) { From 109cdc754ed893edb25d2d2c1493023858c8eccb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 3 Mar 2022 21:46:45 -0800 Subject: [PATCH 12/15] suggest enabling generic_const_exprs feature if const is unevaluatable --- compiler/rustc_trait_selection/src/lib.rs | 1 + .../src/traits/const_evaluatable.rs | 88 +++++++++++++------ .../auxiliary/issue-94287-aux.rs | 21 +++++ .../generic_const_exprs/issue-94287.rs | 10 +++ .../generic_const_exprs/issue-94287.stderr | 14 +++ 5 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/issue-94287.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5569334ff3d20..0403c611d0b3f 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,6 +17,7 @@ #![feature(derive_default_enum)] #![feature(hash_drain_filter)] #![feature(label_break_value)] +#![feature(let_chains)] #![feature(let_else)] #![feature(never_type)] #![feature(crate_visibility_modifier)] diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1994faed70c66..a3121a4da5047 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -35,34 +35,14 @@ pub fn is_const_evaluatable<'cx, 'tcx>( span: Span, ) -> Result<(), NotConstEvaluatable> { debug!("is_const_evaluatable({:?})", uv); - if infcx.tcx.features().generic_const_exprs { - let tcx = infcx.tcx; + let tcx = infcx.tcx; + + if tcx.features().generic_const_exprs { match AbstractConst::new(tcx, uv)? { // We are looking at a generic abstract constant. Some(ct) => { - for pred in param_env.caller_bounds() { - match pred.kind().skip_binder() { - ty::PredicateKind::ConstEvaluatable(uv) => { - if let Some(b_ct) = AbstractConst::new(tcx, uv)? { - // Try to unify with each subtree in the AbstractConst to allow for - // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable` - // predicate for `(N + 1) * 2` - let result = - walk_abstract_const(tcx, b_ct, |b_ct| { - match try_unify(tcx, ct, b_ct) { - true => ControlFlow::BREAK, - false => ControlFlow::CONTINUE, - } - }); - - if let ControlFlow::Break(()) = result { - debug!("is_const_evaluatable: abstract_const ~~> ok"); - return Ok(()); - } - } - } - _ => {} // don't care - } + if satisfied_from_param_env(tcx, ct, param_env)? { + return Ok(()); } // We were unable to unify the abstract constant with @@ -163,6 +143,33 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } } + // If we're evaluating a foreign constant, under a nightly compiler without generic + // const exprs, AND it would've passed if that expression had been evaluated with + // generic const exprs, then suggest using generic const exprs. + if concrete.is_err() + && tcx.sess.is_nightly_build() + && !uv.def.did.is_local() + && !tcx.features().generic_const_exprs + && let Ok(Some(ct)) = AbstractConst::new(tcx, uv) + && satisfied_from_param_env(tcx, ct, param_env) == Ok(true) + { + tcx.sess + .struct_span_fatal( + // Slightly better span than just using `span` alone + if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span }, + "failed to evaluate generic const expression", + ) + .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`") + .span_suggestion_verbose( + rustc_span::DUMMY_SP, + "consider enabling this feature", + "#![feature(generic_const_exprs)]\n".to_string(), + rustc_errors::Applicability::MaybeIncorrect, + ) + .emit(); + rustc_errors::FatalError.raise(); + } + debug!(?concrete, "is_const_evaluatable"); match concrete { Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() { @@ -178,6 +185,37 @@ pub fn is_const_evaluatable<'cx, 'tcx>( } } +fn satisfied_from_param_env<'tcx>( + tcx: TyCtxt<'tcx>, + ct: AbstractConst<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> Result { + for pred in param_env.caller_bounds() { + match pred.kind().skip_binder() { + ty::PredicateKind::ConstEvaluatable(uv) => { + if let Some(b_ct) = AbstractConst::new(tcx, uv)? { + // Try to unify with each subtree in the AbstractConst to allow for + // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable` + // predicate for `(N + 1) * 2` + let result = + walk_abstract_const(tcx, b_ct, |b_ct| match try_unify(tcx, ct, b_ct) { + true => ControlFlow::BREAK, + false => ControlFlow::CONTINUE, + }); + + if let ControlFlow::Break(()) = result { + debug!("is_const_evaluatable: abstract_const ~~> ok"); + return Ok(true); + } + } + } + _ => {} // don't care + } + } + + Ok(false) +} + /// A tree representing an anonymous constant. /// /// This is only able to represent a subset of `MIR`, diff --git a/src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs new file mode 100644 index 0000000000000..df454dae7250f --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] + +use std::str::FromStr; + +pub struct If; + +pub trait True {} + +impl True for If {} + +pub struct FixedI32; + +impl FromStr for FixedI32 +where + If<{ FRAC <= 32 }>: True, +{ + type Err = (); + fn from_str(_s: &str) -> Result { + unimplemented!() + } +} diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-94287.rs b/src/test/ui/const-generics/generic_const_exprs/issue-94287.rs new file mode 100644 index 0000000000000..643126a4640a8 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-94287.rs @@ -0,0 +1,10 @@ +// aux-build:issue-94287-aux.rs +// build-fail + +extern crate issue_94287_aux; + +use std::str::FromStr; + +fn main() { + let _ = >::from_str(""); +} diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr new file mode 100644 index 0000000000000..c918651ba62d9 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-94287.stderr @@ -0,0 +1,14 @@ +error: failed to evaluate generic const expression + --> $DIR/auxiliary/issue-94287-aux.rs:15:8 + | +LL | If<{ FRAC <= 32 }>: True, + | ^^^^^^^^^^^^^^ + | + = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]` +help: consider enabling this feature + | +LL | #![feature(generic_const_exprs)] + | + +error: aborting due to previous error + From 687e53ebfe107fb81288df0273e581c55fd411a4 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 9 Mar 2022 22:37:44 -0600 Subject: [PATCH 13/15] Allow `cargo run` instead of `cargo run -p bootstrap` This was part of Mark's original PR in https://github.com/rust-lang/rust/commit/ecb424f12992a4aebace8a153d5efea040327a01, but I missed it when writing #92260. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index cae48d7951783..4e78399606445 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +default-members = ["src/bootstrap"] members = [ "src/bootstrap", "compiler/rustc", From 5f7ca55df6a89e3caa3131a13490cc01956149e7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Mar 2022 14:28:28 +0000 Subject: [PATCH 14/15] Revert accidental stabilization --- library/alloc/src/boxed.rs | 3 +-- library/alloc/tests/boxed.rs | 2 +- src/test/ui/consts/drop_box.rs | 4 ++++ src/test/ui/consts/drop_box.stderr | 11 +++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/drop_box.rs create mode 100644 src/test/ui/consts/drop_box.stderr diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 68bf59a01b3dd..f753189c68308 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1170,8 +1170,7 @@ impl Box { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box { +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { fn drop(&mut self) { // FIXME: Do nothing, drop is currently performed by compiler. } diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 0d7acfed8c6a1..9e5123be98990 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -160,7 +160,7 @@ fn const_box() { *boxed = 42; assert!(*boxed == 42); - *boxed + *Box::leak(boxed) }; assert!(VALUE == 42); diff --git a/src/test/ui/consts/drop_box.rs b/src/test/ui/consts/drop_box.rs new file mode 100644 index 0000000000000..58a373a967388 --- /dev/null +++ b/src/test/ui/consts/drop_box.rs @@ -0,0 +1,4 @@ +const fn f(_: Box) {} +//~^ ERROR destructors cannot be evaluated at compile-time + +fn main() {} diff --git a/src/test/ui/consts/drop_box.stderr b/src/test/ui/consts/drop_box.stderr new file mode 100644 index 0000000000000..b9d6581e8ecc8 --- /dev/null +++ b/src/test/ui/consts/drop_box.stderr @@ -0,0 +1,11 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop_box.rs:1:15 + | +LL | const fn f(_: Box) {} + | ^ - value is dropped here + | | + | constant functions cannot evaluate destructors + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. From 185e3b95ca198ec10e6777d31e2c8d92c43f2ce2 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 10 Mar 2022 11:16:33 -0500 Subject: [PATCH 15/15] RustWrapper: add missing include This is required after LLVM change 3c4410dfcaaf (aka https://reviews.llvm.org/D121168) did some includes cleanup. --- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index ef6c9ef6627d5..51739df067f9d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -9,6 +9,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Pass.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/Support/Signals.h" #include "llvm/ADT/Optional.h"