Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/rustc_codegen_gcc/build_system/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,6 @@ fn valid_ui_error_pattern_test(file: &str) -> bool {
"type-alias-impl-trait/auxiliary/cross_crate_ice.rs",
"type-alias-impl-trait/auxiliary/cross_crate_ice2.rs",
"macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs",
"imports/ambiguous-1.rs",
"imports/ambiguous-4-extern.rs",
"entry-point/auxiliary/bad_main_functions.rs",
]
.iter()
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4622,7 +4622,7 @@ declare_lint! {
///
/// ### Example
///
/// ```rust,compile_fail
/// ```rust,ignore (needs extern crate)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example and the explanation below it are outdated. Is there a more suitable example that demonstrates the current lint behavior?

/// #![deny(ambiguous_glob_imports)]
/// pub fn foo() -> u32 {
/// use sub::*;
Expand All @@ -4638,8 +4638,6 @@ declare_lint! {
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Previous versions of Rust compile it successfully because it
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
decl: Decl<'ra>,
) {
if let Err(old_decl) =
self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl, false)
self.try_plant_decl_into_local_module(ident, orig_ident_span, ns, decl)
{
self.report_conflict(ident, ns, old_decl, decl);
}
Expand Down Expand Up @@ -87,13 +87,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
vis: Visibility<DefId>,
span: Span,
expansion: LocalExpnId,
ambiguity: Option<Decl<'ra>>,
ambiguity: Option<(Decl<'ra>, bool)>,
) {
let decl = self.arenas.alloc_decl(DeclData {
kind: DeclKind::Def(res),
ambiguity: CmCell::new(ambiguity),
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
warn_ambiguity: CmCell::new(true),
initial_vis: vis,
ambiguity_vis_max: CmCell::new(None),
ambiguity_vis_min: CmCell::new(None),
Expand Down Expand Up @@ -392,7 +390,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child;
let span = child_span(self, reexport_chain, res);
let res = res.expect_non_local();
self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module()))
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
(self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module())), true)
});

// Record primary definitions.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.emit()
}

fn def_path_str(&self, mut def_id: DefId) -> String {
pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
// We can't use `def_path_str` in resolve.
let mut path = vec![def_id];
while let Some(parent) = self.tcx.opt_parent(def_id) {
Expand Down
166 changes: 82 additions & 84 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,9 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
assert_eq!(d1.span, d2.span);
if d1.ambiguity.get() != d2.ambiguity.get() {
assert!(d1.ambiguity.get().is_some());
assert!(d2.ambiguity.get().is_none());
}
// Visibility of the new import declaration may be different,
// because it already incorporates the visibility of the source binding.
// `warn_ambiguity` of a re-fetched glob can also change in both directions.
remove_same_import(d1_next, d2_next)
} else {
(d1, d2)
Expand Down Expand Up @@ -450,7 +448,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.arenas.alloc_decl(DeclData {
kind: DeclKind::Import { source_decl: decl, import },
ambiguity: CmCell::new(None),
warn_ambiguity: CmCell::new(false),
span: import.span,
initial_vis: vis.to_def_id(),
ambiguity_vis_max: CmCell::new(None),
Expand All @@ -460,14 +457,60 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
})
}

fn is_noise_0_7_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
let [seg1, seg2] = &i1.module_path[..] else { return false };
if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin_surflet" {
return false;
}
let [seg1, seg2] = &i2.module_path[..] else { return false };
if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin" {
return false;
}
let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
self.def_path_str(def_id1).ends_with("noise_fns::generators::perlin_surflet::Perlin")
&& self.def_path_str(def_id2).ends_with("noise_fns::generators::perlin::Perlin")
}

fn is_rustybuzz_0_4_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
let [seg1, seg2] = &i1.module_path[..] else { return false };
if seg1.ident.name != kw::Super || seg2.ident.name.as_str() != "gsubgpos" {
return false;
}
let [seg1] = &i2.module_path[..] else { return false };
if seg1.ident.name != kw::Super {
return false;
}
let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
self.def_path_str(def_id1).ends_with("tables::gsubgpos::Class")
&& self.def_path_str(def_id2).ends_with("ggg::Class")
}

