From 50f29d48bd5fb17b7b1669b842aba89bbe9bef6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= <faern@faern.net>
Date: Thu, 10 Nov 2022 19:19:39 +0100
Subject: [PATCH 01/13] Stabilize the const_socketaddr feature

---
 library/std/src/lib.rs             |  1 -
 library/std/src/net/socket_addr.rs | 26 +++++++++++++-------------
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 99cc018631048..762f7a7c9a1a0 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -358,7 +358,6 @@
 #![feature(const_ip)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
-#![feature(const_socketaddr)]
 #![feature(thread_local_internals)]
 //
 #![default_lib_allocator]
diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs
index 33b0dfa03e0ed..1264bae809b26 100644
--- a/library/std/src/net/socket_addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -133,7 +133,7 @@ impl SocketAddr {
     /// ```
     #[stable(feature = "ip_addr", since = "1.7.0")]
     #[must_use]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
         match ip {
             IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
@@ -153,7 +153,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "ip_addr", since = "1.7.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn ip(&self) -> IpAddr {
         match *self {
             SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
@@ -194,7 +194,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn port(&self) -> u16 {
         match *self {
             SocketAddr::V4(ref a) => a.port(),
@@ -238,7 +238,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn is_ipv4(&self) -> bool {
         matches!(*self, SocketAddr::V4(_))
     }
@@ -260,7 +260,7 @@ impl SocketAddr {
     /// ```
     #[must_use]
     #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn is_ipv6(&self) -> bool {
         matches!(*self, SocketAddr::V6(_))
     }
@@ -280,7 +280,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
         SocketAddrV4 { ip, port }
     }
@@ -297,7 +297,7 @@ impl SocketAddrV4 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn ip(&self) -> &Ipv4Addr {
         &self.ip
     }
@@ -330,7 +330,7 @@ impl SocketAddrV4 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn port(&self) -> u16 {
         self.port
     }
@@ -371,7 +371,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
         SocketAddrV6 { ip, port, flowinfo, scope_id }
     }
@@ -388,7 +388,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn ip(&self) -> &Ipv6Addr {
         &self.ip
     }
@@ -421,7 +421,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn port(&self) -> u16 {
         self.port
     }
@@ -464,7 +464,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn flowinfo(&self) -> u32 {
         self.flowinfo
     }
@@ -504,7 +504,7 @@ impl SocketAddrV6 {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
     pub const fn scope_id(&self) -> u32 {
         self.scope_id
     }

From c4d00d710c86aa062f2e08fc90a14345f55a8b4b Mon Sep 17 00:00:00 2001
From: yukang <moorekang@gmail.com>
Date: Thu, 26 Jan 2023 10:52:57 +0800
Subject: [PATCH 02/13] add testcase for #104012

---
 tests/ui/parser/deli-ident-issue-1.rs         | 25 +++++++++++++
 tests/ui/parser/deli-ident-issue-1.stderr     | 37 +++++++++++++++++++
 tests/ui/parser/deli-ident-issue-2.rs         |  7 ++++
 tests/ui/parser/deli-ident-issue-2.stderr     | 21 +++++++++++
 .../ui/parser/issue-68987-unmatch-issue-1.rs  | 12 ++++++
 .../parser/issue-68987-unmatch-issue-1.stderr | 11 ++++++
 .../ui/parser/issue-68987-unmatch-issue-2.rs  | 14 +++++++
 .../parser/issue-68987-unmatch-issue-2.stderr | 21 +++++++++++
 .../ui/parser/issue-68987-unmatch-issue-3.rs  |  8 ++++
 .../parser/issue-68987-unmatch-issue-3.stderr | 21 +++++++++++
 tests/ui/parser/issue-68987-unmatch-issue.rs  | 12 ++++++
 .../parser/issue-68987-unmatch-issue.stderr   | 11 ++++++
 tests/ui/parser/issues/issue-69259.rs         |  3 ++
 tests/ui/parser/issues/issue-69259.stderr     | 13 +++++++
 14 files changed, 216 insertions(+)
 create mode 100644 tests/ui/parser/deli-ident-issue-1.rs
 create mode 100644 tests/ui/parser/deli-ident-issue-1.stderr
 create mode 100644 tests/ui/parser/deli-ident-issue-2.rs
 create mode 100644 tests/ui/parser/deli-ident-issue-2.stderr
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-1.rs
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-1.stderr
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-2.rs
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-2.stderr
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-3.rs
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue-3.stderr
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue.rs
 create mode 100644 tests/ui/parser/issue-68987-unmatch-issue.stderr
 create mode 100644 tests/ui/parser/issues/issue-69259.rs
 create mode 100644 tests/ui/parser/issues/issue-69259.stderr

diff --git a/tests/ui/parser/deli-ident-issue-1.rs b/tests/ui/parser/deli-ident-issue-1.rs
new file mode 100644
index 0000000000000..a8cbf8640f7a3
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-1.rs
@@ -0,0 +1,25 @@
+// error-pattern: this file contains an unclosed delimiter
+#![feature(let_chains)]
+trait Demo {}
+
+impl dyn Demo {
+    pub fn report(&self) -> u32 {
+        let sum = |a: u32,
+                   b: u32,
+                   c: u32| {
+            a + b + c
+        };
+        sum(1, 2, 3)
+    }
+
+    fn check(&self, val: Option<u32>, num: Option<u32>) {
+        if let Some(b) = val
+        && let Some(c) = num {
+        && b == c {
+            //~^ ERROR expected struct
+            //~| ERROR mismatched types
+        }
+    }
+}
+
+fn main() { } //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr
new file mode 100644
index 0000000000000..784f598f9d05c
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-1.stderr
@@ -0,0 +1,37 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/deli-ident-issue-1.rs:25:66
+   |
+LL | impl dyn Demo {
+   |               - unclosed delimiter
+...
+LL |                    c: u32| {
+   |                            - this delimiter might not be properly closed...
+LL |             a + b + c
+LL |         };
+   |         - ...as it matches this but it has different indentation
+...
+LL | fn main() { }
+   |                                                                  ^
+
+error[E0574]: expected struct, variant or union type, found local variable `c`
+  --> $DIR/deli-ident-issue-1.rs:18:17
+   |
+LL |         && b == c {
+   |                 ^ not a struct, variant or union type
+
+error[E0308]: mismatched types
+  --> $DIR/deli-ident-issue-1.rs:18:9
+   |
+LL |       fn check(&self, val: Option<u32>, num: Option<u32>) {
+   |                                                           - expected `()` because of default return type
+...
+LL | /         && b == c {
+LL | |
+LL | |
+LL | |         }
+   | |_________^ expected `()`, found `bool`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0574.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/deli-ident-issue-2.rs b/tests/ui/parser/deli-ident-issue-2.rs
new file mode 100644
index 0000000000000..5394760df7026
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-2.rs
@@ -0,0 +1,7 @@
+fn main() {
+    if 1 < 2 {
+        let _a = vec!]; //~ ERROR mismatched closing delimiter
+    }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr
new file mode 100644
index 0000000000000..782dac8f32d35
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-2.stderr
@@ -0,0 +1,21 @@
+error: unexpected closing delimiter: `}`
+  --> $DIR/deli-ident-issue-2.rs:5:1
+   |
+LL | fn main() {
+   |           - this opening brace...
+...
+LL |     }
+   |     - ...matches this closing brace
+LL | }
+   | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `]`
+  --> $DIR/deli-ident-issue-2.rs:2:14
+   |
+LL |     if 1 < 2 {
+   |              ^ unclosed delimiter
+LL |         let _a = vec!];
+   |                      ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-1.rs b/tests/ui/parser/issue-68987-unmatch-issue-1.rs
new file mode 100644
index 0000000000000..30e7ef467368a
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-1.rs
@@ -0,0 +1,12 @@
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+    match o {
+        Some(_x) => {}   // Extra '}'
+            let _ = if true {};
+        }
+        None => {}
+    }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-1.stderr b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
new file mode 100644
index 0000000000000..b5c1887f76f08
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
@@ -0,0 +1,11 @@
+error: unexpected closing delimiter: `}`
+  --> $DIR/issue-68987-unmatch-issue-1.rs:10:1
+   |
+LL |         None => {}
+   |                 -- block is empty, you might have not meant to close it
+LL |     }
+LL | }
+   | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.rs b/tests/ui/parser/issue-68987-unmatch-issue-2.rs
new file mode 100644
index 0000000000000..89aaa68ba4095
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.rs
@@ -0,0 +1,14 @@
+// FIXME: this case need more work to fix
+// currently the TokenTree matching ')' with '{', which is not user friendly for diagnostics
+async fn obstest() -> Result<> {
+    let obs_connect = || -> Result<(), MyError) { //~ ERROR mismatched closing delimiter
+        async {
+        }
+    }
+
+    if let Ok(version, scene_list) = obs_connect() {
+
+    } else {
+
+    }
+} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
new file mode 100644
index 0000000000000..253f12d44b83f
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
@@ -0,0 +1,21 @@
+error: unexpected closing delimiter: `}`
+  --> $DIR/issue-68987-unmatch-issue-2.rs:14:1
+   |
+LL |     } else {
+   |            - this opening brace...
+LL |
+LL |     }
+   |     - ...matches this closing brace
+LL | }
+   | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
+   |
+LL | async fn obstest() -> Result<> {
+   |                                ^ unclosed delimiter
+LL |     let obs_connect = || -> Result<(), MyError) {
+   |                                               ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.rs b/tests/ui/parser/issue-68987-unmatch-issue-3.rs
new file mode 100644
index 0000000000000..e98df8d7c3c4e
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.rs
@@ -0,0 +1,8 @@
+// the `{` is closed with `)`, there is a missing `(`
+fn f(i: u32, j: u32) {
+    let res = String::new();
+    let mut cnt = i;
+    while cnt < j {
+        write!&mut res, " "); //~ ERROR mismatched closing delimiter
+    }
+} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
new file mode 100644
index 0000000000000..258a692c8557b
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
@@ -0,0 +1,21 @@
+error: unexpected closing delimiter: `}`
+  --> $DIR/issue-68987-unmatch-issue-3.rs:8:1
+   |
+LL | fn f(i: u32, j: u32) {
+   |                      - this opening brace...
+...
+LL |     }
+   |     - ...matches this closing brace
+LL | }
+   | ^ unexpected closing delimiter
+
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
+   |
+LL |     while cnt < j {
+   |                   ^ unclosed delimiter
+LL |         write!&mut res, " ");
+   |                            ^ mismatched closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue.rs b/tests/ui/parser/issue-68987-unmatch-issue.rs
new file mode 100644
index 0000000000000..5a3620bf24bd4
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue.rs
@@ -0,0 +1,12 @@
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+    match o {
+        Some(_x) =>   // Missing '{'
+            let _ = if true {};
+        }
+        None => {}
+    }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/issue-68987-unmatch-issue.stderr b/tests/ui/parser/issue-68987-unmatch-issue.stderr
new file mode 100644
index 0000000000000..00e9c9a5ccee0
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue.stderr
@@ -0,0 +1,11 @@
+error: unexpected closing delimiter: `}`
+  --> $DIR/issue-68987-unmatch-issue.rs:10:1
+   |
+LL |         None => {}
+   |                 -- block is empty, you might have not meant to close it
+LL |     }
+LL | }
+   | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issues/issue-69259.rs b/tests/ui/parser/issues/issue-69259.rs
new file mode 100644
index 0000000000000..01fc2c0854647
--- /dev/null
+++ b/tests/ui/parser/issues/issue-69259.rs
@@ -0,0 +1,3 @@
+fn main() {}
+
+fn f) {} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issues/issue-69259.stderr b/tests/ui/parser/issues/issue-69259.stderr
new file mode 100644
index 0000000000000..f4cb391cb1ff2
--- /dev/null
+++ b/tests/ui/parser/issues/issue-69259.stderr
@@ -0,0 +1,13 @@
+error: unexpected closing delimiter: `)`
+  --> $DIR/issue-69259.rs:3:5
+   |
+LL | fn main() {}
+   |           -- ...matches this closing brace
+   |           |
+   |           this opening brace...
+LL |
+LL | fn f) {}
+   |     ^ unexpected closing delimiter
+
+error: aborting due to previous error
+

