about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-30 00:47:37 +0000
committerbors <bors@rust-lang.org>2020-08-30 00:47:37 +0000
commit62850d882b1f546783d064ca3b51d1f85b92eeb7 (patch)
treef03f9e31723ac3561c7fa3ecbda1c4e41ccdbf41 /src
parentced37a53d9a4d46c5d3137e1e8666897474bd7d6 (diff)
parent9d7d24d5160469741de87df98664b27b09393488 (diff)
Auto merge of #76090 - Dylan-DPC:rollup-eksndcr, r=Dylan-DPC
Rollup of 14 pull requests

Successful merges:

 - #75832 (Move to intra-doc links for wasi/ext/fs.rs, os_str_bytes.rs…)
 - #75852 (Switch to intra-doc links in `core::hash`)
 - #75874 (Shorten liballoc doc intra link while readable)
 - #75881 (Expand rustdoc theme chooser x padding)
 - #75885 (Fix another clashing_extern_declarations false positive.)
 - #75892 (Fix typo in TLS Model in Unstable Book)
 - #75910 (Add test for issue #27130)
 - #75917 (Move to intra doc links for core::ptr::non_null)
 - #75975 (Allow --bess ing expect-tests in tools)
 - #75990 (Add __fastfail for Windows on arm/aarch64)
 - #76015 (Fix loading pretty-printers in rust-lldb script)
 - #76022 (Clean up rustdoc front-end source code)
 - #76029 (Move to intra-doc links for library/core/src/sync/atomic.rs)
 - #76057 (Move retokenize hack to save_analysis)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs5
-rw-r--r--src/bootstrap/dist.rs1
-rw-r--r--src/bootstrap/test.rs5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/tls-model.md2
-rw-r--r--src/etc/lldb_commands1
-rwxr-xr-xsrc/etc/rust-lldb5
-rw-r--r--src/librustc_lint/builtin.rs35
-rw-r--r--src/librustc_lint/types.rs18
-rw-r--r--src/librustc_parse/lexer/mod.rs30
-rw-r--r--src/librustc_save_analysis/Cargo.toml2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs6
-rw-r--r--src/librustc_save_analysis/span_utils.rs84
-rw-r--r--src/librustdoc/html/static/main.js17
-rw-r--r--src/librustdoc/html/static/rustdoc.css2
-rw-r--r--src/test/codegen/issue-27130.rs22
-rw-r--r--src/test/ui/lint/clashing-extern-fn.rs81
-rw-r--r--src/test/ui/lint/clashing-extern-fn.stderr22
17 files changed, 213 insertions, 125 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 6446fa7550d..54eb2e99b8f 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1079,6 +1079,11 @@ impl<'a> Builder<'a> {
             },
         );
 
+        if self.config.cmd.bless() {
+            // Bless `expect!` tests.
+            cargo.env("UPDATE_EXPECT", "1");
+        }
+
         if !mode.is_tool() {
             cargo.env("RUSTC_FORCE_UNSTABLE", "1");
         }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index f0b2254be9e..d021feafbe4 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -647,6 +647,7 @@ impl Step for DebuggerScripts {
 
             cp_debugger_script("lldb_lookup.py");
             cp_debugger_script("lldb_providers.py");
+            cp_debugger_script("lldb_commands")
         }
     }
 }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index afa72b5d58c..ac833a55d4c 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1754,11 +1754,6 @@ impl Step for Crate {
             cargo.arg("--quiet");
         }
 
