From 99182dd8058f0a1153b8b7fcf873028caa6fbfa7 Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Thu, 6 Oct 2022 22:46:15 +0200
Subject: [PATCH 01/16] std: use semaphore for thread parking on Apple
 platforms

---
 .../std/src/sys/unix/thread_parker/darwin.rs  | 131 ++++++++++++++++++
 library/std/src/sys/unix/thread_parker/mod.rs |  10 +-
 2 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 library/std/src/sys/unix/thread_parker/darwin.rs

diff --git a/library/std/src/sys/unix/thread_parker/darwin.rs b/library/std/src/sys/unix/thread_parker/darwin.rs
new file mode 100644
index 0000000000000..510839d5dafbf
--- /dev/null
+++ b/library/std/src/sys/unix/thread_parker/darwin.rs
@@ -0,0 +1,131 @@
+//! Thread parking for Darwin-based systems.
+//!
+//! Darwin actually has futex syscalls (`__ulock_wait`/`__ulock_wake`), but they
+//! cannot be used in `std` because they are non-public (their use will lead to
+//! rejection from the App Store) and because they are only available starting
+//! with macOS version 10.12, even though the minimum target version is 10.7.
+//!
+//! Therefore, we need to look for other synchronization primitives. Luckily, Darwin
+//! supports semaphores, which allow us to implement the behaviour we need with
+//! only one primitive (as opposed to a mutex-condvar pair). We use the semaphore
+//! provided by libdispatch, as the underlying Mach semaphore is only dubiously
+//! public.
+
+use crate::pin::Pin;
+use crate::sync::atomic::{
+    AtomicI8,
+    Ordering::{Acquire, Release},
+};
+use crate::time::Duration;
+
+type dispatch_semaphore_t = *mut crate::ffi::c_void;
+type dispatch_time_t = u64;
+
+const DISPATCH_TIME_NOW: dispatch_time_t = 0;
+const DISPATCH_TIME_FOREVER: dispatch_time_t = !0;
+
+#[link(name = "System", kind = "dylib")]
+extern "C" {
+    fn dispatch_time(when: dispatch_time_t, delta: i64) -> dispatch_time_t;
+    fn dispatch_semaphore_create(val: isize) -> dispatch_semaphore_t;
+    fn dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t) -> isize;
+    fn dispatch_semaphore_signal(dsema: dispatch_semaphore_t) -> isize;
+    fn dispatch_release(object: *mut crate::ffi::c_void);
+}
+
+const EMPTY: i8 = 0;
+const NOTIFIED: i8 = 1;
+const PARKED: i8 = -1;
+
+pub struct Parker {
+    semaphore: dispatch_semaphore_t,
+    state: AtomicI8,
+}
+
+unsafe impl Sync for Parker {}
+unsafe impl Send for Parker {}
+
+impl Parker {
+    pub unsafe fn new(parker: *mut Parker) {
+        let semaphore = dispatch_semaphore_create(0);
+        assert!(
+            !semaphore.is_null(),
+            "failed to create dispatch semaphore for thread synchronization"
+        );
+        parker.write(Parker { semaphore, state: AtomicI8::new(EMPTY) })
+    }
+
+    // Does not need `Pin`, but other implementation do.
+    pub unsafe fn park(self: Pin<&Self>) {
+        // The semaphore counter must be zero at this point, because unparking
+        // threads will not actually increase it until we signalled that we
+        // are waiting.
+
+        // Change NOTIFIED to EMPTY and EMPTY to PARKED.
+        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+            return;
+        }
+
+        // Another thread may increase the semaphore counter from this point on.
+        // If it is faster than us, we will decrement it again immediately below.
+        // If we are faster, we wait.
+
+        // Ensure that the semaphore counter has actually been decremented, even
+        // if the call timed out for some reason.
+        while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
+
+        // At this point, the semaphore counter is zero again.
+
+        // We were definitely woken up, so we don't need to check the state.
+        // Still, we need to reset the state using a swap to observe the state
+        // change with acquire ordering.
+        self.state.swap(EMPTY, Acquire);
+    }
+
+    // Does not need `Pin`, but other implementation do.
+    pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+            return;
+        }
+
+        let nanos = dur.as_nanos().try_into().unwrap_or(i64::MAX);
+        let timeout = dispatch_time(DISPATCH_TIME_NOW, nanos);
+
+        let timeout = dispatch_semaphore_wait(self.semaphore, timeout) != 0;
+
+        let state = self.state.swap(EMPTY, Acquire);
+        if state == NOTIFIED && timeout {
+            // If the state was NOTIFIED but semaphore_wait returned without
+            // decrementing the count because of a timeout, it means another
+            // thread is about to call semaphore_signal. We must wait for that
+            // to happen to ensure the semaphore count is reset.
+            while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
+        } else {
+            // Either a timeout occurred and we reset the state before any thread
+            // tried to wake us up, or we were woken up and reset the state,
+            // making sure to observe the state change with acquire ordering.
+            // Either way, the semaphore counter is now zero again.
+        }
+    }
+
+    // Does not need `Pin`, but other implementation do.
+    pub fn unpark(self: Pin<&Self>) {
+        let state = self.state.swap(NOTIFIED, Release);
+        if state == PARKED {
+            unsafe {
+                dispatch_semaphore_signal(self.semaphore);
+            }
+        }
+    }
+}
+
+impl Drop for Parker {
+    fn drop(&mut self) {
+        // SAFETY:
+        // We always ensure that the semaphore count is reset, so this will
+        // never cause an exception.
+        unsafe {
+            dispatch_release(self.semaphore);
+        }
+    }
+}
diff --git a/library/std/src/sys/unix/thread_parker/mod.rs b/library/std/src/sys/unix/thread_parker/mod.rs
index e2453580dc72a..724ec2d482edb 100644
--- a/library/std/src/sys/unix/thread_parker/mod.rs
+++ b/library/std/src/sys/unix/thread_parker/mod.rs
@@ -11,7 +11,15 @@
 )))]
 
 cfg_if::cfg_if! {
-    if #[cfg(target_os = "netbsd")] {
+    if #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "tvos",
+    ))] {
+        mod darwin;
+        pub use darwin::Parker;
+    } else if #[cfg(target_os = "netbsd")] {
         mod netbsd;
         pub use netbsd::Parker;
     } else {

From 0ad4dd494a67a0fffc5a3e4df08f0c26cf074c59 Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Thu, 6 Oct 2022 22:46:47 +0200
Subject: [PATCH 02/16] std: add thread parking tests

---
 library/std/src/thread/tests.rs | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 130e47c8d44f0..dfb8765ab4eed 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -244,6 +244,28 @@ fn test_try_panic_any_message_unit_struct() {
     }
 }
 
