about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--CONTRIBUTING.md1
-rw-r--r--compiler/rustc_resolve/src/ident.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs12
-rw-r--r--library/core/src/cell.rs2
-rwxr-xr-xsrc/ci/run.sh7
m---------src/doc/book0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/librustdoc/clean/types.rs18
-rw-r--r--src/librustdoc/formats/cache.rs4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/tools/rust-installer/src/compression.rs52
-rw-r--r--tests/codegen/vec-in-place.rs42
-rw-r--r--tests/ui/async-await/missed-capture-issue-107414.rs24
-rw-r--r--tests/ui/fn/fn-ptr-trait-int-float-infer-var.rs10
-rw-r--r--tests/ui/lint/use-redundant/issue-92904.rs17
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-glob-parent.rs16
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr17
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-glob.rs15
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-glob.stderr16
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs21
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-not-parent.rs19
-rw-r--r--tests/ui/lint/use-redundant/use-redundant.rs (renamed from tests/ui/lint/use-redundant.rs)0
-rw-r--r--tests/ui/lint/use-redundant/use-redundant.stderr (renamed from tests/ui/lint/use-redundant.stderr)0
-rw-r--r--triagebot.toml2
27 files changed, 251 insertions, 92 deletions
diff --git a/.mailmap b/.mailmap
index b8a9fc27eb7..92be3174750 100644
--- a/.mailmap
+++ b/.mailmap
@@ -102,6 +102,7 @@ Carol Willing <carolcode@willingconsulting.com>
 Chandler Deng <chandde@microsoft.com>
 Charles Lew <crlf0710@gmail.com> CrLF0710 <crlf0710@gmail.com>
 Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
+Chris Denton <chris@chrisdenton.dev> Chris Denton <ChrisDenton@users.noreply.github.com>
 Chris Gregory <czipperz@gmail.com>
 Chris Pardy <chrispardy36@gmail.com>
 Chris Pressey <cpressey@gmail.com>
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d732075fb2d..dfaa70bb9db 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,7 +33,6 @@ find a mentor! You can learn more about asking questions and getting help in the
 Did a compiler error message tell you to come here? If you want to create an ICE report,
 refer to [this section][contributing-bug-reports] and [open an issue][issue template].
 
