diff --git a/library/core/src/time.rs b/library/core/src/time.rs index acaedbd135e7c..5741f8a53b522 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -30,12 +30,10 @@ const MICROS_PER_SEC: u64 = 1_000_000; /// nanosecond-level precision, APIs binding a system timeout will typically round up /// the number of nanoseconds. /// -/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other -/// [`ops`] traits. It implements `Default` by returning a zero-length `Duration`. +/// [`Duration`]s implement many common traits, including [`Add`], [`Sub`], and other +/// [`ops`] traits. It implements [`Default`] by returning a zero-length `Duration`. /// -/// [`Add`]: ../../std/ops/trait.Add.html -/// [`Sub`]: ../../std/ops/trait.Sub.html -/// [`ops`]: ../../std/ops/index.html +/// [`ops`]: crate::ops /// /// # Examples /// @@ -293,7 +291,7 @@ impl Duration { /// + duration.subsec_nanos() as f64 * 1e-9); /// ``` /// - /// [`subsec_nanos`]: #method.subsec_nanos + /// [`subsec_nanos`]: Duration::subsec_nanos #[stable(feature = "duration", since = "1.3.0")] #[rustc_const_stable(feature = "duration", since = "1.32.0")] #[inline] @@ -421,8 +419,6 @@ impl Duration { /// Checked `Duration` addition. Computes `self + other`, returning [`None`] /// if overflow occurred. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// /// # Examples /// /// Basic usage: @@ -457,8 +453,6 @@ impl Duration { /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] /// if the result would be negative or if overflow occurred. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// /// # Examples /// /// Basic usage: @@ -494,8 +488,6 @@ impl Duration { /// Checked `Duration` multiplication. Computes `self * other`, returning /// [`None`] if overflow occurred. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// /// # Examples /// /// Basic usage: @@ -526,8 +518,6 @@ impl Duration { /// Checked `Duration` division. Computes `self / other`, returning [`None`] /// if `other == 0`. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// /// # Examples /// /// Basic usage: diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 21ab0faed3e5a..08d363a9a2964 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -7,6 +7,8 @@ //! * Executing a panic up to doing the actual implementation //! * Shims around "try" +#![deny(unsafe_op_in_unsafe_fn)] + use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; @@ -322,11 +324,22 @@ pub unsafe fn r#try R>(f: F) -> Result> let mut data = Data { f: ManuallyDrop::new(f) }; let data_ptr = &mut data as *mut _ as *mut u8; - return if intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { - Ok(ManuallyDrop::into_inner(data.r)) - } else { - Err(ManuallyDrop::into_inner(data.p)) - }; + // SAFETY: + // + // Access to the union's fields: this is `std` and we know that the `r#try` + // intrinsic fills in the `r` or `p` union field based on its return value. + // + // The call to `intrinsics::r#try` is made safe by: + // - `do_call`, the first argument, can be called with the initial `data_ptr`. + // - `do_catch`, the second argument, can be called with the `data_ptr` as well. + // See their safety preconditions for more informations + unsafe { + return if intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { + Ok(ManuallyDrop::into_inner(data.r)) + } else { + Err(ManuallyDrop::into_inner(data.p)) + }; + } // We consider unwinding to be rare, so mark this function as cold. However, // do not mark it no-inline -- that decision is best to leave to the @@ -334,13 +347,25 @@ pub unsafe fn r#try R>(f: F) -> Result> // non-cold function, though, as of the writing of this comment). #[cold] unsafe fn cleanup(payload: *mut u8) -> Box { - let obj = Box::from_raw(__rust_panic_cleanup(payload)); + // SAFETY: The whole unsafe block hinges on a correct implementation of + // the panic handler `__rust_panic_cleanup`. As such we can only + // assume it returns the correct thing for `Box::from_raw` to work + // without undefined behavior. + let obj = unsafe { Box::from_raw(__rust_panic_cleanup(payload)) }; panic_count::decrease(); obj } + // SAFETY: + // data must be non-NUL, correctly aligned, and a pointer to a `Data` + // Its must contains a valid `f` (type: F) value that can be use to fill + // `data.r`. + // + // This function cannot be marked as `unsafe` because `intrinsics::r#try` + // expects normal function pointers. #[inline] fn do_call R, R>(data: *mut u8) { + // SAFETY: this is the responsibilty of the caller, see above. unsafe { let data = data as *mut Data; let data = &mut (*data); @@ -352,8 +377,21 @@ pub unsafe fn r#try R>(f: F) -> Result> // We *do* want this part of the catch to be inlined: this allows the // compiler to properly track accesses to the Data union and optimize it // away most of the time. + // + // SAFETY: + // data must be non-NUL, correctly aligned, and a pointer to a `Data` + // Since this uses `cleanup` it also hinges on a correct implementation of + // `__rustc_panic_cleanup`. + // + // This function cannot be marked as `unsafe` because `intrinsics::r#try` + // expects normal function pointers. #[inline] fn do_catch R, R>(data: *mut u8, payload: *mut u8) { + // SAFETY: this is the responsibilty of the caller, see above. + // + // When `__rustc_panic_cleaner` is correctly implemented we can rely + // on `obj` being the correct thing to pass to `data.p` (after wrapping + // in `ManuallyDrop`). unsafe { let data = data as *mut Data; let data = &mut (*data); diff --git a/library/std/src/path.rs b/library/std/src/path.rs index a468f6b4b8d54..e3d529df7de16 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2031,9 +2031,13 @@ impl Path { /// assert!(path.starts_with("/etc")); /// assert!(path.starts_with("/etc/")); /// assert!(path.starts_with("/etc/passwd")); - /// assert!(path.starts_with("/etc/passwd/")); + /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay + /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay /// /// assert!(!path.starts_with("/e")); + /// assert!(!path.starts_with("/etc/passwd.txt")); + /// + /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn starts_with>(&self, base: P) -> bool { diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index ecd6fbc6b9395..66508f06b2884 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -172,7 +172,11 @@ macro_rules! __thread_local_inner { static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); - __KEY.get(__init) + // FIXME: remove the #[allow(...)] marker when macros don't + // raise warning for missing/extraneous unsafe blocks anymore. + // See https://github.com/rust-lang/rust/issues/74838. + #[allow(unused_unsafe)] + unsafe { __KEY.get(__init) } } unsafe { diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 49bbd50db574e..7cfde3fc6d2dc 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -573,7 +573,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .resolver .trait_map() .iter() - .map(|(&k, v)| (self.node_id_to_hir_id[k].unwrap(), v.clone())) + .filter_map(|(&k, v)| { + self.node_id_to_hir_id.get(k).and_then(|id| id.as_ref()).map(|id| (*id, v.clone())) + }) .collect(); let mut def_id_to_hir_id = IndexVec::default(); diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 9eb8ee4e3fdf7..7a1a745b53c12 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -1,4 +1,19 @@ -Negative impls are not allowed to have any items. Negative impls -declare that a trait is **not** implemented (and never will be) and -hence there is no need to specify the values for trait methods or -other items. +An item was added on a negative impl. + +Erroneous code example: + +```compile_fail,E0749 +# #![feature(negative_impls)] +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 { + type Foo = i32; // error! +} +# fn main() {} +``` + +Negative impls are not allowed to have any items. Negative impls declare that a +trait is **not** implemented (and never will be) and hence there is no need to +specify the values for trait methods or other items. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3aec300d86d4f..55a134ae09115 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1733,13 +1733,20 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) } - fn error_missing_in_for_loop(&self) { - let in_span = self.prev_token.span.between(self.token.span); - self.struct_span_err(in_span, "missing `in` in `for` loop") + fn error_missing_in_for_loop(&mut self) { + let (span, msg, sugg) = if self.token.is_ident_named(sym::of) { + // Possibly using JS syntax (#75311). + let span = self.token.span; + self.bump(); + (span, "try using `in` here instead", "in") + } else { + (self.prev_token.span.between(self.token.span), "try adding `in` here", " in ") + }; + self.struct_span_err(span, "missing `in` in `for` loop") .span_suggestion_short( - in_span, - "try adding `in` here", - " in ".into(), + span, + msg, + sugg.into(), // Has been misleading, at least in the past (closed Issue #48492). Applicability::MaybeIncorrect, ) diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index ca9702784a268..caa6de09664bc 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -737,6 +737,7 @@ symbols! { not, note, object_safe_for_dispatch, + of, offset, omit_gdb_pretty_printer_section, on, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5fb2d9f6f917c..4cbc56333b155 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -3450,7 +3450,7 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String { if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) { if out.is_empty() { out.push_str(&format!( - "