+#[test]
+fn test_park_unpark_before() {
+    for _ in 0..10 {
+        thread::current().unpark();
+        thread::park();
+    }
+}
+
+#[test]
+fn test_park_unpark_called_other_thread() {
+    for _ in 0..10 {
+        let th = thread::current();
+
+        let _guard = thread::spawn(move || {
+            super::sleep(Duration::from_millis(50));
+            th.unpark();
+        });
+
+        thread::park();
+    }
+}
+
 #[test]
 fn test_park_timeout_unpark_before() {
     for _ in 0..10 {

From b4c8a7b952de72bc70e798408efbd4124fa15c59 Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Sat, 8 Oct 2022 09:07:28 +0200
Subject: [PATCH 03/16] std: remove unused linker attribute

---
 library/std/src/sys/unix/thread_parker/darwin.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/std/src/sys/unix/thread_parker/darwin.rs b/library/std/src/sys/unix/thread_parker/darwin.rs
index 510839d5dafbf..2f5356fe2276b 100644
--- a/library/std/src/sys/unix/thread_parker/darwin.rs
+++ b/library/std/src/sys/unix/thread_parker/darwin.rs
@@ -24,7 +24,7 @@ type dispatch_time_t = u64;
 const DISPATCH_TIME_NOW: dispatch_time_t = 0;
 const DISPATCH_TIME_FOREVER: dispatch_time_t = !0;
 
-#[link(name = "System", kind = "dylib")]
+// Contained in libSystem.dylib, which is linked by default.
 extern "C" {
     fn dispatch_time(when: dispatch_time_t, delta: i64) -> dispatch_time_t;
     fn dispatch_semaphore_create(val: isize) -> dispatch_semaphore_t;

From c320ab98ff1d4adb32cece206aa895e4effae175 Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Sat, 8 Oct 2022 09:12:06 +0200
Subject: [PATCH 04/16] std: do not use dispatch semaphore under miri (yet)

---
 library/std/src/sys/unix/thread_parker/mod.rs | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/library/std/src/sys/unix/thread_parker/mod.rs b/library/std/src/sys/unix/thread_parker/mod.rs
index 724ec2d482edb..35f1e68a87e5b 100644
--- a/library/std/src/sys/unix/thread_parker/mod.rs
+++ b/library/std/src/sys/unix/thread_parker/mod.rs
@@ -11,11 +11,14 @@
 )))]
 
 cfg_if::cfg_if! {
-    if #[cfg(any(
-        target_os = "macos",
-        target_os = "ios",
-        target_os = "watchos",
-        target_os = "tvos",
+    if #[cfg(all(
+        any(
+            target_os = "macos",
+            target_os = "ios",
+            target_os = "watchos",
+            target_os = "tvos",
+        ),
+        not(miri),
     ))] {
         mod darwin;
         pub use darwin::Parker;

From ad8b24272428b28770471f222c19fa3154a65819 Mon Sep 17 00:00:00 2001
From: Nathan Whitaker <nathan.whitaker01@gmail.com>
Date: Wed, 12 Oct 2022 15:29:08 -0700
Subject: [PATCH 05/16] Let chains should still drop temporaries by the end of
 the condition's execution

---
 compiler/rustc_ast_lowering/src/expr.rs | 45 +++++++++++++-----
 src/test/ui/drop/drop_order.rs          | 63 +++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index c55b490630200..104010f8d435e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         else_opt: Option<&Expr>,
     ) -> hir::ExprKind<'hir> {
         let lowered_cond = self.lower_expr(cond);
-        let new_cond = self.manage_let_cond(lowered_cond);
+        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
         let then_expr = self.lower_block_expr(then);
         if let Some(rslt) = else_opt {
             hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
@@ -397,9 +397,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    // If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
-    // in a temporary block.
-    fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
+    // Wraps a condition (i.e. `cond` in `if cond` or `while cond`) in a terminating scope
+    // so that temporaries created in the condition don't live beyond it.
+    fn wrap_cond_in_drop_scope(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
         fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
             match expr.kind {
                 hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
@@ -407,12 +407,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 _ => false,
             }
         }
-        if has_let_expr(cond) {
-            cond
-        } else {
-            let reason = DesugaringKind::CondTemporary;
-            let span_block = self.mark_span_with_reason(reason, cond.span, None);
-            self.expr_drop_temps(span_block, cond, AttrVec::new())
+
+        // We have to take special care for `let` exprs in the condition, e.g. in
+        // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
+        // condition in this case.
+        //
+        // In order to mantain the drop behavior for the non `let` parts of the condition,
+        // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
+        // gets transformed into `if { let _t = foo; _t } && let pat = val`
+        match cond.kind {
+            hir::ExprKind::Binary(
+                op @ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+                lhs,
+                rhs,
+            ) if has_let_expr(cond) => {
+                let lhs = self.wrap_cond_in_drop_scope(lhs);
+                let rhs = self.wrap_cond_in_drop_scope(rhs);
+
+                self.arena.alloc(self.expr(
+                    cond.span,
+                    hir::ExprKind::Binary(op, lhs, rhs),
+                    AttrVec::new(),
+                ))
+            }
+            hir::ExprKind::Let(_) => cond,
+            _ => {
+                let reason = DesugaringKind::CondTemporary;
+                let span_block = self.mark_span_with_reason(reason, cond.span, None);
+                self.expr_drop_temps(span_block, cond, AttrVec::new())
+            }
         }
     }
 
@@ -440,7 +463,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         opt_label: Option<Label>,
     ) -> hir::ExprKind<'hir> {
         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
-        let new_cond = self.manage_let_cond(lowered_cond);
+        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
         let then = self.lower_block_expr(body);
         let expr_break = self.expr_break(span, AttrVec::new());
         let stmt_break = self.stmt_expr(span, expr_break);
diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs
index e42150dcc09d2..bf740b6a9ab67 100644
--- a/src/test/ui/drop/drop_order.rs
+++ b/src/test/ui/drop/drop_order.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![feature(let_chains)]
 
 use std::cell::RefCell;
 use std::convert::TryInto;
@@ -116,6 +117,58 @@ impl DropOrderCollector {
         }
     }
 
+    fn let_chain(&self) {
+        // take the "then" branch
+        if self.option_loud_drop(2).is_some() // 2
+            && self.option_loud_drop(1).is_some() // 1
+            && let Some(_d) = self.option_loud_drop(4) { // 4
+            self.print(3); // 3
+        }
+
+        // take the "else" branch
+        if self.option_loud_drop(6).is_some() // 2
+            && self.option_loud_drop(5).is_some() // 1
+            && let None = self.option_loud_drop(7) { // 3
+            unreachable!();
+        } else {
+            self.print(8); // 4
+        }
+
+        // let exprs interspersed
+        if self.option_loud_drop(9).is_some() // 1
+            && let Some(_d) = self.option_loud_drop(13) // 5
+            && self.option_loud_drop(10).is_some() // 2
+            && let Some(_e) = self.option_loud_drop(12) { // 4
+            self.print(11); // 3
+        }
+
+        // let exprs first
+        if let Some(_d) = self.option_loud_drop(18) // 5
+            && let Some(_e) = self.option_loud_drop(17) // 4
+            && self.option_loud_drop(14).is_some() // 1
+            && self.option_loud_drop(15).is_some() { // 2
+                self.print(16); // 3
+            }
+
+        // let exprs last
+        if self.option_loud_drop(20).is_some() // 2
+            && self.option_loud_drop(19).is_some() // 1
+            && let Some(_d) = self.option_loud_drop(23) // 5
+            && let Some(_e) = self.option_loud_drop(22) { // 4
+                self.print(21); // 3
+        }
+    }
+
+    fn while_(&self) {
+        let mut v = self.option_loud_drop(4);
+        while let Some(_d) = v
+            && self.option_loud_drop(1).is_some()
+            && self.option_loud_drop(2).is_some() {
+            self.print(3);
+            v = None;
+        }
+    }
+
     fn assert_sorted(self) {
         assert!(
             self.0
@@ -142,4 +195,14 @@ fn main() {
     let collector = DropOrderCollector::default();
     collector.match_();
     collector.assert_sorted();
+
+    println!("-- let chain --");
+    let collector = DropOrderCollector::default();
+    collector.let_chain();
+    collector.assert_sorted();
+
+    println!("-- while --");
+    let collector = DropOrderCollector::default();
+    collector.while_();
+    collector.assert_sorted();
 }

From e8a6e60c5d47d7d2e62e196f80e926bf2dbdd95b Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 9 Oct 2022 17:56:40 +0400
Subject: [PATCH 06/16] resolve: Add some asserts for unexpected lifetime rib
 combinations

---
 compiler/rustc_resolve/src/late.rs            | 38 ++++++++----
 .../ui/lifetimes/unusual-rib-combinations.rs  | 28 +++++++++
 .../lifetimes/unusual-rib-combinations.stderr | 61 +++++++++++++++++++
 3 files changed, 115 insertions(+), 12 deletions(-)
 create mode 100644 src/test/ui/lifetimes/unusual-rib-combinations.rs
 create mode 100644 src/test/ui/lifetimes/unusual-rib-combinations.stderr

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 776c8ad528c0f..52419b582ec58 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1423,9 +1423,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                     } else {
                                         LifetimeUseSet::Many
                                     }),
-                                    LifetimeRibKind::Generics { .. }
-                                    | LifetimeRibKind::ConstGeneric
-                                    | LifetimeRibKind::AnonConst => None,
+                                    LifetimeRibKind::Generics { .. } => None,
+                                    LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
+                                        span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
+                                    }
                                 })
                                 .unwrap_or(LifetimeUseSet::Many);
                             debug!(?use_ctxt, ?use_set);
@@ -1460,7 +1461,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     );
                     return;
                 }
-                _ => {}
+                LifetimeRibKind::AnonymousCreateParameter { .. }
+                | LifetimeRibKind::Elided(_)
+                | LifetimeRibKind::Generics { .. }
+                | LifetimeRibKind::ElisionFailure
+                | LifetimeRibKind::AnonymousReportError => {}
             }
         }
 
@@ -1534,9 +1539,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     return;
                 }
                 LifetimeRibKind::Item => break,
-                LifetimeRibKind::Generics { .. }
-                | LifetimeRibKind::ConstGeneric
-                | LifetimeRibKind::AnonConst => {}
+                LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+                LifetimeRibKind::AnonConst => {
+                    // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+                    span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
+                }
             }
         }
         self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
@@ -1751,9 +1758,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                         self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
                         break;
                     }
-                    LifetimeRibKind::Generics { .. }
-                    | LifetimeRibKind::ConstGeneric
-                    | LifetimeRibKind::AnonConst => {}
+                    LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+                    LifetimeRibKind::AnonConst => {
+                        // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+                        span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
+                    }
                 }
             }
 
@@ -3938,7 +3947,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         fn_id: NodeId,
         async_node_id: Option<(NodeId, Span)>,
     ) {
-        if let Some((async_node_id, _)) = async_node_id {
+        if let Some((async_node_id, span)) = async_node_id {
             let mut extra_lifetime_params =
                 self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
             for rib in self.lifetime_ribs.iter().rev() {
@@ -3952,7 +3961,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             extra_lifetime_params.extend(earlier_fresh);
                         }
                     }
-                    _ => {}
+                    LifetimeRibKind::Generics { .. } => {}
+                    _ => {
+                        // We are in a function definition. We should only find `Generics`
+                        // and `AnonymousCreateParameter` inside the innermost `Item`.
+                        span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
+                    }
                 }
             }
             self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
