From c864238baf2d44e1634c754451d69e66ef56201b Mon Sep 17 00:00:00 2001
From: Xiretza <xiretza@xiretza.xyz>
Date: Mon, 19 Aug 2024 20:20:48 +0000
Subject: [PATCH 1/9] Update annotate-snippets to 0.11

---
 Cargo.lock                                    | 14 +---
 compiler/rustc_errors/Cargo.toml              |  2 +-
 .../src/annotate_snippet_emitter_writer.rs    | 69 ++++++++-----------
 compiler/rustc_fluent_macro/Cargo.toml        |  2 +-
 compiler/rustc_fluent_macro/src/fluent.rs     | 30 +++-----
 5 files changed, 42 insertions(+), 75 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ac347d02af7..a18219b5683 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -94,16 +94,6 @@ dependencies = [
  "yansi-term",
 ]
 
-[[package]]
-name = "annotate-snippets"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d9b665789884a7e8fb06c84b295e923b03ca51edbb7d08f91a6a50322ecbfe6"
-dependencies = [
- "anstyle",
- "unicode-width",
-]
-
 [[package]]
 name = "annotate-snippets"
 version = "0.11.4"
@@ -3642,7 +3632,7 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets 0.10.2",
+ "annotate-snippets 0.11.4",
  "derive_setters",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -3702,7 +3692,7 @@ dependencies = [
 name = "rustc_fluent_macro"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets 0.10.2",
+ "annotate-snippets 0.11.4",
  "fluent-bundle",
  "fluent-syntax",
  "proc-macro2",
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 2fff9f2de50..59cf4e5f210 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.10"
+annotate-snippets = "0.11"
 derive_setters = "0.1.6"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index df4e9792f95..d71ae9d210d 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -5,7 +5,7 @@
 //!
 //! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/
 
-use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
+use annotate_snippets::{Renderer, Snippet};
 use rustc_data_structures::sync::Lrc;
 use rustc_error_messages::FluentArgs;
 use rustc_span::source_map::SourceMap;
@@ -83,15 +83,17 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
     file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
 }
 
-/// Maps `diagnostic::Level` to `snippet::AnnotationType`
-fn annotation_type_for_level(level: Level) -> AnnotationType {
+/// Maps [`crate::Level`] to [`annotate_snippets::Level`]
+fn annotation_level_for_level(level: Level) -> annotate_snippets::Level {
     match level {
-        Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => AnnotationType::Error,
-        Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
-        Level::Note | Level::OnceNote => AnnotationType::Note,
-        Level::Help | Level::OnceHelp => AnnotationType::Help,
+        Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => {
+            annotate_snippets::Level::Error
+        }
+        Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning,
+        Level::Note | Level::OnceNote => annotate_snippets::Level::Note,
+        Level::Help | Level::OnceHelp => annotate_snippets::Level::Help,
         // FIXME(#59346): Not sure how to map this level
-        Level::FailureNote => AnnotationType::Error,
+        Level::FailureNote => annotate_snippets::Level::Error,
         Level::Allow => panic!("Should not call with Allow"),
         Level::Expect(_) => panic!("Should not call with Expect"),
     }
@@ -180,42 +182,29 @@ impl AnnotateSnippetEmitter {
                 })
                 .collect();
             let code = code.map(|code| code.to_string());
-            let snippet = Snippet {
-                title: Some(Annotation {
-                    label: Some(&message),
-                    id: code.as_deref(),
-                    annotation_type: annotation_type_for_level(*level),
-                }),
-                footer: vec![],
-                slices: annotated_files
-                    .iter()
-                    .map(|(file_name, source, line_index, annotations)| {
-                        Slice {
-                            source,
-                            line_start: *line_index,
-                            origin: Some(file_name),
-                            // FIXME(#59346): Not really sure when `fold` should be true or false
-                            fold: false,
-                            annotations: annotations
-                                .iter()
-                                .map(|annotation| SourceAnnotation {
-                                    range: (
-                                        annotation.start_col.display,
-                                        annotation.end_col.display,
-                                    ),
-                                    label: annotation.label.as_deref().unwrap_or_default(),
-                                    annotation_type: annotation_type_for_level(*level),
-                                })
-                                .collect(),
-                        }
-                    })
-                    .collect(),
-            };
+
+            let snippets =
+                annotated_files.iter().map(|(file_name, source, line_index, annotations)| {
+                    Snippet::source(source)
+                        .line_start(*line_index)
+                        .origin(file_name)
+                        // FIXME(#59346): Not really sure when `fold` should be true or false
+                        .fold(false)
+                        .annotations(annotations.iter().map(|annotation| {
+                            annotation_level_for_level(*level)
+                                .span(annotation.start_col.display..annotation.end_col.display)
+                                .label(annotation.label.as_deref().unwrap_or_default())
+                        }))
+                });
+            let mut message = annotation_level_for_level(*level).title(&message).snippets(snippets);
+            if let Some(code) = code.as_deref() {
+                message = message.id(code)
+            }
             // FIXME(#59346): Figure out if we can _always_ print to stderr or not.
             // `emitter.rs` has the `Destination` enum that lists various possible output
             // destinations.
             let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing);
-            eprintln!("{}", renderer.render(snippet))
+            eprintln!("{}", renderer.render(message))
         }
         // FIXME(#59346): Is it ok to return None if there's no source_map?
     }
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index c5a53ae8313..eeceaa4691a 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -8,7 +8,7 @@ proc-macro = true
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.10"
+annotate-snippets = "0.11"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
 proc-macro2 = "1"
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 23795a96b92..ca8bace28f3 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
 use std::fs::read_to_string;
 use std::path::{Path, PathBuf};
 