-        if builder.config.cmd.bless() {
-            // Bless `expect!` tests.
-            cargo.env("UPDATE_EXPECT", "1");
-        }
-
         if target.contains("emscripten") {
             cargo.env(
                 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
diff --git a/src/doc/unstable-book/src/compiler-flags/tls-model.md b/src/doc/unstable-book/src/compiler-flags/tls-model.md
index 0aefaa7fb01..cd625f3fd09 100644
--- a/src/doc/unstable-book/src/compiler-flags/tls-model.md
+++ b/src/doc/unstable-book/src/compiler-flags/tls-model.md
@@ -22,4 +22,4 @@ The TLS data must not be in a library loaded after startup (via `dlopen`).
 but not in a shared library, and is accessed only from that executable.
 
 `rustc` and LLVM may use a more optimized model than specified if they know that we are producing
-and executable rather than a library, or that the `static` item is private enough.
+an executable rather than a library, or that the `static` item is private enough.
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands
index f470c62d899..979f2fa7ae8 100644
--- a/src/etc/lldb_commands
+++ b/src/etc/lldb_commands
@@ -1,4 +1,3 @@
-command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_lookup.py\"
 type synthetic add -l lldb_lookup.synthetic_lookup -x \".*\" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)String$\" --category Rust
 type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^&str$\" --category Rust
diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb
index 28b32ef1ad5..bce72f1bad6 100755
--- a/src/etc/rust-lldb
+++ b/src/etc/rust-lldb
@@ -30,5 +30,8 @@ EOF
     fi
 fi
 
+script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_lookup.py\""
+commands_file="$RUSTC_SYSROOT/lib/rustlib/etc/lldb_commands"
+
 # Call LLDB with the commands added to the argument list
-exec "$lldb" --source-before-file ./lldb_commands "$@"
+exec "$lldb" --one-line-before-file "$script_import" --source-before-file "$commands_file" "$@"
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 4bcf31ef0bf..ea624b9ed30 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -38,6 +38,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
 use rustc_hir::{HirId, HirIdSet, Node};
+use rustc_index::vec::Idx;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
@@ -2162,6 +2163,40 @@ impl ClashingExternDeclarations {
             ckind: CItemKind,
         ) -> bool {
             debug!("structurally_same_type_impl(cx, a = {:?}, b = {:?})", a, b);
+            let tcx = cx.tcx;
+
+            // Given a transparent newtype, reach through and grab the inner
+            // type unless the newtype makes the type non-null.
+            let non_transparent_ty = |ty: Ty<'tcx>| -> Ty<'tcx> {
+                let mut ty = ty;
+                loop {
+                    if let ty::Adt(def, substs) = ty.kind {
+                        let is_transparent = def.subst(tcx, substs).repr.transparent();
+                        let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, &def);
+                        debug!(
+                            "non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
+                            ty, is_transparent, is_non_null
+                        );
+                        if is_transparent && !is_non_null {
+                            debug_assert!(def.variants.len() == 1);
+                            let v = &def.variants[VariantIdx::new(0)];
+                            ty = v
+                                .transparent_newtype_field(tcx)
+                                .expect(
+                                    "single-variant transparent structure with zero-sized field",
+                                )
+                                .ty(tcx, substs);
+                            continue;
+                        }
+                    }
+                    debug!("non_transparent_ty -> {:?}", ty);
+                    return ty;
+                }
+            };
+
+            let a = non_transparent_ty(a);
+            let b = non_transparent_ty(b);
+
             if !seen_types.insert((a, b)) {
                 // We've encountered a cycle. There's no point going any further -- the types are
                 // structurally the same.
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 4ca5f23ebfe..35c462c24c8 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -11,7 +11,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{sign_extend, truncate};
 use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
@@ -527,22 +527,26 @@ enum FfiResult<'tcx> {
     FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option<String> },
 }
 
+crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool {
+    tcx.get_attrs(def.did)
+        .iter()
+        .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed))
+}
+
 /// Is type known to be non-null?
-fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
+crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
     let tcx = cx.tcx;
     match ty.kind {
         ty::FnPtr(_) => true,
         ty::Ref(..) => true,
         ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
         ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
-            let guaranteed_nonnull_optimization = tcx
-                .get_attrs(def.did)
-                .iter()
-                .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed));
+            let marked_non_null = nonnull_optimization_guaranteed(tcx, &def);
 
-            if guaranteed_nonnull_optimization {
+            if marked_non_null {
                 return true;
             }
+
             for variant in &def.variants {
                 if let Some(field) = variant.transparent_newtype_field(tcx) {
                     if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs
index 7503f15ac55..a65d3446819 100644
--- a/src/librustc_parse/lexer/mod.rs
+++ b/src/librustc_parse/lexer/mod.rs
@@ -46,19 +46,10 @@ impl<'a> StringReader<'a> {
         source_file: Lrc<rustc_span::SourceFile>,
         override_span: Option<Span>,
     ) -> Self {
-        // Make sure external source is loaded first, before accessing it.
-        // While this can't show up during normal parsing, `retokenize` may
-        // be called with a source file from an external crate.
-        sess.source_map().ensure_source_file_source_present(Lrc::clone(&source_file));
-
-        let src = if let Some(src) = &source_file.src {
-            Lrc::clone(&src)
-        } else if let Some(src) = source_file.external_src.borrow().get_source() {
-            Lrc::clone(&src)
-        } else {
+        let src = source_file.src.clone().unwrap_or_else(|| {
             sess.span_diagnostic
                 .bug(&format!("cannot lex `source_file` without source: {}", source_file.name));
-        };
+        });
 
         StringReader {
             sess,
@@ -70,23 +61,6 @@ impl<'a> StringReader<'a> {
         }
     }
 
-    pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
-        let begin = sess.source_map().lookup_byte_offset(span.lo());
-        let end = sess.source_map().lookup_byte_offset(span.hi());
-
-        // Make the range zero-length if the span is invalid.
-        if begin.sf.start_pos != end.sf.start_pos {
-            span = span.shrink_to_lo();
-        }
-
-        let mut sr = StringReader::new(sess, begin.sf, None);
-
-        // Seek the lexer to the right byte range.
-        sr.end_src_index = sr.src_index(span.hi());
-
-        sr
-    }
-
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
         self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi))
     }
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index 3c2edc1fa55..979a8da2a9f 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -16,7 +16,7 @@ rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_hir_pretty = { path = "../librustc_hir_pretty" }
-rustc_parse = { path = "../librustc_parse" }
+rustc_lexer = { path = "../librustc_lexer" }
 serde_json = "1"
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 77aecefe5a2..ce484858cbb 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -14,7 +14,7 @@
 //! recording the output.
 
 use rustc_ast as ast;