diff --git a/src/test/ui/lifetimes/unusual-rib-combinations.rs b/src/test/ui/lifetimes/unusual-rib-combinations.rs
new file mode 100644
index 0000000000000..b4c86aab863c8
--- /dev/null
+++ b/src/test/ui/lifetimes/unusual-rib-combinations.rs
@@ -0,0 +1,28 @@
+#![feature(inline_const)]
+
+struct S<'a>(&'a u8);
+fn foo() {}
+
+// Paren generic args in AnonConst
+fn a() -> [u8; foo::()] {
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+//~| ERROR mismatched types
+    panic!()
+}
+
+// Paren generic args in ConstGeneric
+fn b<const C: u8()>() {}
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+
+// Paren generic args in AnonymousReportError
+fn c<T = u8()>() {}
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+//~| ERROR defaults for type parameters are only allowed in
+//~| WARN this was previously accepted
+
+// Elided lifetime in path in ConstGeneric
+fn d<const C: S>() {}
+//~^ ERROR missing lifetime specifier
+//~| ERROR `S<'static>` is forbidden as the type of a const generic parameter
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/unusual-rib-combinations.stderr b/src/test/ui/lifetimes/unusual-rib-combinations.stderr
new file mode 100644
index 0000000000000..6d7b42506982c
--- /dev/null
+++ b/src/test/ui/lifetimes/unusual-rib-combinations.stderr
@@ -0,0 +1,61 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/unusual-rib-combinations.rs:24:15
+   |
+LL | fn d<const C: S>() {}
+   |               ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn d<'a, const C: S<'a>>() {}
+   |      +++           ++++
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unusual-rib-combinations.rs:7:16
+   |
+LL | fn a() -> [u8; foo::()] {
+   |                ^^^^^^^ only `Fn` traits may use parentheses
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unusual-rib-combinations.rs:14:15
+   |
+LL | fn b<const C: u8()>() {}
+   |               ^^^^ only `Fn` traits may use parentheses
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/unusual-rib-combinations.rs:18:10
+   |
+LL | fn c<T = u8()>() {}
+   |          ^^^^ only `Fn` traits may use parentheses
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/unusual-rib-combinations.rs:18:6
+   |
+LL | fn c<T = u8()>() {}
+   |      ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+   = note: `#[deny(invalid_type_param_default)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/unusual-rib-combinations.rs:7:16
+   |
+LL | fn a() -> [u8; foo::()] {
+   |                ^^^^^^^ expected `usize`, found fn item
+   |
+   = note: expected type `usize`
+           found fn item `fn() {foo}`
+
+error: `S<'static>` is forbidden as the type of a const generic parameter
+  --> $DIR/unusual-rib-combinations.rs:24:15
+   |
+LL | fn d<const C: S>() {}
+   |               ^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0106, E0214, E0308.
+For more information about an error, try `rustc --explain E0106`.

From e94ec30dc4205911c53901f1255a47089f95ddd2 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Mon, 10 Oct 2022 17:41:44 +0400
Subject: [PATCH 07/16] resolve: Remove redundant item lifetime ribs

and cleanup lifetime rib walking loops
---
 compiler/rustc_resolve/src/late.rs | 65 +++++++++++++-----------------
 1 file changed, 28 insertions(+), 37 deletions(-)

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 52419b582ec58..194d057c870eb 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -748,35 +748,31 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
             ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
-                self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
-                    this.with_generic_param_rib(
-                        &generics.params,
-                        ItemRibKind(HasGenericParams::Yes(generics.span)),
-                        LifetimeRibKind::Generics {
-                            binder: foreign_item.id,
-                            kind: LifetimeBinderKind::Item,
-                            span: generics.span,
-                        },
-                        |this| visit::walk_foreign_item(this, foreign_item),
-                    )
-                });
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes(generics.span)),
+                    LifetimeRibKind::Generics {
+                        binder: foreign_item.id,
+                        kind: LifetimeBinderKind::Item,
+                        span: generics.span,
+                    },
+                    |this| visit::walk_foreign_item(this, foreign_item),
+                );
             }
             ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
