diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index e01e80939ca..80f20fddf55 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1871,6 +1871,22 @@ pub fn add_elided_lifetime_in_path_suggestion(
     });
 }
 
+pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
+    db: &mut DiagnosticBuilder<'a, G>,
+    ambiguity: rustc_lint_defs::AmbiguityErrorDiag,
+) {
+    db.span_label(ambiguity.label_span, ambiguity.label_msg);
+    db.note(ambiguity.note_msg);
+    db.span_note(ambiguity.b1_span, ambiguity.b1_note_msg);
+    for help_msg in ambiguity.b1_help_msgs {
+        db.help(help_msg);
+    }
+    db.span_note(ambiguity.b2_span, ambiguity.b2_note_msg);
+    for help_msg in ambiguity.b2_help_msgs {
+        db.help(help_msg);
+    }
+}
+
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum TerminalUrl {
     No,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 65c56bff841..f7e56b30553 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -946,6 +946,9 @@ pub trait LintContext: Sized {
                         Applicability::MachineApplicable,
                     );
                 }
+                BuiltinLintDiagnostics::AmbiguousGlobImports { diag } => {
+                    rustc_errors::report_ambiguity_error(db, diag);
+                }
                 BuiltinLintDiagnostics::AmbiguousGlobReexports { name, namespace, first_reexport_span, duplicate_reexport_span } => {
                     db.span_label(first_reexport_span, format!("the name `{name}` in the {namespace} namespace is first re-exported here"));
                     db.span_label(duplicate_reexport_span, format!("but the name `{name}` in the {namespace} namespace is also re-exported here"));
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f1765d653b0..7e3b6e9e218 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3316,6 +3316,7 @@ declare_lint_pass! {
         // tidy-alphabetical-start
         ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
         AMBIGUOUS_ASSOCIATED_ITEMS,
+        AMBIGUOUS_GLOB_IMPORTS,
         AMBIGUOUS_GLOB_REEXPORTS,
         ARITHMETIC_OVERFLOW,
         ASM_SUB_REGISTER,
@@ -4405,3 +4406,46 @@ declare_lint! {
     Warn,
     "unrecognized diagnostic attribute"
 }
+
+declare_lint! {
+    /// The `ambiguous_glob_imports` lint detects glob imports that should report ambiguity
+    /// errors, but previously didn't do that due to rustc bugs.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    ///
+    /// #![deny(ambiguous_glob_imports)]
+    /// pub fn foo() -> u32 {
+    ///     use sub::*;
+    ///     C
+    /// }
+    ///
+    /// mod sub {
+    ///     mod mod1 { pub const C: u32 = 1; }
+    ///     mod mod2 { pub const C: u32 = 2; }
+    ///
+    ///     pub use mod1::*;
+    ///     pub use mod2::*;
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Previous versions of Rust compile it successfully because it
+    /// had lost the ambiguity error when resolve `use sub::mod2::*`.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a
+    /// hard error in the future.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub AMBIGUOUS_GLOB_IMPORTS,
+    Warn,
+    "detects certain glob imports that require reporting an ambiguity error",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseError,
+        reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 10ebe29dfce..f350957f72f 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -467,6 +467,21 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
     }
 }
 
+#[derive(Debug)]
+pub struct AmbiguityErrorDiag {
+    pub msg: String,
+    pub span: Span,
+    pub label_span: Span,
+    pub label_msg: String,
+    pub note_msg: String,
+    pub b1_span: Span,
+    pub b1_note_msg: String,
+    pub b1_help_msgs: Vec<String>,
+    pub b2_span: Span,
+    pub b2_note_msg: String,
+    pub b2_help_msgs: Vec<String>,
+}
+
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
@@ -530,6 +545,9 @@ pub enum BuiltinLintDiagnostics {
         vis_span: Span,
         ident_span: Span,
     },
+    AmbiguousGlobImports {
+        diag: AmbiguityErrorDiag,
+    },
     AmbiguousGlobReexports {
         /// The name for which collision(s) have occurred.
         name: String,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ff63e4e33cb..5814e3d6c13 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -41,6 +41,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a>
         arenas.alloc_name_binding(NameBindingData {
             kind: NameBindingKind::Module(self.0),
             ambiguity: None,
+            warn_ambiguity: false,
             vis: self.1.to_def_id(),
             span: self.2,
             expansion: self.3,
@@ -53,6 +54,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span,
         arenas.alloc_name_binding(NameBindingData {
             kind: NameBindingKind::Res(self.0),
             ambiguity: None,
+            warn_ambiguity: false,
             vis: self.1.to_def_id(),
             span: self.2,
             expansion: self.3,
@@ -69,7 +71,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     {
         let binding = def.to_name_binding(self.arenas);
         let key = self.new_disambiguated_key(ident, ns);
-        if let Err(old_binding) = self.try_define(parent, key, binding) {
+        if let Err(old_binding) = self.try_define(parent, key, binding, false) {
             self.report_conflict(parent, ident, ns, old_binding, binding);
         }
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 73cd596c076..97ac6891d82 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -5,10 +5,8 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
 use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{
-    pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
-};
-use rustc_errors::{struct_span_err, SuggestionStyle};
+use rustc_errors::{pluralize, report_ambiguity_error, struct_span_err, SuggestionStyle};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
@@ -17,8 +15,9 @@ use rustc_hir::PrimTy;
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
+use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS;
 use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiagnostics};
 use rustc_session::Session;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
@@ -135,7 +134,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         for ambiguity_error in &self.ambiguity_errors {
-            self.report_ambiguity_error(ambiguity_error);
+            let diag = self.ambiguity_diagnostics(ambiguity_error);
+            if ambiguity_error.warning {
+                let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
+                    unreachable!()
+                };
+                self.lint_buffer.buffer_lint_with_diagnostic(
+                    AMBIGUOUS_GLOB_IMPORTS,
+                    import.root_id,
+                    ambiguity_error.ident.span,
+                    diag.msg.to_string(),
+                    BuiltinLintDiagnostics::AmbiguousGlobImports { diag },
+                );
+            } else {
+                let mut err = struct_span_err!(self.tcx.sess, diag.span, E0659, "{}", &diag.msg);
+                report_ambiguity_error(&mut err, diag);
+                err.emit();
+            }
         }
 
         let mut reported_spans = FxHashSet::default();
@@ -1540,20 +1555,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
-        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
+    fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'_>) -> AmbiguityErrorDiag {
+        let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error;
         let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
             // We have to print the span-less alternative first, otherwise formatting looks bad.
             (b2, b1, misc2, misc1, true)
         } else {
             (b1, b2, misc1, misc2, false)
         };
-
-        let mut err = struct_span_err!(self.tcx.sess, ident.span, E0659, "`{ident}` is ambiguous");
-        err.span_label(ident.span, "ambiguous name");
-        err.note(format!("ambiguous because of {}", kind.descr()));
-
-        let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
+        let could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
             let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
             let note_msg = format!("`{ident}` could{also} refer to {what}");
 
@@ -1579,16 +1589,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 AmbiguityErrorMisc::FromPrelude | AmbiguityErrorMisc::None => {}
             }
 
-            err.span_note(b.span, note_msg);
-            for (i, help_msg) in help_msgs.iter().enumerate() {
-                let or = if i == 0 { "" } else { "or " };
-                err.help(format!("{}{}", or, help_msg));
-            }
+            (
+                b.span,
+                note_msg,
+                help_msgs
+                    .iter()
+                    .enumerate()
+                    .map(|(i, help_msg)| {
+                        let or = if i == 0 { "" } else { "or " };
+                        format!("{}{}", or, help_msg)
+                    })
+                    .collect::<Vec<_>>(),
+            )
         };
+        let (b1_span, b1_note_msg, b1_help_msgs) = could_refer_to(b1, misc1, "");
+        let (b2_span, b2_note_msg, b2_help_msgs) = could_refer_to(b2, misc2, " also");
 
-        could_refer_to(b1, misc1, "");
-        could_refer_to(b2, misc2, " also");
-        err.emit();
+        AmbiguityErrorDiag {
+            msg: format!("`{ident}` is ambiguous"),
+            span: ident.span,
+            label_span: ident.span,
+            label_msg: "ambiguous name".to_string(),
+            note_msg: format!("ambiguous because of {}", kind.descr()),
+            b1_span,
+            b1_note_msg,
+            b1_help_msgs,
+            b2_span,
+            b2_note_msg,
+            b2_help_msgs,
+        }
     }
 
     /// If the binding refers to a tuple struct constructor with fields,
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index de431444769..00282df700b 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -677,6 +677,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                         ident: orig_ident,
                                         b1: innermost_binding,
                                         b2: binding,
+                                        warning: false,
                                         misc1: misc(innermost_flags),
                                         misc2: misc(flags),
                                     });
