diff --git a/library/core/src/time.rs b/library/core/src/time.rs index acaedbd135e7..5741f8a53b52 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 21ab0faed3e5..08d363a9a296 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 a468f6b4b8d5..e3d529df7de1 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 ecd6fbc6b939..66508f06b288 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 49bbd50db574..7cfde3fc6d2d 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 9eb8ee4e3fdf..7a1a745b53c1 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 3aec300d86d4..55a134ae0911 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 ca9702784a26..caa6de09664b 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 5fb2d9f6f917..4cbc56333b15 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 082f9cca064f..19284018a30d 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 d0312d77a7c5..db0e4f4d31df 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 f4710f6ae873..60f0d25b219e 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 b3b586ba362f..34c6cbbf4fa2 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 b0c5715604ba..137aad4ed439 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 f84486347afc..062bd61a7d00 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 5f10c1ec4a75..15ea1232fd6f 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 d61c248c6ec6..305a9c3292a4 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 3688c69fbc61..43460ec1535c 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 9d7776f32b34..81f419bf687f 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 000000000000..d556132e47ff --- /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 000000000000..da3800affc05 --- /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 9c36d853ef78..2fa0f12d7e8d 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,