From cd233231aa215b7a5642e6a80869959b375e0725 Mon Sep 17 00:00:00 2001
From: yukang <moorekang@gmail.com>
Date: Thu, 26 Jan 2023 11:02:19 +0800
Subject: [PATCH 03/13] Improve unexpected close and mismatch delimiter hint in
 TokenTreesReader

---
 compiler/rustc_parse/src/lexer/diagnostics.rs | 119 ++++++++++++++++
 compiler/rustc_parse/src/lexer/mod.rs         |   1 +
 compiler/rustc_parse/src/lexer/tokentrees.rs  | 129 ++++++------------
 tests/ui/parser/deli-ident-issue-1.rs         |   1 -
 tests/ui/parser/deli-ident-issue-1.stderr     |  16 +--
 tests/ui/parser/deli-ident-issue-2.stderr     |   6 +-
 .../parser/issue-68987-unmatch-issue-1.stderr |  11 +-
 .../parser/issue-68987-unmatch-issue-2.stderr |   8 +-
 .../parser/issue-68987-unmatch-issue-3.stderr |   6 +-
 .../parser/issue-68987-unmatch-issue.stderr   |  11 +-
 tests/ui/parser/issue-81827.stderr            |  10 +-
 tests/ui/parser/issues/issue-62973.stderr     |  12 +-
 tests/ui/parser/issues/issue-63116.stderr     |   5 +-
 tests/ui/parser/issues/issue-69259.stderr     |   5 -
 .../issue-70583-block-is-empty-1.stderr       |   4 +-
 .../issue-70583-block-is-empty-2.stderr       |   6 +-
 .../macro-mismatched-delim-paren-brace.stderr |   4 +-
 tests/ui/typeck/issue-91334.stderr            |  10 +-
 18 files changed, 225 insertions(+), 139 deletions(-)
 create mode 100644 compiler/rustc_parse/src/lexer/diagnostics.rs

diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
new file mode 100644
index 0000000000000..386bf026bb4af
--- /dev/null
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -0,0 +1,119 @@
+use super::UnmatchedBrace;
+use rustc_ast::token::Delimiter;
+use rustc_errors::Diagnostic;
+use rustc_span::source_map::SourceMap;
+use rustc_span::Span;
+
+#[derive(Default)]
+pub struct TokenTreeDiagInfo {
+    /// Stack of open delimiters and their spans. Used for error message.
+    pub open_braces: Vec<(Delimiter, Span)>,
+    pub unmatched_braces: Vec<UnmatchedBrace>,
+
+    /// Used only for error recovery when arriving to EOF with mismatched braces.
+    pub last_unclosed_found_span: Option<Span>,
+
+    /// Collect empty block spans that might have been auto-inserted by editors.
+    pub empty_block_spans: Vec<Span>,
+
+    /// Collect the spans of braces (Open, Close). Used only
+    /// for detecting if blocks are empty and only braces.
+    pub matching_block_spans: Vec<(Span, Span)>,
+}
+
+pub fn same_identation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
+    match (sm.span_to_margin(open_sp), sm.span_to_margin(close_sp)) {
+        (Some(open_padding), Some(close_padding)) => open_padding == close_padding,
+        _ => false,
+    }
+}
+
+// When we get a `)` or `]` for `{`, we should emit help message here
+// it's more friendly compared to report `unmatched error` in later phase
+pub fn report_missing_open_delim(
+    err: &mut Diagnostic,
+    unmatched_braces: &[UnmatchedBrace],
+) -> bool {
+    let mut reported_missing_open = false;
+    for unmatch_brace in unmatched_braces.iter() {
+        if let Some(delim) = unmatch_brace.found_delim
+            && matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket)
+        {
+            let missed_open = match delim {
+                Delimiter::Parenthesis => "(",
+                Delimiter::Bracket => "[",
+                _ => unreachable!(),
+            };
+            err.span_label(
+                unmatch_brace.found_span.shrink_to_lo(),
+                format!("missing open `{}` for this delimiter", missed_open),
+            );
+            reported_missing_open = true;
+        }
+    }
+    reported_missing_open
+}
+
+pub fn report_suspicious_mismatch_block(
+    err: &mut Diagnostic,
+    diag_info: &TokenTreeDiagInfo,
+    sm: &SourceMap,
+    delim: Delimiter,
+) {
+    if report_missing_open_delim(err, &diag_info.unmatched_braces) {
+        return;
+    }
+
+    let mut matched_spans: Vec<(Span, bool)> = diag_info
+        .matching_block_spans
+        .iter()
+        .map(|&(open, close)| (open.with_hi(close.lo()), same_identation_level(sm, open, close)))
+        .collect();
+
+    // sort by `lo`, so the large block spans in the front
+    matched_spans.sort_by(|a, b| a.0.lo().cmp(&b.0.lo()));
+
+    // We use larger block whose identation is well to cover those inner mismatched blocks
+    // O(N^2) here, but we are on error reporting path, so it is fine
+    for i in 0..matched_spans.len() {
+        let (block_span, same_ident) = matched_spans[i];
+        if same_ident {
+            for j in i + 1..matched_spans.len() {
+                let (inner_block, inner_same_ident) = matched_spans[j];
+                if block_span.contains(inner_block) && !inner_same_ident {
+                    matched_spans[j] = (inner_block, true);
+                }
+            }
+        }
+    }
+
+    // Find the inner-most span candidate for final report
+    let candidate_span =
+        matched_spans.into_iter().rev().find(|&(_, same_ident)| !same_ident).map(|(span, _)| span);
+
+    if let Some(block_span) = candidate_span {
+        err.span_label(block_span.shrink_to_lo(), "this delimiter might not be properly closed...");
+        err.span_label(
+            block_span.shrink_to_hi(),
+            "...as it matches this but it has different indentation",
+        );
+
+        // If there is a empty block in the mismatched span, note it
+        if delim == Delimiter::Brace {
+            for span in diag_info.empty_block_spans.iter() {
+                if block_span.contains(*span) {
+                    err.span_label(*span, "block is empty, you might have not meant to close it");
+                    break;
+                }
+            }
+        }
+    } else {
+        // If there is no suspicious span, give the last properly closed block may help
+        if let Some(parent) = diag_info.matching_block_spans.last()
+            && diag_info.open_braces.last().is_none()
+            && diag_info.empty_block_spans.iter().all(|&sp| sp != parent.0.to(parent.1)) {
+                err.span_label(parent.0, "this opening brace...");
+                err.span_label(parent.1, "...matches this closing brace");
+        }
+    }
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 9fe8d9836ba60..e957224a03377 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -17,6 +17,7 @@ use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{edition::Edition, BytePos, Pos, Span};
 
+mod diagnostics;
 mod tokentrees;
 mod unescape_error_reporting;
 mod unicode_chars;
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index b2701817d489b..0de8f79112c65 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,29 +1,18 @@
+use super::diagnostics::report_suspicious_mismatch_block;
+use super::diagnostics::same_identation_level;
+use super::diagnostics::TokenTreeDiagInfo;
 use super::{StringReader, UnmatchedBrace};
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{PErr, PResult};
-use rustc_span::Span;
 
 pub(super) struct TokenTreesReader<'a> {
     string_reader: StringReader<'a>,
     /// The "next" token, which has been obtained from the `StringReader` but
     /// not yet handled by the `TokenTreesReader`.
     token: Token,
-    /// Stack of open delimiters and their spans. Used for error message.
-    open_braces: Vec<(Delimiter, Span)>,
-    unmatched_braces: Vec<UnmatchedBrace>,
-    /// The type and spans for all braces
-    ///
-    /// Used only for error recovery when arriving to EOF with mismatched braces.
-    matching_delim_spans: Vec<(Delimiter, Span, Span)>,
-    last_unclosed_found_span: Option<Span>,
-    /// Collect empty block spans that might have been auto-inserted by editors.
-    last_delim_empty_block_spans: FxHashMap<Delimiter, Span>,
-    /// Collect the spans of braces (Open, Close). Used only
-    /// for detecting if blocks are empty and only braces.
-    matching_block_spans: Vec<(Span, Span)>,
+    diag_info: TokenTreeDiagInfo,
 }
 
 impl<'a> TokenTreesReader<'a> {
@@ -33,15 +22,10 @@ impl<'a> TokenTreesReader<'a> {
         let mut tt_reader = TokenTreesReader {
             string_reader,
             token: Token::dummy(),
-            open_braces: Vec::new(),
-            unmatched_braces: Vec::new(),
-            matching_delim_spans: Vec::new(),
-            last_unclosed_found_span: None,
-            last_delim_empty_block_spans: FxHashMap::default(),
-            matching_block_spans: Vec::new(),
+            diag_info: TokenTreeDiagInfo::default(),
         };
         let res = tt_reader.parse_token_trees(/* is_delimited */ false);
-        (res, tt_reader.unmatched_braces)
+        (res, tt_reader.diag_info.unmatched_braces)
     }
 
     // Parse a stream of tokens into a list of `TokenTree`s.
@@ -92,9 +76,9 @@ impl<'a> TokenTreesReader<'a> {
     fn eof_err(&mut self) -> PErr<'a> {
         let msg = "this file contains an unclosed delimiter";
         let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
-        for &(_, sp) in &self.open_braces {
+        for &(_, sp) in &self.diag_info.open_braces {
             err.span_label(sp, "unclosed delimiter");
-            self.unmatched_braces.push(UnmatchedBrace {
+            self.diag_info.unmatched_braces.push(UnmatchedBrace {
                 expected_delim: Delimiter::Brace,
                 found_delim: None,
                 found_span: self.token.span,
@@ -103,23 +87,13 @@ impl<'a> TokenTreesReader<'a> {
             });
         }
 
-        if let Some((delim, _)) = self.open_braces.last() {
-            if let Some((_, open_sp, close_sp)) =
-                self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| {
-                    let sm = self.string_reader.sess.source_map();
-                    if let Some(close_padding) = sm.span_to_margin(*close_sp) {
-                        if let Some(open_padding) = sm.span_to_margin(*open_sp) {
-                            return delim == d && close_padding != open_padding;
-                        }
-                    }
-                    false
-                })
-            // these are in reverse order as they get inserted on close, but
-            {
-                // we want the last open/first close
-                err.span_label(*open_sp, "this delimiter might not be properly closed...");
-                err.span_label(*close_sp, "...as it matches this but it has different indentation");
-            }
+        if let Some((delim, _)) = self.diag_info.open_braces.last() {
+            report_suspicious_mismatch_block(
+                &mut err,
+                &self.diag_info,
+                &self.string_reader.sess.source_map(),
+                *delim,
+            )
         }
         err
     }
@@ -128,7 +102,7 @@ impl<'a> TokenTreesReader<'a> {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
-        self.open_braces.push((open_delim, self.token.span));
+        self.diag_info.open_braces.push((open_delim, self.token.span));
 
         // Parse the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
@@ -137,35 +111,29 @@ impl<'a> TokenTreesReader<'a> {
 
         // Expand to cover the entire delimited token tree
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
+        let sm = self.string_reader.sess.source_map();
 
         match self.token.kind {
             // Correct delimiter.
             token::CloseDelim(close_delim) if close_delim == open_delim => {
-                let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
+                let (open_brace, open_brace_span) = self.diag_info.open_braces.pop().unwrap();
                 let close_brace_span = self.token.span;
 
-                if tts.is_empty() {
+                if tts.is_empty() && close_delim == Delimiter::Brace {
                     let empty_block_span = open_brace_span.to(close_brace_span);
-                    let sm = self.string_reader.sess.source_map();
                     if !sm.is_multiline(empty_block_span) {
                         // Only track if the block is in the form of `{}`, otherwise it is
                         // likely that it was written on purpose.
-                        self.last_delim_empty_block_spans.insert(open_delim, empty_block_span);
+                        self.diag_info.empty_block_spans.push(empty_block_span);
                     }
                 }
 
-                //only add braces
+                // only add braces
                 if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
-                    self.matching_block_spans.push((open_brace_span, close_brace_span));
+                    // Add all the matching spans, we will sort by span later
+                    self.diag_info.matching_block_spans.push((open_brace_span, close_brace_span));
                 }
 
-                if self.open_braces.is_empty() {
-                    // Clear up these spans to avoid suggesting them as we've found
-                    // properly matched delimiters so far for an entire block.
-                    self.matching_delim_spans.clear();
-                } else {
-                    self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span));
-                }
                 // Move past the closing delimiter.
                 self.token = self.string_reader.next_token().0;
             }
@@ -174,28 +142,25 @@ impl<'a> TokenTreesReader<'a> {
                 let mut unclosed_delimiter = None;
                 let mut candidate = None;
 
-                if self.last_unclosed_found_span != Some(self.token.span) {
+                if self.diag_info.last_unclosed_found_span != Some(self.token.span) {
                     // do not complain about the same unclosed delimiter multiple times
-                    self.last_unclosed_found_span = Some(self.token.span);
+                    self.diag_info.last_unclosed_found_span = Some(self.token.span);
                     // This is a conservative error: only report the last unclosed
                     // delimiter. The previous unclosed delimiters could actually be
                     // closed! The parser just hasn't gotten to them yet.
-                    if let Some(&(_, sp)) = self.open_braces.last() {
+                    if let Some(&(_, sp)) = self.diag_info.open_braces.last() {
                         unclosed_delimiter = Some(sp);
                     };
-                    let sm = self.string_reader.sess.source_map();
-                    if let Some(current_padding) = sm.span_to_margin(self.token.span) {
-                        for (brace, brace_span) in &self.open_braces {
-                            if let Some(padding) = sm.span_to_margin(*brace_span) {
-                                // high likelihood of these two corresponding
-                                if current_padding == padding && brace == &close_delim {
-                                    candidate = Some(*brace_span);
-                                }
-                            }
+                    for (brace, brace_span) in &self.diag_info.open_braces {
+                        if same_identation_level(&sm, self.token.span, *brace_span)
+                            && brace == &close_delim
+                        {
+                            // high likelihood of these two corresponding
+                            candidate = Some(*brace_span);
                         }
                     }
-                    let (tok, _) = self.open_braces.pop().unwrap();
-                    self.unmatched_braces.push(UnmatchedBrace {
+                    let (tok, _) = self.diag_info.open_braces.pop().unwrap();
+                    self.diag_info.unmatched_braces.push(UnmatchedBrace {
                         expected_delim: tok,
                         found_delim: Some(close_delim),
                         found_span: self.token.span,
@@ -203,7 +168,7 @@ impl<'a> TokenTreesReader<'a> {
                         candidate_span: candidate,
                     });
                 } else {
-                    self.open_braces.pop();
+                    self.diag_info.open_braces.pop();
                 }
 
                 // If the incorrect delimiter matches an earlier opening
@@ -213,7 +178,7 @@ impl<'a> TokenTreesReader<'a> {
                 // fn foo() {
                 //     bar(baz(
                 // }  // Incorrect delimiter but matches the earlier `{`
-                if !self.open_braces.iter().any(|&(b, _)| b == close_delim) {
+                if !self.diag_info.open_braces.iter().any(|&(b, _)| b == close_delim) {
                     self.token = self.string_reader.next_token().0;
                 }
             }
@@ -236,22 +201,12 @@ impl<'a> TokenTreesReader<'a> {
         let mut err =
             self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
 
-        // Braces are added at the end, so the last element is the biggest block
-        if let Some(parent) = self.matching_block_spans.last() {
-            if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
-                // Check if the (empty block) is in the last properly closed block
-                if (parent.0.to(parent.1)).contains(span) {
-                    err.span_label(span, "block is empty, you might have not meant to close it");
-                } else {
-                    err.span_label(parent.0, "this opening brace...");
-                    err.span_label(parent.1, "...matches this closing brace");
-                }
-            } else {
-                err.span_label(parent.0, "this opening brace...");
-                err.span_label(parent.1, "...matches this closing brace");
-            }
-        }
-
+        report_suspicious_mismatch_block(
+            &mut err,
+            &self.diag_info,
+            &self.string_reader.sess.source_map(),
+            delim,
+        );
         err.span_label(self.token.span, "unexpected closing delimiter");
         err
     }
diff --git a/tests/ui/parser/deli-ident-issue-1.rs b/tests/ui/parser/deli-ident-issue-1.rs
index a8cbf8640f7a3..54485262a0cc8 100644
--- a/tests/ui/parser/deli-ident-issue-1.rs
+++ b/tests/ui/parser/deli-ident-issue-1.rs
@@ -1,4 +1,3 @@
-// error-pattern: this file contains an unclosed delimiter
 #![feature(let_chains)]
 trait Demo {}
 
diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr
index 784f598f9d05c..1119edb199f05 100644
--- a/tests/ui/parser/deli-ident-issue-1.stderr
+++ b/tests/ui/parser/deli-ident-issue-1.stderr
@@ -1,26 +1,26 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/deli-ident-issue-1.rs:25:66
+  --> $DIR/deli-ident-issue-1.rs:24:66
    |
 LL | impl dyn Demo {
    |               - unclosed delimiter
 ...
-LL |                    c: u32| {
-   |                            - this delimiter might not be properly closed...
-LL |             a + b + c
-LL |         };
-   |         - ...as it matches this but it has different indentation
+LL |         && let Some(c) = num {
+   |                              - this delimiter might not be properly closed...
+...
+LL |     }
+   |     - ...as it matches this but it has different indentation
 ...
 LL | fn main() { }
    |                                                                  ^
 
 error[E0574]: expected struct, variant or union type, found local variable `c`
-  --> $DIR/deli-ident-issue-1.rs:18:17
+  --> $DIR/deli-ident-issue-1.rs:17:17
    |
 LL |         && b == c {
    |                 ^ not a struct, variant or union type
 
 error[E0308]: mismatched types
-  --> $DIR/deli-ident-issue-1.rs:18:9
+  --> $DIR/deli-ident-issue-1.rs:17:9
    |
 LL |       fn check(&self, val: Option<u32>, num: Option<u32>) {
    |                                                           - expected `()` because of default return type
diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr
index 782dac8f32d35..c8f59c9d32b5f 100644
--- a/tests/ui/parser/deli-ident-issue-2.stderr
+++ b/tests/ui/parser/deli-ident-issue-2.stderr
@@ -1,11 +1,9 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/deli-ident-issue-2.rs:5:1
    |
-LL | fn main() {
-   |           - this opening brace...
-...
+LL |         let _a = vec!];
+   |                      - missing open `[` for this delimiter
 LL |     }
-   |     - ...matches this closing brace
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-1.stderr b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
index b5c1887f76f08..2d873b46193ce 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
@@ -1,9 +1,14 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue-1.rs:10:1
    |
-LL |         None => {}
-   |                 -- block is empty, you might have not meant to close it
-LL |     }
+LL |     match o {
+   |             - this delimiter might not be properly closed...
+LL |         Some(_x) => {}   // Extra '}'
+   |                     -- block is empty, you might have not meant to close it
+LL |             let _ = if true {};
+LL |         }
+   |         - ...as it matches this but it has different indentation
+...
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
index 253f12d44b83f..2c08d41a15f1b 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
@@ -1,11 +1,9 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue-2.rs:14:1
    |
-LL |     } else {
-   |            - this opening brace...
-LL |
-LL |     }
-   |     - ...matches this closing brace
+LL |     let obs_connect = || -> Result<(), MyError) {
+   |                                               - missing open `(` for this delimiter
+...
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
index 258a692c8557b..a3fc46a1e883c 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
@@ -1,11 +1,9 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue-3.rs:8:1
    |
-LL | fn f(i: u32, j: u32) {
-   |                      - this opening brace...
-...
+LL |         write!&mut res, " ");
+   |                            - missing open `(` for this delimiter
 LL |     }
-   |     - ...matches this closing brace
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issue-68987-unmatch-issue.stderr b/tests/ui/parser/issue-68987-unmatch-issue.stderr
index 00e9c9a5ccee0..cabd133242f60 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue.stderr
@@ -1,9 +1,14 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue.rs:10:1
    |
-LL |         None => {}
-   |                 -- block is empty, you might have not meant to close it
-LL |     }
+LL |     match o {
+   |             - this delimiter might not be properly closed...
+LL |         Some(_x) =>   // Missing '{'
+LL |             let _ = if true {};
+   |                             -- block is empty, you might have not meant to close it
+LL |         }
+   |         - ...as it matches this but it has different indentation
+...
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issue-81827.stderr b/tests/ui/parser/issue-81827.stderr
index 069de33919494..867244b72e849 100644
--- a/tests/ui/parser/issue-81827.stderr
+++ b/tests/ui/parser/issue-81827.stderr
@@ -2,8 +2,9 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-81827.rs:11:27
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
-   |          -  -             ^
-   |          |  |
+   |          -  -          -  ^
+   |          |  |          |
+   |          |  |          missing open `[` for this delimiter
    |          |  unclosed delimiter
    |          unclosed delimiter
 
@@ -11,8 +12,9 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-81827.rs:11:27
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
-   |          -  -             ^
-   |          |  |
+   |          -  -          -  ^
+   |          |  |          |
+   |          |  |          missing open `[` for this delimiter
    |          |  unclosed delimiter
    |          unclosed delimiter
 
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 4737bc71860c2..3cb6d75a6754b 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -2,8 +2,10 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-62973.rs:8:2
    |
 LL | fn p() { match s { v, E { [) {) }
-   |        -         - unclosed delimiter
-   |        |
+   |        -         -         -  - missing open `(` for this delimiter
+   |        |         |         |
+   |        |         |         missing open `(` for this delimiter
+   |        |         unclosed delimiter
    |        unclosed delimiter
 LL |
 LL |
@@ -13,8 +15,10 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-62973.rs:8:2
    |
 LL | fn p() { match s { v, E { [) {) }
-   |        -         - unclosed delimiter
-   |        |
+   |        -         -         -  - missing open `(` for this delimiter
+   |        |         |         |
+   |        |         |         missing open `(` for this delimiter
+   |        |         unclosed delimiter
    |        unclosed delimiter
 LL |
 LL |
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index cfdd99d1434ae..a1f8a77ffa7c6 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -2,8 +2,9 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-63116.rs:3:18
    |
 LL | impl W <s(f;Y(;]
-   |          -       ^
-   |          |
+   |          -     - ^
+   |          |     |
+   |          |     missing open `[` for this delimiter
    |          unclosed delimiter
 
 error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
diff --git a/tests/ui/parser/issues/issue-69259.stderr b/tests/ui/parser/issues/issue-69259.stderr
index f4cb391cb1ff2..604b7de331946 100644
--- a/tests/ui/parser/issues/issue-69259.stderr
+++ b/tests/ui/parser/issues/issue-69259.stderr
@@ -1,11 +1,6 @@
 error: unexpected closing delimiter: `)`
   --> $DIR/issue-69259.rs:3:5
    |
-LL | fn main() {}
-   |           -- ...matches this closing brace
-   |           |
-   |           this opening brace...
-LL |
 LL | fn f) {}
    |     ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
index 39bf113ef83de..46cbb056d1d88 100644
--- a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
+++ b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
@@ -2,10 +2,10 @@ error: unexpected closing delimiter: `}`
   --> $DIR/issue-70583-block-is-empty-1.rs:20:1
    |
 LL | fn struct_generic(x: Vec<i32>) {
-   |                                - this opening brace...
+   |                                - this delimiter might not be properly closed...
 ...
 LL |     }
-   |     - ...matches this closing brace
+   |     - ...as it matches this but it has different indentation
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
index 5d37b216427f6..9ae94c701869b 100644
--- a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
+++ b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
@@ -1,8 +1,12 @@
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-70583-block-is-empty-2.rs:14:1
    |
+LL |         match self {
+   |                    - this delimiter might not be properly closed...
 LL |             ErrorHandled::Reported => {}}
-   |                                       -- block is empty, you might have not meant to close it
+   |                                       --- ...as it matches this but it has different indentation
+   |                                       |
+   |                                       block is empty, you might have not meant to close it
 ...
 LL | }
    | ^ unexpected closing delimiter
diff --git a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
index 967a3e6fdc11b..689ce1eb6b704 100644
--- a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
+++ b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
@@ -2,10 +2,10 @@ error: unexpected closing delimiter: `}`
   --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
    |
 LL | fn main() {
-   |           - this opening brace...
+   |           - this delimiter might not be properly closed...
 ...
 LL |     }
-   |     - ...matches this closing brace
+   |     - ...as it matches this but it has different indentation
 LL | }
    | ^ unexpected closing delimiter
 
diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr
index 8508f7a38e239..78f392c9a8acc 100644
--- a/tests/ui/typeck/issue-91334.stderr
+++ b/tests/ui/typeck/issue-91334.stderr
@@ -2,8 +2,9 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-91334.rs:10:23
    |
 LL | fn f(){||yield(((){),
-   |       -       -       ^
-   |       |       |
+   |       -       -    -  ^
+   |       |       |    |
+   |       |       |    missing open `(` for this delimiter
    |       |       unclosed delimiter
    |       unclosed delimiter
 
@@ -11,8 +12,9 @@ error: this file contains an unclosed delimiter
   --> $DIR/issue-91334.rs:10:23
    |
 LL | fn f(){||yield(((){),
-   |       -       -       ^
-   |       |       |
+   |       -       -    -  ^
+   |       |       |    |
+   |       |       |    missing open `(` for this delimiter
    |       |       unclosed delimiter
    |       unclosed delimiter
 

From dbe911ff36316c08f1e3316e593c96512d6860d7 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <jtitor@2k36.org>
Date: Fri, 27 Jan 2023 19:46:56 +0900
Subject: [PATCH 04/13] Add regression test for #60755

Signed-off-by: Yuki Okushi <jtitor@2k36.org>
---
 tests/ui/traits/alias/issue-60755.rs | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 tests/ui/traits/alias/issue-60755.rs

diff --git a/tests/ui/traits/alias/issue-60755.rs b/tests/ui/traits/alias/issue-60755.rs
new file mode 100644
index 0000000000000..6b955a752479f
--- /dev/null
+++ b/tests/ui/traits/alias/issue-60755.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+struct MyStruct {}
+trait MyFn = Fn(&MyStruct);
+
+fn foo(_: impl MyFn) {}
+
+fn main() {
+    foo(|_| {});
+}

From ed707a106cac7393db3b59d85b8b065d09840c61 Mon Sep 17 00:00:00 2001
From: clubby789 <jamie@hill-daniel.co.uk>
Date: Thu, 19 Jan 2023 23:48:08 +0000
Subject: [PATCH 05/13] Detect references to non-existant messages in Fluent
 resources

---
 .../rustc_macros/src/diagnostics/fluent.rs    | 34 +++++++++++++++++--
 .../fluent-messages/missing-message-ref.ftl   |  1 +
 tests/ui-fulldeps/fluent-messages/test.rs     |  9 +++++
 tests/ui-fulldeps/fluent-messages/test.stderr | 10 +++++-
 4 files changed, 51 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl

diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 32338f9dfc5e3..08098c9bb2a85 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -4,7 +4,10 @@ use annotate_snippets::{
 };
 use fluent_bundle::{FluentBundle, FluentError, FluentResource};
 use fluent_syntax::{
-    ast::{Attribute, Entry, Identifier, Message},
+    ast::{
+        Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern,
+        PatternElement,
+    },
     parser::ParserError,
 };
 use proc_macro::{Diagnostic, Level, Span};
@@ -185,9 +188,12 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
         };
 
         let mut constants = TokenStream::new();
+        let mut messagerefs = Vec::new();
         for entry in resource.entries() {
             let span = res.krate.span();
-            if let Entry::Message(Message { id: Identifier { name }, attributes, .. }) = entry {
+            if let Entry::Message(Message { id: Identifier { name }, attributes, value, .. }) =
+                entry
+            {
                 let _ = previous_defns.entry(name.to_string()).or_insert(path_span);
 
                 if name.contains('-') {
@@ -200,6 +206,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                     .emit();
                 }
 
+                if let Some(Pattern { elements }) = value {
+                    for elt in elements {
+                        if let PatternElement::Placeable {
+                            expression:
+                                Expression::Inline(InlineExpression::MessageReference { id, .. }),
+                        } = elt
+                        {
+                            messagerefs.push((id.name, *name));
+                        }
+                    }
+                }
+
                 // Require that the message name starts with the crate name
                 // `hir_typeck_foo_bar` (in `hir_typeck.ftl`)
                 // `const_eval_baz` (in `const_eval.ftl`)
@@ -258,6 +276,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
             }
         }
 
+        for (mref, name) in messagerefs.into_iter() {
+            if !previous_defns.contains_key(mref) {
+                Diagnostic::spanned(
+                    path_span,
+                    Level::Error,
+                    format!("referenced message `{mref}` does not exist (in message `{name}`)"),
+                )
+                .help(&format!("you may have meant to use a variable reference (`{{${mref}}}`)"))
+                .emit();
+            }
+        }
+
         if let Err(errs) = bundle.add_resource(resource) {
             for e in errs {
                 match e {
diff --git a/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl
new file mode 100644
index 0000000000000..0cd8229b23010
--- /dev/null
+++ b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl
@@ -0,0 +1 @@
+missing_message_ref = {message}
diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs
index 4e8147e2b76dc..74303e97dba94 100644
--- a/tests/ui-fulldeps/fluent-messages/test.rs
+++ b/tests/ui-fulldeps/fluent-messages/test.rs
@@ -96,3 +96,12 @@ mod missing_crate_name {
 
     use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens};
 }
+
+mod missing_message_ref {
+    use super::fluent_messages;
+
+    fluent_messages! {
+        missing => "./missing-message-ref.ftl"
+//~^ ERROR referenced message `message` does not exist
+    }
+}
diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr
index d1cd4fe26da27..2631b0a623275 100644
--- a/tests/ui-fulldeps/fluent-messages/test.stderr
+++ b/tests/ui-fulldeps/fluent-messages/test.stderr
@@ -93,6 +93,14 @@ LL |         test_crate => "./missing-crate-name.ftl",
    |
    = help: replace any '-'s with '_'s
 
-error: aborting due to 10 previous errors
+error: referenced message `message` does not exist (in message `missing_message_ref`)
+  --> $DIR/test.rs:104:20
+   |
+LL |         missing => "./missing-message-ref.ftl"
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: you may have meant to use a variable reference (`{$message}`)
+
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0428`.

From 0ae0d87c5dd7b0b0b17124dadb2d5a3ce7e2bfef Mon Sep 17 00:00:00 2001
From: clubby789 <jamie@hill-daniel.co.uk>
Date: Thu, 19 Jan 2023 23:53:26 +0000
Subject: [PATCH 06/13] Fix some Fluent typos

---
 compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl | 2 +-
 compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
index 08ce5172574ac..6101b28ab0cdd 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
@@ -23,7 +23,7 @@ codegen_gcc_invalid_monomorphization_unsupported_element =
     invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
 
 codegen_gcc_invalid_monomorphization_invalid_bitmask =
-    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
 codegen_gcc_invalid_monomorphization_simd_shuffle =
     invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
index c8c7afb5f9196..4924105128db6 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
@@ -179,9 +179,9 @@ codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$
 
 codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
 
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error}
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
 
-codegen_ssa_read_file = failed to read file: {message}
+codegen_ssa_read_file = failed to read file: {$message}
 
 codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
 

From 454c473599aab480b704a470407eb9ab59a7fe27 Mon Sep 17 00:00:00 2001
From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com>
Date: Fri, 27 Jan 2023 20:22:54 +0100
Subject: [PATCH 07/13] Remove `BOOL_TY_FOR_UNIT_TESTING`

It is not used anymore for unit testing.
---
 compiler/rustc_middle/src/ty/mod.rs | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 4af29fcbfb586..6fe1676bb7428 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -453,18 +453,6 @@ pub struct CReaderCacheKey {
 #[rustc_pass_by_value]
 pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
 
-impl<'tcx> TyCtxt<'tcx> {
-    /// A "bool" type used in rustc_mir_transform unit tests when we
-    /// have not spun up a TyCtxt.
-    pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
-        Ty(Interned::new_unchecked(&WithCachedTypeInfo {
-            internee: ty::Bool,
-            stable_hash: Fingerprint::ZERO,
-            flags: TypeFlags::empty(),
-            outer_exclusive_binder: DebruijnIndex::from_usize(0),
-        }));
-}
-
 impl ty::EarlyBoundRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).

From 29901e027c8f343e0366e308a9bf7edb2618c867 Mon Sep 17 00:00:00 2001
From: Boxy <supbscripter@gmail.com>
Date: Fri, 27 Jan 2023 19:29:04 +0000
Subject: [PATCH 08/13] yeet

---
 compiler/rustc_infer/src/infer/combine.rs | 114 +++++-----------------
 1 file changed, 26 insertions(+), 88 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 72676b718fabe..a567b6acdbeeb 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -37,7 +37,10 @@ use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{
+    self, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+    TypeVisitable,
+};
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -140,8 +143,6 @@ impl<'tcx> InferCtxt<'tcx> {
         let a = self.shallow_resolve(a);
         let b = self.shallow_resolve(b);
 
-        let a_is_expected = relation.a_is_expected();
-
         match (a.kind(), b.kind()) {
             (
                 ty::ConstKind::Infer(InferConst::Var(a_vid)),
@@ -158,11 +159,11 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             (ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
-                return self.unify_const_variable(relation.param_env(), vid, b, a_is_expected);
+                return self.unify_const_variable(vid, b);
             }
 
             (_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
-                return self.unify_const_variable(relation.param_env(), vid, a, !a_is_expected);
+                return self.unify_const_variable(vid, a);
             }
             (ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
                 // FIXME(#59490): Need to remove the leak check to accommodate
@@ -223,10 +224,8 @@ impl<'tcx> InferCtxt<'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn unify_const_variable(
         &self,
-        param_env: ty::ParamEnv<'tcx>,
         target_vid: ty::ConstVid<'tcx>,
         ct: ty::Const<'tcx>,
-        vid_is_expected: bool,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
         let (for_universe, span) = {
             let mut inner = self.inner.borrow_mut();
@@ -239,8 +238,12 @@ impl<'tcx> InferCtxt<'tcx> {
                 ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
             }
         };
-        let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid }
-            .relate(ct, ct)?;
+        let value = ct.try_fold_with(&mut ConstInferUnifier {
+            infcx: self,
+            span,
+            for_universe,
+            target_vid,
+        })?;
 
         self.inner.borrow_mut().const_unification_table().union_value(
             target_vid,
@@ -800,8 +803,6 @@ struct ConstInferUnifier<'cx, 'tcx> {
 
     span: Span,
 
-    param_env: ty::ParamEnv<'tcx>,
-
     for_universe: ty::UniverseIndex,
 
     /// The vid of the const variable that is in the process of being
@@ -810,61 +811,15 @@ struct ConstInferUnifier<'cx, 'tcx> {
     target_vid: ty::ConstVid<'tcx>,
 }
 
-// We use `TypeRelation` here to propagate `RelateResult` upwards.
-//
-// Both inputs are expected to be the same.
-impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn intercrate(&self) -> bool {
-        assert!(!self.infcx.intercrate);
-        false
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
-    }
-
-    fn tag(&self) -> &'static str {
-        "ConstInferUnifier"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn mark_ambiguous(&mut self) {
-        bug!()
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        _variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        // We don't care about variance here.
-        self.relate(a, b)
-    }
+impl<'tcx> FallibleTypeFolder<'tcx> for ConstInferUnifier<'_, 'tcx> {
+    type Error = TypeError<'tcx>;
 
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>,
-    {
-        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
     }
 
     #[instrument(level = "debug", skip(self), ret)]
-    fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug_assert_eq!(t, _t);
-
+    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
         match t.kind() {
             &ty::Infer(ty::TyVar(vid)) => {
                 let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
@@ -872,7 +827,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 match probe {
                     TypeVariableValue::Known { value: u } => {
                         debug!("ConstOccursChecker: known value {:?}", u);
-                        self.tys(u, u)
+                        u.try_fold_with(self)
                     }
                     TypeVariableValue::Unknown { universe } => {
                         if self.for_universe.can_name(universe) {
@@ -892,16 +847,15 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 }
             }
             ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
-            _ => relate::super_relate_tys(self, t, t),
+            _ => t.try_super_fold_with(self),
         }
     }
 
-    fn regions(
+    #[instrument(level = "debug", skip(self), ret)]
+    fn try_fold_region(
         &mut self,
         r: ty::Region<'tcx>,
-        _r: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug_assert_eq!(r, _r);
+    ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
         debug!("ConstInferUnifier: r={:?}", r);
 
         match *r {
@@ -930,14 +884,8 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self))]
-    fn consts(
-        &mut self,
-        c: ty::Const<'tcx>,
-        _c: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        debug_assert_eq!(c, _c);
-
+    #[instrument(level = "debug", skip(self), ret)]
+    fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
         match c.kind() {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
                 // Check if the current unification would end up
@@ -958,7 +906,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 let var_value =
                     self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
                 match var_value.val {
-                    ConstVariableValue::Known { value: u } => self.consts(u, u),
+                    ConstVariableValue::Known { value: u } => u.try_fold_with(self),
                     ConstVariableValue::Unknown { universe } => {
                         if self.for_universe.can_name(universe) {
                             Ok(c)
@@ -977,17 +925,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                     }
                 }
             }
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
-                let substs = self.relate_with_variance(
-                    ty::Variance::Invariant,
-                    ty::VarianceDiagInfo::default(),
-                    substs,
-                    substs,
-                )?;
-
-                Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
-            }
-            _ => relate::super_relate_consts(self, c, c),
+            _ => c.try_super_fold_with(self),
         }
     }
 }

From 5152e84024cd9bbeeebd7bf27d048628cfc0cd95 Mon Sep 17 00:00:00 2001
From: nils <48135649+Nilstrieb@users.noreply.github.com>
Date: Fri, 27 Jan 2023 20:58:54 +0100
Subject: [PATCH 09/13] Remove unused import

---
 compiler/rustc_middle/src/ty/mod.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6fe1676bb7428..7001f81aa7750 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -31,7 +31,6 @@ pub use generics::*;
 use rustc_ast as ast;
 use rustc_ast::node_id::NodeMap;
 use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};

From 0959149323bd025905cd8b2572426e6fe443b420 Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Fri, 27 Jan 2023 14:23:28 -0700
Subject: [PATCH 10/13] rustdoc: remove inline javascript from copy-path button

---
 src/librustdoc/html/static/js/main.js         | 6 +++++-
 src/librustdoc/html/templates/print_item.html | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 604ab147f6a16..b9ad8ef70e917 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1142,7 +1142,11 @@ function loadCss(cssUrl) {
 (function() {
     let reset_button_timeout = null;
 
-    window.copy_path = but => {
+    const but = document.getElementById("copy-path");
+    if (!but) {
+        return;
+    }
+    but.onclick = () => {
         const parent = but.parentElement;
         const path = [];
 
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
index ee2880bf6d195..3a1867b7feba3 100644
--- a/src/librustdoc/html/templates/print_item.html
+++ b/src/librustdoc/html/templates/print_item.html
@@ -6,7 +6,7 @@ <h1> {#- -#}
         <a href="{{component.path|safe}}index.html">{{component.name}}</a>::<wbr>
         {%- endfor -%}
         <a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
-        <button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
+        <button id="copy-path" title="Copy item path to clipboard"> {#- -#}
         <img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#}
                 width="19" height="18" {# -#}
                 alt="Copy item path"> {#- -#}

From 868d099a7222489565f08e247803b462d020ff30 Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Fri, 27 Jan 2023 19:46:42 -0800
Subject: [PATCH 11/13] Remove `ControlFlow::{BREAK, CONTINUE}`

Libs-API decided to remove these in #102697.

Follow-up to #107023, which removed them from `compiler/`, but a couple new ones showed up since that was merged.
---
 .../src/solve/project_goals.rs                |  8 ++--
 library/core/src/iter/adapters/filter_map.rs  |  2 +-
 library/core/src/iter/adapters/flatten.rs     |  4 +-
 library/core/src/iter/traits/double_ended.rs  |  2 +-
 library/core/src/iter/traits/iterator.rs      | 22 +++++-----
 library/core/src/ops/control_flow.rs          | 43 -------------------
 6 files changed, 19 insertions(+), 62 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 30902c2bc4506..d39979b5d1c31 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -93,24 +93,24 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 if t.needs_infer() {
                     if ty::Term::from(t) == self.term {
-                        ControlFlow::BREAK
+                        ControlFlow::Break(())
                     } else {
                         t.super_visit_with(self)
                     }
                 } else {
-                    ControlFlow::CONTINUE
+                    ControlFlow::Continue(())
                 }
             }
 
             fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 if c.needs_infer() {
                     if ty::Term::from(c) == self.term {
-                        ControlFlow::BREAK
+                        ControlFlow::Break(())
                     } else {
                         c.super_visit_with(self)
                     }
                 } else {
-                    ControlFlow::CONTINUE
+                    ControlFlow::Continue(())
                 }
             }
         }
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index e0d665c9e12ba..6bdf53f7fc9dd 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -99,7 +99,7 @@ where
         ) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
             move |(), x| match f(x) {
                 Some(x) => ControlFlow::Break(x),
-                None => ControlFlow::CONTINUE,
+                None => ControlFlow::Continue(()),
             }
         }
 
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 307016c269099..b040a0ea9011b 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -539,7 +539,7 @@ where
         #[rustc_inherit_overflow_checks]
         fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
             match iter.advance_by(n) {
-                Ok(()) => ControlFlow::BREAK,
+                Ok(()) => ControlFlow::Break(()),
                 Err(advanced) => ControlFlow::Continue(n - advanced),
             }
         }
@@ -629,7 +629,7 @@ where
         #[rustc_inherit_overflow_checks]
         fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
             match iter.advance_back_by(n) {
-                Ok(()) => ControlFlow::BREAK,
+                Ok(()) => ControlFlow::Break(()),
                 Err(advanced) => ControlFlow::Continue(n - advanced),
             }
         }
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index bdf94c792c27c..ed23873cdde7c 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -352,7 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
         #[inline]
         fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
             move |(), x| {
-                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
             }
         }
 
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index a4a665d48d58c..5a0b8594104ee 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2601,10 +2601,10 @@ pub trait Iterator {
         #[inline]
         fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
             move |(), x| {
-                if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+                if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
             }
         }
-        self.try_fold((), check(f)) == ControlFlow::CONTINUE
+        self.try_fold((), check(f)) == ControlFlow::Continue(())
     }
 
     /// Tests if any element of the iterator matches a predicate.
@@ -2654,11 +2654,11 @@ pub trait Iterator {
         #[inline]
         fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
             move |(), x| {
-                if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
+                if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
             }
         }
 
-        self.try_fold((), check(f)) == ControlFlow::BREAK
+        self.try_fold((), check(f)) == ControlFlow::Break(())
     }
 
     /// Searches for an element of an iterator that satisfies a predicate.
@@ -2717,7 +2717,7 @@ pub trait Iterator {
         #[inline]
         fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
             move |(), x| {
-                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+                if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
             }
         }
 
@@ -2749,7 +2749,7 @@ pub trait Iterator {
         fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> ControlFlow<B> {
             move |(), x| match f(x) {
                 Some(x) => ControlFlow::Break(x),
-                None => ControlFlow::CONTINUE,
+                None => ControlFlow::Continue(()),
             }
         }
 
@@ -2812,7 +2812,7 @@ pub trait Iterator {
             R: Residual<Option<I>>,
         {
             move |(), x| match f(&x).branch() {
-                ControlFlow::Continue(false) => ControlFlow::CONTINUE,
+                ControlFlow::Continue(false) => ControlFlow::Continue(()),
                 ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))),
                 ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)),
             }
@@ -3491,7 +3491,7 @@ pub trait Iterator {
             F: FnMut(X, Y) -> Ordering,
         {
             move |x, y| match cmp(x, y) {
-                Ordering::Equal => ControlFlow::CONTINUE,
+                Ordering::Equal => ControlFlow::Continue(()),
                 non_eq => ControlFlow::Break(non_eq),
             }
         }
@@ -3567,7 +3567,7 @@ pub trait Iterator {
             F: FnMut(X, Y) -> Option<Ordering>,
         {
             move |x, y| match partial_cmp(x, y) {
-                Some(Ordering::Equal) => ControlFlow::CONTINUE,
+                Some(Ordering::Equal) => ControlFlow::Continue(()),
                 non_eq => ControlFlow::Break(non_eq),
             }
         }
@@ -3625,7 +3625,7 @@ pub trait Iterator {
             F: FnMut(X, Y) -> bool,
         {
             move |x, y| {
-                if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+                if eq(x, y) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
             }
         }
 
@@ -3859,7 +3859,7 @@ pub trait Iterator {
 
 /// Compares two iterators element-wise using the given function.
 ///
-/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next
+/// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next
 /// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and
 /// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements,
 /// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index cd183540cd5e9..117706fb4b28d 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -259,46 +259,3 @@ impl<R: ops::Try> ControlFlow<R, R::Output> {
         }
     }
 }
-
-impl<B> ControlFlow<B, ()> {
-    /// It's frequently the case that there's no value needed with `Continue`,
-    /// so this provides a way to avoid typing `(())`, if you prefer it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(control_flow_enum)]
-    /// use std::ops::ControlFlow;
-    ///
-    /// let mut partial_sum = 0;
-    /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
-    ///     partial_sum += x;
-    ///     if partial_sum > 100 { ControlFlow::Break(x) }
-    ///     else { ControlFlow::CONTINUE }
-    /// });
-    /// assert_eq!(last_used.break_value(), Some(22));
-    /// ```
-    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
-    pub const CONTINUE: Self = ControlFlow::Continue(());
-}
-
-impl<C> ControlFlow<(), C> {
-    /// APIs like `try_for_each` don't need values with `Break`,
-    /// so this provides a way to avoid typing `(())`, if you prefer it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(control_flow_enum)]
-    /// use std::ops::ControlFlow;
-    ///
-    /// let mut partial_sum = 0;
-    /// (1..10).chain(20..25).try_for_each(|x| {
-    ///     if partial_sum > 100 { ControlFlow::BREAK }
-    ///     else { partial_sum += x; ControlFlow::CONTINUE }
-    /// });
-    /// assert_eq!(partial_sum, 108);
-    /// ```
-    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
-    pub const BREAK: Self = ControlFlow::Break(());
-}

From c4fa0d3ea6e8a8d1e8f2965b5a84d9775f31610b Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Fri, 27 Jan 2023 20:02:51 -0800
Subject: [PATCH 12/13] Remove from librustdoc and clippy too

---
 src/librustdoc/html/length_limit.rs                         | 4 ++--
 src/librustdoc/html/length_limit/tests.rs                   | 2 +-
 src/librustdoc/html/markdown.rs                             | 6 +++---
 src/librustdoc/lib.rs                                       | 1 -
 src/tools/clippy/clippy_lints/src/lib.rs                    | 1 -
 .../clippy_lints/src/methods/collapsible_str_replace.rs     | 2 +-
 src/tools/clippy/clippy_utils/src/lib.rs                    | 1 -
 src/tools/clippy/clippy_utils/src/macros.rs                 | 2 +-
 src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs  | 2 +-
 9 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
index bbdc91c8d2ec8..4c8db2c6784a5 100644
--- a/src/librustdoc/html/length_limit.rs
+++ b/src/librustdoc/html/length_limit.rs
@@ -61,14 +61,14 @@ impl HtmlWithLimit {
     /// and returns [`ControlFlow::Break`].
     pub(super) fn push(&mut self, text: &str) -> ControlFlow<(), ()> {
         if self.len + text.len() > self.limit {
-            return ControlFlow::BREAK;
+            return ControlFlow::Break(());
         }
 
         self.flush_queue();
         write!(self.buf, "{}", Escape(text)).unwrap();
         self.len += text.len();
 
-        ControlFlow::CONTINUE
+        ControlFlow::Continue(())
     }
 
     /// Open an HTML tag.
diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs
index 2d02b8a16da67..2185c034890fa 100644
--- a/src/librustdoc/html/length_limit/tests.rs
+++ b/src/librustdoc/html/length_limit/tests.rs
@@ -83,7 +83,7 @@ fn past_the_limit() {
         buf.push("word#")?;
         buf.push(&n.to_string())?;
         buf.close_tag();
-        ControlFlow::CONTINUE
+        ControlFlow::Continue(())
     });
     buf.close_tag();
     assert_eq!(
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index d7739b8534f30..00e3f859bfcb3 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1188,18 +1188,18 @@ fn markdown_summary_with_limit(
             Event::Start(tag) => match tag {
                 Tag::Emphasis => buf.open_tag("em"),
                 Tag::Strong => buf.open_tag("strong"),
-                Tag::CodeBlock(..) => return ControlFlow::BREAK,
+                Tag::CodeBlock(..) => return ControlFlow::Break(()),
                 _ => {}
             },
             Event::End(tag) => match tag {
                 Tag::Emphasis | Tag::Strong => buf.close_tag(),
-                Tag::Paragraph | Tag::Heading(..) => return ControlFlow::BREAK,
+                Tag::Paragraph | Tag::Heading(..) => return ControlFlow::Break(()),
                 _ => {}
             },
             Event::HardBreak | Event::SoftBreak => buf.push(" ")?,
             _ => {}
         };
-        ControlFlow::CONTINUE
+        ControlFlow::Continue(())
     });
 
     (buf.finish(), stopped_early)
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index a689b502f0fcc..64108c8828518 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -6,7 +6,6 @@
 #![feature(array_methods)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
-#![feature(control_flow_enum)]
 #![feature(drain_filter)]
 #![feature(is_terminal)]
 #![feature(let_chains)]
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 5c4b604104417..d06830397761b 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -1,7 +1,6 @@
 #![feature(array_windows)]
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(box_patterns)]
-#![feature(control_flow_enum)]
 #![feature(drain_filter)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
diff --git a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
index ac61b4377885b..5e01ed90ff099 100644
--- a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -54,7 +54,7 @@ fn collect_replace_calls<'tcx>(
                 from_args.push_front(from);
                 ControlFlow::Continue(())
             } else {
-                ControlFlow::BREAK
+                ControlFlow::Break(())
             }
         } else {
             ControlFlow::Continue(())
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index e2965146cfe6d..a246291f9a9bd 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,6 +1,5 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
-#![feature(control_flow_enum)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 659063b97e74a..d7f466c197636 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -327,7 +327,7 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) ->
         } else {
             match cx.tcx.item_name(macro_call.def_id) {
                 // `cfg!(debug_assertions)` in `debug_assert!`
-                sym::cfg => ControlFlow::CONTINUE,
+                sym::cfg => ControlFlow::Continue(()),
                 // assert!(other_macro!(..))
                 _ => ControlFlow::Break(true),
             }
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index 9adae77338945..5836eb73bd94c 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -140,7 +140,7 @@ impl TypeVisitor<'_> for ContainsRegion {
     type BreakTy = ();
 
     fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
-        ControlFlow::BREAK
+        ControlFlow::Break(())
     }
 }
 

From c50d3e28ab0bfaedd1f0f90a376e6f93e4e83c62 Mon Sep 17 00:00:00 2001
From: Ayush Singh <ayushsingh1325@gmail.com>
Date: Sat, 10 Dec 2022 13:34:19 +0530
Subject: [PATCH 13/13] Replace libc::{type} with crate::ffi::{type}

Replace libc::{type} imports with crate::ffi::{type} outside of
`std::sys` and `std::os`.

Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
---
 library/std/src/fs/tests.rs                   | 4 ++--
 library/std/src/personality/emcc.rs           | 2 +-
 library/std/src/personality/gcc.rs            | 3 ++-
 library/std/src/sys/windows/thread_parking.rs | 2 +-
 library/std/src/sys_common/net.rs             | 8 ++++----
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index eb582be012bd5..839fdc96632d1 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -12,6 +12,8 @@ use crate::time::{Duration, Instant};
 
 use rand::RngCore;
 
+#[cfg(target_os = "macos")]
+use crate::ffi::{c_char, c_int};
 #[cfg(unix)]
 use crate::os::unix::fs::symlink as symlink_dir;
 #[cfg(unix)]
@@ -24,8 +26,6 @@ use crate::os::windows::fs::{symlink_dir, symlink_file};
 use crate::sys::fs::symlink_junction;
 #[cfg(target_os = "macos")]
 use crate::sys::weak::weak;
-#[cfg(target_os = "macos")]
-use libc::{c_char, c_int};
 
 macro_rules! check {
     ($e:expr) => {
diff --git a/library/std/src/personality/emcc.rs b/library/std/src/personality/emcc.rs
index f942bdf18c180..cb52ae89b1911 100644
--- a/library/std/src/personality/emcc.rs
+++ b/library/std/src/personality/emcc.rs
@@ -1,7 +1,7 @@
 //! On Emscripten Rust panics are wrapped in C++ exceptions, so we just forward
 //! to `__gxx_personality_v0` which is provided by Emscripten.
 
-use libc::c_int;
+use crate::ffi::c_int;
 use unwind as uw;
 
 // This is required by the compiler to exist (e.g., it's a lang item), but it's
diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs
index 5fc1b91a1c357..41c0fe725a540 100644
--- a/library/std/src/personality/gcc.rs
+++ b/library/std/src/personality/gcc.rs
@@ -37,7 +37,8 @@
 //! and the last personality routine transfers control to the catch block.
 
 use super::dwarf::eh::{self, EHAction, EHContext};
-use libc::{c_int, uintptr_t};
+use crate::ffi::c_int;
+use libc::uintptr_t;
 use unwind as uw;
 
 // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
diff --git a/library/std/src/sys/windows/thread_parking.rs b/library/std/src/sys/windows/thread_parking.rs
index 5d43676adbb11..eb9167cd8552b 100644
--- a/library/std/src/sys/windows/thread_parking.rs
+++ b/library/std/src/sys/windows/thread_parking.rs
@@ -221,7 +221,7 @@ impl Parker {
 
 fn keyed_event_handle() -> c::HANDLE {
     const INVALID: c::HANDLE = ptr::invalid_mut(!0);
-    static HANDLE: AtomicPtr<libc::c_void> = AtomicPtr::new(INVALID);
+    static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(INVALID);
     match HANDLE.load(Relaxed) {
         INVALID => {
             let mut handle = c::INVALID_HANDLE_VALUE;
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index fad4a63331b59..2c38dfecf9734 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -14,7 +14,7 @@ use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
-use libc::{c_int, c_void};
+use crate::ffi::{c_int, c_void};
 
 cfg_if::cfg_if! {
     if #[cfg(any(
@@ -47,7 +47,7 @@ cfg_if::cfg_if! {
         target_os = "dragonfly", target_os = "freebsd",
         target_os = "openbsd", target_os = "netbsd",
         target_os = "solaris", target_os = "illumos"))] {
-        use libc::c_uchar;
+        use crate::ffi::c_uchar;
         type IpV4MultiCastType = c_uchar;
     } else {
         type IpV4MultiCastType = c_int;
@@ -127,8 +127,8 @@ fn to_ipv6mr_interface(value: u32) -> c_int {
 }
 
 #[cfg(not(target_os = "android"))]
-fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
-    value as libc::c_uint
+fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
+    value as crate::ffi::c_uint
 }
 
 ////////////////////////////////////////////////////////////////////////////////