-use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
+use annotate_snippets::{Renderer, Snippet};
 use fluent_bundle::{FluentBundle, FluentError, FluentResource};
 use fluent_syntax::ast::{
     Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement,
@@ -154,27 +154,15 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                     .unwrap()
                     .0;
 
-                let snippet = Snippet {
-                    title: Some(Annotation {
-                        label: Some(&err),
-                        id: None,
-                        annotation_type: AnnotationType::Error,
-                    }),
-                    footer: vec![],
-                    slices: vec![Slice {
-                        source: this.source(),
-                        line_start,
-                        origin: Some(&relative_ftl_path),
-                        fold: true,
-                        annotations: vec![SourceAnnotation {
-                            label: "",
-                            annotation_type: AnnotationType::Error,
-                            range: (pos.start, pos.end - 1),
-                        }],
-                    }],
-                };
+                let message = annotate_snippets::Level::Error.title(&err).snippet(
+                    Snippet::source(this.source())
+                        .line_start(line_start)
+                        .origin(&relative_ftl_path)
+                        .fold(true)
+                        .annotation(annotate_snippets::Level::Error.span(pos.start..pos.end - 1)),
+                );
                 let renderer = Renderer::plain();
-                eprintln!("{}\n", renderer.render(snippet));
+                eprintln!("{}\n", renderer.render(message));
             }
 
             return failed(&crate_name);

From 78d0e08504a30e5ff8b8e0ba88126af95a16a398 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Mon, 19 Aug 2024 10:57:03 -0400
Subject: [PATCH 2/9] Don't consider RibKind::Module's bindings when checking
 generics shadowing

---
 compiler/rustc_resolve/src/late.rs              | 6 +++---
 tests/ui/resolve/local-shadows-inner-generic.rs | 8 ++++++++
 2 files changed, 11 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/resolve/local-shadows-inner-generic.rs

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 4a70fc0f308..40fdb01a72c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2677,14 +2677,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // We also can't shadow bindings from associated parent items.
             for ns in [ValueNS, TypeNS] {
                 for parent_rib in self.ribs[ns].iter().rev() {
-                    seen_bindings
-                        .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
-
                     // Break at mod level, to account for nested items which are
                     // allowed to shadow generic param names.
                     if matches!(parent_rib.kind, RibKind::Module(..)) {
                         break;
                     }
+
+                    seen_bindings
+                        .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
                 }
             }
 
diff --git a/tests/ui/resolve/local-shadows-inner-generic.rs b/tests/ui/resolve/local-shadows-inner-generic.rs
new file mode 100644
index 00000000000..d9145b9fe2c
--- /dev/null
+++ b/tests/ui/resolve/local-shadows-inner-generic.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+
+pub fn main() {
+    let a = 1;
+    struct Foo<a> { field: a, };
+}

From dfea11d6206be57feca5283c67c17b9c3ee12960 Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Mon, 19 Aug 2024 22:39:04 -0700
Subject: [PATCH 3/9] Stabilize `iter::repeat_n`

---
 library/alloc/src/lib.rs                  |  1 -
 library/core/src/iter/mod.rs              |  2 +-
 library/core/src/iter/sources.rs          |  2 +-
 library/core/src/iter/sources/repeat_n.rs | 18 ++++++++----------
 library/core/tests/lib.rs                 |  1 -
 5 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 3e44adf73f0..5e4b08df6cb 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -131,7 +131,6 @@
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
-#![feature(iter_repeat_n)]
 #![feature(layout_for_ptr)]
 #![feature(local_waker)]
 #![feature(maybe_uninit_slice)]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 1f2bf49d2b7..5dad9e1a75e 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -436,7 +436,7 @@ pub use self::sources::{once, Once};
 pub use self::sources::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::sources::{repeat, Repeat};
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub use self::sources::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::sources::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 6a94051b7c7..55901e1e50b 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -24,7 +24,7 @@ pub use self::once::{once, Once};
 pub use self::once_with::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::repeat::{repeat, Repeat};
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub use self::repeat_n::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::repeat_with::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 4c4ae39f836..2e247a34075 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -18,7 +18,6 @@ use crate::num::NonZero;
 /// Basic usage:
 ///
 /// ```
-/// #![feature(iter_repeat_n)]
 /// use std::iter;
 ///
 /// // four of the number four:
@@ -36,7 +35,6 @@ use crate::num::NonZero;
 /// For non-`Copy` types,
 ///
 /// ```
-/// #![feature(iter_repeat_n)]
 /// use std::iter;
 ///
 /// let v: Vec<i32> = Vec::with_capacity(123);
@@ -58,7 +56,7 @@ use crate::num::NonZero;
 /// assert_eq!(None, it.next());
 /// ```
 #[inline]
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
     let mut element = ManuallyDrop::new(element);
 
