about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-10 00:09:45 +0000
committerbors <bors@rust-lang.org>2020-08-10 00:09:45 +0000
commitcee62c17aa3e413e8541b3f60b800a365368e94e (patch)
treee913b1bd95fe8377d4dec020c720ea2d7804211e
parentf5fef3c715f69bbc5ab2f9e18b9e79308f1e33ae (diff)
parent53696196932d6221d657b0dcc11f91a79344c7e9 (diff)
Auto merge of #75351 - JohnTitor:rollup-q9udsyx, r=JohnTitor
Rollup of 8 pull requests

Successful merges:

 - #74200 (Std panicking unsafe block in unsafe fn)
 - #75286 (Add additional case for Path starts with)
 - #75318 (Resolve `char` as a primitive even if there is a module in scope)
 - #75320 (Detect likely `for foo of bar` JS syntax)
 - #75328 (Cleanup E0749)
 - #75344 (Rename "Important traits" to "Notable traits")
 - #75348 (Move to intra-doc links in library/core/src/time.rs)
 - #75350 (Do not ICE when lowering invalid extern fn with bodies)

Failed merges:

r? @ghost
-rw-r--r--library/core/src/time.rs18
-rw-r--r--library/std/src/panicking.rs50
-rw-r--r--library/std/src/path.rs6
-rw-r--r--library/std/src/thread/local.rs6
-rw-r--r--src/librustc_ast_lowering/lib.rs4
-rw-r--r--src/librustc_error_codes/error_codes/E0749.md23
-rw-r--r--src/librustc_parse/parser/expr.rs19
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/librustdoc/html/render/mod.rs4
-rw-r--r--src/librustdoc/html/static/main.js4
-rw-r--r--src/librustdoc/html/static/rustdoc.css28
-rw-r--r--src/librustdoc/html/static/themes/ayu.css2
-rw-r--r--src/librustdoc/html/static/themes/dark.css2
-rw-r--r--src/librustdoc/html/static/themes/light.css2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs8
-rw-r--r--src/test/rustdoc/intra-link-prim-precedence.rs7
-rw-r--r--src/test/ui/issues/issue-40782.fixed2
-rw-r--r--src/test/ui/issues/issue-40782.rs2
-rw-r--r--src/test/ui/issues/issue-40782.stderr8
-rw-r--r--src/test/ui/issues/issue-75283.rs6
-rw-r--r--src/test/ui/issues/issue-75283.stderr18
-rw-r--r--src/tools/tidy/src/error_codes_check.rs2
22 files changed, 162 insertions, 60 deletions
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index acaedbd135e..5741f8a53b5 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 21ab0faed3e..08d363a9a29 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: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     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::<F, R>, data_ptr, do_catch::<F, R>) == 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::<F, R>, data_ptr, do_catch::<F, R>) == 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: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     // non-cold function, though, as of the writing of this comment).
     #[cold]
     unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
-        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<F, R>`
+    // 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<F: FnOnce() -> R, R>(data: *mut u8) {
+        // SAFETY: this is the responsibilty of the caller, see above.
         unsafe {
             let data = data as *mut Data<F, R>;
             let data = &mut (*data);
@@ -352,8 +377,21 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     // 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<F, R>`
+    // 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<F: FnOnce() -> 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<F, R>;
             let data = &mut (*data);
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index a468f6b4b8d..e3d529df7de 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<P: AsRef<Path>>(&self, base: P) -> bool {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index ecd6fbc6b93..66508f06b28 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 49bbd50db57..7cfde3fc6d2 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 9eb8ee4e3fd..7a1a745b53c 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 3aec300d86d..55a134ae091 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 ca9702784a2..caa6de09664 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 5fb2d9f6f91..4cbc56333b1 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!(
-                            "<h3 class=\"important\">Important traits for {}</h3>\
+                            "<h3 class=\"notable\">Notable traits for {}</h3>\
                                       <code class=\"content\">",
                             impl_.for_.print()
                         ));
@@ -3485,7 +3485,7 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String {
     if !out.is_empty() {
         out.insert_str(
             0,
-            "<span class=\"important-traits\"><span class=\"important-traits-tooltip\">ⓘ<div class='important-traits-tooltiptext'><span class=\"docblock\">"
+            "<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ<div class='notable-traits-tooltiptext'><span class=\"docblock\">"
 
         );
         out.push_str("</code></span></div></span></span>");
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 082f9cca064..19284018a30 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 d0312d77a7c..db0e4f4d31d 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 f4710f6ae87..60f0d25b219 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 b3b586ba362..34c6cbbf4fa 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 b0c5715604b..137aad4ed43 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 f84486347af..062bd61a7d0 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 5f10c1ec4a7..15ea1232fd6 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 d61c248c6ec..305a9c3292a 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 3688c69fbc6..43460ec1535 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 9d7776f32b3..81f419bf687 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 00000000000..d556132e47f
--- /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 00000000000..da3800affc0
--- /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 9c36d853ef7..2fa0f12d7e8 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,