-use rustc_ast::{token, walk_list};
+use rustc_ast::walk_list;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind as HirDefKind, Res};
@@ -1207,9 +1207,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
 
                 // Otherwise it's a span with wrong macro expansion info, which
                 // we don't want to track anyway, since it's probably macro-internal `use`
-                if let Some(sub_span) =
-                    self.span.sub_span_of_token(item.span, token::BinOp(token::Star))
-                {
+                if let Some(sub_span) = self.span.sub_span_of_star(item.span) {
                     if !self.span.filter_generated(item.span) {
                         let access = access_from!(self.save_ctxt, item, item.hir_id);
                         let span = self.span_from_span(sub_span);
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index d5f992b0de0..edcd4925773 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -1,6 +1,6 @@
 use crate::generated_code;
-use rustc_ast::token::{self, TokenKind};
-use rustc_parse::lexer::{self, StringReader};
+use rustc_data_structures::sync::Lrc;
+use rustc_lexer::{tokenize, TokenKind};
 use rustc_session::Session;
 use rustc_span::*;
 
@@ -43,61 +43,37 @@ impl<'a> SpanUtils<'a> {
         }
     }
 
-    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
-        lexer::StringReader::retokenize(&self.sess.parse_sess, span)
-    }
-
-    pub fn sub_span_of_token(&self, span: Span, tok: TokenKind) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        loop {
-            let next = toks.next_token();
-            if next == token::Eof {
-                return None;
-            }
-            if next == tok {
-                return Some(next.span);
-            }
+    /// Finds the span of `*` token withing the larger `span`.
+    pub fn sub_span_of_star(&self, mut span: Span) -> Option<Span> {
+        let begin = self.sess.source_map().lookup_byte_offset(span.lo());
+        let end = self.sess.source_map().lookup_byte_offset(span.hi());
+        // Make the range zero-length if the span is invalid.
+        if begin.sf.start_pos != end.sf.start_pos {
+            span = span.shrink_to_lo();
         }
-    }
 
-    // // Return the name for a macro definition (identifier after first `!`)
-    // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
-    //     let mut toks = self.retokenise_span(span);
-    //     loop {
-    //         let ts = toks.real_token();
-    //         if ts == token::Eof {
-    //             return None;
-    //         }
-    //         if ts == token::Not {
-    //             let ts = toks.real_token();
-    //             if ts.kind.is_ident() {
-    //                 return Some(ts.sp);
-    //             } else {
-    //                 return None;
-    //             }
-    //         }
-    //     }
-    // }
+        let sf = Lrc::clone(&begin.sf);
 
-    // // Return the name for a macro use (identifier before first `!`).
-    // pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
-    //     let mut toks = self.retokenise_span(span);
-    //     let mut prev = toks.real_token();
-    //     loop {
-    //         if prev == token::Eof {
-    //             return None;
-    //         }
-    //         let ts = toks.real_token();
-    //         if ts == token::Not {
-    //             if prev.kind.is_ident() {
-    //                 return Some(prev.sp);
-    //             } else {
-    //                 return None;
-    //             }
-    //         }
-    //         prev = ts;
-    //     }
-    // }
+        self.sess.source_map().ensure_source_file_source_present(Lrc::clone(&sf));
+        let src =
+            sf.src.clone().or_else(|| sf.external_src.borrow().get_source().map(Lrc::clone))?;
+        let to_index = |pos: BytePos| -> usize { (pos - sf.start_pos).0 as usize };
+        let text = &src[to_index(span.lo())..to_index(span.hi())];
+        let start_pos = {
+            let mut pos = 0;
+            tokenize(text)
+                .map(|token| {
+                    let start = pos;
+                    pos += token.len;
+                    (start, token)
+                })
+                .find(|(_pos, token)| token.kind == TokenKind::Star)?
+                .0
+        };
+        let lo = span.lo() + BytePos(start_pos as u32);
+        let hi = lo + BytePos(1);
+        Some(span.with_lo(lo).with_hi(hi))
+    }
 
     /// Return true if the span is generated code, and
     /// it is not a subspan of the root callsite.
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 881b27a5d61..a1eef5c1202 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -92,6 +92,7 @@ function defocusSearchBar() {
     var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") === "true";
     var search_input = getSearchInput();
     var searchTimeout = null;
+    var toggleAllDocsId = "toggle-all-docs";
 
     // On the search screen, so you remain on the last tab you opened.
     //
@@ -1397,8 +1398,8 @@ function defocusSearchBar() {
                 // "current" is used to know which tab we're looking into.
                 var current = 0;
                 onEachLazy(document.getElementById("results").childNodes, function(e) {
-                    onEachLazy(e.getElementsByClassName("highlighted"), function(e) {
-                        actives[current].push(e);
+                    onEachLazy(e.getElementsByClassName("highlighted"), function(h_e) {
+                        actives[current].push(h_e);
                     });
                     current += 1;
                 });
@@ -2121,7 +2122,7 @@ function defocusSearchBar() {
     }
 
     function toggleAllDocs(pageId, fromAutoCollapse) {
-        var innerToggle = document.getElementById("toggle-all-docs");
+        var innerToggle = document.getElementById(toggleAllDocsId);
         if (!innerToggle) {
             return;
         }
@@ -2314,11 +2315,6 @@ function defocusSearchBar() {
         }
     }
 
-    var toggles = document.getElementById("toggle-all-docs");
-    if (toggles) {
-        toggles.onclick = toggleAllDocs;
-    }
-
     function insertAfter(newNode, referenceNode) {
         referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
     }
@@ -2368,6 +2364,11 @@ function defocusSearchBar() {
     }
 
     (function() {
+        var toggles = document.getElementById(toggleAllDocsId);
+        if (toggles) {
+            toggles.onclick = toggleAllDocs;
+        }
+
         var toggle = createSimpleToggle(false);
         var hideMethodDocs = getCurrentValue("rustdoc-auto-hide-method-docs") === "true";
         var hideImplementors = getCurrentValue("rustdoc-auto-collapse-implementors") !== "false";
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 346ceacc928..55dcaec8ae1 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1290,7 +1290,7 @@ h4 > .notable-traits {
 #theme-choices > button {
 	border: none;
 	width: 100%;
-	padding: 4px;
+	padding: 4px 8px;
 	text-align: center;
 	background: rgba(0,0,0,0);
 }
diff --git a/src/test/codegen/issue-27130.rs b/src/test/codegen/issue-27130.rs
new file mode 100644
index 00000000000..7ae78782ff9
--- /dev/null
+++ b/src/test/codegen/issue-27130.rs
@@ -0,0 +1,22 @@
+// compile-flags: -O
+// min-llvm-version: 11.0
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @trim_in_place
+#[no_mangle]
+pub fn trim_in_place(a: &mut &[u8]) {
+    while a.first() == Some(&42) {
+        // CHECK-NOT: slice_index_order_fail
+        *a = &a[1..];
+    }
+}
+
+// CHECK-LABEL: @trim_in_place2
+#[no_mangle]
+pub fn trim_in_place2(a: &mut &[u8]) {
+    while let Some(&42) = a.first() {
+        // CHECK-NOT: slice_index_order_fail
+        *a = &a[2..];
+    }
+}
diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs
index 44cef19b0d3..41f0baecf24 100644
--- a/src/test/ui/lint/clashing-extern-fn.rs
+++ b/src/test/ui/lint/clashing-extern-fn.rs
@@ -182,7 +182,9 @@ mod same_sized_members_clash {
             y: f32,
             z: f32,
         }
-        extern "C" { fn origin() -> Point3; }
+        extern "C" {
+            fn origin() -> Point3;
+        }
     }
     mod b {
         #[repr(C)]
@@ -191,8 +193,9 @@ mod same_sized_members_clash {
             y: i32,
             z: i32, // NOTE: Incorrectly redeclared as i32
         }
-        extern "C" { fn origin() -> Point3; }
-        //~^ WARN `origin` redeclared with a different signature
+        extern "C" {
+            fn origin() -> Point3; //~ WARN `origin` redeclared with a different signature
+        }
     }
 }
 
@@ -258,6 +261,78 @@ mod non_zero_and_non_null {
     }
 }
 
+// See #75739
+mod non_zero_transparent {
+    mod a1 {
+        use std::num::NonZeroUsize;
+        extern "C" {
+            fn f1() -> NonZeroUsize;
+        }
+    }
+
+    mod b1 {
+        #[repr(transparent)]
+        struct X(NonZeroUsize);
+        use std::num::NonZeroUsize;
+        extern "C" {
+            fn f1() -> X;
+        }
+    }
+
+    mod a2 {
+        use std::num::NonZeroUsize;
+        extern "C" {
+            fn f2() -> NonZeroUsize;
+        }
+    }
+
+    mod b2 {
+        #[repr(transparent)]
+        struct X1(NonZeroUsize);
+
+        #[repr(transparent)]
+        struct X(X1);
+
+        use std::num::NonZeroUsize;
+        extern "C" {
+            // Same case as above, but with two layers of newtyping.
+            fn f2() -> X;
+        }
+    }
+
+    mod a3 {
+        #[repr(transparent)]
+        struct X(core::ptr::NonNull<i32>);
+
+        use std::num::NonZeroUsize;
+        extern "C" {
+            fn f3() -> X;
+        }
+    }
+
+    mod b3 {
+        extern "C" {
+            fn f3() -> core::ptr::NonNull<i32>;
+        }
+    }
+
+    mod a4 {
+        #[repr(transparent)]
+        enum E {
+            X(std::num::NonZeroUsize),
+        }
+        extern "C" {
+            fn f4() -> E;
+        }
+    }
+
+    mod b4 {
+        extern "C" {
+            fn f4() -> std::num::NonZeroUsize;
+        }
+    }
+}
+
 mod null_optimised_enums {
     mod a {
         extern "C" {
diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr
index cca0c4c59eb..0a18f05ba29 100644
--- a/src/test/ui/lint/clashing-extern-fn.stderr
+++ b/src/test/ui/lint/clashing-extern-fn.stderr
@@ -106,19 +106,19 @@ LL |             fn draw_point(p: Point);
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
 warning: `origin` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:194:22
+  --> $DIR/clashing-extern-fn.rs:197:13
    |
-LL |         extern "C" { fn origin() -> Point3; }
-   |                      ---------------------- `origin` previously declared here
+LL |             fn origin() -> Point3;
+   |             ---------------------- `origin` previously declared here
 ...
-LL |         extern "C" { fn origin() -> Point3; }
-   |                      ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+LL |             fn origin() -> Point3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
    = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3`
               found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
 
 warning: `transparent_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:217:13
+  --> $DIR/clashing-extern-fn.rs:220:13
    |
 LL |             fn transparent_incorrect() -> T;
    |             -------------------------------- `transparent_incorrect` previously declared here
@@ -130,7 +130,7 @@ LL |             fn transparent_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `missing_return_type` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:235:13
+  --> $DIR/clashing-extern-fn.rs:238:13
    |
 LL |             fn missing_return_type() -> usize;
    |             ---------------------------------- `missing_return_type` previously declared here
@@ -142,7 +142,7 @@ LL |             fn missing_return_type();
               found `unsafe extern "C" fn()`
 
 warning: `non_zero_usize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:253:13
+  --> $DIR/clashing-extern-fn.rs:256:13
    |
 LL |             fn non_zero_usize() -> core::num::NonZeroUsize;
    |             ----------------------------------------------- `non_zero_usize` previously declared here
@@ -154,7 +154,7 @@ LL |             fn non_zero_usize() -> usize;
               found `unsafe extern "C" fn() -> usize`
 
 warning: `non_null_ptr` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:255:13
+  --> $DIR/clashing-extern-fn.rs:258:13
    |
 LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
    |             ----------------------------------------------- `non_null_ptr` previously declared here
@@ -166,7 +166,7 @@ LL |             fn non_null_ptr() -> *const usize;
               found `unsafe extern "C" fn() -> *const usize`
 
 warning: `option_non_zero_usize_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:281:13
+  --> $DIR/clashing-extern-fn.rs:356:13
    |
 LL |             fn option_non_zero_usize_incorrect() -> usize;
    |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
@@ -178,7 +178,7 @@ LL |             fn option_non_zero_usize_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `option_non_null_ptr_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:283:13
+  --> $DIR/clashing-extern-fn.rs:358:13
    |
 LL |             fn option_non_null_ptr_incorrect() -> *const usize;
    |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here