about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-02 09:39:18 +0000
committerbors <bors@rust-lang.org>2022-02-02 09:39:18 +0000
commit250384edc5d78533e993f38c60d64e42b21684b2 (patch)
treeccf15ae68cfe680aa65f11310e7006faf94401ae
parentd5f9c40e6a9ecc62432e71e886cef83a4c2c9b98 (diff)
parent344bb595302b1c20c212598e84c74f28030da3ad (diff)
downloadrust-250384edc5d78533e993f38c60d64e42b21684b2.tar.gz
rust-250384edc5d78533e993f38c60d64e42b21684b2.zip
Auto merge of #93573 - matthiaskrgr:rollup-nrjmygz, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #92758 (librustdoc: impl core::fmt::Write for rustdoc::html::render::Buffer)
 - #92788 (Detect `::` -> `:` typo in type argument)
 - #93420 (Improve wrapping on settings page)
 - #93493 (Document valid values of the char type)
 - #93531 (Fix incorrect panic message in example)
 - #93559 (Add missing | between print options)
 - #93560 (Fix two incorrect "it's" (typos in comments))

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs37
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--library/core/src/primitive_docs.rs59
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/primitive_docs.rs59
-rw-r--r--src/librustdoc/html/format.rs17
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs3
-rw-r--r--src/librustdoc/html/static/css/settings.css16
-rw-r--r--src/test/rustdoc-gui/mobile.goml6
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs14
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr46
14 files changed, 248 insertions, 25 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b1ab0f5b533..e9e6d613310 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<DefId>),
 
     /// 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 {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 2c678e71ae1..6aed3223480 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -400,6 +400,8 @@ struct DiagnosticMetadata<'ast> {
 
     /// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
     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 7e1e5c78805..d05f139e3bf 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 &params.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/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index a756de4c0fc..d2d5b06ad67 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<RustcOptGroup> {
             "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"),
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 8fcd8cdeb10..ebb1d8971b9 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -275,20 +275,69 @@ 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
 /// '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 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:
+///
+/// ```compile_fail
+/// // Each of these is a compiler error
+/// ['\u{D800}', '\u{DFFF}', '\u{110000}'];
+/// ```
+///
+/// ```should_panic
+/// // Panics; from_u32 returns None.
+/// char::from_u32(0xDE01).unwrap();
+/// ```
+///
+/// ```no_run
+/// // Undefined behaviour
+/// unsafe { char::from_u32_unchecked(0x110000) };
+/// ```
+///
+/// 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 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
 ///
 /// `char` is always four bytes in size. This is a different representation than
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 1ba54d892e3..cc4e4fd4fdc 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");
     /// ```
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 8fcd8cdeb10..ebb1d8971b9 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -275,20 +275,69 @@ 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
 /// '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 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:
+///
+/// ```compile_fail
+/// // Each of these is a compiler error
+/// ['\u{D800}', '\u{DFFF}', '\u{110000}'];
+/// ```
+///
+/// ```should_panic
+/// // Panics; from_u32 returns None.
+/// char::from_u32(0xDE01).unwrap();
+/// ```
+///
+/// ```no_run
+/// // Undefined behaviour
+/// unsafe { char::from_u32_unchecked(0x110000) };
+/// ```
+///
+/// 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 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
 ///
 /// `char` is always four bytes in size. This is a different representation than
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 08840626259..f4df9ef4a8c 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -64,6 +64,23 @@ crate struct Buffer {
     buffer: String,
 }
 
+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 {
     crate fn empty_from(v: &Buffer) -> Buffer {
         Buffer { for_html: v.for_html, buffer: String::new() }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index cc12b7ba05b..59a6187b62b 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!(
-                "<div class=\"setting-line\"><div class=\"radio-line\" id=\"{}\"><span class=\"setting-name\">{}</span>{}</div></div>",
+                "<div class=\"setting-line\"><div class=\"radio-line\" id=\"{}\"><span class=\"setting-name\">{}</span><div class=\"choices\">{}</div></div></div>",
                 js_data_name,
                 description,
                 options
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index f2c111495ed..6592a56ba46 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),
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 932000487b0..7b337c2bc7a 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 8f9c9248f5f..7be46a613c4 100644
--- a/src/test/rustdoc-gui/mobile.goml
+++ b/src/test/rustdoc-gui/mobile.goml
@@ -19,3 +19,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})
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 00000000000..48d19f6dd4e
--- /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> = 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 00000000000..951ff23d635
--- /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> = 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> = 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> = A::B;
+   |                ^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/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> = 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<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+   |            ^^^ -
+help: add missing generic argument
+   |
+LL |     let _: Vec<T, A:B> = 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> = 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`.