From 6c941362c9814bc5d2c9c436830543ce37e694b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Fri, 31 Mar 2023 09:37:39 +0200
Subject: [PATCH 1/9] Workaround #109797 on windows-gnu

---
 library/std/src/sys/common/thread_local/os_local.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs
index ce74ad3486e10..1442a397e767e 100644
--- a/library/std/src/sys/common/thread_local/os_local.rs
+++ b/library/std/src/sys/common/thread_local/os_local.rs
@@ -49,7 +49,9 @@ macro_rules! __thread_local_inner {
             #[inline]
             fn __init() -> $t { $init }
 
-            #[cfg_attr(not(bootstrap), inline)]
+            // `#[inline] does not work on windows-gnu due to linking errors around dllimports.
+            // See https://github.com/rust-lang/rust/issues/109797.
+            #[cfg_attr(not(windows), inline)]
             unsafe fn __getit(
                 init: $crate::option::Option<&mut $crate::option::Option<$t>>,
             ) -> $crate::option::Option<&'static $t> {

From 6861750e663dbbf8c347e90a35e056d8d2e8c5b1 Mon Sep 17 00:00:00 2001
From: Thom Chiovoloni <thom@shift.click>
Date: Wed, 5 Apr 2023 00:37:30 -0700
Subject: [PATCH 2/9] Fix buffer overrun in (test-only) symlink_junction

---
 library/std/src/sys/windows/fs.rs | 34 +++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 373157bd9e836..956db577d5371 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
     opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
     let f = File::open(junction, &opts)?;
     let h = f.as_inner().as_raw_handle();
-
     unsafe {
         let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
         let data_ptr = data.0.as_mut_ptr();
+        let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
         let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
         // Zero the header to ensure it's fully initialized, including reserved parameters.
         *db = mem::zeroed();
-        let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
-        let mut i = 0;
+        let reparse_target_slice = {
+            let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
+            // Compute offset in bytes and then divide so that we round down
+            // rather than hit any UB (admittedly this arithmetic should work
+            // out so that this isn't necessary)
+            let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap();
+            let buf_len_wchars = buf_len_bytes / core::mem::size_of::<c::WCHAR>();
+            core::slice::from_raw_parts_mut(buf_start, buf_len_wchars)
+        };
+
         // FIXME: this conversion is very hacky
-        let v = br"\??\";
-        let v = v.iter().map(|x| *x as u16);
-        for c in v.chain(original.as_os_str().encode_wide()) {
-            *buf.add(i) = c;
+        let iter = br"\??\"
+            .iter()
+            .map(|x| *x as u16)
+            .chain(original.as_os_str().encode_wide())
+            .chain(core::iter::once(0));
+        let mut i = 0;
+        for c in iter {
+            if i >= reparse_target_slice.len() {
+                return Err(crate::io::const_io_error!(
+                    crate::io::ErrorKind::InvalidFilename,
+                    "Input filename is too long"
+                ));
+            }
+            reparse_target_slice[i] = c;
             i += 1;
         }
-        *buf.add(i) = 0;
-        i += 1;
         (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
         (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD;
         (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD;

From 12dff54a6acf271e367a8fb0c3d149d6554d9d90 Mon Sep 17 00:00:00 2001
From: Thom Chiovoloni <thom@shift.click>
Date: Wed, 5 Apr 2023 00:54:46 -0700
Subject: [PATCH 3/9] Fix same issue in bootstrap

---
 src/bootstrap/util.rs | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 9a6aaffe22b24..8cea8c974077a 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -212,18 +212,35 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
             struct Align8<T>(T);
             let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
             let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
-            let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16;
-            let mut i = 0;
+            let end = db.cast::<u8>().add(MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize);
+            let reparse_target_slice = {
+                let buf_start = core::ptr::addr_of_mut!((*db).ReparseTarget).cast::<u16>();
+                // Compute offset in bytes and then divide so that we round down
+                // rather than hit any UB (admittedly this arithmetic should work
+                // out so that this isn't necessary)
+                let buf_len_bytes =
+                    usize::try_from(end.offset_from(buf_start.cast::<u8>())).unwrap();
+                let buf_len_wchars = buf_len_bytes / core::mem::size_of::<u16>();
+                core::slice::from_raw_parts_mut(buf_start, buf_len_wchars)
+            };
+
             // FIXME: this conversion is very hacky
-            let v = br"\??\";
-            let v = v.iter().map(|x| *x as u16);
-            for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
-                *buf.offset(i) = c;
+            let iter = br"\??\"
+                .iter()
+                .map(|x| *x as u16)
+                .chain(path.iter().copied())
+                .chain(core::iter::once(0));
+            let mut i = 0;
+            for c in iter {
+                if i >= reparse_target_slice.len() {
+                    return Err(io::Error::new(
+                        io::ErrorKind::Other,
+                        format!("path too long for reparse target: {target:?}"),
+                    ));
+                }
+                reparse_target_slice[i] = c;
                 i += 1;
             }
-            *buf.offset(i) = 0;
-            i += 1;
-
             (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
             (*db).ReparseTargetMaximumLength = (i * 2) as u16;
             (*db).ReparseTargetLength = ((i - 1) * 2) as u16;

From 42e38e89498ec4690479b268066ad1ca58917aec Mon Sep 17 00:00:00 2001
From: Thom Chiovoloni <thom@shift.click>
Date: Wed, 5 Apr 2023 01:27:11 -0700
Subject: [PATCH 4/9] Use the `junction` crate in bootstrap instead of manually
 creating the junction

---
 src/bootstrap/Cargo.lock |  11 ++++
 src/bootstrap/Cargo.toml |   3 +
 src/bootstrap/util.rs    | 116 +--------------------------------------
 3 files changed, 15 insertions(+), 115 deletions(-)

diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 965dfa5f39867..a158d1f718e2c 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -45,6 +45,7 @@ dependencies = [
  "hex",
  "ignore",
  "is-terminal",
+ "junction",
  "libc",
  "object",
  "once_cell",
@@ -349,6 +350,16 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
 
+[[package]]
+name = "junction"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca39ef0d69b18e6a2fd14c2f0a1d593200f4a4ed949b240b5917ab51fac754cb"
+dependencies = [
+ "scopeguard",
+ "winapi",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 2fbe7aa57aa52..eeda6d7c121f7 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -61,6 +61,9 @@ sysinfo = { version = "0.26.0", optional = true }
 [target.'cfg(not(target_os = "solaris"))'.dependencies]
 fd-lock = "3.0.8"
 
+[target.'cfg(windows)'.dependencies.junction]
+version = "1.0.0"
+
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.46.0"
 features = [
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 8cea8c974077a..2e1adbf63bb10 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -146,123 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
         fs::symlink(src, dest)
     }
 
-    // Creating a directory junction on windows involves dealing with reparse
-    // points and the DeviceIoControl function, and this code is a skeleton of
-    // what can be found here:
-    //
-    // http://www.flexhex.com/docs/articles/hard-links.phtml
     #[cfg(windows)]
     fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
-        use std::ffi::OsStr;
-        use std::os::windows::ffi::OsStrExt;
-
-        use windows::{
-            core::PCWSTR,
-            Win32::Foundation::{CloseHandle, HANDLE},
-            Win32::Storage::FileSystem::{
-                CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS,
-                FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
-                MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING,
-            },
-            Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT,
-            Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT},
-            Win32::System::IO::DeviceIoControl,
-        };
-
-        #[allow(non_snake_case)]
-        #[repr(C)]
-        struct REPARSE_MOUNTPOINT_DATA_BUFFER {
-            ReparseTag: u32,
-            ReparseDataLength: u32,
-            Reserved: u16,
-            ReparseTargetLength: u16,
-            ReparseTargetMaximumLength: u16,
-            Reserved1: u16,
-            ReparseTarget: u16,
-        }
-
-        fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
-            Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
-        }
-
-        // We're using low-level APIs to create the junction, and these are more
-        // picky about paths. For example, forward slashes cannot be used as a
-        // path separator, so we should try to canonicalize the path first.
-        let target = fs::canonicalize(target)?;
-
-        fs::create_dir(junction)?;
-
-        let path = to_u16s(junction)?;
-
-        let h = unsafe {
-            CreateFileW(
-                PCWSTR(path.as_ptr()),
-                FILE_ACCESS_FLAGS(GENERIC_WRITE),
-                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                None,
-                OPEN_EXISTING,
-                FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
-                HANDLE::default(),
-            )
-        }
-        .map_err(|_| io::Error::last_os_error())?;
-
-        unsafe {
-            #[repr(C, align(8))]
-            struct Align8<T>(T);
-            let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
-            let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
-            let end = db.cast::<u8>().add(MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize);
-            let reparse_target_slice = {
-                let buf_start = core::ptr::addr_of_mut!((*db).ReparseTarget).cast::<u16>();
-                // Compute offset in bytes and then divide so that we round down
-                // rather than hit any UB (admittedly this arithmetic should work
-                // out so that this isn't necessary)
-                let buf_len_bytes =
-                    usize::try_from(end.offset_from(buf_start.cast::<u8>())).unwrap();
-                let buf_len_wchars = buf_len_bytes / core::mem::size_of::<u16>();
-                core::slice::from_raw_parts_mut(buf_start, buf_len_wchars)
-            };
-
-            // FIXME: this conversion is very hacky
-            let iter = br"\??\"
-                .iter()
-                .map(|x| *x as u16)
-                .chain(path.iter().copied())
-                .chain(core::iter::once(0));
-            let mut i = 0;
-            for c in iter {
-                if i >= reparse_target_slice.len() {
-                    return Err(io::Error::new(
-                        io::ErrorKind::Other,
-                        format!("path too long for reparse target: {target:?}"),
-                    ));
-                }
-                reparse_target_slice[i] = c;
-                i += 1;
-            }
-            (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-            (*db).ReparseTargetMaximumLength = (i * 2) as u16;
-            (*db).ReparseTargetLength = ((i - 1) * 2) as u16;
-            (*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32;
-
-            let mut ret = 0u32;
-            DeviceIoControl(
-                h,
-                FSCTL_SET_REPARSE_POINT,
-                Some(db.cast()),
-                (*db).ReparseDataLength + 8,
-                None,
-                0,
-                Some(&mut ret),
-                None,
-            )
-            .ok()
-            .map_err(|_| io::Error::last_os_error())?;
-        }
-
-        unsafe { CloseHandle(h) };
-        Ok(())
+        junction::create(&target, &junction)
     }
 }
 

From b904ce94a23744032f930841b6fecb6ac2620cd9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Wed, 5 Apr 2023 06:33:52 +0200
Subject: [PATCH 5/9] account for self type when looking for source of unsolved
 ty var

---
 .../infer/error_reporting/need_type_info.rs   |  5 +++-
 .../inference/need_type_info/concrete-impl.rs |  3 +++
 .../need_type_info/concrete-impl.stderr       |  9 ++++---
 .../inference/need_type_info/issue-109905.rs  | 25 +++++++++++++++++++
 .../need_type_info/issue-109905.stderr        | 15 +++++++++++
 5 files changed, 52 insertions(+), 5 deletions(-)
 create mode 100644 tests/ui/inference/need_type_info/issue-109905.rs
 create mode 100644 tests/ui/inference/need_type_info/issue-109905.stderr

diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index bde16fad82162..d7b900ca02d3e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                 have_turbofish,
             } = args;
             let generics = tcx.generics_of(generics_def_id);
-            if let Some(argument_index) = generics
+            if let Some(mut argument_index) = generics
                 .own_substs(substs)
                 .iter()
                 .position(|&arg| self.generic_arg_contains_target(arg))
             {
+                if generics.parent.is_none() && generics.has_self {
+                    argument_index += 1;
+                }
                 let substs = self.infcx.resolve_vars_if_possible(substs);
                 let generic_args = &generics.own_substs_no_defaults(tcx, substs)
                     [generics.own_counts().lifetimes..];
diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs
index 72e0e74f32342..fc79e6201bdb8 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.rs
+++ b/tests/ui/inference/need_type_info/concrete-impl.rs
@@ -7,10 +7,13 @@ struct Two;
 struct Struct;
 
 impl Ambiguous<One> for Struct {}
+//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found
 impl Ambiguous<Two> for Struct {}
 
 fn main() {
     <Struct as Ambiguous<_>>::method();
     //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `A`
     //~| ERROR type annotations needed
+    //~| NOTE infer type of the type parameter `A`
 }
diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr
index aa32969950d6b..74c3f6cd5cfad 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.stderr
+++ b/tests/ui/inference/need_type_info/concrete-impl.stderr
@@ -1,20 +1,21 @@
 error[E0282]: type annotations needed
-  --> $DIR/concrete-impl.rs:13:5
+  --> $DIR/concrete-impl.rs:14:5
    |
 LL |     <Struct as Ambiguous<_>>::method();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
 
 error[E0283]: type annotations needed
-  --> $DIR/concrete-impl.rs:13:5
+  --> $DIR/concrete-impl.rs:14:5
    |
 LL |     <Struct as Ambiguous<_>>::method();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
    |
 note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
   --> $DIR/concrete-impl.rs:9:1
    |
 LL | impl Ambiguous<One> for Struct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
 LL | impl Ambiguous<Two> for Struct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/inference/need_type_info/issue-109905.rs b/tests/ui/inference/need_type_info/issue-109905.rs
new file mode 100644
index 0000000000000..99d10a5eae047
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-109905.rs
@@ -0,0 +1,25 @@
+// Test that we show the correct type parameter that couldn't be inferred and that we don't
+// end up stating nonsense like "type parameter `'a`" which we used to do.
+
+trait Trait<'a, T> {
+    fn m(self);
+}
+
+impl<'a, A> Trait<'a, A> for () {
+    fn m(self) {}
+}
+
+fn qualified() {
+    <() as Trait<'static, _>>::m(());
+    //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `T`
+
+}
+
+fn unqualified() {
+    Trait::<'static, _>::m(());
+    //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `T`
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/issue-109905.stderr b/tests/ui/inference/need_type_info/issue-109905.stderr
new file mode 100644
index 0000000000000..fcdd50f142266
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-109905.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-109905.rs:13:5
+   |
+LL |     <() as Trait<'static, _>>::m(());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-109905.rs:20:5
+   |
+LL |     Trait::<'static, _>::m(());
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.

From 00d54c879bfb6adb5b7a611af6bd522499d07a1d Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 6 Apr 2023 16:49:43 +0000
Subject: [PATCH 6/9] Label non_exhaustive on privacy errors

---
 compiler/rustc_resolve/src/diagnostics.rs     |  8 +++++-
 .../ui/rfc-2008-non-exhaustive/struct.stderr  | 11 +++++---
 .../ui/rfc-2008-non-exhaustive/variant.stderr | 25 +++++++++++++++++++
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e69a9d0aecaf4..bb473d62a7bbc 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1607,7 +1607,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut err =
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("private {}", descr));
-        if let Some(span) = ctor_fields_span {
+
+        if let Some(def_id) = res.opt_def_id()
+            && !def_id.is_local()
+            && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
+        {
+            err.span_label(attr.span, format!("the {nonimport_descr} is `#[non_exhaustive]`"));
+        } else if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
             if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
                 err.multipart_suggestion_verbose(
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
index 2cb9ba0d1d14b..36154fe51a4e6 100644
--- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,10 +10,10 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:12:24
+  ::: $DIR/auxiliary/structs.rs:11:1
    |
-LL | pub struct TupleStruct(pub u16, pub u16);
-   |                        ---------------- a constructor is private if any of the fields is private
+LL | #[non_exhaustive]
+   | ----------------- the tuple struct constructor is `#[non_exhaustive]`
    |
 note: the tuple struct constructor `TupleStruct` is defined here
   --> $DIR/auxiliary/structs.rs:12:1
@@ -27,6 +27,11 @@ error[E0603]: unit struct `UnitStruct` is private
 LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
+  ::: $DIR/auxiliary/structs.rs:8:1
+   |
+LL | #[non_exhaustive]
+   | ----------------- the unit struct is `#[non_exhaustive]`
+   |
 note: the unit struct `UnitStruct` is defined here
   --> $DIR/auxiliary/structs.rs:9:1
    |
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
index 720b7b119cec9..551ecb5acf276 100644
--- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -4,6 +4,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
    |                                                ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
@@ -16,6 +21,11 @@ error[E0603]: unit variant `Unit` is private
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
    |                                               ^^^^ private unit variant
    |
+  ::: $DIR/auxiliary/variants.rs:4:5
+   |
+LL |     #[non_exhaustive] Unit,
+   |     ----------------- the unit variant is `#[non_exhaustive]`
+   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
@@ -28,6 +38,11 @@ error[E0603]: unit variant `Unit` is private
 LL |         NonExhaustiveVariants::Unit => "",
    |                                ^^^^ private unit variant
    |
+  ::: $DIR/auxiliary/variants.rs:4:5
+   |
+LL |     #[non_exhaustive] Unit,
+   |     ----------------- the unit variant is `#[non_exhaustive]`
+   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
@@ -40,6 +55,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
    |                                ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
@@ -52,6 +72,11 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
    |                                   ^^^^^ private tuple variant
    |
+  ::: $DIR/auxiliary/variants.rs:5:5
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |     ----------------- the tuple variant is `#[non_exhaustive]`
+   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |

From 8ed2dc0bcee8c7ca43d2b6a66c9743cacf8dcddf Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 6 Apr 2023 16:52:17 +0000
Subject: [PATCH 7/9] Make span a bit better

---
 compiler/rustc_resolve/src/diagnostics.rs     | 14 +++++-
 .../ui/rfc-2008-non-exhaustive/struct.stderr  | 14 ++----
 .../ui/rfc-2008-non-exhaustive/variant.stderr | 45 +++++++------------
 3 files changed, 32 insertions(+), 41 deletions(-)

diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index bb473d62a7bbc..0c9d306081eb8 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1608,11 +1608,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("private {}", descr));
 
+        let mut non_exhaustive = None;
+        // If an ADT is foreign and marked as `non_exhaustive`, then that's
+        // probably why we have the privacy error.
+        // Otherwise, point out if the struct has any private fields.
         if let Some(def_id) = res.opt_def_id()
             && !def_id.is_local()
             && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
         {
-            err.span_label(attr.span, format!("the {nonimport_descr} is `#[non_exhaustive]`"));
+            non_exhaustive = Some(attr.span);
         } else if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
             if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
@@ -1662,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if !first && binding.vis.is_public() {
                 note_span.push_span_label(def_span, "consider importing it directly");
             }
+            // Final step in the import chain, point out if the ADT is `non_exhaustive`
+            // which is probably why this privacy violation occurred.
+            if next_binding.is_none() && let Some(span) = non_exhaustive {
+                note_span.push_span_label(
+                    span,
+                    format!("cannot be constructed because it is `#[non_exhaustive]`"),
+                );
+            }
             err.span_note(note_span, &msg);
         }
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
index 36154fe51a4e6..39b1ef1e078c7 100644
--- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,14 +10,11 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:11:1
-   |
-LL | #[non_exhaustive]
-   | ----------------- the tuple struct constructor is `#[non_exhaustive]`
-   |
 note: the tuple struct constructor `TupleStruct` is defined here
   --> $DIR/auxiliary/structs.rs:12:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct TupleStruct(pub u16, pub u16);
    | ^^^^^^^^^^^^^^^^^^^^^^
 
@@ -27,14 +24,11 @@ error[E0603]: unit struct `UnitStruct` is private
 LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
-  ::: $DIR/auxiliary/structs.rs:8:1
-   |
-LL | #[non_exhaustive]
-   | ----------------- the unit struct is `#[non_exhaustive]`
-   |
 note: the unit struct `UnitStruct` is defined here
   --> $DIR/auxiliary/structs.rs:9:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct UnitStruct;
    | ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
index 551ecb5acf276..4083f57a9cdf9 100644
--- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -4,16 +4,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
    |                                                ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
@@ -21,16 +18,13 @@ error[E0603]: unit variant `Unit` is private
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
    |                                               ^^^^ private unit variant
    |
-  ::: $DIR/auxiliary/variants.rs:4:5
-   |
-LL |     #[non_exhaustive] Unit,
-   |     ----------------- the unit variant is `#[non_exhaustive]`
-   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
@@ -38,16 +32,13 @@ error[E0603]: unit variant `Unit` is private
 LL |         NonExhaustiveVariants::Unit => "",
    |                                ^^^^ private unit variant
    |
-  ::: $DIR/auxiliary/variants.rs:4:5
-   |
-LL |     #[non_exhaustive] Unit,
-   |     ----------------- the unit variant is `#[non_exhaustive]`
-   |
 note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
@@ -55,16 +46,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
    |                                ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
@@ -72,16 +60,13 @@ error[E0603]: tuple variant `Tuple` is private
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
    |                                   ^^^^^ private tuple variant
    |
-  ::: $DIR/auxiliary/variants.rs:5:5
-   |
-LL |     #[non_exhaustive] Tuple(u32),
-   |     ----------------- the tuple variant is `#[non_exhaustive]`
-   |
 note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26

From 529ceeeefc7b5f77834f707362044fd48b6247fd Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Thu, 6 Apr 2023 20:26:27 +0200
Subject: [PATCH 8/9] Run collapsed GUI test in mobile mode as well

---
 tests/rustdoc-gui/go-to-collapsed-elem.goml | 33 ++++++++++++++++-----
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml
index 279048e37c1f3..ec42312523641 100644
--- a/tests/rustdoc-gui/go-to-collapsed-elem.goml
+++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml
@@ -9,13 +9,32 @@ property: ("#implementations-list .implementors-toggle", {"open": "false"})
 click: "//*[@class='sidebar']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
 
-// Now we do the same through search result.
-// First we reload the page without the anchor in the URL.
+define-function: ("collapsed-from-search", (), block {
+    // Now we do the same through search result.
+    // First we reload the page without the anchor in the URL.
+    goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+    // Then we collapse the section again...
+    property: ("#implementations-list .implementors-toggle", {"open": "false"})
+    // Then we run the search.
+    write: (".search-input", "foo::must_use")
+    wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+})
+
+call-function: ("collapsed-from-search", {})
+
+// Now running the same check but with mobile.
+size: (600, 600)
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-// Then we collapse the section again...
+// We check that the implementors block is expanded.
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+// We now collapse the implementors block.
 property: ("#implementations-list .implementors-toggle", {"open": "false"})
-// Then we run the search.
-write: (".search-input", "foo::must_use")
-wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
-click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+// First we expand the mobile menu.
+click: ".sidebar-menu-toggle"
+// Then we click on the link to the method to ensure it'll expand the implementors block.
+click: "//*[@class='sidebar shown']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+
+call-function: ("collapsed-from-search", {})

From 9dbf20ef27b56c0bff35366689861ebbe5dfb7e5 Mon Sep 17 00:00:00 2001
From: Ezra Shaw <ezrasure@outlook.com>
Date: Fri, 7 Apr 2023 08:54:13 +1200
Subject: [PATCH 9/9] fix: fix regression in #109203

---
 .../rustc_parse/src/parser/diagnostics.rs     |  4 ++--
 tests/ui/parser/issues/issue-110014.rs        |  3 +++
 tests/ui/parser/issues/issue-110014.stderr    | 19 +++++++++++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/parser/issues/issue-110014.rs
 create mode 100644 tests/ui/parser/issues/issue-110014.stderr

diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 5210b8fe69d6e..e03ce5d712056 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -423,11 +423,11 @@ impl<'a> Parser<'a> {
         if let token::Literal(Lit {
             kind: token::LitKind::Integer | token::LitKind::Float,
             symbol,
-            suffix,
+            suffix: Some(suffix), // no suffix makes it a valid literal
         }) = self.token.kind
             && rustc_ast::MetaItemLit::from_token(&self.token).is_none()
         {
-            Some((symbol.as_str().len(), suffix.unwrap()))
+            Some((symbol.as_str().len(), suffix))
         } else {
             None
         }
diff --git a/tests/ui/parser/issues/issue-110014.rs b/tests/ui/parser/issues/issue-110014.rs
new file mode 100644
index 0000000000000..69d8f402bb620
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.rs
@@ -0,0 +1,3 @@
+fn`2222222222222222222222222222222222222222() {}
+//~^ ERROR unknown start of token: `
+//~^^ ERROR expected identifier, found `2222222222222222222222222222222222222222`
diff --git a/tests/ui/parser/issues/issue-110014.stderr b/tests/ui/parser/issues/issue-110014.stderr
new file mode 100644
index 0000000000000..7f1dd592e1238
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.stderr
@@ -0,0 +1,19 @@
+error: unknown start of token: `
+  --> $DIR/issue-110014.rs:1:3
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |   ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | fn'2222222222222222222222222222222222222222() {}
+   |   ~
+
+error: expected identifier, found `2222222222222222222222222222222222222222`
+  --> $DIR/issue-110014.rs:1:4
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier
+
+error: aborting due to 2 previous errors
+