Important traits for {}

\ + "

Notable traits for {}

\ ", impl_.for_.print() )); @@ -3485,7 +3485,7 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String { if !out.is_empty() { out.insert_str( 0, - "
" + "
" ); out.push_str("
"); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 082f9cca064f1..19284018a30db 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2636,9 +2636,9 @@ function defocusSearchBar() { }); }()); - onEachLazy(document.getElementsByClassName("important-traits"), function(e) { + onEachLazy(document.getElementsByClassName("notable-traits"), function(e) { e.onclick = function() { - this.getElementsByClassName('important-traits-tooltiptext')[0] + this.getElementsByClassName('notable-traits-tooltiptext')[0] .classList.toggle("force-tooltip"); }; }); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index d0312d77a7c5d..db0e4f4d31df8 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -91,7 +91,7 @@ h2 { h3 { font-size: 1.3em; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { font-weight: 500; margin: 20px 0 15px 0; @@ -528,7 +528,7 @@ h4 > code, h3 > code, .invisible > code { font-size: 0.8em; } -.content .methods > div:not(.important-traits) { +.content .methods > div:not(.notable-traits) { margin-left: 40px; margin-bottom: 15px; } @@ -1099,17 +1099,17 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { font-size: 20px; } -.important-traits-tooltip { +.notable-traits-tooltip { display: inline-block; cursor: pointer; } -.important-traits:hover .important-traits-tooltiptext, -.important-traits .important-traits-tooltiptext.force-tooltip { +.notable-traits:hover .notable-traits-tooltiptext, +.notable-traits .notable-traits-tooltiptext.force-tooltip { display: inline-block; } -.important-traits .important-traits-tooltiptext { +.notable-traits .notable-traits-tooltiptext { display: none; padding: 5px 3px 3px 3px; border-radius: 6px; @@ -1121,18 +1121,18 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { border: 1px solid; } -.important-traits-tooltip::after { +.notable-traits-tooltip::after { /* The margin on the tooltip does not capture hover events, this extends the area of hover enough so that mouse hover is not lost when moving the mouse to the tooltip */ content: "\00a0\00a0\00a0"; } -.important-traits .important, .important-traits .docblock { +.notable-traits .notable, .notable-traits .docblock { margin: 0; } -.important-traits .docblock code.content{ +.notable-traits .docblock code.content{ margin: 0; padding: 0; font-size: 20px; @@ -1183,13 +1183,13 @@ pre.rust { font-size: 16px; } -.important-traits { +.notable-traits { cursor: pointer; z-index: 2; margin-left: 5px; } -h4 > .important-traits { +h4 > .notable-traits { position: absolute; left: -44px; top: 2px; @@ -1431,7 +1431,7 @@ h4 > .important-traits { z-index: 1; } - h4 > .important-traits { + h4 > .notable-traits { position: absolute; left: -22px; top: 24px; @@ -1522,7 +1522,7 @@ h4 > .important-traits { margin-top: 0; } - .important-traits .important-traits-tooltiptext { + .notable-traits .notable-traits-tooltiptext { left: 0; top: 100%; } @@ -1544,7 +1544,7 @@ h4 > .important-traits { } } -h3.important { +h3.notable { margin: 0; margin-bottom: 13px; font-size: 19px; diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index f4710f6ae873a..60f0d25b219e7 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -389,7 +389,7 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent #314559 transparent transparent; } -.important-traits-tooltiptext { +.notable-traits-tooltiptext { background-color: #314559; border-color: #5c6773; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index b3b586ba362fa..34c6cbbf4fa21 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -339,7 +339,7 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits-tooltiptext { +.notable-traits-tooltiptext { background-color: #111; border-color: #777; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index b0c5715604baa..137aad4ed4398 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -333,7 +333,7 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits-tooltiptext { +.notable-traits-tooltiptext { background-color: #eee; border-color: #999; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f84486347afcd..062bd61a7d002 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -217,9 +217,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return Ok((res, Some(path_str.to_owned()))); } Res::Def(DefKind::Mod, _) => { - // This resolved to a module, but if we were passed `type@`, - // we want primitive types to take precedence instead. - if disambiguator == Some(Disambiguator::Namespace(Namespace::TypeNS)) { + // This resolved to a module, but we want primitive types to take precedence instead. + if matches!( + disambiguator, + None | Some(Disambiguator::Namespace(Namespace::TypeNS)) + ) { if let Some(prim) = is_primitive(path_str, ns) { if extra_fragment.is_some() { return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); diff --git a/src/test/rustdoc/intra-link-prim-precedence.rs b/src/test/rustdoc/intra-link-prim-precedence.rs index 5f10c1ec4a75c..15ea1232fd6fb 100644 --- a/src/test/rustdoc/intra-link-prim-precedence.rs +++ b/src/test/rustdoc/intra-link-prim-precedence.rs @@ -8,5 +8,10 @@ pub mod char {} pub struct MyString; /// See also [char] -// @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'intra_link_prim_precedence/char/index.html' +// @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' pub struct MyString2; + +/// See also [crate::char] and [mod@char] +// @has intra_link_prim_precedence/struct.MyString3.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char' +// @has - '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'mod@char' +pub struct MyString3; diff --git a/src/test/ui/issues/issue-40782.fixed b/src/test/ui/issues/issue-40782.fixed index d61c248c6ec62..305a9c3292a4c 100644 --- a/src/test/ui/issues/issue-40782.fixed +++ b/src/test/ui/issues/issue-40782.fixed @@ -3,4 +3,6 @@ fn main() { for _i in 0..2 { //~ ERROR missing `in` } + for _i in 0..2 { //~ ERROR missing `in` + } } diff --git a/src/test/ui/issues/issue-40782.rs b/src/test/ui/issues/issue-40782.rs index 3688c69fbc613..43460ec1535ce 100644 --- a/src/test/ui/issues/issue-40782.rs +++ b/src/test/ui/issues/issue-40782.rs @@ -3,4 +3,6 @@ fn main() { for _i 0..2 { //~ ERROR missing `in` } + for _i of 0..2 { //~ ERROR missing `in` + } } diff --git a/src/test/ui/issues/issue-40782.stderr b/src/test/ui/issues/issue-40782.stderr index 9d7776f32b345..81f419bf687f4 100644 --- a/src/test/ui/issues/issue-40782.stderr +++ b/src/test/ui/issues/issue-40782.stderr @@ -4,5 +4,11 @@ error: missing `in` in `for` loop LL | for _i 0..2 { | ^ help: try adding `in` here -error: aborting due to previous error +error: missing `in` in `for` loop + --> $DIR/issue-40782.rs:6:12 + | +LL | for _i of 0..2 { + | ^^ help: try using `in` here instead + +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-75283.rs b/src/test/ui/issues/issue-75283.rs new file mode 100644 index 0000000000000..d556132e47ffd --- /dev/null +++ b/src/test/ui/issues/issue-75283.rs @@ -0,0 +1,6 @@ +extern "C" { + fn lol() { //~ ERROR incorrect function inside `extern` block + println!(""); + } +} +fn main() {} diff --git a/src/test/ui/issues/issue-75283.stderr b/src/test/ui/issues/issue-75283.stderr new file mode 100644 index 0000000000000..da3800affc05a --- /dev/null +++ b/src/test/ui/issues/issue-75283.stderr @@ -0,0 +1,18 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-75283.rs:2:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn lol() { + | ________^^^___- + | | | + | | cannot have a body +LL | | println!(""); +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 9c36d853ef78d..2fa0f12d7e8dc 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -16,7 +16,7 @@ const EXEMPTED_FROM_TEST: &[&str] = &[ ]; // Some error codes don't have any tests apparently... -const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0570", "E0601", "E0602", "E0639", "E0729", "E0749"]; +const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0570", "E0601", "E0602", "E0639", "E0729"]; fn check_error_code_explanation( f: &str,