-[Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust
 [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
 [std-dev-guide]: https://std-dev-guide.rust-lang.org/
 [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 06206efb9ab..7ff440e49aa 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -869,17 +869,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let resolution =
             self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
 
-        if let Some(Finalize { path_span, report_private, .. }) = finalize {
-            // If the primary binding is unusable, search further and return the shadowed glob
-            // binding if it exists. What we really want here is having two separate scopes in
-            // a module - one for non-globs and one for globs, but until that's done use this
-            // hack to avoid inconsistent resolution ICEs during import validation.
-            let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map(
-                |binding| match (binding, ignore_binding) {
+        // If the primary binding is unusable, search further and return the shadowed glob
+        // binding if it exists. What we really want here is having two separate scopes in
+        // a module - one for non-globs and one for globs, but until that's done use this
+        // hack to avoid inconsistent resolution ICEs during import validation.
+        let binding =
+            [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| {
+                match (binding, ignore_binding) {
                     (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
                     _ => binding,
-                },
-            );
+                }
+            });
+
+        if let Some(Finalize { path_span, report_private, .. }) = finalize {
             let Some(binding) = binding else {
                 return Err((Determined, Weak::No));
             };
@@ -927,15 +929,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
-            if let Some(ignored) = ignore_binding && ptr::eq(binding, ignored) {
-                return Err((Determined, Weak::No));
-            }
             let usable = this.is_accessible_from(binding.vis, parent_scope.module);
             if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
         };
 
         // Items and single imports are not shadowable, if we have one, then it's determined.
-        if let Some(binding) = resolution.binding {
+        if let Some(binding) = binding {
             if !binding.is_glob_import() {
                 return check_usable(self, binding);
             }
@@ -952,6 +951,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if !self.is_accessible_from(import_vis, parent_scope.module) {
                 continue;
             }
+            if let Some(ignored) = ignore_binding &&
+                let NameBindingKind::Import { import, .. } = ignored.kind &&
+                ptr::eq(import, &**single_import) {
+                // Ignore not just the binding itself, but if it has a shadowed_glob,
+                // ignore that, too, because this loop is supposed to only process
+                // named imports.
+                continue;
+            }
             let Some(module) = single_import.imported_module.get() else {
                 return Err((Undetermined, Weak::No));
             };
@@ -989,7 +996,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
         // shadowing is enabled, see `macro_expanded_macro_export_errors`).
         let unexpanded_macros = !module.unexpanded_invocations.borrow().is_empty();
-        if let Some(binding) = resolution.binding {
+        if let Some(binding) = binding {
             if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
                 return check_usable(self, binding);
             } else {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 47a351590b1..090312338e0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -998,8 +998,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Alias(..)
             | ty::Param(..)
             | ty::Bound(..)
-            | ty::Error(_) => {}
-            ty::Infer(_) => {
+            | ty::Error(_)
+            | ty::Infer(
+                ty::InferTy::IntVar(_)
+                | ty::InferTy::FloatVar(_)
+                | ty::InferTy::FreshIntTy(_)
+                | ty::InferTy::FreshFloatTy(_),
+            ) => {}
+            ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => {
                 candidates.ambiguous = true;
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3ed3dd2d20d..b58e62536d6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -177,14 +177,14 @@ struct TraitObligationStack<'prev, 'tcx> {
 }
 
 struct SelectionCandidateSet<'tcx> {
-    // A list of candidates that definitely apply to the current
-    // obligation (meaning: types unify).
+    /// A list of candidates that definitely apply to the current
+    /// obligation (meaning: types unify).
     vec: Vec<SelectionCandidate<'tcx>>,
 
-    // If `true`, then there were candidates that might or might
-    // not have applied, but we couldn't tell. This occurs when some
-    // of the input types are type variables, in which case there are
-    // various "builtin" rules that might or might not trigger.
+    /// If `true`, then there were candidates that might or might
+    /// not have applied, but we couldn't tell. This occurs when some
+    /// of the input types are type variables, in which case there are
+    /// various "builtin" rules that might or might not trigger.
     ambiguous: bool,
 }
 
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 63bce5d0ccd..d728dc03817 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1816,7 +1816,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 /// `UnsafeCell<T>` opts-out of the immutability guarantee for `&T`: a shared reference
 /// `&UnsafeCell<T>` may point to data that is being mutated. This is called "interior mutability".
 ///
-/// All other types that allow internal mutability, such as `Cell<T>` and `RefCell<T>`, internally
+/// All other types that allow internal mutability, such as [`Cell<T>`] and [`RefCell<T>`], internally
 /// use `UnsafeCell` to wrap their data.
 ///
 /// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 5f4e4a8e1b4..3056d9fc054 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -58,7 +58,12 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-native-static"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1"
-RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set dist.compression-profile=best"
+# rust-lang/promote-release will recompress CI artifacts, and while we care
+# about the per-commit artifact sizes, it's not as important that they're
+# highly compressed as it is that the process is fast. Best compression
+# generally implies single-threaded compression which results in wasting most
+# of our CPU resources.
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set dist.compression-profile=balanced"
 
 # When building for mingw, limit the number of parallel linker jobs during
 # the LLVM build, as not to run out of memory.
diff --git a/src/doc/book b/src/doc/book
-Subproject 21a2ed14f4480dab62438dcc1130291bebc6537
+Subproject 0510ca84c2ce6bf93c4ccf9248756e9e4fd00b1
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject cfbfd648ce33926c3490f24de9a5b56cce404b8
+Subproject ba84bf35d0f17d404003349309201654d25f61a
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject d08baa166b463537229eeb737c4ccadabd83cf7
+Subproject fca8af6c154c6cde2512f1331cf2704f214a818
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index ffa13ebb77c..a37d4f31643 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -452,10 +452,12 @@ impl Item {
     pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
         use crate::html::format::{href, link_tooltip};
 
-        cx.cache()
+        let Some(links) = cx.cache()
             .intra_doc_links
-            .get(&self.item_id)
-            .map_or(&[][..], |v| v.as_slice())
+            .get(&self.item_id) else {
+                return vec![]
+            };
+        links
             .iter()
             .filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| {
                 debug!(?id);
@@ -483,10 +485,12 @@ impl Item {
     /// the link text, but does need to know which `[]`-bracketed names
     /// are actually links.
     pub(crate) fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
-        cache
+        let Some(links) = cache
             .intra_doc_links
-            .get(&self.item_id)
-            .map_or(&[][..], |v| v.as_slice())
+            .get(&self.item_id) else {
+                return vec![];
+            };
+        links
             .iter()
             .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
                 original_text: s.clone(),
@@ -1006,7 +1010,7 @@ pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) struct ItemLink {
     /// The original link written in the markdown
     pub(crate) link: Box<str>,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 0295de8437e..c0329182032 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -1,6 +1,6 @@
 use std::mem;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Symbol;
@@ -118,7 +118,7 @@ pub(crate) struct Cache {
     /// All intra-doc links resolved so far.
     ///
     /// Links are indexed by the DefId of the item they document.
-    pub(crate) intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
+    pub(crate) intra_doc_links: FxHashMap<ItemId, FxIndexSet<clean::ItemLink>>,
     /// Cfg that have been hidden via #![doc(cfg_hide(...))]
     pub(crate) hidden_cfg: FxHashSet<clean::cfg::Cfg>,
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 1c6ab44a4c7..2cd9c8a8781 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -978,7 +978,7 @@ impl LinkCollector<'_, '_> {
             for md_link in preprocessed_markdown_links(&doc) {
                 let link = self.resolve_link(item, item_id, module_id, &doc, &md_link);
                 if let Some(link) = link {
-                    self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
+                    self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
                 }
             }
         }
diff --git a/src/tools/rust-installer/src/compression.rs b/src/tools/rust-installer/src/compression.rs
index 510c914163c..7c9c946e0b5 100644
--- a/src/tools/rust-installer/src/compression.rs
+++ b/src/tools/rust-installer/src/compression.rs
@@ -89,43 +89,11 @@ impl CompressionFormat {
                         xz2::stream::MtStreamBuilder::new().threads(6).preset(6).encoder().unwrap()
                     }
                     CompressionProfile::Best => {
-                        let mut filters = xz2::stream::Filters::new();
-                        // the preset is overridden by the other options so it doesn't matter
-                        let mut lzma_ops = xz2::stream::LzmaOptions::new_preset(9).unwrap();
-                        // This sets the overall dictionary size, which is also how much memory (baseline)
-                        // is needed for decompression.
-                        lzma_ops.dict_size(64 * 1024 * 1024);
-                        // Use the best match finder for compression ratio.
-                        lzma_ops.match_finder(xz2::stream::MatchFinder::BinaryTree4);
-                        lzma_ops.mode(xz2::stream::Mode::Normal);
-                        // Set nice len to the maximum for best compression ratio
-                        lzma_ops.nice_len(273);
-                        // Set depth to a reasonable value, 0 means auto, 1000 is somwhat high but gives
-                        // good results.
-                        lzma_ops.depth(1000);
-                        // 2 is the default and does well for most files
-                        lzma_ops.position_bits(2);
-                        // 0 is the default and does well for most files
-                        lzma_ops.literal_position_bits(0);
-                        // 3 is the default and does well for most files
-                        lzma_ops.literal_context_bits(3);
-
-                        filters.lzma2(&lzma_ops);
-
-                        let mut builder = xz2::stream::MtStreamBuilder::new();
-                        builder.filters(filters);
-
-                        // On 32-bit platforms limit ourselves to 3 threads, otherwise we exceed memory
-                        // usage this process can take. In the future we'll likely only do super-fast
-                        // compression in CI and move this heavyweight processing to promote-release (which
-                        // is always 64-bit and can run on big-memory machines) but for now this lets us
-                        // move forward.
-                        if std::mem::size_of::<usize>() == 4 {
-                            builder.threads(3);
-                        } else {
-                            builder.threads(6);
-                        }
-                        builder.encoder().unwrap()
+                        // Note that this isn't actually the best compression settings for the
+                        // produced artifacts, the production artifacts on static.rust-lang.org are
+                        // produced by rust-lang/promote-release which hosts recompression logic
+                        // and is tuned for optimal compression.
+                        xz2::stream::MtStreamBuilder::new().threads(6).preset(9).encoder().unwrap()
                     }
                 };
 
@@ -245,20 +213,14 @@ impl Write for CombinedEncoder {
     }
 
     fn flush(&mut self) -> std::io::Result<()> {
-        self.encoders
-            .par_iter_mut()
-            .map(|w| w.flush())
-            .collect::<std::io::Result<Vec<()>>>()?;
+        self.encoders.par_iter_mut().map(|w| w.flush()).collect::<std::io::Result<Vec<()>>>()?;
         Ok(())
     }
 }
 
 impl Encoder for CombinedEncoder {
     fn finish(self: Box<Self>) -> Result<(), Error> {
-        self.encoders
-            .into_par_iter()
-            .map(|e| e.finish())
-            .collect::<Result<Vec<()>, Error>>()?;
+        self.encoders.into_par_iter().map(|e| e.finish()).collect::<Result<Vec<()>, Error>>()?;
         Ok(())
     }
 }
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
index 9992604221b..d68067ceb19 100644
--- a/tests/codegen/vec-in-place.rs
+++ b/tests/codegen/vec-in-place.rs
@@ -1,11 +1,13 @@
 // ignore-debug: the debug assertions get in the way
 // compile-flags: -O -Z merge-functions=disabled
+// min-llvm-version: 16
 #![crate_type = "lib"]
 
 // Ensure that trivial casts of vec elements are O(1)
 
 pub struct Wrapper<T>(T);
 
+// previously repr(C) caused the optimization to fail
 #[repr(C)]
 pub struct Foo {
     a: u64,
@@ -14,9 +16,8 @@ pub struct Foo {
     d: u64,
 }
 
-// Going from an aggregate struct to another type currently requires Copy to
-// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
-// reliably recognize the loops as noop for repr(C) or non-Copy structs.
+// implementing Copy exercises the TrustedRandomAccess specialization inside the in-place
+// specialization
 #[derive(Copy, Clone)]
 pub struct Bar {
     a: u64,
@@ -25,6 +26,14 @@ pub struct Bar {
     d: u64,
 }
 
+// this exercises the try-fold codepath
+pub struct Baz {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+}
+
 // CHECK-LABEL: @vec_iterator_cast_primitive
 #[no_mangle]
 pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
@@ -52,18 +61,29 @@ pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
 // CHECK-LABEL: @vec_iterator_cast_aggregate
 #[no_mangle]
 pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
-    // FIXME These checks should be the same as other functions.
-    // CHECK-NOT: @__rust_alloc
-    // CHECK-NOT: @__rust_alloc
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
     vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
 }
 
-// CHECK-LABEL: @vec_iterator_cast_deaggregate
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_tra
 #[no_mangle]
-pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> {
-    // FIXME These checks should be the same as other functions.
-    // CHECK-NOT: @__rust_alloc
-    // CHECK-NOT: @__rust_alloc
+pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
+
+    // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+    // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+    // the UCG may add additional guarantees for homogenous types in the future that would make this
+    // correct.
+    vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_fold
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: call
 
     // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
     // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
diff --git a/tests/ui/async-await/missed-capture-issue-107414.rs b/tests/ui/async-await/missed-capture-issue-107414.rs
new file mode 100644
index 00000000000..0ab4f5ade98
--- /dev/null
+++ b/tests/ui/async-await/missed-capture-issue-107414.rs
@@ -0,0 +1,24 @@
+// check-pass
+// edition:2018
+
+fn main() {}
+
+struct StructA {}
+struct StructB {}
+
+impl StructA {
+    fn fn_taking_struct_b(&self, struct_b: &StructB) -> bool {
+        true
+    }
+}
+
+async fn get_struct_a_async() -> StructA {
+    StructA {}
+}
+
+async fn ice() {
+    match Some(StructB {}) {
+        Some(struct_b) if get_struct_a_async().await.fn_taking_struct_b(&struct_b) => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/fn/fn-ptr-trait-int-float-infer-var.rs b/tests/ui/fn/fn-ptr-trait-int-float-infer-var.rs
new file mode 100644
index 00000000000..eec7da044c0
--- /dev/null
+++ b/tests/ui/fn/fn-ptr-trait-int-float-infer-var.rs
@@ -0,0 +1,10 @@
+// check-pass
+trait MyCmp {
+    fn cmp(&self) {}
+}
+impl MyCmp for f32 {}
+
+fn main() {
+    // Ensure that `impl<F: FnPtr> Ord for F` is never considered for int and float infer vars.
+    0.0.cmp();
+}
diff --git a/tests/ui/lint/use-redundant/issue-92904.rs b/tests/ui/lint/use-redundant/issue-92904.rs
new file mode 100644
index 00000000000..511d9d263cf
--- /dev/null
+++ b/tests/ui/lint/use-redundant/issue-92904.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+pub struct Foo(bar::Bar);
+
+pub mod bar {
+    pub struct Foo(pub Bar);
+    pub struct Bar(pub char);
+}
+
+pub fn warning() -> Foo {
+    use bar::*;
+    #[deny(unused_imports)]
+    use self::Foo; // no error
+    Foo(Bar('a'))
+}
+
+fn main() {}
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs
new file mode 100644
index 00000000000..6b1e018d2dc
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs
@@ -0,0 +1,16 @@
+// check-pass
+#![warn(unused_imports)]
+
+pub mod bar {
+    pub struct Foo(pub Bar);
+    pub struct Bar(pub char);
+}
+
+use bar::*;
+
+pub fn warning() -> Foo {
+    use bar::Foo; //~ WARNING imported redundantly
+    Foo(Bar('a'))
+}
+
+fn main() {}
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr
new file mode 100644
index 00000000000..2c3b3345270
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr
@@ -0,0 +1,17 @@
+warning: the item `Foo` is imported redundantly
+  --> $DIR/use-redundant-glob-parent.rs:12:9
+   |
+LL | use bar::*;
+   |     ------ the item `Foo` is already imported here
+...
+LL |     use bar::Foo;
+   |         ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/use-redundant-glob-parent.rs:2:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.rs b/tests/ui/lint/use-redundant/use-redundant-glob.rs
new file mode 100644
index 00000000000..bd9e51b6f59
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob.rs
@@ -0,0 +1,15 @@
+// check-pass
+#![warn(unused_imports)]
+
+pub mod bar {
+    pub struct Foo(pub Bar);
+    pub struct Bar(pub char);
+}
+
+pub fn warning() -> bar::Foo {
+    use bar::*;
+    use bar::Foo; //~ WARNING imported redundantly
+    Foo(Bar('a'))
+}
+
+fn main() {}
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.stderr b/tests/ui/lint/use-redundant/use-redundant-glob.stderr
new file mode 100644
index 00000000000..d3b406d82b6
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob.stderr
@@ -0,0 +1,16 @@
+warning: the item `Foo` is imported redundantly
+  --> $DIR/use-redundant-glob.rs:11:9
+   |
+LL |     use bar::*;
+   |         ------ the item `Foo` is already imported here
+LL |     use bar::Foo;
+   |         ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/use-redundant-glob.rs:2:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs b/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs
new file mode 100644
index 00000000000..0fb60840f8a
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-multiple-namespaces.rs
@@ -0,0 +1,21 @@
+// check-pass
+#![allow(nonstandard_style)]
+
+pub mod bar {
+    pub struct Foo { pub bar: Bar }
+    pub struct Bar(pub char);
+}
+
+pub mod x {
+    use crate::bar;
+    pub const Foo: bar::Bar = bar::Bar('a');
+}
+
+pub fn warning() -> bar::Foo {
+    #![deny(unused_imports)] // no error
+    use bar::*;
+    use x::Foo;
+    Foo { bar: Foo }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/use-redundant/use-redundant-not-parent.rs b/tests/ui/lint/use-redundant/use-redundant-not-parent.rs
new file mode 100644
index 00000000000..c97a3d34163
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-not-parent.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+pub mod bar {
+    pub struct Foo(pub Bar);
+    pub struct Bar(pub char);
+}
+
+pub mod x {
+    pub struct Foo(pub crate::bar::Bar);
+}
+
+pub fn warning() -> x::Foo {
+    use bar::*;
+    #[deny(unused_imports)]
+    use x::Foo; // no error
+    Foo(Bar('a'))
+}
+
+fn main() {}
diff --git a/tests/ui/lint/use-redundant.rs b/tests/ui/lint/use-redundant/use-redundant.rs
index 53315dcf638..53315dcf638 100644
--- a/tests/ui/lint/use-redundant.rs
+++ b/tests/ui/lint/use-redundant/use-redundant.rs
diff --git a/tests/ui/lint/use-redundant.stderr b/tests/ui/lint/use-redundant/use-redundant.stderr
index c861a1956e1..c861a1956e1 100644
--- a/tests/ui/lint/use-redundant.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant.stderr
diff --git a/triagebot.toml b/triagebot.toml
index c86c1613fa9..20a8be283b9 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -482,7 +482,7 @@ message = "This PR changes src/bootstrap/defaults/config.codegen.toml. If approp
 
 [assign]
 warn_non_default_branch = true
-contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html"
+contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 
 [assign.adhoc_groups]
 compiler-team = [