about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-31 06:53:02 +0000
committerbors <bors@rust-lang.org>2022-05-31 06:53:02 +0000
commitd35d972e6974d40d30362344ea619a5b560aae20 (patch)
tree739cf333b1f507f7d5d77e99f42ccd4c5f684164
parent989b806f61cf12840ddcd8b2bf16d6bef055bd01 (diff)
parentefd2519e10e05ddeddc2bee7ed3819fcf6c69ef0 (diff)
downloadrust-d35d972e6974d40d30362344ea619a5b560aae20.tar.gz
rust-d35d972e6974d40d30362344ea619a5b560aae20.zip
Auto merge of #97574 - Dylan-DPC:rollup-jq850l6, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #97089 (Improve settings theme display)
 - #97229 (Document the current aliasing rules for `Box<T>`.)
 - #97371 (Suggest adding a semicolon to a closure without block)
 - #97455 (Stabilize `toowned_clone_into`)
 - #97565 (Add doc alias `memset` to `write_bytes`)
 - #97569 (Remove `memset` alias from `fill_with`.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs25
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs42
-rw-r--r--library/alloc/src/borrow.rs3
-rw-r--r--library/alloc/src/boxed.rs14
-rw-r--r--library/core/src/intrinsics.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs1
-rw-r--r--library/core/src/slice/mod.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--src/librustdoc/html/static/css/settings.css53
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css39
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css35
-rw-r--r--src/librustdoc/html/static/css/themes/light.css35
-rw-r--r--src/librustdoc/html/static/js/settings.js2
-rw-r--r--src/test/rustdoc-gui/settings.goml60
-rw-r--r--src/test/ui/closures/add_semicolon_non_block_closure.rs11
-rw-r--r--src/test/ui/closures/add_semicolon_non_block_closure.stderr16
16 files changed, 266 insertions, 73 deletions
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 1af50191cb0..d6a8659d54b 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -1500,7 +1500,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             coercion_error.clone(),
                             fcx,
                             parent_id,
-                            expression.map(|expr| (expr, blk_id)),
+                            expression,
+                            Some(blk_id),
                         );
                         if !fcx.tcx.features().unsized_locals {
                             unsized_return = self.is_return_ty_unsized(fcx, blk_id);
@@ -1514,6 +1515,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             coercion_error.clone(),
                             fcx,
                             id,
+                            expression,
                             None,
                         );
                         if !fcx.tcx.features().unsized_locals {
@@ -1564,21 +1566,28 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         ty_err: TypeError<'tcx>,
         fcx: &FnCtxt<'a, 'tcx>,
         id: hir::HirId,
-        expression: Option<(&'tcx hir::Expr<'tcx>, hir::HirId)>,
+        expression: Option<&'tcx hir::Expr<'tcx>>,
+        blk_id: Option<hir::HirId>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
 
         let mut pointing_at_return_type = false;
         let mut fn_output = None;
 
+        let parent_id = fcx.tcx.hir().get_parent_node(id);
+        let parent = fcx.tcx.hir().get(parent_id);
+        if let Some(expr) = expression
+            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, body_id, ..), .. }) = parent
+            && !matches!(fcx.tcx.hir().get(body_id.hir_id), hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(..), .. }))
+        {
+            fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
+        }
         // Verify that this is a tail expression of a function, otherwise the
         // label pointing out the cause for the type coercion will be wrong
         // as prior return coercions would not be relevant (#57664).