fn is_pdf_0_9_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this hack be removed since pdf-0.9.1 had fixed this (#149195 (comment))?

let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };
let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };
let [seg1, seg2] = &i1.module_path[..] else { return false };
if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "content" {
return false;
}
let [seg1, seg2] = &i2.module_path[..] else { return false };
if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "object" {
return false;
}
let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };
let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };
self.def_path_str(def_id1).ends_with("crate::content::Rect")
&& self.def_path_str(def_id2).ends_with("crate::object::types::Rect")
}

/// If `glob_decl` attempts to overwrite `old_glob_decl` in a module,
/// decide which one to keep.
fn select_glob_decl(
&self,
old_glob_decl: Decl<'ra>,
glob_decl: Decl<'ra>,
warn_ambiguity: bool,
) -> Decl<'ra> {
fn select_glob_decl(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> Decl<'ra> {
assert!(glob_decl.is_glob_import());
assert!(old_glob_decl.is_glob_import());
assert_ne!(glob_decl, old_glob_decl);
Expand All @@ -476,9 +519,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// all these overwrites will be re-fetched by glob imports importing
// from that module without generating new ambiguities.
// - A glob decl is overwritten by a non-glob decl arriving later.
// - A glob decl is overwritten by its clone after setting ambiguity in it.
// FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch
// with the same decl in some way.
// - A glob decl is overwritten by a glob decl re-fetching an
// overwritten decl from other module (the recursive case).
// Here we are detecting all such re-fetches and overwrite old decls
Expand All @@ -489,29 +529,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if deep_decl != glob_decl {
// Some import layers have been removed, need to overwrite.
assert_ne!(old_deep_decl, old_glob_decl);
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
// assert_ne!(old_deep_decl, deep_decl);
// assert!(old_deep_decl.is_glob_import());
assert!(!deep_decl.is_glob_import());
if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
if let Some((old_ambig, _)) = old_glob_decl.ambiguity.get()
&& glob_decl.ambiguity.get().is_none()
{
// Do not lose glob ambiguities when re-fetching the glob.
glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
}
if glob_decl.is_ambiguity_recursive() {
glob_decl.warn_ambiguity.set_unchecked(true);
glob_decl.ambiguity.set_unchecked(Some((old_ambig, true)));
}
glob_decl
} else if glob_decl.res() != old_glob_decl.res() {
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
old_glob_decl.warn_ambiguity.set_unchecked(warn_ambiguity);
if warn_ambiguity {
old_glob_decl
} else {
// Need a fresh decl so other glob imports importing it could re-fetch it
// and set their own `warn_ambiguity` to true.
// FIXME: remove this when `warn_ambiguity` is removed (#149195).
self.arenas.alloc_decl((*old_glob_decl).clone())
}
let warning = self.is_noise_0_7_0(old_glob_decl, glob_decl)
|| self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl)
|| self.is_pdf_0_9_0(old_glob_decl, glob_decl);
old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, warning)));
old_glob_decl
} else if let old_vis = old_glob_decl.vis()
&& let vis = glob_decl.vis()
&& old_vis != vis
Expand All @@ -529,8 +560,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
old_glob_decl
} else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {
// Overwriting a non-ambiguous glob import with an ambiguous glob import.
old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));
old_glob_decl.warn_ambiguity.set_unchecked(true);
old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, true)));
old_glob_decl
} else {
old_glob_decl
Expand All @@ -545,9 +575,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
orig_ident_span: Span,
ns: Namespace,
decl: Decl<'ra>,
warn_ambiguity: bool,
) -> Result<(), Decl<'ra>> {
assert!(!decl.warn_ambiguity.get());
assert!(decl.ambiguity.get().is_none());
assert!(decl.ambiguity_vis_max.get().is_none());
assert!(decl.ambiguity_vis_min.get().is_none());
Expand All @@ -562,31 +590,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module.underscore_disambiguator.update_unchecked(|d| d + 1);
module.underscore_disambiguator.get()
});
self.update_local_resolution(
module,
key,
orig_ident_span,
warn_ambiguity,
|this, resolution| {
if decl.is_glob_import() {
resolution.glob_decl = Some(match resolution.glob_decl {
Some(old_decl) => this.select_glob_decl(
old_decl,
decl,
warn_ambiguity && resolution.non_glob_decl.is_none(),
),
None => decl,
})
} else {
resolution.non_glob_decl = Some(match resolution.non_glob_decl {
Some(old_decl) => return Err(old_decl),
None => decl,
})
}
self.update_local_resolution(module, key, orig_ident_span, |this, resolution| {
if decl.is_glob_import() {
resolution.glob_decl = Some(match resolution.glob_decl {
Some(old_decl) => this.select_glob_decl(old_decl, decl),
None => decl,
});
} else {
resolution.non_glob_decl = Some(match resolution.non_glob_decl {
Some(old_decl) => return Err(old_decl),
None => decl,
})
}

Ok(())
},
)
Ok(())
})
}