-                self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
-                    this.with_generic_param_rib(
-                        &generics.params,
-                        ItemRibKind(HasGenericParams::Yes(generics.span)),
-                        LifetimeRibKind::Generics {
-                            binder: foreign_item.id,
-                            kind: LifetimeBinderKind::Function,
-                            span: generics.span,
-                        },
-                        |this| visit::walk_foreign_item(this, foreign_item),
-                    )
-                });
+                self.with_generic_param_rib(
+                    &generics.params,
+                    ItemRibKind(HasGenericParams::Yes(generics.span)),
+                    LifetimeRibKind::Generics {
+                        binder: foreign_item.id,
+                        kind: LifetimeBinderKind::Function,
+                        span: generics.span,
+                    },
+                    |this| visit::walk_foreign_item(this, foreign_item),
+                );
             }
             ForeignItemKind::Static(..) => {
-                self.with_item_rib(|this| {
+                self.with_static_rib(|this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
             }
@@ -1391,9 +1387,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             return self.resolve_anonymous_lifetime(lifetime, false);
         }
 
-        let mut indices = (0..self.lifetime_ribs.len()).rev();
-        for i in &mut indices {
-            let rib = &self.lifetime_ribs[i];
+        let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
+        while let Some(rib) = lifetime_rib_iter.next() {
             let normalized_ident = ident.normalize_to_macros_2_0();
             if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
                 self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
@@ -1470,8 +1465,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         }
 
         let mut outer_res = None;
-        for i in indices {
-            let rib = &self.lifetime_ribs[i];
+        for rib in lifetime_rib_iter {
             let normalized_ident = ident.normalize_to_macros_2_0();
             if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
                 outer_res = Some(outer);
@@ -1498,8 +1492,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             count: 1,
         };
         let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
-        for i in (0..self.lifetime_ribs.len()).rev() {
-            let rib = &mut self.lifetime_ribs[i];
+        for rib in self.lifetime_ribs.iter().rev() {
             debug!(?rib.kind);
             match rib.kind {
                 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
@@ -2213,7 +2206,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             }
 
             ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
-                self.with_item_rib(|this| {
+                self.with_static_rib(|this| {
                     this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
                         this.visit_ty(ty);
                     });
@@ -2408,11 +2401,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         self.label_ribs.pop();
     }
 
-    fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+    fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
         let kind = ItemRibKind(HasGenericParams::No);
-        self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
-            this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
-        })
+        self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
     }
 
     // HACK(min_const_generics,const_evaluatable_unchecked): We

From f6341065912ff1b284e54acfec96b000dee81a34 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Mon, 10 Oct 2022 18:31:08 +0400
Subject: [PATCH 08/16] resolve: Regroup lifetime rib kinds to account for
 their purpose

---
 compiler/rustc_resolve/src/late.rs | 39 ++++++++++++++++++------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 194d057c870eb..060f7987a5d6d 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -224,22 +224,14 @@ enum LifetimeUseSet {
 
 #[derive(Copy, Clone, Debug)]
 enum LifetimeRibKind {
-    /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
-    Item,
-
+    // -- Ribs introducing named lifetimes
+    //
     /// This rib declares generic parameters.
+    /// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
     Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
 
-    /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
-    /// generics. We are disallowing this until we can decide on how we want to handle non-'static
-    /// lifetimes in const generics. See issue #74052 for discussion.
-    ConstGeneric,
-
-    /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
-    /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
-    /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
-    AnonConst,
-
+    // -- Ribs introducing unnamed lifetimes
+    //
     /// Create a new anonymous lifetime parameter and reference it.
     ///
     /// If `report_in_path`, report an error when encountering lifetime elision in a path:
@@ -256,16 +248,31 @@ enum LifetimeRibKind {
     /// ```
     AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
 
+    /// Replace all anonymous lifetimes by provided lifetime.
+    Elided(LifetimeRes),
+
+    // -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
+    //
     /// Give a hard error when either `&` or `'_` is written. Used to
     /// rule out things like `where T: Foo<'_>`. Does not imply an
     /// error on default object bounds (e.g., `Box<dyn Foo>`).
     AnonymousReportError,
 
-    /// Replace all anonymous lifetimes by provided lifetime.
-    Elided(LifetimeRes),
-
     /// Signal we cannot find which should be the anonymous lifetime.
     ElisionFailure,
+
+    /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
+    /// generics. We are disallowing this until we can decide on how we want to handle non-'static
+    /// lifetimes in const generics. See issue #74052 for discussion.
+    ConstGeneric,
+
+    /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
+    /// This function will emit an error if `generic_const_exprs` is not enabled, the body
+    /// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
+    AnonConst,
+
+    /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
+    Item,
 }
 
 #[derive(Copy, Clone, Debug)]

From 709a08ade6a8873dad8dc3987e842ed26523ef1f Mon Sep 17 00:00:00 2001
From: Nathan Whitaker <nathan.whitaker01@gmail.com>
Date: Thu, 13 Oct 2022 18:20:39 -0700
Subject: [PATCH 09/16] Lower condition directly from AST to HIR

---
 compiler/rustc_ast_lowering/src/expr.rs | 46 +++++++++++++------------
 1 file changed, 24 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 104010f8d435e..ec9c393502056 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -387,23 +387,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
         then: &Block,
         else_opt: Option<&Expr>,
     ) -> hir::ExprKind<'hir> {
-        let lowered_cond = self.lower_expr(cond);
-        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
+        let lowered_cond = self.lower_cond(cond);
         let then_expr = self.lower_block_expr(then);
         if let Some(rslt) = else_opt {
-            hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
+            hir::ExprKind::If(
+                lowered_cond,
+                self.arena.alloc(then_expr),
+                Some(self.lower_expr(rslt)),
+            )
         } else {
-            hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
+            hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
         }
     }
 
-    // Wraps a condition (i.e. `cond` in `if cond` or `while cond`) in a terminating scope
+    // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
     // so that temporaries created in the condition don't live beyond it.
-    fn wrap_cond_in_drop_scope(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
-        fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
-            match expr.kind {
-                hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
-                hir::ExprKind::Let(..) => true,
+    fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
+        fn has_let_expr(expr: &Expr) -> bool {
+            match &expr.kind {
+                ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
+                ExprKind::Let(..) => true,
                 _ => false,
             }
         }
@@ -415,14 +418,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // In order to mantain the drop behavior for the non `let` parts of the condition,
         // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
         // gets transformed into `if { let _t = foo; _t } && let pat = val`
-        match cond.kind {
-            hir::ExprKind::Binary(
-                op @ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
-                lhs,
-                rhs,
-            ) if has_let_expr(cond) => {
-                let lhs = self.wrap_cond_in_drop_scope(lhs);
-                let rhs = self.wrap_cond_in_drop_scope(rhs);
+        match &cond.kind {
+            ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
+                if has_let_expr(cond) =>
+            {
+                let op = self.lower_binop(*op);
+                let lhs = self.lower_cond(lhs);
+                let rhs = self.lower_cond(rhs);
 
                 self.arena.alloc(self.expr(
                     cond.span,
@@ -430,8 +432,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     AttrVec::new(),
                 ))
             }
-            hir::ExprKind::Let(_) => cond,
+            ExprKind::Let(..) => self.lower_expr(cond),
             _ => {
+                let cond = self.lower_expr(cond);
                 let reason = DesugaringKind::CondTemporary;
                 let span_block = self.mark_span_with_reason(reason, cond.span, None);
                 self.expr_drop_temps(span_block, cond, AttrVec::new())
@@ -462,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: &Block,
         opt_label: Option<Label>,
     ) -> hir::ExprKind<'hir> {
-        let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
-        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
+        let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
         let then = self.lower_block_expr(body);
         let expr_break = self.expr_break(span, AttrVec::new());
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
         let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
-        let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
+        let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
         let if_expr = self.expr(span, if_kind, AttrVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));

From 4e1c09dcd64507c03ded02844c1e5022031b9e38 Mon Sep 17 00:00:00 2001
From: Nathan Whitaker <nathan.whitaker01@gmail.com>
Date: Thu, 13 Oct 2022 18:29:25 -0700
Subject: [PATCH 10/16] Validate MIR in the `drop_order` test

---
 src/test/ui/drop/drop_order.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs
index bf740b6a9ab67..ba1ac53aa7ce8 100644
--- a/src/test/ui/drop/drop_order.rs
+++ b/src/test/ui/drop/drop_order.rs
@@ -1,4 +1,5 @@
 // run-pass
+// compile-flags: -Z validate-mir
 #![feature(let_chains)]
 
 use std::cell::RefCell;

From b8418485bc400d5a00f197ff328655bfa367835e Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Thu, 13 Oct 2022 13:07:56 +0900
Subject: [PATCH 11/16] check if the self type is `ty::Float` before getting
 second substs

---
 .../src/traits/error_reporting/suggestions.rs | 22 +++---
 src/test/ui/traits/issue-102989.rs            | 18 +++++
 src/test/ui/traits/issue-102989.stderr        | 72 +++++++++++++++++++
 3 files changed, 99 insertions(+), 13 deletions(-)
 create mode 100644 src/test/ui/traits/issue-102989.rs
 create mode 100644 src/test/ui/traits/issue-102989.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fda6a2236b195..4431cf9f4436b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2937,19 +2937,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span,
             _ => return,
         };
-        match (
-            trait_ref.skip_binder().self_ty().kind(),
-            trait_ref.skip_binder().substs.type_at(1).kind(),
-        ) {
-            (ty::Float(_), ty::Infer(InferTy::IntVar(_))) => {
-                err.span_suggestion_verbose(
-                    rhs_span.shrink_to_hi(),
-                    "consider using a floating-point literal by writing it with `.0`",
-                    ".0",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            _ => {}
+        if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
+            && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
+        {
+            err.span_suggestion_verbose(
+                rhs_span.shrink_to_hi(),
+                "consider using a floating-point literal by writing it with `.0`",
+                ".0",
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 
diff --git a/src/test/ui/traits/issue-102989.rs b/src/test/ui/traits/issue-102989.rs
new file mode 100644
index 0000000000000..cd517a1c4ac87
--- /dev/null
+++ b/src/test/ui/traits/issue-102989.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Cinstrument-coverage
+//~^ ERROR can't find crate for `profiler_builtins`
+
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { } //~ ERROR found duplicate lang item `sized`
+
+fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+    //~^ ERROR `self` parameter is only allowed in associated functions
+    //~| ERROR cannot find type `Struct` in this scope
+    //~| ERROR mismatched types
+    let x = x << 1;
+    //~^ ERROR the size for values of type `{integer}` cannot be known at compilation time
+    //~| ERROR cannot find value `x` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-102989.stderr b/src/test/ui/traits/issue-102989.stderr
new file mode 100644
index 0000000000000..255fa6966efc9
--- /dev/null
+++ b/src/test/ui/traits/issue-102989.stderr
@@ -0,0 +1,72 @@
+error: `self` parameter is only allowed in associated functions
+  --> $DIR/issue-102989.rs:9:15
+   |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |               ^^^^ not semantically valid as function parameter
+   |
+   = note: associated functions are those in `impl` or `trait` definitions
+
+error[E0412]: cannot find type `Struct` in this scope
+  --> $DIR/issue-102989.rs:9:22
+   |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                      ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-102989.rs:13:13
+   |
+LL |     let x = x << 1;
+   |             ^ help: a local variable with a similar name exists: `f`
+
+error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+error[E0463]: can't find crate for `profiler_builtins`
+   |
+   = note: the compiler may have been built without the profiler runtime
+
+error[E0152]: found duplicate lang item `sized`
+  --> $DIR/issue-102989.rs:7:1
+   |
+LL | trait Sized { }
+   | ^^^^^^^^^^^
+   |
+   = note: the lang item is first defined in crate `core`.
+   = note: first definition in `core` loaded from $BUILD_DIR/aarch64-apple-darwin/stage1/lib/rustlib/aarch64-apple-darwin/lib/libcore-500f4c12402b1108.rlib
+   = note: second definition in the local crate (`issue_102989`)
+
+error: `#[panic_handler]` function required, but not found
+
+error: language item required, but not found: `eh_personality`
+   |
+   = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
+   = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
+
+error[E0277]: the size for values of type `{integer}` cannot be known at compilation time
+  --> $DIR/issue-102989.rs:13:15
+   |
+LL |     let x = x << 1;
+   |               ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `core::marker::Sized` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-102989.rs:9:42
+   |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |    ----------                            ^^^^ expected `&u32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+   |
+note: consider returning one of these bindings
+  --> $DIR/issue-102989.rs:9:30
+   |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                              ^
+...
+LL |     let x = x << 1;
+   |         ^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425, E0463.
+For more information about an error, try `rustc --explain E0152`.

From 5378677c31e89ae2fe4de954631bde8efeac91d1 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Thu, 13 Oct 2022 15:07:39 +0900
Subject: [PATCH 12/16] normalize stderr

---
 src/test/ui/traits/issue-102989.rs     |  3 ++-
 src/test/ui/traits/issue-102989.stderr | 16 ++++++++--------
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/test/ui/traits/issue-102989.rs b/src/test/ui/traits/issue-102989.rs
index cd517a1c4ac87..cb1e3271d26e8 100644
--- a/src/test/ui/traits/issue-102989.rs
+++ b/src/test/ui/traits/issue-102989.rs
@@ -1,5 +1,6 @@
+//~ ERROR can't find crate for `profiler_builtins`
 // compile-flags: -Cinstrument-coverage
-//~^ ERROR can't find crate for `profiler_builtins`
+// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib"
 
 #![no_core]
 #![feature(no_core, lang_items)]
diff --git a/src/test/ui/traits/issue-102989.stderr b/src/test/ui/traits/issue-102989.stderr
index 255fa6966efc9..efea2251a13f8 100644
--- a/src/test/ui/traits/issue-102989.stderr
+++ b/src/test/ui/traits/issue-102989.stderr
@@ -1,5 +1,5 @@
 error: `self` parameter is only allowed in associated functions
-  --> $DIR/issue-102989.rs:9:15
+  --> $DIR/issue-102989.rs:10:15
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |               ^^^^ not semantically valid as function parameter
@@ -7,13 +7,13 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    = note: associated functions are those in `impl` or `trait` definitions
 
 error[E0412]: cannot find type `Struct` in this scope
-  --> $DIR/issue-102989.rs:9:22
+  --> $DIR/issue-102989.rs:10:22
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                      ^^^^^^ not found in this scope
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/issue-102989.rs:13:13
+  --> $DIR/issue-102989.rs:14:13
    |
 LL |     let x = x << 1;
    |             ^ help: a local variable with a similar name exists: `f`
@@ -25,13 +25,13 @@ error[E0463]: can't find crate for `profiler_builtins`
    = note: the compiler may have been built without the profiler runtime
 
 error[E0152]: found duplicate lang item `sized`
-  --> $DIR/issue-102989.rs:7:1
+  --> $DIR/issue-102989.rs:8:1
    |
 LL | trait Sized { }
    | ^^^^^^^^^^^
    |
    = note: the lang item is first defined in crate `core`.
-   = note: first definition in `core` loaded from $BUILD_DIR/aarch64-apple-darwin/stage1/lib/rustlib/aarch64-apple-darwin/lib/libcore-500f4c12402b1108.rlib
+   = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib
    = note: second definition in the local crate (`issue_102989`)
 
 error: `#[panic_handler]` function required, but not found
@@ -42,7 +42,7 @@ error: language item required, but not found: `eh_personality`
    = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
 
 error[E0277]: the size for values of type `{integer}` cannot be known at compilation time
-  --> $DIR/issue-102989.rs:13:15
+  --> $DIR/issue-102989.rs:14:15
    |
 LL |     let x = x << 1;
    |               ^^ doesn't have a size known at compile-time
@@ -50,7 +50,7 @@ LL |     let x = x << 1;
    = help: the trait `core::marker::Sized` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-102989.rs:9:42
+  --> $DIR/issue-102989.rs:10:42
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |    ----------                            ^^^^ expected `&u32`, found `()`
@@ -58,7 +58,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |    implicitly returns `()` as its body has no tail or `return` expression
    |
 note: consider returning one of these bindings
-  --> $DIR/issue-102989.rs:9:30
+  --> $DIR/issue-102989.rs:10:30
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                              ^

From 40bb4b740b094e79ce93f0649fa4522ddaa2eafd Mon Sep 17 00:00:00 2001
From: Weihang Lo <me@weihanglo.tw>
Date: Fri, 14 Oct 2022 09:58:48 +0100
Subject: [PATCH 13/16] Update cargo

12 commits in b8f30cb23c4e5f20854a4f683325782b7cff9837..b332991a57c9d055f1864de1eed93e2178d49440
2022-10-10 19:16:06 +0000 to 2022-10-13 22:05:28 +0000
- Differentiate the warning when an alias (built-in or user-defined) shadows an external subcommand (rust-lang/cargo#11170)
- chore: Update tests for latest clap (rust-lang/cargo#11235)
- feat(publish): Support 'publish.timeout' config behind '-Zpublish-timeout' (rust-lang/cargo#11230)
- Add missing edition (rust-lang/cargo#11231)
- doc(profiles): add module level doc (rust-lang/cargo#11219)
- refactor(publish): Clarify which SourceId is being used (rust-lang/cargo#11216)
- Add new SourceKind::SparseRegistry to differentiate sparse registries (rust-lang/cargo#11209)
- Fix deadlock when build scripts are waiting for input on stdin (rust-lang/cargo#11205)
- refactor: New variant `FeaturesFor::ArtifactDep` (rust-lang/cargo#11184)
- Fix rustdoc warning about unclosed HTML tag (rust-lang/cargo#11221)
- refactor(tests): Prepare for wait-for-publish test changes (rust-lang/cargo#11210)
- Add configuration option for controlling crates.io protocol (rust-lang/cargo#11215)
---
 Cargo.lock      | 8 ++++----
 src/tools/cargo | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0cc7f8a1c7ce3..f393a91809417 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -297,7 +297,7 @@ dependencies = [
  "cargo-test-macro",
  "cargo-test-support",
  "cargo-util",
- "clap 4.0.9",
+ "clap 4.0.15",
  "crates-io",
  "curl",
  "curl-sys",
@@ -439,7 +439,7 @@ dependencies = [
 
 [[package]]
 name = "cargo-util"
-version = "0.2.1"
+version = "0.2.2"
 dependencies = [
  "anyhow",
  "core-foundation",
@@ -602,9 +602,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.9"
+version = "4.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30607dd93c420c6f1f80b544be522a0238a7db35e6a12968d28910983fee0df0"
+checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
 dependencies = [
  "atty",
  "bitflags",
diff --git a/src/tools/cargo b/src/tools/cargo
index b8f30cb23c4e5..b332991a57c9d 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit b8f30cb23c4e5f20854a4f683325782b7cff9837
+Subproject commit b332991a57c9d055f1864de1eed93e2178d49440

From f528414e4092815e96690275c527717871ff411d Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Wed, 12 Oct 2022 11:32:00 +0200
Subject: [PATCH 14/16] Add missing checks for `doc(cfg_hide(...))` attribute

---
 .../locales/en-US/passes.ftl                  |  3 +++
 compiler/rustc_passes/src/check_attr.rs       | 23 +++++++++++++++++++
 compiler/rustc_passes/src/errors.rs           |  4 ++++
 3 files changed, 30 insertions(+)

diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 1f1c9c29d665a..4bc6bd9fb2207 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -145,6 +145,9 @@ passes_doc_test_takes_list =
 passes_doc_primitive =
     `doc(primitive)` should never have been stable
 
+passes_doc_cfg_hide_takes_list =
+    `#[doc(cfg_hide(...)]` takes a list of attributes
+
 passes_doc_test_unknown_any =
     unknown `doc` attribute `{$path}`
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 73fb89bbc385e..c5ba4eb68fac0 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -934,6 +934,22 @@ impl CheckAttrVisitor<'_> {
         is_valid
     }
 
+    /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
+    /// Returns `true` if valid.
+    fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+        if meta.meta_item_list().is_some() {
+            true
+        } else {
+            self.tcx.emit_spanned_lint(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                errors::DocCfgHideTakesList,
+            );
+            false
+        }
+    }
+
     /// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
     ///
     /// `specified_inline` should be initialized to `None` and kept for the scope
@@ -987,6 +1003,13 @@ impl CheckAttrVisitor<'_> {
                             is_valid = false;
                         }
 
+                        sym::cfg_hide
+                            if !self.check_attr_crate_level(attr, meta, hir_id)
+                                || !self.check_doc_cfg_hide(meta, hir_id) =>
+                        {
+                            is_valid = false;
+                        }
+
                         sym::inline | sym::no_inline
                             if !self.check_doc_inline(
                                 attr,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 1cc81a9ab9884..ed54834134453 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -271,6 +271,10 @@ pub struct DocTestUnknown {
 #[diag(passes::doc_test_takes_list)]
 pub struct DocTestTakesList;
 
+#[derive(LintDiagnostic)]
+#[diag(passes::doc_cfg_hide_takes_list)]
+pub struct DocCfgHideTakesList;
+
 #[derive(LintDiagnostic)]
 #[diag(passes::doc_primitive)]
 pub struct DocPrimitive;

From 6f0c2470dbc3eeff7aa243965ec8c3dc7b64e254 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Wed, 12 Oct 2022 11:32:26 +0200
Subject: [PATCH 15/16] Add UI test for invalid `doc(cfg_hide(...))` attributes

---
 src/test/rustdoc-ui/doc_cfg_hide.rs     | 11 +++++++
 src/test/rustdoc-ui/doc_cfg_hide.stderr | 40 +++++++++++++++++++++++++
 2 files changed, 51 insertions(+)
 create mode 100644 src/test/rustdoc-ui/doc_cfg_hide.rs
 create mode 100644 src/test/rustdoc-ui/doc_cfg_hide.stderr

diff --git a/src/test/rustdoc-ui/doc_cfg_hide.rs b/src/test/rustdoc-ui/doc_cfg_hide.rs
new file mode 100644
index 0000000000000..5d8791748a012
--- /dev/null
+++ b/src/test/rustdoc-ui/doc_cfg_hide.rs
@@ -0,0 +1,11 @@
+#![feature(doc_cfg_hide)]
+#![deny(warnings)]
+
+#![doc(cfg_hide = "test")] //~ ERROR
+//~^ WARN
+#![doc(cfg_hide)] //~ ERROR
+//~^ WARN
+
+#[doc(cfg_hide(doc))] //~ ERROR
+//~^ WARN
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc_cfg_hide.stderr b/src/test/rustdoc-ui/doc_cfg_hide.stderr
new file mode 100644
index 0000000000000..03623368cd047
--- /dev/null
+++ b/src/test/rustdoc-ui/doc_cfg_hide.stderr
@@ -0,0 +1,40 @@
+error: this attribute can only be applied at the crate level
+  --> $DIR/doc_cfg_hide.rs:9:7
+   |
+LL | #[doc(cfg_hide(doc))]
+   |       ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+note: the lint level is defined here
+  --> $DIR/doc_cfg_hide.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+help: to apply to the crate, use an inner attribute
+   |
+LL | #![doc(cfg_hide(doc))]
+   | ~~~~~~~~~~~~~~~~~~~~~~
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+  --> $DIR/doc_cfg_hide.rs:4:8
+   |
+LL | #![doc(cfg_hide = "test")]
+   |        ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+  --> $DIR/doc_cfg_hide.rs:6:8
+   |
+LL | #![doc(cfg_hide)]
+   |        ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 3 previous errors
+

From 062ea9ce4ded4e5a864dfb4109d6533e03d67679 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Sat, 15 Oct 2022 02:45:11 +0900
Subject: [PATCH 16/16] remove no_core feature

---
 src/test/ui/traits/issue-102989.rs     |  5 +---
 src/test/ui/traits/issue-102989.stderr | 35 ++++++++------------------
 2 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/src/test/ui/traits/issue-102989.rs b/src/test/ui/traits/issue-102989.rs
index cb1e3271d26e8..62f95272fbfd2 100644
--- a/src/test/ui/traits/issue-102989.rs
+++ b/src/test/ui/traits/issue-102989.rs
@@ -1,9 +1,6 @@
-//~ ERROR can't find crate for `profiler_builtins`
-// compile-flags: -Cinstrument-coverage
 // normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib"
 
-#![no_core]
-#![feature(no_core, lang_items)]
+#![feature(lang_items)]
 #[lang="sized"]
 trait Sized { } //~ ERROR found duplicate lang item `sized`
 
diff --git a/src/test/ui/traits/issue-102989.stderr b/src/test/ui/traits/issue-102989.stderr
index efea2251a13f8..efe1a24677457 100644
--- a/src/test/ui/traits/issue-102989.stderr
+++ b/src/test/ui/traits/issue-102989.stderr
@@ -1,5 +1,5 @@
 error: `self` parameter is only allowed in associated functions
-  --> $DIR/issue-102989.rs:10:15
+  --> $DIR/issue-102989.rs:7:15
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |               ^^^^ not semantically valid as function parameter
@@ -7,50 +7,37 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    = note: associated functions are those in `impl` or `trait` definitions
 
 error[E0412]: cannot find type `Struct` in this scope
-  --> $DIR/issue-102989.rs:10:22
+  --> $DIR/issue-102989.rs:7:22
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                      ^^^^^^ not found in this scope
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/issue-102989.rs:14:13
+  --> $DIR/issue-102989.rs:11:13
    |
 LL |     let x = x << 1;
    |             ^ help: a local variable with a similar name exists: `f`
 
-error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
-
-error[E0463]: can't find crate for `profiler_builtins`
-   |
-   = note: the compiler may have been built without the profiler runtime
-
 error[E0152]: found duplicate lang item `sized`
-  --> $DIR/issue-102989.rs:8:1
+  --> $DIR/issue-102989.rs:5:1
    |
 LL | trait Sized { }
    | ^^^^^^^^^^^
    |
-   = note: the lang item is first defined in crate `core`.
+   = note: the lang item is first defined in crate `core` (which `std` depends on)
    = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib
    = note: second definition in the local crate (`issue_102989`)
 
-error: `#[panic_handler]` function required, but not found
-
-error: language item required, but not found: `eh_personality`
-   |
-   = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
-   = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
-
 error[E0277]: the size for values of type `{integer}` cannot be known at compilation time
-  --> $DIR/issue-102989.rs:14:15
+  --> $DIR/issue-102989.rs:11:15
    |
 LL |     let x = x << 1;
    |               ^^ doesn't have a size known at compile-time
    |
-   = help: the trait `core::marker::Sized` is not implemented for `{integer}`
+   = help: the trait `std::marker::Sized` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-102989.rs:10:42
+  --> $DIR/issue-102989.rs:7:42
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |    ----------                            ^^^^ expected `&u32`, found `()`
@@ -58,7 +45,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |    implicitly returns `()` as its body has no tail or `return` expression
    |
 note: consider returning one of these bindings
-  --> $DIR/issue-102989.rs:10:30
+  --> $DIR/issue-102989.rs:7:30
    |
 LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                              ^
@@ -66,7 +53,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
 LL |     let x = x << 1;
    |         ^
 
-error: aborting due to 10 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425, E0463.
+Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425.
 For more information about an error, try `rustc --explain E0152`.