-        let parent_id = fcx.tcx.hir().get_parent_node(id);
-        let fn_decl = if let Some((expr, blk_id)) = expression {
+        let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
             pointing_at_return_type =
                 fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
-            let parent = fcx.tcx.hir().get(parent_id);
             if let (Some(cond_expr), true, false) = (
                 fcx.tcx.hir().get_if_cause(expr.hir_id),
                 expected.is_unit(),
@@ -1607,7 +1616,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         };
 
         if let Some((fn_decl, can_suggest)) = fn_decl {
-            if expression.is_none() {
+            if blk_id.is_none() {
                 pointing_at_return_type |= fcx.suggest_missing_return_type(
                     &mut err,
                     &fn_decl,
@@ -1625,8 +1634,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let parent_id = fcx.tcx.hir().get_parent_item(id);
         let parent_item = fcx.tcx.hir().get_by_def_id(parent_id);
 
-        if let (Some((expr, _)), Some((fn_decl, _, _))) =
-            (expression, fcx.get_node_fn_decl(parent_item))
+        if let (Some(expr), Some(_), Some((fn_decl, _, _))) =
+            (expression, blk_id, fcx.get_node_fn_decl(parent_item))
         {
             fcx.suggest_missing_break_or_return_expr(
                 &mut err,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index bd58a675448..76add2fb9c2 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -46,12 +46,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk_id: hir::HirId,
     ) -> bool {
         let expr = expr.peel_drop_temps();
-        // If the expression is from an external macro, then do not suggest
-        // adding a semicolon, because there's nowhere to put it.
-        // See issue #81943.
-        if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, expr.span) {
-            self.suggest_missing_semicolon(err, expr, expected);
-        }
+        self.suggest_missing_semicolon(err, expr, expected, false);
         let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
             let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
@@ -473,11 +468,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// This routine checks if the return expression in a block would make sense on its own as a
     /// statement and the return type has been left as default or has been specified as `()`. If so,
     /// it suggests adding a semicolon.
-    fn suggest_missing_semicolon(
+    ///
+    /// If the expression is the expression of a closure without block (`|| expr`), a
+    /// block is needed to be added too (`|| { expr; }`). This is denoted by `needs_block`.
+    pub fn suggest_missing_semicolon(
         &self,
         err: &mut Diagnostic,
         expression: &'tcx hir::Expr<'tcx>,
         expected: Ty<'tcx>,
+        needs_block: bool,
     ) {
         if expected.is_unit() {
             // `BlockTailExpression` only relevant if the tail expr would be
@@ -489,14 +488,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 | ExprKind::If(..)
                 | ExprKind::Match(..)
                 | ExprKind::Block(..)
-                    if expression.can_have_side_effects() =>
+                    if expression.can_have_side_effects()
+                        // If the expression is from an external macro, then do not suggest
+                        // adding a semicolon, because there's nowhere to put it.
+                        // See issue #81943.
+                        && !in_external_macro(self.tcx.sess, expression.span) =>
                 {
-                    err.span_suggestion(
-                        expression.span.shrink_to_hi(),
-                        "consider using a semicolon here",
-                        ";".to_string(),
-                        Applicability::MachineApplicable,
-                    );
+                    if needs_block {
+                        err.multipart_suggestion(
+                            "consider using a semicolon here",
+                            vec![
+                                (expression.span.shrink_to_lo(), "{ ".to_owned()),
+                                (expression.span.shrink_to_hi(), "; }".to_owned()),
+                            ],
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.span_suggestion(
+                            expression.span.shrink_to_hi(),
+                            "consider using a semicolon here",
+                            ";".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
                 }
                 _ => (),
             }
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index cb4e438f8be..7a79fb77dea 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -67,14 +67,13 @@ pub trait ToOwned {
     /// Basic usage:
     ///
     /// ```
-    /// # #![feature(toowned_clone_into)]
     /// let mut s: String = String::new();
     /// "hello".clone_into(&mut s);
     ///
     /// let mut v: Vec<i32> = Vec::new();
     /// [1, 2][..].clone_into(&mut v);
     /// ```
-    #[unstable(feature = "toowned_clone_into", reason = "recently added", issue = "41263")]
+    #[stable(feature = "toowned_clone_into", since = "1.63.0")]
     fn clone_into(&self, target: &mut Self::Owned) {
         *target = self.to_owned();
     }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index c07536f0d0c..41f3b1fa3dd 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -122,7 +122,21 @@
 //! definition is just using `T*` can lead to undefined behavior, as
 //! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
 //!
+//! # Considerations for unsafe code
+//!
+//! **Warning: This section is not normative and is subject to change, possibly
+//! being relaxed in the future! It is a simplified summary of the rules
+//! currently implemented in the compiler.**
+//!
+//! The aliasing rules for `Box<T>` are the same as for `&mut T`. `Box<T>`
+//! asserts uniqueness over its content. Using raw pointers derived from a box
+//! after that box has been mutated through, moved or borrowed as `&mut T`
+//! is not allowed. For more guidance on working with box from unsafe code, see
+//! [rust-lang/unsafe-code-guidelines#326][ucg#326].
+//!
+//!
 //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
+//! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326
 //! [dereferencing]: core::ops::Deref
 //! [`Box::<T>::from_raw(value)`]: Box::from_raw
 //! [`Global`]: crate::alloc::Global
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 678d00c68c5..0b76790c009 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2287,6 +2287,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 /// // Now the box is fine
 /// assert_eq!(*v, 42);
 /// ```
+#[doc(alias = "memset")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
 #[inline]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 37cf2ef4bfb..1aaa274a054 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1412,6 +1412,7 @@ impl<T: ?Sized> *mut T {
     /// See [`ptr::write_bytes`] for safety concerns and examples.
     ///
     /// [`ptr::write_bytes`]: crate::ptr::write_bytes()
+    #[doc(alias = "memset")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     #[inline(always)]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index f5a90cb3d7a..77fd1ec2b8e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3083,7 +3083,6 @@ impl<T> [T] {
     /// buf.fill_with(Default::default);
     /// assert_eq!(buf, vec![0; 10]);
     /// ```
-    #[doc(alias = "memset")]
     #[stable(feature = "slice_fill_with", since = "1.51.0")]
     pub fn fill_with<F>(&mut self, mut f: F)
     where
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 519f050d2fc..71ea5f1a1f0 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -299,7 +299,6 @@
 #![feature(map_try_insert)]
 #![feature(new_uninit)]
 #![feature(thin_box)]
-#![feature(toowned_clone_into)]
 #![feature(try_reserve_kind)]
 #![feature(vec_into_raw_parts)]
 #![feature(slice_concat_trait)]
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index c69ff04236d..1cd8e39e036 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -3,44 +3,40 @@
 	position: relative;
 }
 
-.setting-line > div {
-	display: inline-block;
-	vertical-align: top;
-	font-size: 17px;
-	padding-top: 2px;
-}
-
-.setting-line > .title {
-	font-size: 19px;
-	width: 100%;
-	max-width: none;
-	border-bottom: 1px solid;
-}
-
-.setting-line .radio-line,
 .setting-line .choices {
 	display: flex;
 	flex-wrap: wrap;
 }
 
-.setting-line .radio-line .setting-name {
-	flex-grow: 1;
-	margin-top: auto;
-	margin-bottom: auto;
-}
-
 .setting-line .radio-line input {
 	margin-right: 0.3em;
+	height: 1.2rem;
+	width: 1.2rem;
+	border: 1px solid;
+	outline: none;
+	-webkit-appearance: none;
+	cursor: pointer;
+	border-radius: 50%;
+}
+.setting-line .radio-line input + span {
+	padding-bottom: 1px;
+}
+
+.radio-line .setting-name {
+	width: 100%;
 }
 
 .radio-line .choice {
-	border-radius: 0.1em;
-	border: 1px solid;
-	margin-left: 0.5em;
 	margin-top: 0.1em;
 	margin-bottom: 0.1em;
 	min-width: 3.8em;
 	padding: 0.3em;
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+}
+.radio-line .choice + .choice {
+	margin-left: 0.5em;
 }
 
 .toggle {
@@ -77,18 +73,9 @@
 	width: 19px;
 	left: 4px;
 	bottom: 4px;
-	background-color: white;
 	transition: .3s;
 }
 
-input:checked + .slider {
-	background-color: #2196F3;
-}
-
-input:focus + .slider {
-	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
-
 input:checked + .slider:before {
 	transform: translateX(19px);
 }
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index d32bb4cf22d..7303cecc0d6 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -10,6 +10,38 @@ body, #settings-menu #settings, #settings-menu #settings::before {
 	color: #c5c5c5;
 }
 
+.setting-line .radio-line input {
+	border-color: #c5c5c5;
+}
+.setting-line .radio-line input:checked {
+	box-shadow: inset 0 0 0 3px #0f1419;
+	background-color: #ffb454;
+}
+.setting-line .radio-line input:focus {
+	box-shadow: 0 0 1px 1px #ffb454;
+}
+/* In here we combine both `:focus` and `:checked` properties. */
+.setting-line .radio-line input:checked:focus {
+	box-shadow: inset 0 0 0 3px 0f1419,
+		0 0 2px 2px #ffb454;
+}
+.setting-line .radio-line input:hover {
+	border-color: #ffb454 !important;
+}
+
+.slider {
+	background-color: #ccc;
+}
+.slider:before {
+	background-color: white;
+}
+input:checked + .slider {
+	background-color: #ffb454;
+}
+input:focus + .slider {
+	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
+}
+
 h1, h2, h3, h4 {
 	color: white;
 }
@@ -601,13 +633,6 @@ div.files > .selected {
 	background-color: #14191f;
 	color: #ffb44c;
 }
-.setting-line > .title {
-	border-bottom-color: #5c6773;
-}
-input:checked + .slider {
-	background-color: #ffb454 !important;
-}
-
 
 .scraped-example-list .scrape-help {
 	border-color: #aaa;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 4957f25bcf3..34a4f446b56 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -3,6 +3,38 @@ body, #settings-menu #settings, #settings-menu #settings::before {
 	color: #ddd;
 }
 
+.setting-line .radio-line input {
+	border-color: #ddd;
+}
+.setting-line .radio-line input:checked {
+	box-shadow: inset 0 0 0 3px #353535;
+	background-color: #2196f3;
+}
+.setting-line .radio-line input:focus {
+	box-shadow: 0 0 1px 1px #2196f3;
+}
+/* In here we combine both `:focus` and `:checked` properties. */
+.setting-line .radio-line input:checked:focus {
+	box-shadow: inset 0 0 0 3px #353535,
+		0 0 2px 2px #2196f3;
+}
+.setting-line .radio-line input:hover {
+	border-color: #2196f3 !important;
+}
+
+.slider {
+	background-color: #ccc;
+}
+.slider:before {
+	background-color: white;
+}
+input:checked + .slider {
+	background-color: #2196F3;
+}
+input:focus + .slider {
+	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
+}
+
 h1, h2, h3, h4 {
 	color: #ddd;
 }
@@ -472,9 +504,6 @@ div.files > a:hover, div.name:hover {
 div.files > .selected {
 	background-color: #333;
 }
-.setting-line > .title {
-	border-bottom-color: #ddd;
-}
 
 .scraped-example-list .scrape-help {
 	border-color: #aaa;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 7d4acc6c611..aa6ad2f5473 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -5,6 +5,38 @@ body, #settings-menu #settings, #settings-menu #settings::before {
 	color: black;
 }
 
+.setting-line .radio-line input {
+	border-color: black;
+}
+.setting-line .radio-line input:checked {
+	box-shadow: inset 0 0 0 3px white;
+	background-color: #2196f3;
+}
+.setting-line .radio-line input:focus {
+	box-shadow: 0 0 1px 1px #2196f3;
+}
+/* In here we combine both `:focus` and `:checked` properties. */
+.setting-line .radio-line input:checked:focus {
+	box-shadow: inset 0 0 0 3px white,
+		0 0 2px 2px #2196f3;
+}
+.setting-line .radio-line input:hover {
+	border-color: #2196f3 !important;
+}
+
+.slider {
+	background-color: #ccc;
+}
+.slider:before {
+	background-color: white;
+}
+input:checked + .slider {
+	background-color: #2196F3;
+}
+input:focus + .slider {
+	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
+}
+
 h1, h2, h3, h4 {
 	color: black;
 }
@@ -456,9 +488,6 @@ div.files > a:hover, div.name:hover {
 div.files > .selected {
 	background-color: #fff;
 }
-.setting-line > .title {
-	border-bottom-color: #D5D5D5;
-}
 
 .scraped-example-list .scrape-help {
 	border-color: #555;
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 3d1d942eaa9..41bf0ec8955 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -123,7 +123,7 @@
                     output += `<label for="${js_data_name}-${option}" class="choice">\
                            <input type="radio" name="${js_data_name}" \
                                 id="${js_data_name}-${option}" value="${option}"${checked}>\
-                           ${option}\
+                           <span>${option}</span>\
                          </label>`;
                 });
                 output += "</div></div>";
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index cbfc67e7906..237a4751a8d 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -1,5 +1,6 @@
 // This test ensures that the settings menu display is working as expected.
 goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true // needed when we check for colors below.
 // First, we check that the settings page doesn't exist.
 assert-false: "#settings"
 // We now click on the settings button.
@@ -43,6 +44,65 @@ assert: ".setting-line.hidden #preferred-light-theme"
 // We check that the correct theme is selected.
 assert-property: ("#theme .choices #theme-dark", {"checked": "true"})
 
+// Some style checks...
+// First we check the "default" display.
+assert-css: (
+    "#theme-dark",
+    {
+        "border-color": "rgb(221, 221, 221)",
+        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset",
+    },
+)
+assert-css: ("#theme-light", {"border-color": "rgb(221, 221, 221)", "box-shadow": "none"})
+// Let's start with the hover.
+move-cursor-to: "#theme-dark"
+assert-css: (
+    "#theme-dark",
+    {
+        "border-color": "rgb(33, 150, 243)",
+        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset",
+    },
+)
+move-cursor-to: "#theme-light"
+assert-css: ("#theme-light", {"border-color": "rgb(33, 150, 243)", "box-shadow": "none"})
+move-cursor-to: "#theme-ayu"
+// Let's now check with the focus.
+focus: "#theme-dark"
+assert-css: (
+    "#theme-dark",
+    {
+        "border-color": "rgb(221, 221, 221)",
+        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px",
+    },
+)
+focus: "#theme-light"
+assert-css: (
+    "#theme-light",
+    {
+        "border-color": "rgb(221, 221, 221)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+// Now we check we both focus and hover.
+move-cursor-to: "#theme-dark"
+focus: "#theme-dark"
+assert-css: (
+    "#theme-dark",
+    {
+        "border-color": "rgb(33, 150, 243)",
+        "box-shadow": "rgb(53, 53, 53) 0px 0px 0px 3px inset, rgb(33, 150, 243) 0px 0px 2px 2px",
+    },
+)
+move-cursor-to: "#theme-light"
+focus: "#theme-light"
+assert-css: (
+    "#theme-light",
+    {
+        "border-color": "rgb(33, 150, 243)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+
 // We now switch the display.
 click: "#use-system-theme"
 // Wait for the hidden element to show up.
diff --git a/src/test/ui/closures/add_semicolon_non_block_closure.rs b/src/test/ui/closures/add_semicolon_non_block_closure.rs
new file mode 100644
index 00000000000..3ae91be60c5
--- /dev/null
+++ b/src/test/ui/closures/add_semicolon_non_block_closure.rs
@@ -0,0 +1,11 @@
+fn foo(_f: impl Fn()) {}
+
+fn bar() -> i32 {
+    1
+}
+
+fn main() {
+    foo(|| bar())
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider using a semicolon here
+}
diff --git a/src/test/ui/closures/add_semicolon_non_block_closure.stderr b/src/test/ui/closures/add_semicolon_non_block_closure.stderr
new file mode 100644
index 00000000000..ed829fc98f8
--- /dev/null
+++ b/src/test/ui/closures/add_semicolon_non_block_closure.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/add_semicolon_non_block_closure.rs:8:12
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     foo(|| bar())
+   |            ^^^^^ expected `()`, found `i32`
+   |
+help: consider using a semicolon here
+   |
+LL |     foo(|| { bar(); })
+   |            +      +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.