// Use `f` to mutate the resolution of the name in the module.
Expand All @@ -596,15 +614,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module: LocalModule<'ra>,
key: BindingKey,
orig_ident_span: Span,
warn_ambiguity: bool,
f: F,
) -> T
where
F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> 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, warn_ambiguity) = {
let (binding, t) = {
let resolution = &mut *self
.resolution_or_default(module.to_module(), key, orig_ident_span)
.borrow_mut_unchecked();
Expand All @@ -616,7 +633,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if let Some(binding) = resolution.determined_decl()
&& (old_decl != Some(binding) || old_vis != Some(binding.vis()))
{
(binding, t, warn_ambiguity || old_decl.is_some())
(binding, t)
} else {
return t;
}
Expand All @@ -639,14 +656,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
if self.is_accessible_from(binding.vis(), scope) {
let import_decl = self.new_import_decl(binding, *import);
self.try_plant_decl_into_local_module(
ident,
orig_ident_span,
key.ns,
import_decl,
warn_ambiguity,
)
.expect("planting a glob cannot fail");
self.try_plant_decl_into_local_module(ident, orig_ident_span, key.ns, import_decl)
.expect("planting a glob cannot fail");
}
}

Expand All @@ -665,21 +676,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.per_ns(|this, ns| {
let ident = IdentKey::new(target);
// This can fail, dummies are inserted only in non-occupied slots.
let _ = this.try_plant_decl_into_local_module(
ident,
target.span,
ns,
dummy_decl,
false,
);
let _ = this.try_plant_decl_into_local_module(ident, target.span, ns, dummy_decl);
// Don't remove underscores from `single_imports`, they were never added.
if target.name != kw::Underscore {
let key = BindingKey::new(ident, ns);
this.update_local_resolution(
import.parent_scope.module.expect_local(),
key,
target.span,
false,
|_, resolution| {
resolution.single_imports.swap_remove(&import);
},
Expand Down Expand Up @@ -846,7 +850,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

if let DeclKind::Import { import, .. } = binding.kind
&& let Some(amb_binding) = binding.ambiguity.get()
&& let Some((amb_binding, _)) = binding.ambiguity.get()
&& binding.res() != Res::Err
&& exported_ambiguities.contains(&binding)
{
Expand Down Expand Up @@ -1134,7 +1138,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent.expect_local(),
key,
target.span,
false,
|_, resolution| {
resolution.single_imports.swap_remove(&import);
},
Expand Down Expand Up @@ -1820,16 +1823,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
if self.is_accessible_from(binding.vis(), scope) {
let import_decl = self.new_import_decl(binding, import);
let warn_ambiguity = self
.resolution(import.parent_scope.module, key)
.and_then(|r| r.determined_decl())
.is_some_and(|binding| binding.warn_ambiguity_recursive());
self.try_plant_decl_into_local_module(
key.ident,
orig_ident_span,
key.ns,
import_decl,
warn_ambiguity,
)
.expect("planting a glob cannot fail");
}
Expand Down
Loading
Loading