diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 1af50191cb006..d6a8659d54b58 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, ) -> 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 bd58a6754481a..76add2fb9c285 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 cb4e438f8bea2..7a79fb77dea55 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 = 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 c07536f0d0ce1..41f3b1fa3dddb 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` are the same as for `&mut T`. `Box` +//! 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::::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 678d00c68c5c3..0b76790c0097e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2287,6 +2287,7 @@ pub const unsafe fn copy(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 37cf2ef4bfbb5..1aaa274a05434 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1412,6 +1412,7 @@ impl *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 f5a90cb3d7ac9..77fd1ec2b8ea2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3083,7 +3083,6 @@ impl [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(&mut self, mut f: F) where diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6dc3fd9858451..5145790fa6b36 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -298,7 +298,6 @@ #![feature(map_try_insert)] #![feature(new_uninit)] #![feature(thin_box)] -#![feature(toowned_clone_into)] #![feature(try_reserve_kind)] #![feature(vec_into_raw_parts)] // diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index c69ff04236dcb..1cd8e39e03648 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 d32bb4cf22d6e..7303cecc0d61a 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 4957f25bcf358..34a4f446b560b 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 7d4acc6c61181..aa6ad2f547333 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 3d1d942eaa9ee..41bf0ec895580 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -123,7 +123,7 @@ output += ``; }); output += ""; diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index cbfc67e790603..237a4751a8d66 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 0000000000000..3ae91be60c5a0 --- /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 0000000000000..ed829fc98f86f --- /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`.