Rollup merge of #150491 - petrochenkov:ambigeffvis, r=yaahc
resolve: Mark items under exported ambiguous imports as exported After https://github.com/rust-lang/rust/pull/147984 one of the imports in an ambiguous import set becomes accessible under a deny-by-default deprecation lint. So if it points to something, that something needs to be marked as exported, so its MIR is encoded into metadata, its symbol is not lost from object files, etc. The added test shows an example. This fixes around 10-20 crater regressions found in https://github.com/rust-lang/rust/pull/149195#issuecomment-3641704823. Unblocks https://github.com/rust-lang/rust/pull/149195.
This commit is contained in:
commit
8bdd8dc5e1
6 changed files with 60 additions and 32 deletions
|
|
@ -96,13 +96,10 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
|
|||
// is the maximum value among visibilities of declarations corresponding to that def id.
|
||||
for (decl, eff_vis) in visitor.import_effective_visibilities.iter() {
|
||||
let DeclKind::Import { import, .. } = decl.kind else { unreachable!() };
|
||||
if !decl.is_ambiguity_recursive() {
|
||||
if let Some(node_id) = import.id() {
|
||||
r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
|
||||
}
|
||||
} else if decl.ambiguity.get().is_some()
|
||||
&& eff_vis.is_public_at_level(Level::Reexported)
|
||||
{
|
||||
if let Some(node_id) = import.id() {
|
||||
r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
|
||||
}
|
||||
if decl.ambiguity.get().is_some() && eff_vis.is_public_at_level(Level::Reexported) {
|
||||
exported_ambiguities.insert(*decl);
|
||||
}
|
||||
}
|
||||
|
|
@ -123,31 +120,13 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
|
|||
// Set the given effective visibility level to `Level::Direct` and
|
||||
// sets the rest of the `use` chain to `Level::Reexported` until
|
||||
// we hit the actual exported item.
|
||||
//
|
||||
// If the binding is ambiguous, put the root ambiguity binding and all reexports
|
||||
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
|
||||
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
|
||||
let is_ambiguity =
|
||||
|decl: Decl<'ra>, warn: bool| decl.ambiguity.get().is_some() && !warn;
|
||||
let mut parent_id = ParentId::Def(module_id);
|
||||
let mut warn_ambiguity = decl.warn_ambiguity.get();
|
||||
while let DeclKind::Import { source_decl, .. } = decl.kind {
|
||||
self.update_import(decl, parent_id);
|
||||
|
||||
if is_ambiguity(decl, warn_ambiguity) {
|
||||
// Stop at the root ambiguity, further bindings in the chain should not
|
||||
// be reexported because the root ambiguity blocks any access to them.
|
||||
// (Those further bindings are most likely not ambiguities themselves.)
|
||||
break;
|
||||
}
|
||||
|
||||
parent_id = ParentId::Import(decl);
|
||||
decl = source_decl;
|
||||
warn_ambiguity |= source_decl.warn_ambiguity.get();
|
||||
}
|
||||
if !is_ambiguity(decl, warn_ambiguity)
|
||||
&& let Some(def_id) = decl.res().opt_def_id().and_then(|id| id.as_local())
|
||||
{
|
||||
if let Some(def_id) = decl.res().opt_def_id().and_then(|id| id.as_local()) {
|
||||
self.update_def(def_id, decl.vis().expect_local(), parent_id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
//@ has 'glob_shadowing/index.html'
|
||||
//@ count - '//dt' 6
|
||||
//@ !has - '//dd' 'sub1::describe'
|
||||
//@ count - '//dt' 7
|
||||
//@ !has - '//dd' 'sub1::describe1'
|
||||
//@ has - '//dd' 'sub2::describe'
|
||||
|
||||
//@ !has - '//dd' 'sub1::describe2'
|
||||
//@ has - '//dd' 'sub1::describe2'
|
||||
|
||||
//@ !has - '//dd' 'sub1::prelude'
|
||||
//@ has - '//dd' 'mod::prelude'
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
mod sub1 {
|
||||
// this should be shadowed by sub2::describe
|
||||
/// sub1::describe
|
||||
/// sub1::describe1
|
||||
pub fn describe() -> &'static str {
|
||||
"sub1::describe"
|
||||
}
|
||||
|
|
@ -33,7 +33,9 @@ mod sub1 {
|
|||
pub struct Foo;
|
||||
|
||||
// this should be shadowed,
|
||||
// because both sub1::describe2 and sub3::describe2 are from glob reexport
|
||||
// because both sub1::describe2 and sub3::describe2 are from glob reexport,
|
||||
// but it is still usable from other crates under the `ambiguous_glob_imports` lint,
|
||||
// so it is reachable and documented
|
||||
/// sub1::describe2
|
||||
pub fn describe2() -> &'static str {
|
||||
"sub1::describe2"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// Regression test for https://github.com/rust-lang/rust/issues/100973
|
||||
// Update: the rules has changed after #147984, one of the colliding items is now available
|
||||
// from other crates under a deprecation lint.
|
||||
|
||||
//@ set m1 = "$.index[?(@.name == 'm1' && @.inner.module)].id"
|
||||
//@ is "$.index[?(@.name == 'm1')].inner.module.items" []
|
||||
//@ is "$.index[?(@.name == 'm1')].inner.module.items" [0]
|
||||
//@ is "$.index[?(@.name == 'm1')].inner.module.is_stripped" true
|
||||
mod m1 {
|
||||
pub fn f() {}
|
||||
|
|
|
|||
8
tests/ui/imports/ambiguous-reachable.rs
Normal file
8
tests/ui/imports/ambiguous-reachable.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//@ build-pass
|
||||
//@ aux-crate: ambiguous_reachable_extern=ambiguous-reachable-extern.rs
|
||||
|
||||
#![allow(ambiguous_glob_imports)]
|
||||
|
||||
fn main() {
|
||||
ambiguous_reachable_extern::generic::<u8>();
|
||||
}
|
||||
23
tests/ui/imports/ambiguous-reachable.stderr
Normal file
23
tests/ui/imports/ambiguous-reachable.stderr
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: `generic` is ambiguous
|
||||
--> $DIR/ambiguous-reachable.rs:7:33
|
||||
|
|
||||
LL | ambiguous_reachable_extern::generic::<u8>();
|
||||
| ^^^^^^^ 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: `generic` could refer to the function defined here
|
||||
--> $DIR/auxiliary/ambiguous-reachable-extern.rs:13:9
|
||||
|
|
||||
LL | pub use m1::*;
|
||||
| ^^
|
||||
= help: consider updating this dependency to resolve this error
|
||||
= help: if updating the dependency does not resolve the problem report the problem to the author of the relevant crate
|
||||
note: `generic` could also refer to the function defined here
|
||||
--> $DIR/auxiliary/ambiguous-reachable-extern.rs:14:9
|
||||
|
|
||||
LL | pub use m2::*;
|
||||
| ^^
|
||||
|
||||
14
tests/ui/imports/auxiliary/ambiguous-reachable-extern.rs
Normal file
14
tests/ui/imports/auxiliary/ambiguous-reachable-extern.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
mod m1 {
|
||||
pub fn generic<T>() {
|
||||
let x = 10;
|
||||
let y = 11;
|
||||
println!("hello {x} world {:?}", y);
|
||||
}
|
||||
}
|
||||
|
||||
mod m2 {
|
||||
pub fn generic() {}
|
||||
}
|
||||
|
||||
pub use m1::*;
|
||||
pub use m2::*;
|
||||
Loading…
Add table
Add a link
Reference in a new issue