@@ -77,7 +75,7 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
 /// This `struct` is created by the [`repeat_n()`] function.
 /// See its documentation for more.
 #[derive(Clone, Debug)]
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 pub struct RepeatN<A> {
     count: usize,
     // Invariant: has been dropped iff count == 0.
@@ -101,14 +99,14 @@ impl<A> RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A> Drop for RepeatN<A> {
     fn drop(&mut self) {
         self.take_element();
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> Iterator for RepeatN<A> {
     type Item = A;
 
@@ -156,14 +154,14 @@ impl<A: Clone> Iterator for RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> ExactSizeIterator for RepeatN<A> {
     fn len(&self) -> usize {
         self.count
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
@@ -181,12 +179,12 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     }
 }
 
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> FusedIterator for RepeatN<A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
-#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
+#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
 impl<A: Clone> UncheckedIterator for RepeatN<A> {
     #[inline]
     unsafe fn next_unchecked(&mut self) -> Self::Item {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 8872b4cbfd5..2f0d03abed3 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -73,7 +73,6 @@
 #![feature(iter_next_chunk)]
 #![feature(iter_order_by)]
 #![feature(iter_partition_in_place)]
-#![feature(iter_repeat_n)]
 #![feature(iterator_try_collect)]
 #![feature(iterator_try_reduce)]
 #![feature(layout_for_ptr)]

From df019a9f46d58fcb1b32ee69022a294a93e1a0a7 Mon Sep 17 00:00:00 2001
From: bohan <bohan-zhang@foxmail.com>
Date: Fri, 16 Aug 2024 23:58:19 +0800
Subject: [PATCH 4/9] skip updating when external binding is existed

---
 .../rustc_resolve/src/build_reduced_graph.rs  | 18 ++++++++----
 src/tools/tidy/src/issues.txt                 |  3 +-
 .../{issue-85992-extern-2.rs => empty.rs}     |  0
 ...5992-extern-1.rs => issue-85992-extern.rs} |  2 +-
 tests/ui/imports/issue-85992.rs               | 12 ++++----
 tests/ui/imports/issue-85992.stderr           |  6 ++--
 .../multiple-extern-by-macro-for-buitlin.rs   | 18 ++++++++++++
 ...ultiple-extern-by-macro-for-buitlin.stderr | 22 ++++++++++++++
 .../multiple-extern-by-macro-for-custom.rs    | 19 ++++++++++++
 ...multiple-extern-by-macro-for-custom.stderr | 22 ++++++++++++++
 .../multiple-extern-by-macro-for-inexist.rs   | 19 ++++++++++++
 ...ultiple-extern-by-macro-for-inexist.stderr | 29 +++++++++++++++++++
 ...multiple-extern-by-macro-for-underscore.rs | 18 ++++++++++++
 ...iple-extern-by-macro-for-underscore.stderr |  8 +++++
 14 files changed, 179 insertions(+), 17 deletions(-)
 rename tests/ui/imports/auxiliary/{issue-85992-extern-2.rs => empty.rs} (100%)
 rename tests/ui/imports/auxiliary/{issue-85992-extern-1.rs => issue-85992-extern.rs} (54%)
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-custom.rs
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-custom.stderr
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-inexist.rs
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-underscore.rs
 create mode 100644 tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr

diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index d57dabdd78d..3a27f96dde8 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -896,7 +896,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         self.r.potentially_unused_imports.push(import);
         let imported_binding = self.r.import(binding, import);
         if parent == self.r.graph_root {
-            if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
+            let ident = ident.normalize_to_macros_2_0();
+            if let Some(entry) = self.r.extern_prelude.get(&ident) {
                 if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
                     self.r.dcx().emit_err(
                         errors::MacroExpandedExternCrateCannotShadowExternArguments {
@@ -913,14 +914,21 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             let entry = self
                 .r
                 .extern_prelude
-                .entry(ident.normalize_to_macros_2_0())
+                .entry(ident)
                 .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
-            // Binding from `extern crate` item in source code can replace
-            // a binding from `--extern` on command line here.
-            entry.binding = Some(imported_binding);
             if orig_name.is_some() {
                 entry.introduced_by_item = true;
             }
+            // Binding from `extern crate` item in source code can replace
+            // a binding from `--extern` on command line here.
+            if !entry.is_import() {
+                entry.binding = Some(imported_binding)
+            } else if ident.name != kw::Underscore {
+                self.r.dcx().span_delayed_bug(
+                    item.span,
+                    format!("it had been define the external module '{ident}' multiple times"),
+                );
+            }
         }
         self.r.define(parent, ident, TypeNS, imported_binding);
     }
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 57310977704..5205fa14294 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -1289,8 +1289,7 @@ ui/imports/auxiliary/issue-52891.rs
 ui/imports/auxiliary/issue-55811.rs
 ui/imports/auxiliary/issue-56125.rs
 ui/imports/auxiliary/issue-59764.rs
-ui/imports/auxiliary/issue-85992-extern-1.rs
-ui/imports/auxiliary/issue-85992-extern-2.rs
+ui/imports/auxiliary/issue-85992-extern.rs
 ui/imports/issue-109148.rs
 ui/imports/issue-109343.rs
 ui/imports/issue-113953.rs
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-2.rs b/tests/ui/imports/auxiliary/empty.rs
similarity index 100%
rename from tests/ui/imports/auxiliary/issue-85992-extern-2.rs
rename to tests/ui/imports/auxiliary/empty.rs
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs b/tests/ui/imports/auxiliary/issue-85992-extern.rs
similarity index 54%
rename from tests/ui/imports/auxiliary/issue-85992-extern-1.rs
rename to tests/ui/imports/auxiliary/issue-85992-extern.rs
index a2d0e206065..076d6045190 100644
--- a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs
+++ b/tests/ui/imports/auxiliary/issue-85992-extern.rs
@@ -1,6 +1,6 @@
 #[macro_export]
 macro_rules! m {
    () => {
-        use issue_85992_extern_2::Outcome;
+        use empty::Outcome;
    }
 }
diff --git a/tests/ui/imports/issue-85992.rs b/tests/ui/imports/issue-85992.rs
index 321c3a9218d..38cf0384501 100644
--- a/tests/ui/imports/issue-85992.rs
+++ b/tests/ui/imports/issue-85992.rs
@@ -1,11 +1,11 @@
 //@ edition: 2021
-//@ compile-flags: --extern issue_85992_extern_1 --extern issue_85992_extern_2
-//@ aux-build: issue-85992-extern-1.rs
-//@ aux-build: issue-85992-extern-2.rs
+//@ compile-flags: --extern issue_85992_extern --extern empty
+//@ aux-build: issue-85992-extern.rs
+//@ aux-build: empty.rs
 
-issue_85992_extern_1::m!();
+issue_85992_extern::m!();
 
-use crate::issue_85992_extern_2;
-//~^ ERROR unresolved import `crate::issue_85992_extern_2`
+use crate::empty;
+//~^ ERROR unresolved import `crate::empty`
 
 fn main() {}
diff --git a/tests/ui/imports/issue-85992.stderr b/tests/ui/imports/issue-85992.stderr
index 6c75b45d926..490b2d4d88b 100644
--- a/tests/ui/imports/issue-85992.stderr
+++ b/tests/ui/imports/issue-85992.stderr
@@ -1,8 +1,8 @@
-error[E0432]: unresolved import `crate::issue_85992_extern_2`
+error[E0432]: unresolved import `crate::empty`
   --> $DIR/issue-85992.rs:8:5
    |
-LL | use crate::issue_85992_extern_2;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root
+LL | use crate::empty;
+   |     ^^^^^^^^^^^^ no `empty` in the root
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs
new file mode 100644
index 00000000000..f0e5e4b4325
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate core;
+
+macro_rules! m {
+    () => {
+        extern crate std as core;
+        //~^ ERROR: the name `core` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::core;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr
new file mode 100644
index 00000000000..a84a6c42aa8
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr
@@ -0,0 +1,22 @@
+error[E0259]: the name `core` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-buitlin.rs:9:9
+   |
+LL | extern crate core;
+   | ------------------ previous import of the extern crate `core` here
+...
+LL |         extern crate std as core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ `core` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_core;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.rs b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs
new file mode 100644
index 00000000000..6bf544566e3
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.rs
@@ -0,0 +1,19 @@
+//@ edition: 2021
+//@ aux-build: empty.rs
+
+// issue#128813
+
+extern crate empty;
+
+macro_rules! m {
+    () => {
+        extern crate std as empty;
+        //~^ ERROR: the name `empty` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::empty;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr
new file mode 100644
index 00000000000..556d75a4dbb
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr
@@ -0,0 +1,22 @@
+error[E0259]: the name `empty` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-custom.rs:10:9
+   |
+LL | extern crate empty;
+   | ------------------- previous import of the extern crate `empty` here
+...
+LL |         extern crate std as empty;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ `empty` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `empty` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_empty;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs
new file mode 100644
index 00000000000..c23f275b9ff
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.rs
@@ -0,0 +1,19 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate non_existent;
+//~^ ERROR: can't find crate for `non_existent`
+
+macro_rules! m {
+    () => {
+        extern crate std as non_existent;
+        //~^ ERROR: the name `non_existent` is defined multiple times
+    };
+}
+
+m!();
+
+fn main() {
+    use ::non_existent;
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr
new file mode 100644
index 00000000000..ec34489f232
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr
@@ -0,0 +1,29 @@
+error[E0463]: can't find crate for `non_existent`
+  --> $DIR/multiple-extern-by-macro-for-inexist.rs:5:1
+   |
+LL | extern crate non_existent;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
+
+error[E0259]: the name `non_existent` is defined multiple times
+  --> $DIR/multiple-extern-by-macro-for-inexist.rs:10:9
+   |
+LL | extern crate non_existent;
+   | -------------------------- previous import of the extern crate `non_existent` here
+...
+LL |         extern crate std as non_existent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `non_existent` reimported here
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `non_existent` must be defined only once in the type namespace of this module
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you can use `as` to change the binding name of the import
+   |
+LL |         extern crate std as other_non_existent;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0259, E0463.
+For more information about an error, try `rustc --explain E0259`.
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs
new file mode 100644
index 00000000000..ddf735d8947
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+// issue#128813
+
+extern crate core as _;
+
+macro_rules! m {
+    () => {
+        extern crate std as _;
+    };
+}
+
+m!();
+
+fn main() {
+    use ::_;
+    //~^ ERROR: expected identifier, found reserved identifier `_`
+}
diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr
new file mode 100644
index 00000000000..1da5aa87070
--- /dev/null
+++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/multiple-extern-by-macro-for-underscore.rs:16:11
+   |
+LL |     use ::_;
+   |           ^ expected identifier, found reserved identifier
+
+error: aborting due to 1 previous error
+

From 257519615227104e57b1d69bf637e0278281806c Mon Sep 17 00:00:00 2001
From: c8ef <c8ef@outlook.com>
Date: Tue, 20 Aug 2024 20:50:32 +0800
Subject: [PATCH 5/9] fix: simple typo in compiler directory

---
 compiler/rustc_mir_build/src/build/scope.rs             | 2 +-
 compiler/rustc_query_system/src/dep_graph/serialized.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 8546a2539d7..693037d03e0 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -748,7 +748,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
     }
 
-    /// Sets up the drops for explict tail calls.
+    /// Sets up the drops for explicit tail calls.
     ///
     /// Unlike other kinds of early exits, tail calls do not go through the drop tree.
     /// Instead, all scheduled drops are immediately added to the CFG.
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index ff1c3431b7c..ab4a8be0fbf 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -547,7 +547,7 @@ impl<D: Deps> EncoderState<D> {
     /// Encodes a node that was promoted from the previous graph. It reads the information directly from
     /// the previous dep graph for performance reasons.
     ///
-    /// This differs from `encode_node` where you have to explictly provide the relevant `NodeInfo`.
+    /// This differs from `encode_node` where you have to explicitly provide the relevant `NodeInfo`.
     ///
     /// It expects all edges to already have a new dep node index assigned.
     #[inline]

From 38af7b068f506019a3aaa7c107e22bc1395f7b27 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Tue, 20 Aug 2024 14:58:10 +0200
Subject: [PATCH 6/9] ctfe: make CompileTimeInterpCx type alias public

---
 compiler/rustc_const_eval/src/const_eval/machine.rs | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index a075bdc1911..c3d94ca0e59 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -40,7 +40,10 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
 /// power of two of interpreted terminators.
 const PROGRESS_INDICATOR_START: usize = 4_000_000;
 
-/// Extra machine state for CTFE, and the Machine instance
+/// Extra machine state for CTFE, and the Machine instance.
+//
+// Should be public because out-of-tree rustc consumers need this
+// if they want to interact with constant values.
 pub struct CompileTimeMachine<'tcx> {
     /// The number of terminators that have been evaluated.
     ///
@@ -160,7 +163,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
     }
 }
 
-pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
+pub type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum MemoryKind {

From df568af244cc67eb6706ad5a27b9800043b37893 Mon Sep 17 00:00:00 2001
From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com>
Date: Wed, 21 Aug 2024 00:14:04 +0900
Subject: [PATCH 7/9] fix link in mir/mod

change url path when rewrite those code
---
 compiler/rustc_middle/src/mir/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 46c4d586f6a..5b2aac781eb 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1368,7 +1368,7 @@ rustc_index::newtype_index! {
     /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
     /// [data-flow analyses]:
     ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
-    /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
+    /// [`CriticalCallEdges`]: ../../rustc_mir_transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
     #[derive(HashStable)]
     #[encodable]

From 83fce478f43c91dd94b140a6fc4430d68ddc87a9 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Tue, 20 Aug 2024 18:09:58 +0200
Subject: [PATCH 8/9] Remove unneeded conversion to `DefId` for `ExtraInfo`

---
 src/librustdoc/clean/types.rs                 |  7 ++-
 src/librustdoc/doctest/rust.rs                |  2 +-
 src/librustdoc/html/markdown.rs               | 44 +++++++++----------
 .../passes/lint/check_code_block_syntax.rs    |  6 ++-
 4 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ff5c16f2b3e..63d71a73cdf 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -12,7 +12,7 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel, StableS
 use rustc_const_eval::const_eval::is_unstable_const_fn;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyId, Mutability};
 use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
@@ -88,6 +88,11 @@ impl ItemId {
         }
     }
 
+    #[inline]
+    pub(crate) fn as_local_def_id(self) -> Option<LocalDefId> {
+        self.as_def_id().and_then(|id| id.as_local())
+    }
+
     #[inline]
     pub(crate) fn krate(self) -> CrateNum {
         match self {
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index abd66f15dc0..5c0898f28fc 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -136,7 +136,7 @@ impl<'a, 'tcx> HirCollector<'a, 'tcx> {
                 self.enable_per_target_ignores,
                 Some(&crate::html::markdown::ExtraInfo::new(
                     self.tcx,
-                    def_id.to_def_id(),
+                    def_id,
                     span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
                 )),
             );
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 7bfe5d87d39..364d4e077b1 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -40,7 +40,7 @@ use pulldown_cmark::{
 };
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagMessage};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
 pub(crate) use rustc_resolve::rustdoc::main_body_opts;
 use rustc_resolve::rustdoc::may_be_doc_link;
@@ -818,27 +818,25 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
 }
 
 pub(crate) struct ExtraInfo<'tcx> {
-    def_id: DefId,
+    def_id: LocalDefId,
     sp: Span,
     tcx: TyCtxt<'tcx>,
 }
 
 impl<'tcx> ExtraInfo<'tcx> {
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: DefId, sp: Span) -> ExtraInfo<'tcx> {
+    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, sp: Span) -> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
     fn error_invalid_codeblock_attr(&self, msg: impl Into<DiagMessage>) {
-        if let Some(def_id) = self.def_id.as_local() {
-            self.tcx.node_span_lint(
-                crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.local_def_id_to_hir_id(def_id),
-                self.sp,
-                |lint| {
-                    lint.primary_message(msg);
-                },
-            );
-        }
+        self.tcx.node_span_lint(
+            crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
+            self.tcx.local_def_id_to_hir_id(self.def_id),
+            self.sp,
+            |lint| {
+                lint.primary_message(msg);
+            },
+        );
     }
 
     fn error_invalid_codeblock_attr_with_help(
@@ -846,17 +844,15 @@ impl<'tcx> ExtraInfo<'tcx> {
         msg: impl Into<DiagMessage>,
         f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
-        if let Some(def_id) = self.def_id.as_local() {
-            self.tcx.node_span_lint(
-                crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.local_def_id_to_hir_id(def_id),
-                self.sp,
-                |lint| {
-                    lint.primary_message(msg);
-                    f(lint);
-                },
-            );
-        }
+        self.tcx.node_span_lint(
+            crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
+            self.tcx.local_def_id_to_hir_id(self.def_id),
+            self.sp,
+            |lint| {
+                lint.primary_message(msg);
+                f(lint);
+            },
+        );
     }
 }
 
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index ef05befdddc..977c0953336 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -16,9 +16,11 @@ use crate::core::DocContext;
 use crate::html::markdown::{self, RustCodeBlock};
 
 pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
-    if let Some(dox) = &item.opt_doc_value() {
+    if let Some(def_id) = item.item_id.as_local_def_id()
+        && let Some(dox) = &item.opt_doc_value()
+    {
         let sp = item.attr_span(cx.tcx);
-        let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
+        let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp);
         for code_block in markdown::rust_code_blocks(dox, &extra) {
             check_rust_syntax(cx, item, dox, code_block);
         }

From ef25fbd0b4ffa79cdf34a73795bbfbe8ebe6e267 Mon Sep 17 00:00:00 2001
From: Ding Xiang Fei <dingxiangfei2009@protonmail.ch>
Date: Mon, 5 Aug 2024 03:50:15 +0800
Subject: [PATCH 9/9] lint on tail expr drop order change in Edition 2024

---
 compiler/rustc_lint/messages.ftl              |   3 +
 compiler/rustc_lint/src/lib.rs                |   3 +
 .../rustc_lint/src/tail_expr_drop_order.rs    | 306 ++++++++++++++++++
 src/tools/lint-docs/src/lib.rs                |   1 +
 .../drop/lint-tail-expr-drop-order-gated.rs   |  35 ++
 tests/ui/drop/lint-tail-expr-drop-order.rs    |  71 ++++
 .../ui/drop/lint-tail-expr-drop-order.stderr  |  42 +++
 7 files changed, 461 insertions(+)
 create mode 100644 compiler/rustc_lint/src/tail_expr_drop_order.rs
 create mode 100644 tests/ui/drop/lint-tail-expr-drop-order-gated.rs
 create mode 100644 tests/ui/drop/lint-tail-expr-drop-order.rs
 create mode 100644 tests/ui/drop/lint-tail-expr-drop-order.stderr

diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7a394a6d6c1..28aef9055ef 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -758,6 +758,9 @@ lint_suspicious_double_ref_clone =
 lint_suspicious_double_ref_deref =
     using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
+lint_tail_expr_drop_order = these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    .label = these values have significant drop implementation and will observe changes in drop order under Edition 2024
+
 lint_trailing_semi_macro = trailing semicolon in macro used in expression position
     .note1 = macro invocations at the end of a block are treated as expressions
     .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4f3933d461b..1828b6ea93c 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -78,6 +78,7 @@ mod ptr_nulls;
 mod redundant_semicolon;
 mod reference_casting;
 mod shadowed_into_iter;
+mod tail_expr_drop_order;
 mod traits;
 mod types;
 mod unit_bindings;
@@ -115,6 +116,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use shadowed_into_iter::ShadowedIntoIter;
 pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
+use tail_expr_drop_order::TailExprDropOrder;
 use traits::*;
 use types::*;
 use unit_bindings::*;
@@ -238,6 +240,7 @@ late_lint_methods!(
             AsyncFnInTrait: AsyncFnInTrait,
             NonLocalDefinitions: NonLocalDefinitions::default(),
             ImplTraitOvercaptures: ImplTraitOvercaptures,
+            TailExprDropOrder: TailExprDropOrder,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/tail_expr_drop_order.rs b/compiler/rustc_lint/src/tail_expr_drop_order.rs
new file mode 100644
index 00000000000..f9ecc8c9806
--- /dev/null
+++ b/compiler/rustc_lint/src/tail_expr_drop_order.rs
@@ -0,0 +1,306 @@
+use std::mem::swap;
+
+use rustc_ast::UnOp;
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir, Block, Expr, ExprKind, LetStmt, Pat, PatKind, QPath, StmtKind};
+use rustc_macros::LintDiagnostic;
+use rustc_middle::ty;
+use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::edition::Edition;
+use rustc_span::Span;
+
+use crate::{LateContext, LateLintPass};
+
+declare_lint! {
+    /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location, that of type
+    /// with a significant `Drop` implementation, such as locks.
+    /// In case there are also local variables of type with significant `Drop` implementation as well,
+    /// this lint warns you of a potential transposition in the drop order.
+    /// Your discretion on the new drop order introduced by Edition 2024 is required.
+    ///
+    /// ### Example
+    /// ```rust,edition2024
+    /// #![feature(shorter_tail_lifetimes)]
+    /// #![warn(tail_expr_drop_order)]
+    /// struct Droppy(i32);
+    /// impl Droppy {
+    ///     fn get(&self) -> i32 {
+    ///         self.0
+    ///     }
+    /// }
+    /// impl Drop for Droppy {
+    ///     fn drop(&mut self) {
+    ///         // This is a custom destructor and it induces side-effects that is observable
+    ///         // especially when the drop order at a tail expression changes.
+    ///         println!("loud drop {}", self.0);
+    ///     }
+    /// }
+    /// fn edition_2024() -> i32 {
+    ///     let another_droppy = Droppy(0);
+    ///     Droppy(1).get()
+    /// }
+    /// fn main() {
+    ///     edition_2024();
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// In tail expression of blocks or function bodies,
+    /// values of type with significant `Drop` implementation has an ill-specified drop order
+    /// before Edition 2024 so that they are dropped only after dropping local variables.
+    /// Edition 2024 introduces a new rule with drop orders for them,
+    /// so that they are dropped first before dropping local variables.
+    ///
+    /// A significant `Drop::drop` destructor here refers to an explicit, arbitrary
+    /// implementation of the `Drop` trait on the type, with exceptions including `Vec`,
+    /// `Box`, `Rc`, `BTreeMap` and `HashMap` that are marked by the compiler otherwise
+    /// so long that the generic types have no significant destructor recursively.
+    /// In other words, a type has a significant drop destructor when it has a `Drop` implementation
+    /// or its destructor invokes a significant destructor on a type.
+    /// Since we cannot completely reason about the change by just inspecting the existence of
+    /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default.
+    ///
+    /// This lint only points out the issue with `Droppy`, which will be dropped before `another_droppy`
+    /// does in Edition 2024.
+    /// No fix will be proposed by this lint.
+    /// However, the most probable fix is to hoist `Droppy` into its own local variable binding.
+    /// ```rust
+    /// struct Droppy(i32);
+    /// impl Droppy {
+    ///     fn get(&self) -> i32 {
+    ///         self.0
+    ///     }
+    /// }
+    /// fn edition_2024() -> i32 {
+    ///     let value = Droppy(0);
+    ///     let another_droppy = Droppy(1);
+    ///     value.get()
+    /// }
+    /// ```
+    pub TAIL_EXPR_DROP_ORDER,
+    Allow,
+    "Detect and warn on significant change in drop order in tail expression location",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+        reference: "issue #123739 <https://github.com/rust-lang/rust/issues/123739>",
+    };
+}
+
+declare_lint_pass!(TailExprDropOrder => [TAIL_EXPR_DROP_ORDER]);
+
+impl TailExprDropOrder {
+    fn check_fn_or_closure<'tcx>(
+        cx: &LateContext<'tcx>,
+        fn_kind: hir::intravisit::FnKind<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
+        def_id: rustc_span::def_id::LocalDefId,
+    ) {
+        let mut locals = vec![];
+        if matches!(fn_kind, hir::intravisit::FnKind::Closure) {
+            for &capture in cx.tcx.closure_captures(def_id) {
+                if matches!(capture.info.capture_kind, ty::UpvarCapture::ByValue)
+                    && capture.place.ty().has_significant_drop(cx.tcx, cx.param_env)
+                {
+                    locals.push(capture.var_ident.span);
+                }
+            }
+        }
+        for param in body.params {
+            if cx
+                .typeck_results()
+                .node_type(param.hir_id)
+                .has_significant_drop(cx.tcx, cx.param_env)
+            {
+                locals.push(param.span);
+            }
+        }
+        if let hir::ExprKind::Block(block, _) = body.value.kind {
+            LintVisitor { cx, locals }.check_block_inner(block);
+        } else {
+            LintTailExpr { cx, locals: &locals, is_root_tail_expr: true }.visit_expr(body.value);
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: hir::intravisit::FnKind<'tcx>,
+        _: &'tcx hir::FnDecl<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
+        _: Span,
+        def_id: rustc_span::def_id::LocalDefId,
+    ) {
+        if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes {
+            Self::check_fn_or_closure(cx, fn_kind, body, def_id);
+        }
+    }
+}
+
+struct LintVisitor<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    // We only record locals that have significant drops
+    locals: Vec<Span>,
+}
+
+struct LocalCollector<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    locals: &'a mut Vec<Span>,
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LocalCollector<'tcx, 'a> {
+    type Result = ();
+    fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
+        if let PatKind::Binding(_binding_mode, id, ident, pat) = pat.kind {
+            let ty = self.cx.typeck_results().node_type(id);
+            if ty.has_significant_drop(self.cx.tcx, self.cx.param_env) {
+                self.locals.push(ident.span);
+            }
+            if let Some(pat) = pat {
+                self.visit_pat(pat);
+            }
+        } else {
+            intravisit::walk_pat(self, pat);
+        }
+    }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LintVisitor<'tcx, 'a> {
+    fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
+        let mut locals = <_>::default();
+        swap(&mut locals, &mut self.locals);
+        self.check_block_inner(block);
+        swap(&mut locals, &mut self.locals);
+    }
+    fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
+        LocalCollector { cx: self.cx, locals: &mut self.locals }.visit_local(local);
+    }
+}
+
+impl<'tcx, 'a> LintVisitor<'tcx, 'a> {
+    fn check_block_inner(&mut self, block: &Block<'tcx>) {
+        if !block.span.at_least_rust_2024() {
+            // We only lint for Edition 2024 onwards
+            return;
+        }
+        let Some(tail_expr) = block.expr else { return };
+        for stmt in block.stmts {
+            match stmt.kind {
+                StmtKind::Let(let_stmt) => self.visit_local(let_stmt),
+                StmtKind::Item(_) => {}
+                StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
+            }
+        }
+        if self.locals.is_empty() {
+            return;
+        }
+        LintTailExpr { cx: self.cx, locals: &self.locals, is_root_tail_expr: true }
+            .visit_expr(tail_expr);
+    }
+}
+
+struct LintTailExpr<'tcx, 'a> {
+    cx: &'a LateContext<'tcx>,
+    is_root_tail_expr: bool,
+    locals: &'a [Span],
+}
+
+impl<'tcx, 'a> LintTailExpr<'tcx, 'a> {
+    fn expr_eventually_point_into_local(mut expr: &Expr<'tcx>) -> bool {
+        loop {
+            match expr.kind {
+                ExprKind::Index(access, _, _) | ExprKind::Field(access, _) => expr = access,
+                ExprKind::AddrOf(_, _, referee) | ExprKind::Unary(UnOp::Deref, referee) => {
+                    expr = referee
+                }
+                ExprKind::Path(_)
+                    if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind
+                        && let [local, ..] = path.segments
+                        && let Res::Local(_) = local.res =>
+                {
+                    return true;
+                }
+                _ => return false,
+            }
+        }
+    }
+
+    fn expr_generates_nonlocal_droppy_value(&self, expr: &Expr<'tcx>) -> bool {
+        if Self::expr_eventually_point_into_local(expr) {
+            return false;
+        }
+        self.cx.typeck_results().expr_ty(expr).has_significant_drop(self.cx.tcx, self.cx.param_env)
+    }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for LintTailExpr<'tcx, 'a> {
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if self.is_root_tail_expr {
+            self.is_root_tail_expr = false;
+        } else if self.expr_generates_nonlocal_droppy_value(expr) {
+            self.cx.tcx.emit_node_span_lint(
+                TAIL_EXPR_DROP_ORDER,
+                expr.hir_id,
+                expr.span,
+                TailExprDropOrderLint { spans: self.locals.to_vec() },
+            );
+            return;
+        }
+        match expr.kind {
+            ExprKind::Match(scrutinee, _, _) => self.visit_expr(scrutinee),
+
+            ExprKind::ConstBlock(_)
+            | ExprKind::Array(_)
+            | ExprKind::Break(_, _)
+            | ExprKind::Continue(_)
+            | ExprKind::Ret(_)
+            | ExprKind::Become(_)
+            | ExprKind::Yield(_, _)
+            | ExprKind::InlineAsm(_)
+            | ExprKind::If(_, _, _)
+            | ExprKind::Loop(_, _, _, _)
+            | ExprKind::Closure(_)
+            | ExprKind::DropTemps(_)
+            | ExprKind::OffsetOf(_, _)
+            | ExprKind::Assign(_, _, _)
+            | ExprKind::AssignOp(_, _, _)
+            | ExprKind::Lit(_)
+            | ExprKind::Err(_) => {}
+
+            ExprKind::MethodCall(_, _, _, _)
+            | ExprKind::Call(_, _)
+            | ExprKind::Type(_, _)
+            | ExprKind::Tup(_)
+            | ExprKind::Binary(_, _, _)
+            | ExprKind::Unary(_, _)
+            | ExprKind::Path(_)
+            | ExprKind::Let(_)
+            | ExprKind::Cast(_, _)
+            | ExprKind::Field(_, _)
+            | ExprKind::Index(_, _, _)
+            | ExprKind::AddrOf(_, _, _)
+            | ExprKind::Struct(_, _, _)
+            | ExprKind::Repeat(_, _) => intravisit::walk_expr(self, expr),
+
+            ExprKind::Block(_, _) => {
+                // We do not lint further because the drop order stays the same inside the block
+            }
+        }
+    }
+    fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
+        LintVisitor { cx: self.cx, locals: <_>::default() }.check_block_inner(block);
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_tail_expr_drop_order)]
+struct TailExprDropOrderLint {
+    #[label]
+    pub spans: Vec<Span>,
+}
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index e0aef13ca79..72bb9db7e74 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -444,6 +444,7 @@ impl<'a> LintExtractor<'a> {
         let mut cmd = Command::new(self.rustc_path);
         if options.contains(&"edition2024") {
             cmd.arg("--edition=2024");
+            cmd.arg("-Zunstable-options");
         } else if options.contains(&"edition2021") {
             cmd.arg("--edition=2021");
         } else if options.contains(&"edition2018") {
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-gated.rs b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs
new file mode 100644
index 00000000000..b22e72bcfad
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order-gated.rs
@@ -0,0 +1,35 @@
+// This test ensures that `tail_expr_drop_order` does not activate in case Edition 2024 is not used
+// or the feature gate `shorter_tail_lifetimes` is disabled.
+
+//@ revisions: neither no_feature_gate edition_less_than_2024
+//@ check-pass
+//@ [neither] edition: 2021
+//@ [no_feature_gate] compile-flags: -Z unstable-options
+//@ [no_feature_gate] edition: 2024
+//@ [edition_less_than_2024] edition: 2021
+
+#![deny(tail_expr_drop_order)]
+#![cfg_attr(edition_less_than_2024, feature(shorter_tail_lifetimes))]
+
+struct LoudDropper;
+impl Drop for LoudDropper {
+    fn drop(&mut self) {
+        // This destructor should be considered significant because it is a custom destructor
+        // and we will assume that the destructor can generate side effects arbitrarily so that
+        // a change in drop order is visible.
+        println!("loud drop");
+    }
+}
+impl LoudDropper {
+    fn get(&self) -> i32 {
+        0
+    }
+}
+
+fn should_not_lint() -> i32 {
+    let x = LoudDropper;
+    x.get() + LoudDropper.get()
+    // Lint should not action
+}
+
+fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.rs b/tests/ui/drop/lint-tail-expr-drop-order.rs
new file mode 100644
index 00000000000..0aa0ef02610
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order.rs
@@ -0,0 +1,71 @@
+//@ compile-flags: -Z unstable-options
+//@ edition: 2024
+
+// Edition 2024 lint for change in drop order at tail expression
+// This lint is to capture potential change in program semantics
+// due to implementation of RFC 3606 <https://github.com/rust-lang/rfcs/pull/3606>
+
+#![deny(tail_expr_drop_order)]
+#![feature(shorter_tail_lifetimes)]
+
+struct LoudDropper;
+impl Drop for LoudDropper {
+    fn drop(&mut self) {
+        // This destructor should be considered significant because it is a custom destructor
+        // and we will assume that the destructor can generate side effects arbitrarily so that
+        // a change in drop order is visible.
+        println!("loud drop");
+    }
+}
+impl LoudDropper {
+    fn get(&self) -> i32 {
+        0
+    }
+}
+
+fn should_lint() -> i32 {
+    let x = LoudDropper;
+    // Should lint
+    x.get() + LoudDropper.get()
+    //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    //~| WARN: this changes meaning in Rust 2024
+}
+
+fn should_lint_closure() -> impl FnOnce() -> i32 {
+    let x = LoudDropper;
+    move || x.get() + LoudDropper.get()
+    //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+    //~| WARN: this changes meaning in Rust 2024
+}
+
+fn should_not_lint() -> i32 {
+    let x = LoudDropper;
+    // Should not lint
+    x.get()
+}
+
+fn should_not_lint_in_nested_block() -> i32 {
+    let x = LoudDropper;
+    // Should not lint because Edition 2021 drops temporaries in blocks earlier already
+    { LoudDropper.get() }
+}
+
+fn should_not_lint_in_match_arm() -> i32 {
+    let x = LoudDropper;
+    // Should not lint because Edition 2021 drops temporaries in blocks earlier already
+    match &x {
+        _ => LoudDropper.get(),
+    }
+}
+
+fn should_lint_in_nested_items() {
+    fn should_lint_me() -> i32 {
+        let x = LoudDropper;
+        // Should lint
+        x.get() + LoudDropper.get()
+        //~^ ERROR: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+        //~| WARN: this changes meaning in Rust 2024
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr
new file mode 100644
index 00000000000..630f0a80f09
--- /dev/null
+++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr
@@ -0,0 +1,42 @@
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:29:15
+   |
+LL |     let x = LoudDropper;
+   |         - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |     // Should lint
+LL |     x.get() + LoudDropper.get()
+   |               ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+note: the lint level is defined here
+  --> $DIR/lint-tail-expr-drop-order.rs:8:9
+   |
+LL | #![deny(tail_expr_drop_order)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:36:23
+   |
+LL |     let x = LoudDropper;
+   |         - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |     move || x.get() + LoudDropper.get()
+   |                       ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+
+error: these values and local bindings have significant drop implementation that will have a different drop order from that of Edition 2021
+  --> $DIR/lint-tail-expr-drop-order.rs:65:19
+   |
+LL |         let x = LoudDropper;
+   |             - these values have significant drop implementation and will observe changes in drop order under Edition 2024
+LL |         // Should lint
+LL |         x.get() + LoudDropper.get()
+   |                   ^^^^^^^^^^^
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see issue #123739 <https://github.com/rust-lang/rust/issues/123739>
+
+error: aborting due to 3 previous errors
+