From 4d4ec97e0a11eae5878ae6715536875c5689f074 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Sun, 30 Jan 2022 22:16:41 +0000 Subject: [PATCH 01/12] Document char validity --- library/core/src/primitive_docs.rs | 38 ++++++++++++++++++++++++++---- library/std/src/primitive_docs.rs | 38 ++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 8fcd8cdeb1042..e8b4fffbdd275 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -279,16 +279,44 @@ mod prim_never {} /// /// The `char` type represents a single character. More specifically, since /// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode -/// scalar value]', which is similar to, but not the same as, a '[Unicode code -/// point]'. -/// -/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value -/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// scalar value]'. /// /// This documentation describes a number of methods and trait implementations on the /// `char` type. For technical reasons, there is additional, separate /// documentation in [the `std::char` module](char/index.html) as well. /// +/// # Validity +/// +/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' +/// other than a [surrogate code point]. This has a fixed numerical definition: +/// code points are in the range `'\0'` to `char::MAX` (`'\u{10FFFF}'`), inclusive. +/// Surrogate code points, used by UTF-16, are in the range U+D800 to U+DFFF. +/// +/// No `char` may be constructed, whether as a literal or at runtime, that is not a +/// Unicode scalar value: +/// +/// ```text +/// let forbidden_chars = [ +/// // Each of these is a compiler error +/// '\u{D800}', '\u{DFFF}', '\u{110000}', +/// +/// // Panics; from_u32 returns None. +/// char::from_u32(0xDE01).unwrap(), +/// +/// // Undefined behaviour +/// unsafe { char::from_u32_unchecked(0x110000) }, +/// ]; +/// ``` +/// +/// Unicode is regularly updated. Many USVs are not currently assigned to a +/// character, but may be in the future ("reserved"); some will never be a character +/// ("noncharacters"); and some may be given different meanings by different users +/// ("private use"). +/// +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point +/// /// # Representation /// /// `char` is always four bytes in size. This is a different representation than diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 8fcd8cdeb1042..e8b4fffbdd275 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -279,16 +279,44 @@ mod prim_never {} /// /// The `char` type represents a single character. More specifically, since /// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode -/// scalar value]', which is similar to, but not the same as, a '[Unicode code -/// point]'. -/// -/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value -/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// scalar value]'. /// /// This documentation describes a number of methods and trait implementations on the /// `char` type. For technical reasons, there is additional, separate /// documentation in [the `std::char` module](char/index.html) as well. /// +/// # Validity +/// +/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' +/// other than a [surrogate code point]. This has a fixed numerical definition: +/// code points are in the range `'\0'` to `char::MAX` (`'\u{10FFFF}'`), inclusive. +/// Surrogate code points, used by UTF-16, are in the range U+D800 to U+DFFF. +/// +/// No `char` may be constructed, whether as a literal or at runtime, that is not a +/// Unicode scalar value: +/// +/// ```text +/// let forbidden_chars = [ +/// // Each of these is a compiler error +/// '\u{D800}', '\u{DFFF}', '\u{110000}', +/// +/// // Panics; from_u32 returns None. +/// char::from_u32(0xDE01).unwrap(), +/// +/// // Undefined behaviour +/// unsafe { char::from_u32_unchecked(0x110000) }, +/// ]; +/// ``` +/// +/// Unicode is regularly updated. Many USVs are not currently assigned to a +/// character, but may be in the future ("reserved"); some will never be a character +/// ("noncharacters"); and some may be given different meanings by different users +/// ("private use"). +/// +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point +/// /// # Representation /// /// `char` is always four bytes in size. This is a different representation than From c790128c3c2c26a4ca347fd68cffd4000ecb3295 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Fri, 28 Jan 2022 05:21:34 -0800 Subject: [PATCH 02/12] Improve wrapping on settings page Previously, the radio button choices for themes would wrap awkwardly on narrow screens. With this change, the group of choices will prefer bumping down to the next line together, leaving the setting name on its own line. Also fix some minor spacing issues: - Align the setting name vertically with the radio button choices. - Use margin instead of padding for most spacing choices. - Use no margin/padding on the right-hand side. --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/static/css/settings.css | 16 +++++++++------- src/test/rustdoc-gui/mobile.goml | 6 ++++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 32e4a82918421..a512511cff3b0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -376,7 +376,7 @@ impl Setting { description, ), Setting::Select { js_data_name, description, default_value, ref options } => format!( - "
{}{}
", + "
{}
{}
", js_data_name, description, options diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 932000487b0a8..7b337c2bc7a33 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -1,5 +1,5 @@ .setting-line { - padding: 5px; + margin: 0.6em 0 0.6em 0.3em; position: relative; } @@ -17,17 +17,16 @@ border-bottom: 1px solid; } -.setting-line .radio-line { +.setting-line .radio-line, +.setting-line .choices { display: flex; flex-wrap: wrap; } -.setting-line .radio-line > * { - padding: 0.3em; -} - .setting-line .radio-line .setting-name { flex-grow: 1; + margin-top: auto; + margin-bottom: auto; } .setting-line .radio-line input { @@ -38,7 +37,10 @@ border-radius: 0.1em; border: 1px solid; margin-left: 0.5em; - min-width: 3.5em; + margin-top: 0.1em; + margin-bottom: 0.1em; + min-width: 3.8em; + padding: 0.3em; } .toggle { diff --git a/src/test/rustdoc-gui/mobile.goml b/src/test/rustdoc-gui/mobile.goml index acde112392521..9edf662976d59 100644 --- a/src/test/rustdoc-gui/mobile.goml +++ b/src/test/rustdoc-gui/mobile.goml @@ -15,3 +15,9 @@ assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" } size: (1000, 1000) assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" }) + +// On the settings page, the theme buttons should not line-wrap. Instead, they should +// all be placed as a group on a line below the setting name "Theme." +goto: file://|DOC_PATH|/settings.html +size: (400, 600) +compare-elements-position-near-false: ("#preferred-light-theme .setting-name", "#preferred-light-theme .choice", {"y": 16}) From 5357ec1473c8a44dd8e324b2c664951bf4306b5a Mon Sep 17 00:00:00 2001 From: George Bateman Date: Mon, 31 Jan 2022 23:49:16 +0000 Subject: [PATCH 03/12] (#93493) Add items from code review --- library/core/src/primitive_docs.rs | 50 +++++++++++++++++++++--------- library/std/src/primitive_docs.rs | 50 +++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index e8b4fffbdd275..b9d71178921f7 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -289,32 +289,52 @@ mod prim_never {} /// /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' /// other than a [surrogate code point]. This has a fixed numerical definition: -/// code points are in the range `'\0'` to `char::MAX` (`'\u{10FFFF}'`), inclusive. -/// Surrogate code points, used by UTF-16, are in the range U+D800 to U+DFFF. +/// code points are in the range 0 to 0x10FFFF, inclusive. +/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a /// Unicode scalar value: /// /// ```text -/// let forbidden_chars = [ -/// // Each of these is a compiler error -/// '\u{D800}', '\u{DFFF}', '\u{110000}', +/// // Each of these is a compiler error +/// ['\u{D800}', '\u{DFFF}', '\u{110000}']; +/// ``` /// -/// // Panics; from_u32 returns None. -/// char::from_u32(0xDE01).unwrap(), +/// ```should_panic +/// // Panics; from_u32 returns None. +/// char::from_u32(0xDE01).unwrap(); +/// ``` /// -/// // Undefined behaviour -/// unsafe { char::from_u32_unchecked(0x110000) }, -/// ]; +/// ``` +/// // Undefined behaviour +/// unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// Unicode is regularly updated. Many USVs are not currently assigned to a -/// character, but may be in the future ("reserved"); some will never be a character -/// ("noncharacters"); and some may be given different meanings by different users -/// ("private use"). +/// USVs are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store +/// any `char` in a `str` or read any character from a `str` as a `char`. +/// +/// The gap in valid `char` values is understood by the compiler, so in the +/// below example the two ranges are understood to cover the whole range of +/// possible `char` values and there is no error for a [non-exhaustive match]. +/// +/// ``` +/// let c: char = 'a'; +/// match c { +/// '\0' ..= '\u{D7FF}' => false, +/// '\u{E000}' ..= '\u{10FFFF}' => true, +/// }; +/// ``` +/// +/// All USVs are valid `char` values, but not all of them represent a real +/// character. Many USVs are not currently assigned to a character, but may be +/// in the future ("reserved"); some will never be a character +/// ("noncharacters"); and some may be given different meanings by different +/// users ("private use"). /// -/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value /// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive /// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point /// /// # Representation diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index e8b4fffbdd275..b9d71178921f7 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -289,32 +289,52 @@ mod prim_never {} /// /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' /// other than a [surrogate code point]. This has a fixed numerical definition: -/// code points are in the range `'\0'` to `char::MAX` (`'\u{10FFFF}'`), inclusive. -/// Surrogate code points, used by UTF-16, are in the range U+D800 to U+DFFF. +/// code points are in the range 0 to 0x10FFFF, inclusive. +/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a /// Unicode scalar value: /// /// ```text -/// let forbidden_chars = [ -/// // Each of these is a compiler error -/// '\u{D800}', '\u{DFFF}', '\u{110000}', +/// // Each of these is a compiler error +/// ['\u{D800}', '\u{DFFF}', '\u{110000}']; +/// ``` /// -/// // Panics; from_u32 returns None. -/// char::from_u32(0xDE01).unwrap(), +/// ```should_panic +/// // Panics; from_u32 returns None. +/// char::from_u32(0xDE01).unwrap(); +/// ``` /// -/// // Undefined behaviour -/// unsafe { char::from_u32_unchecked(0x110000) }, -/// ]; +/// ``` +/// // Undefined behaviour +/// unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// Unicode is regularly updated. Many USVs are not currently assigned to a -/// character, but may be in the future ("reserved"); some will never be a character -/// ("noncharacters"); and some may be given different meanings by different users -/// ("private use"). +/// USVs are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store +/// any `char` in a `str` or read any character from a `str` as a `char`. +/// +/// The gap in valid `char` values is understood by the compiler, so in the +/// below example the two ranges are understood to cover the whole range of +/// possible `char` values and there is no error for a [non-exhaustive match]. +/// +/// ``` +/// let c: char = 'a'; +/// match c { +/// '\0' ..= '\u{D7FF}' => false, +/// '\u{E000}' ..= '\u{10FFFF}' => true, +/// }; +/// ``` +/// +/// All USVs are valid `char` values, but not all of them represent a real +/// character. Many USVs are not currently assigned to a character, but may be +/// in the future ("reserved"); some will never be a character +/// ("noncharacters"); and some may be given different meanings by different +/// users ("private use"). /// -/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value /// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive /// [surrogate code point]: https://www.unicode.org/glossary/#surrogate_code_point /// /// # Representation From 76aa92906bb60adc36ea79393702b9585df6e9ed Mon Sep 17 00:00:00 2001 From: TheVoid <593767573@qq.com> Date: Tue, 1 Feb 2022 10:19:08 +0800 Subject: [PATCH 04/12] Fix incorrect panic message in example --- library/std/src/net/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 1ba54d892e3ce..cc4e4fd4fdc77 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -405,7 +405,7 @@ impl TcpStream { /// use std::net::TcpStream; /// /// let stream = TcpStream::connect("127.0.0.1:8000") - /// .expect("couldn't bind to address"); + /// .expect("Couldn't connect to the server..."); /// let mut buf = [0; 10]; /// let len = stream.peek(&mut buf).expect("peek failed"); /// ``` From 95bd87f849ebbd6a6d4bc24c318c40986a78b4f4 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Tue, 11 Jan 2022 13:09:05 +0530 Subject: [PATCH 05/12] librustdoc: impl core::fmt::Write for rustdoc::html::render::Buffer Signed-off-by: Muhammad Falak R Wani --- src/librustdoc/html/format.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 08840626259dc..47d626a1d8877 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -64,6 +64,12 @@ crate struct Buffer { buffer: String, } +impl core::fmt::Write for Buffer { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.buffer.write_str(s) + } +} + impl Buffer { crate fn empty_from(v: &Buffer) -> Buffer { Buffer { for_html: v.for_html, buffer: String::new() } From 66d7e50cb6424f1928eb810e0bbc6d856e22a567 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Tue, 11 Jan 2022 19:28:11 +0530 Subject: [PATCH 06/12] librustdoc: inline and forward all methods for `impl Write for Buffer` Signed-off-by: Muhammad Falak R Wani --- src/librustdoc/html/format.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 47d626a1d8877..f4df9ef4a8c9d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -65,9 +65,20 @@ crate struct Buffer { } impl core::fmt::Write for Buffer { + #[inline] fn write_str(&mut self, s: &str) -> fmt::Result { self.buffer.write_str(s) } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.buffer.write_char(c) + } + + #[inline] + fn write_fmt(self: &mut Self, args: fmt::Arguments<'_>) -> fmt::Result { + self.buffer.write_fmt(args) + } } impl Buffer { From 62bea63888a7f1753c019852258d20788a544dfb Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Tue, 1 Feb 2022 18:06:58 +0530 Subject: [PATCH 07/12] librustdoc: render: use render_into instead of creating a temp string Signed-off-by: Muhammad Falak R Wani --- src/librustdoc/html/render/print_item.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f2c111495edfb..6592a56ba46a8 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -139,8 +139,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, src_href: src_href.as_deref(), }; - let heading = item_vars.render().unwrap(); - buf.write_str(&heading); + item_vars.render_into(buf).unwrap(); match *item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), From e22729b46466a171b020f601e40e5e50283b1d8b Mon Sep 17 00:00:00 2001 From: Daniel Frampton Date: Tue, 1 Feb 2022 12:40:01 -0800 Subject: [PATCH 08/12] Add missing | between print options --- compiler/rustc_session/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a756de4c0fc45..d2d5b06ad67b6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1188,7 +1188,7 @@ pub fn rustc_short_optgroups() -> Vec { "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ target-cpus|target-features|relocation-models|code-models|\ - tls-models|target-spec-json|native-static-libs|stack-protector-strategies\ + tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\ link-args]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), From 63b12aea27a5a6cd7a792660bbdeacb6c7eafbef Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Tue, 1 Feb 2022 22:32:02 +0100 Subject: [PATCH 09/12] Fix two incorrect "it's" --- compiler/rustc_middle/src/mir/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b1ab0f5b533dd..e9e6d61331077 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1642,7 +1642,7 @@ pub enum FakeReadCause { ForMatchedPlace(Option), /// A fake read of the RefWithinGuard version of a bind-by-value variable - /// in a match guard to ensure that it's value hasn't change by the time + /// in a match guard to ensure that its value hasn't change by the time /// we create the OutsideGuard version. ForGuardBinding, @@ -2939,7 +2939,7 @@ impl Location { let mut visited = FxHashSet::default(); while let Some(block) = queue.pop() { - // If we haven't visited this block before, then make sure we visit it's predecessors. + // If we haven't visited this block before, then make sure we visit its predecessors. if visited.insert(block) { queue.extend(predecessors[block].iter().cloned()); } else { From d372baf3f9a6401fdd4f74e3385ba553667b287d Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 1 Feb 2022 21:44:53 +0000 Subject: [PATCH 10/12] Fix annotation of code blocks --- library/core/src/primitive_docs.rs | 5 +++-- library/std/src/primitive_docs.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index b9d71178921f7..ebb1d8971b99d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -275,6 +275,7 @@ mod prim_bool {} mod prim_never {} #[doc(primitive = "char")] +#[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. /// /// The `char` type represents a single character. More specifically, since @@ -295,7 +296,7 @@ mod prim_never {} /// No `char` may be constructed, whether as a literal or at runtime, that is not a /// Unicode scalar value: /// -/// ```text +/// ```compile_fail /// // Each of these is a compiler error /// ['\u{D800}', '\u{DFFF}', '\u{110000}']; /// ``` @@ -305,7 +306,7 @@ mod prim_never {} /// char::from_u32(0xDE01).unwrap(); /// ``` /// -/// ``` +/// ```no_run /// // Undefined behaviour /// unsafe { char::from_u32_unchecked(0x110000) }; /// ``` diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index b9d71178921f7..ebb1d8971b99d 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -275,6 +275,7 @@ mod prim_bool {} mod prim_never {} #[doc(primitive = "char")] +#[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. /// /// The `char` type represents a single character. More specifically, since @@ -295,7 +296,7 @@ mod prim_never {} /// No `char` may be constructed, whether as a literal or at runtime, that is not a /// Unicode scalar value: /// -/// ```text +/// ```compile_fail /// // Each of these is a compiler error /// ['\u{D800}', '\u{DFFF}', '\u{110000}']; /// ``` @@ -305,7 +306,7 @@ mod prim_never {} /// char::from_u32(0xDE01).unwrap(); /// ``` /// -/// ``` +/// ```no_run /// // Undefined behaviour /// unsafe { char::from_u32_unchecked(0x110000) }; /// ``` From d6c508b759093f9cb33aba5d125534ffd853e839 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 21 Jan 2022 00:15:39 +0000 Subject: [PATCH 11/12] Do not point at whole file missing `fn main` Only point at the end of the crate. We could try making it point at the beginning of the crate, but that is confused with `DUMMY_SP`, causing the output to be *worse*. This change will make it so that VSCode will *not* underline the whole file when `main` is missing, so other errors will be visible. --- compiler/rustc_passes/src/entry.rs | 6 +++--- src/test/ui/attributes/issue-90873.rs | 2 +- src/test/ui/attributes/issue-90873.stderr | 16 +++++---------- .../cfg-attr-cfg-2.stderr | 7 +++---- .../cfg-in-crate-1.stderr | 4 ++-- src/test/ui/continue-after-missing-main.rs | 4 ++-- .../ui/continue-after-missing-main.stderr | 12 +++-------- src/test/ui/elided-test.stderr | 8 +++----- ...orted_main_const_fn_item_type_forbidden.rs | 3 +-- ...d_main_const_fn_item_type_forbidden.stderr | 20 +++++++------------ .../imported_main_const_forbidden.rs | 3 +-- .../imported_main_const_forbidden.stderr | 16 +++++---------- src/test/ui/main-wrong-location.rs | 3 +-- src/test/ui/main-wrong-location.stderr | 13 ++++-------- src/test/ui/missing/missing-main.stderr | 4 ++-- src/test/ui/parser/issues/issue-49040.stderr | 4 ++-- 16 files changed, 45 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index fdabe41dafaed..f5040a373c296 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -218,9 +218,9 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. - if tcx.sess.source_map().lookup_line(sp.lo()).is_ok() { - err.set_span(sp); - err.span_label(sp, ¬e); + if tcx.sess.source_map().lookup_line(sp.hi()).is_ok() { + err.set_span(sp.shrink_to_hi()); + err.span_label(sp.shrink_to_hi(), ¬e); } else { err.note(¬e); } diff --git a/src/test/ui/attributes/issue-90873.rs b/src/test/ui/attributes/issue-90873.rs index 76708ea98305f..0f62d4153089a 100644 --- a/src/test/ui/attributes/issue-90873.rs +++ b/src/test/ui/attributes/issue-90873.rs @@ -1,9 +1,9 @@ #![u=||{static d=||1;}] //~^ unexpected token //~| cannot find attribute `u` in this scope -//~| `main` function not found in crate `issue_90873` //~| missing type for `static` item #![a={impl std::ops::Neg for i8 {}}] //~^ ERROR unexpected token //~| ERROR cannot find attribute `a` in this scope +//~| ERROR `main` function not found in crate `issue_90873` diff --git a/src/test/ui/attributes/issue-90873.stderr b/src/test/ui/attributes/issue-90873.stderr index 2718b65108cdd..fbdc05ef6f004 100644 --- a/src/test/ui/attributes/issue-90873.stderr +++ b/src/test/ui/attributes/issue-90873.stderr @@ -10,7 +10,7 @@ LL | #![u=||{static d=||1;}] error: unexpected token: `{ impl std::ops::Neg for i8 {} }` - --> $DIR/issue-90873.rs:7:6 + --> $DIR/issue-90873.rs:6:6 | LL | #![a={impl std::ops::Neg for i8 {}}] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,22 +22,16 @@ LL | #![u=||{static d=||1;}] | ^ error: cannot find attribute `a` in this scope - --> $DIR/issue-90873.rs:7:4 + --> $DIR/issue-90873.rs:6:4 | LL | #![a={impl std::ops::Neg for i8 {}}] | ^ error[E0601]: `main` function not found in crate `issue_90873` - --> $DIR/issue-90873.rs:1:1 + --> $DIR/issue-90873.rs:6:37 | -LL | / #![u=||{static d=||1;}] -LL | | -LL | | -LL | | -LL | | -LL | | -LL | | #![a={impl std::ops::Neg for i8 {}}] - | |____________________________________^ consider adding a `main` function to `$DIR/issue-90873.rs` +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^ consider adding a `main` function to `$DIR/issue-90873.rs` error: missing type for `static` item --> $DIR/issue-90873.rs:1:16 diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr index e9df780def5df..d61872c48ea96 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -1,9 +1,8 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` - --> $DIR/cfg-attr-cfg-2.rs:8:1 + --> $DIR/cfg-attr-cfg-2.rs:9:14 | -LL | / #[cfg_attr(foo, cfg(bar))] -LL | | fn main() { } - | |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` +LL | fn main() { } + | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr index 0b5c3e0335586..ff72c43efbd08 100644 --- a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,8 +1,8 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` - --> $DIR/cfg-in-crate-1.rs:3:1 + --> $DIR/cfg-in-crate-1.rs:3:13 | LL | #![cfg(bar)] - | ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` + | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` error: aborting due to previous error diff --git a/src/test/ui/continue-after-missing-main.rs b/src/test/ui/continue-after-missing-main.rs index 55796408e9d79..1019cacce6421 100644 --- a/src/test/ui/continue-after-missing-main.rs +++ b/src/test/ui/continue-after-missing-main.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] //~ ERROR `main` function not found in crate +#![allow(dead_code)] struct Tableau<'a, MP> { provider: &'a MP, @@ -27,4 +27,4 @@ fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( ) { let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); //~^ ERROR lifetime mismatch -} +} //~ ERROR `main` function not found in crate diff --git a/src/test/ui/continue-after-missing-main.stderr b/src/test/ui/continue-after-missing-main.stderr index 439f9e5221f66..29e7dc1e56c73 100644 --- a/src/test/ui/continue-after-missing-main.stderr +++ b/src/test/ui/continue-after-missing-main.stderr @@ -1,14 +1,8 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` - --> $DIR/continue-after-missing-main.rs:1:1 + --> $DIR/continue-after-missing-main.rs:30:2 | -LL | / #![allow(dead_code)] -LL | | -LL | | struct Tableau<'a, MP> { -LL | | provider: &'a MP, -... | -LL | | -LL | | } - | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` +LL | } + | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` error[E0623]: lifetime mismatch --> $DIR/continue-after-missing-main.rs:28:56 diff --git a/src/test/ui/elided-test.stderr b/src/test/ui/elided-test.stderr index 175bd033067bc..c74c307c492fe 100644 --- a/src/test/ui/elided-test.stderr +++ b/src/test/ui/elided-test.stderr @@ -1,10 +1,8 @@ error[E0601]: `main` function not found in crate `elided_test` - --> $DIR/elided-test.rs:5:1 + --> $DIR/elided-test.rs:7:2 | -LL | / #[test] -LL | | fn main() { -LL | | } - | |_^ consider adding a `main` function to `$DIR/elided-test.rs` +LL | } + | ^ consider adding a `main` function to `$DIR/elided-test.rs` error: aborting due to previous error diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs index e0bb7dbfae9f1..dab9c687e2498 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -1,7 +1,6 @@ #![feature(imported_main)] #![feature(type_alias_impl_trait)] #![allow(incomplete_features)] -//~^^^ ERROR `main` function not found in crate pub mod foo { type MainFn = impl Fn(); //~^ ERROR could not find defining uses @@ -11,4 +10,4 @@ pub mod foo { //~^ ERROR mismatched types [E0308] } -use foo::BAR as main; +use foo::BAR as main; //~ ERROR `main` function not found in crate diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index c731c32832222..b9bc0262a56b2 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -1,19 +1,13 @@ error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden` - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:1:1 + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:13:22 | -LL | / #![feature(imported_main)] -LL | | #![feature(type_alias_impl_trait)] -LL | | #![allow(incomplete_features)] -LL | | -... | -LL | | -LL | | use foo::BAR as main; - | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs` - | | - | non-function item at `crate::main` is found +LL | use foo::BAR as main; + | ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs` + | | + | non-function item at `crate::main` is found error[E0308]: mismatched types - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29 + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:9:29 | LL | type MainFn = impl Fn(); | --------- the expected opaque type @@ -25,7 +19,7 @@ LL | pub const BAR: MainFn = bar; found fn item `fn() {bar}` error: could not find defining uses - --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19 + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:5:19 | LL | type MainFn = impl Fn(); | ^^^^^^^^^ diff --git a/src/test/ui/entry-point/imported_main_const_forbidden.rs b/src/test/ui/entry-point/imported_main_const_forbidden.rs index 989a6c97a8004..1508280c0fa57 100644 --- a/src/test/ui/entry-point/imported_main_const_forbidden.rs +++ b/src/test/ui/entry-point/imported_main_const_forbidden.rs @@ -1,7 +1,6 @@ #![feature(imported_main)] -//~^ ERROR `main` function not found in crate pub mod foo { pub const BAR: usize = 42; } -use foo::BAR as main; +use foo::BAR as main; //~ ERROR `main` function not found in crate diff --git a/src/test/ui/entry-point/imported_main_const_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_forbidden.stderr index 4640513c2bb5f..9d8b40dc3c9bc 100644 --- a/src/test/ui/entry-point/imported_main_const_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_forbidden.stderr @@ -1,16 +1,10 @@ error[E0601]: `main` function not found in crate `imported_main_const_forbidden` - --> $DIR/imported_main_const_forbidden.rs:1:1 + --> $DIR/imported_main_const_forbidden.rs:6:22 | -LL | / #![feature(imported_main)] -LL | | -LL | | pub mod foo { -LL | | pub const BAR: usize = 42; -LL | | } -LL | | -LL | | use foo::BAR as main; - | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs` - | | - | non-function item at `crate::main` is found +LL | use foo::BAR as main; + | ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs` + | | + | non-function item at `crate::main` is found error: aborting due to previous error diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs index f3acd80a7a48f..d7deeaed99da2 100644 --- a/src/test/ui/main-wrong-location.rs +++ b/src/test/ui/main-wrong-location.rs @@ -1,6 +1,5 @@ mod m { -//~^ ERROR `main` function not found // An inferred main entry point // must appear at the top of the crate fn main() { } -} +} //~ ERROR `main` function not found diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index 754ff0f80eb9a..0058af9b79ebf 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -1,16 +1,11 @@ error[E0601]: `main` function not found in crate `main_wrong_location` - --> $DIR/main-wrong-location.rs:1:1 + --> $DIR/main-wrong-location.rs:5:2 | -LL | / mod m { -LL | | -LL | | // An inferred main entry point -LL | | // must appear at the top of the crate -LL | | fn main() { } -LL | | } - | |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`) +LL | } + | ^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`) | note: here is a function named `main` - --> $DIR/main-wrong-location.rs:5:5 + --> $DIR/main-wrong-location.rs:4:5 | LL | fn main() { } | ^^^^^^^^^^^^^ diff --git a/src/test/ui/missing/missing-main.stderr b/src/test/ui/missing/missing-main.stderr index 6a35f5117efd6..5113dc6ec08c4 100644 --- a/src/test/ui/missing/missing-main.stderr +++ b/src/test/ui/missing/missing-main.stderr @@ -1,8 +1,8 @@ error[E0601]: `main` function not found in crate `missing_main` - --> $DIR/missing-main.rs:2:1 + --> $DIR/missing-main.rs:2:14 | LL | fn mian() { } - | ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs` + | ^ consider adding a `main` function to `$DIR/missing-main.rs` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-49040.stderr b/src/test/ui/parser/issues/issue-49040.stderr index 56befe3a0a75d..8af7838c79138 100644 --- a/src/test/ui/parser/issues/issue-49040.stderr +++ b/src/test/ui/parser/issues/issue-49040.stderr @@ -5,10 +5,10 @@ LL | #![allow(unused_variables)]; | ^ help: remove this semicolon error[E0601]: `main` function not found in crate `issue_49040` - --> $DIR/issue-49040.rs:1:1 + --> $DIR/issue-49040.rs:1:29 | LL | #![allow(unused_variables)]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs` + | ^ consider adding a `main` function to `$DIR/issue-49040.rs` error: aborting due to 2 previous errors From b26ad8d10fabe45ead09aff0e2cd5b5e1289274a Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 11 Jan 2022 21:56:10 +0000 Subject: [PATCH 12/12] Detect `::` -> `:` typo in type argument When writing `Vec`, suggest `Vec`. --- compiler/rustc_resolve/src/late.rs | 6 ++- .../rustc_resolve/src/late/diagnostics.rs | 37 +++++++++++++++ ...type-ascription-instead-of-path-in-type.rs | 14 ++++++ ...-ascription-instead-of-path-in-type.stderr | 46 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2c678e71ae179..6aed3223480f1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -400,6 +400,8 @@ struct DiagnosticMetadata<'ast> { /// Given `where ::Baz: String`, suggest `where T: Bar`. current_where_predicate: Option<&'ast WherePredicate>, + + current_type_path: Option<&'ast Ty>, } struct LateResolutionVisitor<'a, 'b, 'ast> { @@ -472,8 +474,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_ty(&mut self, ty: &'ast Ty) { let prev = self.diagnostic_metadata.current_trait_object; + let prev_ty = self.diagnostic_metadata.current_type_path; match ty.kind { TyKind::Path(ref qself, ref path) => { + self.diagnostic_metadata.current_type_path = Some(ty); self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } TyKind::ImplicitSelf => { @@ -490,6 +494,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } visit::walk_ty(self, ty); self.diagnostic_metadata.current_trait_object = prev; + self.diagnostic_metadata.current_type_path = prev_ty; } fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { self.smart_resolve_path( @@ -1936,7 +1941,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let instead = res.is_some(); let suggestion = if res.is_none() { this.report_missing_type_error(path) } else { None }; - // get_from_node_id this.r.use_injections.push(UseError { err, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7e1e5c788052b..d05f139e3bf5a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use std::iter; +use std::ops::Deref; use tracing::debug; @@ -265,6 +266,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } + self.detect_assoct_type_constraint_meant_as_path(base_span, &mut err); + // Emit special messages for unresolved `Self` and `self`. if is_self_type(path, ns) { err.code(rustc_errors::error_code!(E0411)); @@ -603,6 +606,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { (err, candidates) } + fn detect_assoct_type_constraint_meant_as_path( + &self, + base_span: Span, + err: &mut DiagnosticBuilder<'_>, + ) { + let Some(ty) = self.diagnostic_metadata.current_type_path else { return; }; + let TyKind::Path(_, path) = &ty.kind else { return; }; + for segment in &path.segments { + let Some(params) = &segment.args else { continue; }; + let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; }; + for param in ¶ms.args { + let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; }; + let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else { + continue; + }; + for bound in bounds { + let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) + = bound else + { + continue; + }; + if base_span == trait_ref.span { + err.span_suggestion_verbose( + constraint.ident.span.between(trait_ref.span), + "you might have meant to write a path instead of an associated type bound", + "::".to_string(), + Applicability::MachineApplicable, + ); + } + } + } + } + } + fn get_single_associated_item( &mut self, path: &[Segment], diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs new file mode 100644 index 0000000000000..48d19f6dd4e3f --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs @@ -0,0 +1,14 @@ +enum A { + B, +} + +fn main() { + let _: Vec = A::B; + //~^ ERROR cannot find trait `B` in this scope + //~| HELP you might have meant to write a path instead of an associated type bound + //~| ERROR associated type bounds are unstable + //~| HELP add `#![feature(associated_type_bounds)]` to the crate attributes to enable + //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied + //~| HELP add missing generic argument + //~| ERROR associated type bindings are not allowed here +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr new file mode 100644 index 0000000000000..951ff23d63563 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr @@ -0,0 +1,46 @@ +error[E0405]: cannot find trait `B` in this scope + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:18 + | +LL | let _: Vec = A::B; + | ^ not found in this scope + | +help: you might have meant to write a path instead of an associated type bound + | +LL | let _: Vec = A::B; + | ~~ + +error[E0658]: associated type bounds are unstable + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec = A::B; + | ^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12 + | +LL | let _: Vec = A::B; + | ^^^ expected at least 1 generic argument + | +note: struct defined here, with at least 1 generic parameter: `T` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub struct Vec { + | ^^^ - +help: add missing generic argument + | +LL | let _: Vec = A::B; + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec = A::B; + | ^^^ associated type not allowed here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0229, E0405, E0658. +For more information about an error, try `rustc --explain E0107`.