@@ -905,6 +906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     ident,
                     b1: binding,
                     b2: shadowed_glob,
+                    warning: false,
                     misc1: AmbiguityErrorMisc::None,
                     misc2: AmbiguityErrorMisc::None,
                 });
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f3cf61c5b93..e1dae57d34f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -284,6 +284,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.arenas.alloc_name_binding(NameBindingData {
             kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
             ambiguity: None,
+            warn_ambiguity: false,
             span: import.span,
             vis,
             expansion: import.parent_scope.expansion,
@@ -291,16 +292,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     /// Define the name or return the existing binding if there is a collision.
+    /// `update` indicates if the definition is a redefinition of an existing binding.
     pub(crate) fn try_define(
         &mut self,
         module: Module<'a>,
         key: BindingKey,
         binding: NameBinding<'a>,
+        warn_ambiguity: bool,
     ) -> Result<(), NameBinding<'a>> {
         let res = binding.res();
         self.check_reserved_macro_name(key.ident, res);
         self.set_binding_parent_module(binding, module);
-        self.update_resolution(module, key, |this, resolution| {
+        self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
                 if res == Res::Err && old_binding.res() != Res::Err {
                     // Do not override real bindings with `Res::Err`s from error recovery.
@@ -308,15 +311,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
                 match (old_binding.is_glob_import(), binding.is_glob_import()) {
                     (true, true) => {
-                        if res != old_binding.res() {
-                            resolution.binding = Some(this.ambiguity(
-                                AmbiguityKind::GlobVsGlob,
-                                old_binding,
-                                binding,
-                            ));
+                        // FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity.
+                        if !binding.is_ambiguity()
+                            && let NameBindingKind::Import { import: old_import, .. } = old_binding.kind
+                            && let NameBindingKind::Import { import, .. } = binding.kind
+                            && old_import == import {
+                            // We should replace the `old_binding` with `binding` regardless
+                            // of whether they has same resolution or not when they are
+                            // imported from the same glob-import statement.
+                            // However we currently using `Some(old_binding)` for back compact
+                            // purposes.
+                            // This case can be removed after once `Undetermined` is prepared
+                            // for glob-imports.
+                        } else if res != old_binding.res() {
+                            let binding = if warn_ambiguity {
+                                this.warn_ambiguity(
+                                    AmbiguityKind::GlobVsGlob,
+                                    old_binding,
+                                    binding,
+                                )
+                            } else {
+                                this.ambiguity(
+                                    AmbiguityKind::GlobVsGlob,
+                                    old_binding,
+                                    binding,
+                                )
+                            };
+                            resolution.binding = Some(binding);
                         } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
                             // We are glob-importing the same item but with greater visibility.
                             resolution.binding = Some(binding);
+                        } else if binding.is_ambiguity() {
+                            resolution.binding =
+                                Some(self.arenas.alloc_name_binding(NameBindingData {
+                                    warn_ambiguity: true,
+                                    ..(*binding).clone()
+                                }));
                         }
                     }
                     (old_glob @ true, false) | (old_glob @ false, true) => {
@@ -374,29 +404,52 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         })
     }
 
+    fn warn_ambiguity(
+        &self,
+        kind: AmbiguityKind,
+        primary_binding: NameBinding<'a>,
+        secondary_binding: NameBinding<'a>,
+    ) -> NameBinding<'a> {
+        self.arenas.alloc_name_binding(NameBindingData {
+            ambiguity: Some((secondary_binding, kind)),
+            warn_ambiguity: true,
+            ..(*primary_binding).clone()
+        })
+    }
+
     // Use `f` to mutate the resolution of the name in the module.
     // If the resolution becomes a success, define it in the module's glob importers.
-    fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F) -> T
+    fn update_resolution<T, F>(
+        &mut self,
+        module: Module<'a>,
+        key: BindingKey,
+        warn_ambiguity: bool,
+        f: F,
+    ) -> T
     where
         F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T,
     {
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
         // during which the resolution might end up getting re-defined via a glob cycle.
-        let (binding, t) = {
+        let (binding, t, warn_ambiguity) = {
             let resolution = &mut *self.resolution(module, key).borrow_mut();
             let old_binding = resolution.binding();
 
             let t = f(self, resolution);
 
-            if old_binding.is_none() && let Some(binding) = resolution.binding() {
-                (binding, t)
+            if let Some(binding) = resolution.binding() && old_binding != Some(binding) {
+                (binding, t, warn_ambiguity || old_binding.is_some())
             } else {
                 return t;
             }
         };
 
-        // Define `binding` in `module`s glob importers.
-        for import in module.glob_importers.borrow_mut().iter() {
+        let Ok(glob_importers) = module.glob_importers.try_borrow_mut() else {
+            return t;
+        };
+
+        // Define or update `binding` in `module`s glob importers.
+        for import in glob_importers.iter() {
             let mut ident = key.ident;
             let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
                 Some(Some(def)) => self.expn_def_scope(def),
@@ -406,7 +459,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if self.is_accessible_from(binding.vis, scope) {
                 let imported_binding = self.import(binding, *import);
                 let key = BindingKey { ident, ..key };
-                let _ = self.try_define(import.parent_scope.module, key, imported_binding);
+                let _ = self.try_define(
+                    import.parent_scope.module,
+                    key,
+                    imported_binding,
+                    warn_ambiguity,
+                );
             }
         }
 
@@ -425,7 +483,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
                 let key = BindingKey::new(target, ns);
-                let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
+                let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
             });
             self.record_use(target, dummy_binding, false);
         } else if import.imported_module.get().is_none() {
@@ -700,7 +758,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Segment::names_to_string(&import.module_path),
             module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),
         );
-
         let module = if let Some(module) = import.imported_module.get() {
             module
         } else {
@@ -773,7 +830,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 .emit();
                         }
                         let key = BindingKey::new(target, ns);
-                        this.update_resolution(parent, key, |_, resolution| {
+                        this.update_resolution(parent, key, false, |_, resolution| {
                             resolution.single_imports.remove(&import);
                         });
                     }
@@ -989,7 +1046,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             initial_binding.res()
                         });
                         let res = binding.res();
-                        if res == Res::Err || !this.ambiguity_errors.is_empty() {
+                        let has_ambiguity_error = this
+                            .ambiguity_errors
+                            .iter()
+                            .filter(|error| !error.warning)
+                            .next()
+                            .is_some();
+                        if res == Res::Err || has_ambiguity_error {
                             this.tcx
                                 .sess
                                 .delay_span_bug(import.span, "some error happened for an import");
@@ -1338,7 +1401,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             };
             if self.is_accessible_from(binding.vis, scope) {
                 let imported_binding = self.import(binding, import);
-                let _ = self.try_define(import.parent_scope.module, key, imported_binding);
+                let warn_ambiguity = self
+                    .resolution(import.parent_scope.module, key)
+                    .borrow()
+                    .binding()
+                    .is_some_and(|binding| binding.is_warn_ambiguity());
+                let _ = self.try_define(
+                    import.parent_scope.module,
+                    key,
+                    imported_binding,
+                    warn_ambiguity,
+                );
             }
         }
 
@@ -1357,7 +1430,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             module.for_each_child(self, |this, ident, _, binding| {
                 let res = binding.res().expect_non_local();
-                if res != def::Res::Err && !binding.is_ambiguity() {
+                let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity;
+                if res != def::Res::Err && !error_ambiguity {
                     let mut reexport_chain = SmallVec::new();
                     let mut next_binding = binding;
                     while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index faa672db59c..91d89f44dbf 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -658,6 +658,7 @@ impl<'a> fmt::Debug for Module<'a> {
 struct NameBindingData<'a> {
     kind: NameBindingKind<'a>,
     ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>,
+    warn_ambiguity: bool,
     expansion: LocalExpnId,
     span: Span,
     vis: ty::Visibility<DefId>,
@@ -767,6 +768,7 @@ struct AmbiguityError<'a> {
     b2: NameBinding<'a>,
     misc1: AmbiguityErrorMisc,
     misc2: AmbiguityErrorMisc,
+    warning: bool,
 }
 
 impl<'a> NameBindingData<'a> {
@@ -794,6 +796,14 @@ impl<'a> NameBindingData<'a> {
             }
     }
 
+    fn is_warn_ambiguity(&self) -> bool {
+        self.warn_ambiguity
+            || match self.kind {
+                NameBindingKind::Import { binding, .. } => binding.is_warn_ambiguity(),
+                _ => false,
+            }
+    }
+
     fn is_possibly_imported_variant(&self) -> bool {
         match self.kind {
             NameBindingKind::Import { binding, .. } => binding.is_possibly_imported_variant(),
@@ -1322,6 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             dummy_binding: arenas.alloc_name_binding(NameBindingData {
                 kind: NameBindingKind::Res(Res::Err),
                 ambiguity: None,
+                warn_ambiguity: false,
                 expansion: LocalExpnId::ROOT,
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
@@ -1685,6 +1696,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) {
+        self.record_use_inner(ident, used_binding, is_lexical_scope, used_binding.warn_ambiguity);
+    }
+
+    fn record_use_inner(
+        &mut self,
+        ident: Ident,
+        used_binding: NameBinding<'a>,
+        is_lexical_scope: bool,
+        warn_ambiguity: bool,
+    ) {
         if let Some((b2, kind)) = used_binding.ambiguity {
             let ambiguity_error = AmbiguityError {
                 kind,
@@ -1693,9 +1714,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 b2,
                 misc1: AmbiguityErrorMisc::None,
                 misc2: AmbiguityErrorMisc::None,
+                warning: warn_ambiguity,
             };
             if !self.matches_previous_ambiguity_error(&ambiguity_error) {
-                // avoid duplicated span information to be emitt out
+                // avoid duplicated span information to be emit out
                 self.ambiguity_errors.push(ambiguity_error);
             }
         }
@@ -1715,7 +1737,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 self.used_imports.insert(id);
             }
             self.add_to_glob_map(import, ident);
-            self.record_use(ident, binding, false);
+            self.record_use_inner(ident, binding, false, warn_ambiguity || binding.warn_ambiguity);
         }
     }
 
diff --git a/tests/ui/imports/ambiguous-1.rs b/tests/ui/imports/ambiguous-1.rs
new file mode 100644
index 00000000000..2c9815864f0
--- /dev/null
+++ b/tests/ui/imports/ambiguous-1.rs
@@ -0,0 +1,30 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/112743#issuecomment-1601986883
+
+macro_rules! m {
+    () => {
+      pub fn id() {}
+    };
+}
+
+mod openssl {
+    pub use self::evp::*;
+    //~^ WARNING ambiguous glob re-exports
+    pub use self::handwritten::*;
+
+    mod evp {
+      m!();
+    }
+
+    mod handwritten {
+      m!();
+    }
+}
+
+pub use openssl::*;
+
+fn main() {
+    id();
+    //~^ WARNING `id` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-1.stderr b/tests/ui/imports/ambiguous-1.stderr
new file mode 100644
index 00000000000..61b3077c354
--- /dev/null
+++ b/tests/ui/imports/ambiguous-1.stderr
@@ -0,0 +1,36 @@
+warning: ambiguous glob re-exports
+  --> $DIR/ambiguous-1.rs:11:13
+   |
+LL |     pub use self::evp::*;
+   |             ^^^^^^^^^^^^ the name `id` in the value namespace is first re-exported here
+LL |
+LL |     pub use self::handwritten::*;
+   |             -------------------- but the name `id` in the value namespace is also re-exported here
+   |
+   = note: `#[warn(ambiguous_glob_reexports)]` on by default
+
+warning: `id` is ambiguous
+  --> $DIR/ambiguous-1.rs:27:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-1.rs:11:13
+   |
+LL |     pub use self::evp::*;
+   |             ^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-1.rs:13:13
+   |
+LL |     pub use self::handwritten::*;
+   |             ^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/imports/ambiguous-10.rs b/tests/ui/imports/ambiguous-10.rs
new file mode 100644
index 00000000000..5078b734b47
--- /dev/null
+++ b/tests/ui/imports/ambiguous-10.rs
@@ -0,0 +1,19 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1637022296
+
+mod a {
+    pub enum Token {}
+}
+
+mod b {
+    use crate::a::*;
+    #[derive(Debug)]
+    pub enum Token {}
+}
+
+use crate::a::*;
+use crate::b::*;
+fn c(_: Token) {}
+//~^ WARNING `Token` is ambiguous
+//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+fn main() { }
diff --git a/tests/ui/imports/ambiguous-10.stderr b/tests/ui/imports/ambiguous-10.stderr
new file mode 100644
index 00000000000..704af616b43
--- /dev/null
+++ b/tests/ui/imports/ambiguous-10.stderr
@@ -0,0 +1,25 @@
+warning: `Token` is ambiguous
+  --> $DIR/ambiguous-10.rs:16:9
+   |
+LL | fn c(_: Token) {}
+   |         ^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Token` could refer to the enum imported here
+  --> $DIR/ambiguous-10.rs:14:5
+   |
+LL | use crate::a::*;
+   |     ^^^^^^^^^^^
+   = help: consider adding an explicit import of `Token` to disambiguate
+note: `Token` could also refer to the enum imported here
+  --> $DIR/ambiguous-10.rs:15:5
+   |
+LL | use crate::b::*;
+   |     ^^^^^^^^^^^
+   = help: consider adding an explicit import of `Token` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-11.rs b/tests/ui/imports/ambiguous-11.rs
new file mode 100644
index 00000000000..0565b9d22ac
--- /dev/null
+++ b/tests/ui/imports/ambiguous-11.rs
@@ -0,0 +1,14 @@
+// aux-build: ambiguous-11-extern.rs
+
+extern crate ambiguous_11_extern;
+
+mod s {
+  pub trait Error {}
+}
+
+use s::*;
+use ambiguous_11_extern::*;
+fn a<E: Error>(_: E) {}
+//~^ ERROR `Error` is ambiguous
+
+fn main() {}
diff --git a/tests/ui/imports/ambiguous-11.stderr b/tests/ui/imports/ambiguous-11.stderr
new file mode 100644
index 00000000000..765d6afa8d7
--- /dev/null
+++ b/tests/ui/imports/ambiguous-11.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `Error` is ambiguous
+  --> $DIR/ambiguous-11.rs:11:9
+   |
+LL | fn a<E: Error>(_: E) {}
+   |         ^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Error` could refer to the trait imported here
+  --> $DIR/ambiguous-11.rs:9:5
+   |
+LL | use s::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+note: `Error` could also refer to the enum imported here
+  --> $DIR/ambiguous-11.rs:10:5
+   |
+LL | use ambiguous_11_extern::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-12.rs b/tests/ui/imports/ambiguous-12.rs
new file mode 100644
index 00000000000..6259c13572c
--- /dev/null
+++ b/tests/ui/imports/ambiguous-12.rs
@@ -0,0 +1,25 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1637022296
+
+macro_rules! m {
+    () => {
+        pub fn b() {}
+    };
+}
+
+pub mod ciphertext {
+    m!();
+}
+pub mod public {
+    use crate::ciphertext::*;
+    m!();
+}
+
+use crate::ciphertext::*;
+use crate::public::*;
+
+fn main() {
+    b();
+    //~^ WARNING `b` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-12.stderr b/tests/ui/imports/ambiguous-12.stderr
new file mode 100644
index 00000000000..4725c38849c
--- /dev/null
+++ b/tests/ui/imports/ambiguous-12.stderr
@@ -0,0 +1,25 @@
+warning: `b` is ambiguous
+  --> $DIR/ambiguous-12.rs:22:5
+   |
+LL |     b();
+   |     ^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `b` could refer to the function imported here
+  --> $DIR/ambiguous-12.rs:18:5
+   |
+LL | use crate::ciphertext::*;
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `b` to disambiguate
+note: `b` could also refer to the function imported here
+  --> $DIR/ambiguous-12.rs:19:5
+   |
+LL | use crate::public::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `b` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-13.rs b/tests/ui/imports/ambiguous-13.rs
new file mode 100644
index 00000000000..82f933c49ac
--- /dev/null
+++ b/tests/ui/imports/ambiguous-13.rs
@@ -0,0 +1,22 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1637022296
+
+pub mod object {
+    #[derive(Debug)]
+    pub struct Rect;
+}
+
+pub mod content {
+  use crate::object::*;
+
+  #[derive(Debug)]
+  pub struct Rect;
+}
+
+use crate::object::*;
+use crate::content::*;
+
+fn a(_: Rect) {}
+//~^ WARNING `Rect` is ambiguous
+//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+fn main() { }
diff --git a/tests/ui/imports/ambiguous-13.stderr b/tests/ui/imports/ambiguous-13.stderr
new file mode 100644
index 00000000000..3e78100b658
--- /dev/null
+++ b/tests/ui/imports/ambiguous-13.stderr
@@ -0,0 +1,25 @@
+warning: `Rect` is ambiguous
+  --> $DIR/ambiguous-13.rs:19:9
+   |
+LL | fn a(_: Rect) {}
+   |         ^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Rect` could refer to the struct imported here
+  --> $DIR/ambiguous-13.rs:16:5
+   |
+LL | use crate::object::*;
+   |     ^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `Rect` to disambiguate
+note: `Rect` could also refer to the struct imported here
+  --> $DIR/ambiguous-13.rs:17:5
+   |
+LL | use crate::content::*;
+   |     ^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `Rect` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-14.rs b/tests/ui/imports/ambiguous-14.rs
new file mode 100644
index 00000000000..5e880b48c36
--- /dev/null
+++ b/tests/ui/imports/ambiguous-14.rs
@@ -0,0 +1,26 @@
+// check-pass
+// https://github.com/rust-lang/rust/issues/98467
+
+mod a {
+    pub fn foo() {}
+}
+
+mod b {
+    pub fn foo() {}
+}
+
+mod f {
+    pub use a::*;
+    pub use b::*;
+}
+
+mod g {
+    pub use a::*;
+    pub use f::*;
+}
+
+fn main() {
+    g::foo();
+    //~^ WARNING `foo` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-14.stderr b/tests/ui/imports/ambiguous-14.stderr
new file mode 100644
index 00000000000..bece5853668
--- /dev/null
+++ b/tests/ui/imports/ambiguous-14.stderr
@@ -0,0 +1,25 @@
+warning: `foo` is ambiguous
+  --> $DIR/ambiguous-14.rs:23:8
+   |
+LL |     g::foo();
+   |        ^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `foo` could refer to the function imported here
+  --> $DIR/ambiguous-14.rs:13:13
+   |
+LL |     pub use a::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the function imported here
+  --> $DIR/ambiguous-14.rs:14:13
+   |
+LL |     pub use b::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-15.rs b/tests/ui/imports/ambiguous-15.rs
new file mode 100644
index 00000000000..8c75c393a41
--- /dev/null
+++ b/tests/ui/imports/ambiguous-15.rs
@@ -0,0 +1,27 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1638206152
+
+mod t2 {
+    #[derive(Debug)]
+    pub enum Error {}
+
+    mod s {
+        pub use std::fmt::*;
+        pub trait Error: Sized {}
+    }
+
+    use self::s::*;
+}
+
+pub use t2::*;
+
+mod t3 {
+    pub trait Error {}
+}
+
+use self::t3::*;
+fn a<E: Error>(_: E) {}
+//~^ WARNING `Error` is ambiguous
+//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+fn main() {}
diff --git a/tests/ui/imports/ambiguous-15.stderr b/tests/ui/imports/ambiguous-15.stderr
new file mode 100644
index 00000000000..838256752d0
--- /dev/null
+++ b/tests/ui/imports/ambiguous-15.stderr
@@ -0,0 +1,25 @@
+warning: `Error` is ambiguous
+  --> $DIR/ambiguous-15.rs:23:9
+   |
+LL | fn a<E: Error>(_: E) {}
+   |         ^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Error` could refer to the trait imported here
+  --> $DIR/ambiguous-15.rs:22:5
+   |
+LL | use self::t3::*;
+   |     ^^^^^^^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+note: `Error` could also refer to the enum imported here
+  --> $DIR/ambiguous-15.rs:16:9
+   |
+LL | pub use t2::*;
+   |         ^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-16.rs b/tests/ui/imports/ambiguous-16.rs
new file mode 100644
index 00000000000..e51e30e3ed5
--- /dev/null
+++ b/tests/ui/imports/ambiguous-16.rs
@@ -0,0 +1,27 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099
+
+mod framing {
+    mod public_message {
+        use super::*;
+
+        #[derive(Debug)]
+        pub struct ConfirmedTranscriptHashInput;
+    }
+
+    mod public_message_in {
+        use super::*;
+
+        #[derive(Debug)]
+        pub struct ConfirmedTranscriptHashInput;
+    }
+
+    pub use self::public_message::*;
+    pub use self::public_message_in::*;
+}
+
+use crate::framing::ConfirmedTranscriptHashInput;
+//~^ WARNING `ConfirmedTranscriptHashInput` is ambiguous
+//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+fn main() { }
diff --git a/tests/ui/imports/ambiguous-16.stderr b/tests/ui/imports/ambiguous-16.stderr
new file mode 100644
index 00000000000..7366cabc47a
--- /dev/null
+++ b/tests/ui/imports/ambiguous-16.stderr
@@ -0,0 +1,25 @@
+warning: `ConfirmedTranscriptHashInput` is ambiguous
+  --> $DIR/ambiguous-16.rs:23:21
+   |
+LL | use crate::framing::ConfirmedTranscriptHashInput;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `ConfirmedTranscriptHashInput` could refer to the struct imported here
+  --> $DIR/ambiguous-16.rs:19:13
+   |
+LL |     pub use self::public_message::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `ConfirmedTranscriptHashInput` to disambiguate
+note: `ConfirmedTranscriptHashInput` could also refer to the struct imported here
+  --> $DIR/ambiguous-16.rs:20:13
+   |
+LL |     pub use self::public_message_in::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `ConfirmedTranscriptHashInput` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-17.rs b/tests/ui/imports/ambiguous-17.rs
new file mode 100644
index 00000000000..7d01404ce07
--- /dev/null
+++ b/tests/ui/imports/ambiguous-17.rs
@@ -0,0 +1,29 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1638206152
+
+pub use evp::*; //~ WARNING ambiguous glob re-exports
+pub use handwritten::*;
+
+macro_rules! m {
+    () => {
+        pub fn id() {}
+    };
+}
+mod evp {
+    use *;
+    m!();
+}
+
+mod handwritten {
+    pub use handwritten::evp::*;
+    mod evp {
+        use *;
+        m!();
+    }
+}
+
+fn main() {
+    id();
+    //~^ WARNING `id` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-17.stderr b/tests/ui/imports/ambiguous-17.stderr
new file mode 100644
index 00000000000..55bc01095c7
--- /dev/null
+++ b/tests/ui/imports/ambiguous-17.stderr
@@ -0,0 +1,35 @@
+warning: ambiguous glob re-exports
+  --> $DIR/ambiguous-17.rs:4:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^ the name `id` in the value namespace is first re-exported here
+LL | pub use handwritten::*;
+   |         -------------- but the name `id` in the value namespace is also re-exported here
+   |
+   = note: `#[warn(ambiguous_glob_reexports)]` on by default
+
+warning: `id` is ambiguous
+  --> $DIR/ambiguous-17.rs:26:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-17.rs:4:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-17.rs:5:9
+   |
+LL | pub use handwritten::*;
+   |         ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/imports/ambiguous-2.rs b/tests/ui/imports/ambiguous-2.rs
new file mode 100644
index 00000000000..7b38f3006b1
--- /dev/null
+++ b/tests/ui/imports/ambiguous-2.rs
@@ -0,0 +1,9 @@
+// check-pass
+// aux-build: ../ambiguous-1.rs
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1633574396
+
+extern crate ambiguous_1;
+
+fn main() {
+    ambiguous_1::id();
+}
diff --git a/tests/ui/imports/ambiguous-3.rs b/tests/ui/imports/ambiguous-3.rs
new file mode 100644
index 00000000000..61a5b6b83fb
--- /dev/null
+++ b/tests/ui/imports/ambiguous-3.rs
@@ -0,0 +1,21 @@
+// check-pass
+// https://github.com/rust-lang/rust/issues/47525
+
+fn main() {
+    use a::*;
+    x();
+    //~^ WARNING `x` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+mod a {
+    mod b {
+        pub fn x() { println!(module_path!()); }
+    }
+    mod c {
+        pub fn x() { println!(module_path!()); }
+    }
+
+    pub use self::b::*;
+    pub use self::c::*;
+}
diff --git a/tests/ui/imports/ambiguous-3.stderr b/tests/ui/imports/ambiguous-3.stderr
new file mode 100644
index 00000000000..f019f6d8957
--- /dev/null
+++ b/tests/ui/imports/ambiguous-3.stderr
@@ -0,0 +1,25 @@
+warning: `x` is ambiguous
+  --> $DIR/ambiguous-3.rs:6:5
+   |
+LL |     x();
+   |     ^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `x` could refer to the function imported here
+  --> $DIR/ambiguous-3.rs:19:13
+   |
+LL |     pub use self::b::*;
+   |             ^^^^^^^^^^
+   = help: consider adding an explicit import of `x` to disambiguate
+note: `x` could also refer to the function imported here
+  --> $DIR/ambiguous-3.rs:20:13
+   |
+LL |     pub use self::c::*;
+   |             ^^^^^^^^^^
+   = help: consider adding an explicit import of `x` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-4-extern.rs b/tests/ui/imports/ambiguous-4-extern.rs
new file mode 100644
index 00000000000..02546768e0e
--- /dev/null
+++ b/tests/ui/imports/ambiguous-4-extern.rs
@@ -0,0 +1,26 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/112743#issuecomment-1601986883
+
+macro_rules! m {
+    () => {
+      pub fn id() {}
+    };
+}
+
+pub use evp::*; //~ WARNING ambiguous glob re-exports
+pub use handwritten::*;
+
+mod evp {
+    use *;
+    m! {}
+}
+mod handwritten {
+    use *;
+    m! {}
+}
+
+fn main() {
+    id();
+    //~^ WARNING `id` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-4-extern.stderr b/tests/ui/imports/ambiguous-4-extern.stderr
new file mode 100644
index 00000000000..0011973212b
--- /dev/null
+++ b/tests/ui/imports/ambiguous-4-extern.stderr
@@ -0,0 +1,35 @@
+warning: ambiguous glob re-exports
+  --> $DIR/ambiguous-4-extern.rs:10:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^ the name `id` in the value namespace is first re-exported here
+LL | pub use handwritten::*;
+   |         -------------- but the name `id` in the value namespace is also re-exported here
+   |
+   = note: `#[warn(ambiguous_glob_reexports)]` on by default
+
+warning: `id` is ambiguous
+  --> $DIR/ambiguous-4-extern.rs:23:5
+   |
+LL |     id();
+   |     ^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `id` could refer to the function imported here
+  --> $DIR/ambiguous-4-extern.rs:10:9
+   |
+LL | pub use evp::*;
+   |         ^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+note: `id` could also refer to the function imported here
+  --> $DIR/ambiguous-4-extern.rs:11:9
+   |
+LL | pub use handwritten::*;
+   |         ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `id` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/imports/ambiguous-4.rs b/tests/ui/imports/ambiguous-4.rs
new file mode 100644
index 00000000000..10f883339c3
--- /dev/null
+++ b/tests/ui/imports/ambiguous-4.rs
@@ -0,0 +1,9 @@
+// check-pass
+// aux-build: ../ambiguous-4-extern.rs
+
+extern crate ambiguous_4_extern;
+
+fn main() {
+    ambiguous_4_extern::id();
+    // `warning_ambiguous` had been lost at metadata.
+}
diff --git a/tests/ui/imports/ambiguous-5.rs b/tests/ui/imports/ambiguous-5.rs
new file mode 100644
index 00000000000..56092246ab3
--- /dev/null
+++ b/tests/ui/imports/ambiguous-5.rs
@@ -0,0 +1,24 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1637022296
+
+mod a {
+    pub struct Class(u16);
+}
+
+use a::Class;
+
+mod gpos {
+    use super::gsubgpos::*;
+    use super::*;
+    struct MarkRecord(Class);
+    //~^ WARNING `Class` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+mod gsubgpos {
+    use super::*;
+    #[derive(Clone)]
+    pub struct Class;
+}
+
+fn main() { }
diff --git a/tests/ui/imports/ambiguous-5.stderr b/tests/ui/imports/ambiguous-5.stderr
new file mode 100644
index 00000000000..4bc35f86d3a
--- /dev/null
+++ b/tests/ui/imports/ambiguous-5.stderr
@@ -0,0 +1,25 @@
+warning: `Class` is ambiguous
+  --> $DIR/ambiguous-5.rs:13:23
+   |
+LL |     struct MarkRecord(Class);
+   |                       ^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Class` could refer to the struct imported here
+  --> $DIR/ambiguous-5.rs:12:9
+   |
+LL |     use super::*;
+   |         ^^^^^^^^
+   = help: consider adding an explicit import of `Class` to disambiguate
+note: `Class` could also refer to the struct imported here
+  --> $DIR/ambiguous-5.rs:11:9
+   |
+LL |     use super::gsubgpos::*;
+   |         ^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `Class` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-6.rs b/tests/ui/imports/ambiguous-6.rs
new file mode 100644
index 00000000000..ba2623bf48a
--- /dev/null
+++ b/tests/ui/imports/ambiguous-6.rs
@@ -0,0 +1,20 @@
+// check-pass
+// edition: 2021
+// https://github.com/rust-lang/rust/issues/112713
+
+pub fn foo() -> u32 {
+    use sub::*;
+    C
+    //~^ WARNING `C` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+mod sub {
+    mod mod1 { pub const C: u32 = 1; }
+    mod mod2 { pub const C: u32 = 2; }
+
+    pub use mod1::*;
+    pub use mod2::*;
+}
+
+fn main() {}
diff --git a/tests/ui/imports/ambiguous-6.stderr b/tests/ui/imports/ambiguous-6.stderr
new file mode 100644
index 00000000000..d7871a0b8cb
--- /dev/null
+++ b/tests/ui/imports/ambiguous-6.stderr
@@ -0,0 +1,25 @@
+warning: `C` is ambiguous
+  --> $DIR/ambiguous-6.rs:7:5
+   |
+LL |     C
+   |     ^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `C` could refer to the constant imported here
+  --> $DIR/ambiguous-6.rs:16:13
+   |
+LL |     pub use mod1::*;
+   |             ^^^^^^^
+   = help: consider adding an explicit import of `C` to disambiguate
+note: `C` could also refer to the constant imported here
+  --> $DIR/ambiguous-6.rs:17:13
+   |
+LL |     pub use mod2::*;
+   |             ^^^^^^^
+   = help: consider adding an explicit import of `C` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/imports/ambiguous-7.rs b/tests/ui/imports/ambiguous-7.rs
new file mode 100644
index 00000000000..5148ff4cc33
--- /dev/null
+++ b/tests/ui/imports/ambiguous-7.rs
@@ -0,0 +1,18 @@
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1638206152
+
+mod t2 {
+    #[derive(Debug)]
+    pub enum Error {}
+}
+
+pub use t2::*;
+
+mod t3 {
+    pub trait Error {}
+}
+
+use self::t3::*;
+fn a<E: Error>(_: E) {}
+//~^ ERROR `Error` is ambiguous
+
+fn main() {}
diff --git a/tests/ui/imports/ambiguous-7.stderr b/tests/ui/imports/ambiguous-7.stderr
new file mode 100644
index 00000000000..2c6b56c61fd
--- /dev/null
+++ b/tests/ui/imports/ambiguous-7.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `Error` is ambiguous
+  --> $DIR/ambiguous-7.rs:15:9
+   |
+LL | fn a<E: Error>(_: E) {}
+   |         ^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Error` could refer to the trait imported here
+  --> $DIR/ambiguous-7.rs:14:5
+   |
+LL | use self::t3::*;
+   |     ^^^^^^^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+note: `Error` could also refer to the enum imported here
+  --> $DIR/ambiguous-7.rs:8:9
+   |
+LL | pub use t2::*;
+   |         ^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-8.rs b/tests/ui/imports/ambiguous-8.rs
new file mode 100644
index 00000000000..d44cd9587ac
--- /dev/null
+++ b/tests/ui/imports/ambiguous-8.rs
@@ -0,0 +1,14 @@
+// aux-build: ambiguous-8-extern.rs
+
+extern crate ambiguous_8_extern;
+
+mod s {
+  pub trait Error {}
+}
+
+use s::*;
+use ambiguous_8_extern::*;
+fn a<E: Error>(_: E) {}
+//~^ ERROR `Error` is ambiguous
+
+fn main() {}
diff --git a/tests/ui/imports/ambiguous-8.stderr b/tests/ui/imports/ambiguous-8.stderr
new file mode 100644
index 00000000000..32056fba69f
--- /dev/null
+++ b/tests/ui/imports/ambiguous-8.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `Error` is ambiguous
+  --> $DIR/ambiguous-8.rs:11:9
+   |
+LL | fn a<E: Error>(_: E) {}
+   |         ^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `Error` could refer to the trait imported here
+  --> $DIR/ambiguous-8.rs:9:5
+   |
+LL | use s::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+note: `Error` could also refer to the enum imported here
+  --> $DIR/ambiguous-8.rs:10:5
+   |
+LL | use ambiguous_8_extern::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `Error` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/ambiguous-9.rs b/tests/ui/imports/ambiguous-9.rs
new file mode 100644
index 00000000000..9da2467ad9d
--- /dev/null
+++ b/tests/ui/imports/ambiguous-9.rs
@@ -0,0 +1,29 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1638206152
+
+pub mod dsl {
+    mod range {
+        pub fn date_range() {}
+    }
+    pub use self::range::*; //~ WARNING ambiguous glob re-exports
+    use super::prelude::*;
+}
+
+pub mod prelude {
+    mod t {
+      pub fn date_range() {}
+    }
+    pub use self::t::*; //~ WARNING ambiguous glob re-exports
+    pub use super::dsl::*;
+}
+
+use dsl::*;
+use prelude::*;
+
+fn main() {
+    date_range();
+    //~^ WARNING `date_range` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    //~| WARNING `date_range` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr
new file mode 100644
index 00000000000..6c7d79174da
--- /dev/null
+++ b/tests/ui/imports/ambiguous-9.stderr
@@ -0,0 +1,65 @@
+warning: ambiguous glob re-exports
+  --> $DIR/ambiguous-9.rs:8:13
+   |
+LL |     pub use self::range::*;
+   |             ^^^^^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here
+LL |     use super::prelude::*;
+   |         ----------------- but the name `date_range` in the value namespace is also re-exported here
+   |
+   = note: `#[warn(ambiguous_glob_reexports)]` on by default
+
+warning: `date_range` is ambiguous
+  --> $DIR/ambiguous-9.rs:24:5
+   |
+LL |     date_range();
+   |     ^^^^^^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `date_range` could refer to the function imported here
+  --> $DIR/ambiguous-9.rs:8:13
+   |
+LL |     pub use self::range::*;
+   |             ^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+note: `date_range` could also refer to the function imported here
+  --> $DIR/ambiguous-9.rs:9:9
+   |
+LL |     use super::prelude::*;
+   |         ^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+warning: ambiguous glob re-exports
+  --> $DIR/ambiguous-9.rs:16:13
+   |
+LL |     pub use self::t::*;
+   |             ^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here
+LL |     pub use super::dsl::*;
+   |             ------------- but the name `date_range` in the value namespace is also re-exported here
+
+warning: `date_range` is ambiguous
+  --> $DIR/ambiguous-9.rs:24:5
+   |
+LL |     date_range();
+   |     ^^^^^^^^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `date_range` could refer to the function imported here
+  --> $DIR/ambiguous-9.rs:20:5
+   |
+LL | use dsl::*;
+   |     ^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+note: `date_range` could also refer to the function imported here
+  --> $DIR/ambiguous-9.rs:21:5
+   |
+LL | use prelude::*;
+   |     ^^^^^^^^^^
+   = help: consider adding an explicit import of `date_range` to disambiguate
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/imports/auxiliary/ambiguous-11-extern.rs b/tests/ui/imports/auxiliary/ambiguous-11-extern.rs
new file mode 100644
index 00000000000..e679bc3dc45
--- /dev/null
+++ b/tests/ui/imports/auxiliary/ambiguous-11-extern.rs
@@ -0,0 +1,6 @@
+mod t2 {
+    #[derive(Debug)]
+    pub enum Error {}
+}
+
+pub use t2::*;
diff --git a/tests/ui/imports/auxiliary/ambiguous-8-extern.rs b/tests/ui/imports/auxiliary/ambiguous-8-extern.rs
new file mode 100644
index 00000000000..c7bf1bae038
--- /dev/null
+++ b/tests/ui/imports/auxiliary/ambiguous-8-extern.rs
@@ -0,0 +1,12 @@
+mod t2 {
+    #[derive(Debug)]
+    pub enum Error {}
+
+    mod t {
+        pub trait Error: Sized {}
+    }
+
+    use self::t::*;
+}
+
+pub use t2::*;
diff --git a/tests/ui/imports/auxiliary/extern-with-ambiguous-1-extern.rs b/tests/ui/imports/auxiliary/extern-with-ambiguous-1-extern.rs
new file mode 100644
index 00000000000..5cd10212281
--- /dev/null
+++ b/tests/ui/imports/auxiliary/extern-with-ambiguous-1-extern.rs
@@ -0,0 +1,4 @@
+mod a {
+    pub mod error {}
+}
+pub use a::*;
diff --git a/tests/ui/imports/auxiliary/extern-with-ambiguous-2-extern.rs b/tests/ui/imports/auxiliary/extern-with-ambiguous-2-extern.rs
new file mode 100644
index 00000000000..37899676892
--- /dev/null
+++ b/tests/ui/imports/auxiliary/extern-with-ambiguous-2-extern.rs
@@ -0,0 +1,9 @@
+mod a {
+    pub mod error {}
+}
+pub use a::*;
+
+mod b {
+    pub mod error {}
+}
+pub use b::*;
diff --git a/tests/ui/imports/auxiliary/extern-with-ambiguous-3-extern.rs b/tests/ui/imports/auxiliary/extern-with-ambiguous-3-extern.rs
new file mode 100644
index 00000000000..ad4e0480493
--- /dev/null
+++ b/tests/ui/imports/auxiliary/extern-with-ambiguous-3-extern.rs
@@ -0,0 +1,14 @@
+mod a {
+    pub mod error {}
+}
+pub use a::*;
+
+mod b {
+    pub mod error {}
+}
+pub use b::*;
+
+mod c {
+    pub mod error {}
+}
+pub use c::*;
diff --git a/tests/ui/imports/duplicate.rs b/tests/ui/imports/duplicate.rs
index db6538969ec..0c5a376da38 100644
--- a/tests/ui/imports/duplicate.rs
+++ b/tests/ui/imports/duplicate.rs
@@ -34,6 +34,8 @@ fn main() {
     e::foo();
     f::foo(); //~ ERROR `foo` is ambiguous
     g::foo();
+    //~^ WARNING `foo` is ambiguous
+    //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 mod ambiguous_module_errors {
diff --git a/tests/ui/imports/duplicate.stderr b/tests/ui/imports/duplicate.stderr
index 997a2741b38..d7a7dfce921 100644
--- a/tests/ui/imports/duplicate.stderr
+++ b/tests/ui/imports/duplicate.stderr
@@ -9,20 +9,20 @@ LL |     use a::foo;
    = note: `foo` must be defined only once in the value namespace of this module
 
 error[E0659]: `foo` is ambiguous
-  --> $DIR/duplicate.rs:46:15
+  --> $DIR/duplicate.rs:48:15
    |
 LL |     use self::foo::bar;
    |               ^^^ ambiguous name
    |
    = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the module imported here
-  --> $DIR/duplicate.rs:43:9
+  --> $DIR/duplicate.rs:45:9
    |
 LL |     use self::m1::*;
    |         ^^^^^^^^^^^
    = help: consider adding an explicit import of `foo` to disambiguate
 note: `foo` could also refer to the module imported here
-  --> $DIR/duplicate.rs:44:9
+  --> $DIR/duplicate.rs:46:9
    |
 LL |     use self::m2::*;
    |         ^^^^^^^^^^^
@@ -49,26 +49,49 @@ LL |     pub use b::*;
    = help: consider adding an explicit import of `foo` to disambiguate
 
 error[E0659]: `foo` is ambiguous
-  --> $DIR/duplicate.rs:49:9
+  --> $DIR/duplicate.rs:51:9
    |
 LL |         foo::bar();
    |         ^^^ ambiguous name
    |
    = note: ambiguous because of multiple glob imports of a name in the same module
 note: `foo` could refer to the module imported here
-  --> $DIR/duplicate.rs:43:9
+  --> $DIR/duplicate.rs:45:9
    |
 LL |     use self::m1::*;
    |         ^^^^^^^^^^^
    = help: consider adding an explicit import of `foo` to disambiguate
 note: `foo` could also refer to the module imported here
-  --> $DIR/duplicate.rs:44:9
+  --> $DIR/duplicate.rs:46:9
    |
 LL |     use self::m2::*;
    |         ^^^^^^^^^^^
    = help: consider adding an explicit import of `foo` to disambiguate
 
-error: aborting due to 4 previous errors
+warning: `foo` is ambiguous
+  --> $DIR/duplicate.rs:36:8
+   |
+LL |     g::foo();
+   |        ^^^ ambiguous name
+   |
+   = 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 #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `foo` could refer to the function imported here
+  --> $DIR/duplicate.rs:24:13
+   |
+LL |     pub use a::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+note: `foo` could also refer to the function imported here
+  --> $DIR/duplicate.rs:25:13
+   |
+LL |     pub use b::*;
+   |             ^^^^
+   = help: consider adding an explicit import of `foo` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+error: aborting due to 4 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0252, E0659.
 For more information about an error, try `rustc --explain E0252`.
diff --git a/tests/ui/imports/extern-with-ambiguous-1.rs b/tests/ui/imports/extern-with-ambiguous-1.rs
new file mode 100644
index 00000000000..42c3c20686b
--- /dev/null
+++ b/tests/ui/imports/extern-with-ambiguous-1.rs
@@ -0,0 +1,19 @@
+// edition: 2021
+// aux-build: extern-with-ambiguous-1-extern.rs
+
+// `extern-with-ambiguous-1-extern.rs` doesn't has
+// ambiguous, just for compare.
+
+extern crate extern_with_ambiguous_1_extern;
+
+mod s {
+    pub mod error {
+        use extern_with_ambiguous_1_extern::*;
+    }
+}
+use s::*;
+use extern_with_ambiguous_1_extern::*;
+use error::*;
+//~^ ERROR `error` is ambiguous
+
+fn main() {}
diff --git a/tests/ui/imports/extern-with-ambiguous-1.stderr b/tests/ui/imports/extern-with-ambiguous-1.stderr
new file mode 100644
index 00000000000..dca2b4ebee7
--- /dev/null
+++ b/tests/ui/imports/extern-with-ambiguous-1.stderr
@@ -0,0 +1,23 @@
+error[E0659]: `error` is ambiguous
+  --> $DIR/extern-with-ambiguous-1.rs:16:5
+   |
+LL | use error::*;
+   |     ^^^^^ ambiguous name
+   |
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `error` could refer to the module imported here
+  --> $DIR/extern-with-ambiguous-1.rs:14:5
+   |
+LL | use s::*;
+   |     ^^^^
+   = help: consider adding an explicit import of `error` to disambiguate
+note: `error` could also refer to the module imported here
+  --> $DIR/extern-with-ambiguous-1.rs:15:5
+   |
+LL | use extern_with_ambiguous_1_extern::*;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider adding an explicit import of `error` to disambiguate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/imports/extern-with-ambiguous-2.rs b/tests/ui/imports/extern-with-ambiguous-2.rs
new file mode 100644
index 00000000000..68c623c1c4a
--- /dev/null
+++ b/tests/ui/imports/extern-with-ambiguous-2.rs
@@ -0,0 +1,16 @@
+// check-pass
+// edition: 2021
+// aux-build: extern-with-ambiguous-2-extern.rs
+
+extern crate extern_with_ambiguous_2_extern;
+
+mod s {
+    pub mod error {
+        use extern_with_ambiguous_2_extern::*;
+    }
+}
+use s::*;
+use extern_with_ambiguous_2_extern::*;
+use error::*;
+
+fn main() {}
diff --git a/tests/ui/imports/extern-with-ambiguous-3.rs b/tests/ui/imports/extern-with-ambiguous-3.rs
new file mode 100644
index 00000000000..282c1d569b0
--- /dev/null
+++ b/tests/ui/imports/extern-with-ambiguous-3.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+// aux-build: extern-with-ambiguous-3-extern.rs
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1643974121
+
+extern crate extern_with_ambiguous_3_extern;
+
+mod s {
+    pub mod error {
+        use extern_with_ambiguous_3_extern::*;
+    }
+}
+use s::*;
+use extern_with_ambiguous_3_extern::*;
+use error::*;
+
+fn main() {}
diff --git a/tests/ui/imports/import-after-macro-expand-1.rs b/tests/ui/imports/import-after-macro-expand-1.rs
new file mode 100644
index 00000000000..d7a8aaf2f2e
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-1.rs
@@ -0,0 +1,19 @@
+// check-pass
+// https://github.com/rust-lang/rust/issues/56593#issue-388659456
+
+struct Foo;
+
+mod foo {
+    use super::*;
+
+    #[derive(Debug)]
+    pub struct Foo;
+}
+
+mod bar {
+    use super::foo::*;
+
+    fn bar(_: Foo) {}
+}
+
+fn main() {}
diff --git a/tests/ui/imports/import-after-macro-expand-2.rs b/tests/ui/imports/import-after-macro-expand-2.rs
new file mode 100644
index 00000000000..b3996d48840
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-2.rs
@@ -0,0 +1,27 @@
+// check-pass
+// https://github.com/rust-lang/rust/issues/56593#issuecomment-1133174514
+
+use thing::*;
+
+#[derive(Debug)]
+pub enum Thing {
+    Foo
+}
+
+mod tests {
+    use super::*;
+
+    fn test_thing() {
+        let thing: crate::thing::Thing = Thing::Bar;
+        // FIXME: `thing` should refer to `crate::Thing`,
+        // FIXME: but doesn't currently refer to it due to backward compatibility
+    }
+}
+
+mod thing {
+    pub enum Thing {
+        Bar
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/imports/import-after-macro-expand-3.rs b/tests/ui/imports/import-after-macro-expand-3.rs
new file mode 100644
index 00000000000..3babe1470fc
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-3.rs
@@ -0,0 +1,24 @@
+// check-pass
+// similar with `import-after-macro-expand-2.rs`
+
+use thing::*;
+
+pub enum Thing {
+    Foo
+}
+
+mod tests {
+    use super::*;
+
+    fn test_thing() {
+        let thing: crate::Thing = Thing::Foo;
+    }
+}
+
+mod thing {
+    pub enum Thing {
+        Bar
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/imports/import-after-macro-expand-4.rs b/tests/ui/imports/import-after-macro-expand-4.rs
new file mode 100644
index 00000000000..02cc3f01af9
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-4.rs
@@ -0,0 +1,30 @@
+// https://github.com/rust-lang/rust/pull/113242#issuecomment-1616034904
+// similar with `import-after-macro-expand-2.rs`
+
+mod a {
+    pub trait P {}
+}
+
+pub use a::*;
+
+mod c {
+    use crate::*;
+    pub struct S(Vec<P>);
+    //~^ ERROR the size for values of type
+    //~| WARNING trait objects without an explicit
+    //~| WARNING this is accepted in the current edition
+    //~| WARNING trait objects without an explicit
+    //~| WARNING this is accepted in the current edition
+    //~| WARNING trait objects without an explicit
+    //~| WARNING this is accepted in the current edition
+
+    // FIXME: should works, but doesn't currently refer
+    // to it due to backward compatibility
+}
+
+#[derive(Clone)]
+pub enum P {
+    A
+}
+
+fn main() {}
diff --git a/tests/ui/imports/import-after-macro-expand-4.stderr b/tests/ui/imports/import-after-macro-expand-4.stderr
new file mode 100644
index 00000000000..01f70cfc5bf
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-4.stderr
@@ -0,0 +1,53 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/import-after-macro-expand-4.rs:12:22
+   |
+LL |     pub struct S(Vec<P>);
+   |                      ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+help: use `dyn`
+   |
+LL |     pub struct S(Vec<dyn P>);
+   |                      +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/import-after-macro-expand-4.rs:12:22
+   |
+LL |     pub struct S(Vec<P>);
+   |                      ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+   |
+LL |     pub struct S(Vec<dyn P>);
+   |                      +++
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/import-after-macro-expand-4.rs:12:22
+   |
+LL |     pub struct S(Vec<P>);
+   |                      ^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+   |
+LL |     pub struct S(Vec<dyn P>);
+   |                      +++
+
+error[E0277]: the size for values of type `(dyn a::P + 'static)` cannot be known at compilation time
+  --> $DIR/import-after-macro-expand-4.rs:12:18
+   |
+LL |     pub struct S(Vec<P>);
+   |                  ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn a::P + 'static)`
+note: required by a bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/imports/import-after-macro-expand-5.rs b/tests/ui/imports/import-after-macro-expand-5.rs
new file mode 100644
index 00000000000..ba28b6deac7
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-5.rs
@@ -0,0 +1,31 @@
+// edition: 2021
+// check-pass
+// https://github.com/rust-lang/rust/issues/105235#issue-1474295873
+
+mod abc {
+    pub struct Beeblebrox;
+    pub struct Zaphod;
+}
+
+mod foo {
+    pub mod bar {
+        use crate::abc::*;
+
+        #[derive(Debug)]
+        pub enum Zaphod {
+            Whale,
+            President,
+        }
+    }
+    pub use bar::*;
+}
+
+mod baz {
+    pub fn do_something() {
+        println!("{:?}", crate::foo::Zaphod::Whale);
+    }
+}
+
+fn main() {
+    baz::do_something();
+}
diff --git a/tests/ui/imports/import-after-macro-expand-6.rs b/tests/ui/imports/import-after-macro-expand-6.rs
new file mode 100644
index 00000000000..ab5bb37a175
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-6.rs
@@ -0,0 +1,24 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113099#issuecomment-1633574396
+
+pub mod a {
+    pub use crate::b::*;
+}
+
+mod b {
+    pub mod http {
+        pub struct HeaderMap;
+    }
+
+    pub use self::http::*;
+    #[derive(Debug)]
+    pub struct HeaderMap;
+}
+
+use crate::a::HeaderMap;
+
+fn main() {
+    let h: crate::b::http::HeaderMap = HeaderMap;
+    // FIXME: should refer to `crate::b::HeaderMap`,
+    // FIXME: but doesn't currently refer to it due to backward compatibility
+}
diff --git a/tests/ui/imports/import-after-macro-expand-7.rs b/tests/ui/imports/import-after-macro-expand-7.rs
new file mode 100644
index 00000000000..0402dfdfda7
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-7.rs
@@ -0,0 +1,21 @@
+// check-pass
+// a compared case for `import-after-macro-expand-6.rs`
+
+pub mod a {
+    pub use crate::b::*;
+}
+
+mod b {
+    mod http {
+        pub struct HeaderMap;
+    }
+
+    pub use self::http::*;
+    pub struct HeaderMap;
+}
+
+use crate::a::HeaderMap;
+
+fn main() {
+    let h: crate::b::HeaderMap = HeaderMap;
+}
diff --git a/tests/ui/imports/import-after-macro-expand-8.rs b/tests/ui/imports/import-after-macro-expand-8.rs
new file mode 100644
index 00000000000..e11d65effdf
--- /dev/null
+++ b/tests/ui/imports/import-after-macro-expand-8.rs
@@ -0,0 +1,22 @@
+// check-pass
+// https://github.com/rust-lang/rust/pull/113242#issuecomment-1616034904
+
+mod a {
+    pub trait P {}
+}
+pub use a::*;
+
+mod b {
+    #[derive(Clone)]
+    pub enum P {
+        A
+    }
+}
+pub use b::P;
+
+mod c {
+    use crate::*;
+    pub struct S(Vec<P>);
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-112831.rs b/tests/ui/resolve/derive-macro-1.rs
similarity index 82%
rename from tests/ui/resolve/issue-112831.rs
rename to tests/ui/resolve/derive-macro-1.rs
index ffd83ea8bc1..90cbd903ad6 100644
--- a/tests/ui/resolve/issue-112831.rs
+++ b/tests/ui/resolve/derive-macro-1.rs
@@ -1,19 +1,17 @@
 // check-pass
 // aux-build:issue-112831-aux.rs
 
-mod zeroable {
+mod z {
     pub trait Zeroable {}
 }
 
-use zeroable::*;
+use z::*;
 
 mod pod {
     use super::*;
     pub trait Pod: Zeroable {}
 }
 
-use pod::*;
-
 extern crate issue_112831_aux;
 use issue_112831_aux::Zeroable;
 
diff --git a/tests/ui/resolve/derive-macro-2.rs b/tests/ui/resolve/derive-macro-2.rs
new file mode 100644
index 00000000000..7cecdd9e38e
--- /dev/null
+++ b/tests/ui/resolve/derive-macro-2.rs
@@ -0,0 +1,18 @@
+// check-pass
+// aux-build:issue-112831-aux.rs
+
+extern crate issue_112831_aux;
+use issue_112831_aux::Zeroable;
+
+mod z {
+    pub trait Zeroable {}
+}
+
+use z::*;
+
+mod pod {
+    use super::*;
+    pub trait Pod: Zeroable {}
+}
+
+fn main() {}