mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Merge pull request #18390 from ShoyuVanilla/issue-18308
fix: Prevent public re-export of private item
This commit is contained in:
commit
b12fead6da
4 changed files with 98 additions and 9 deletions
|
@ -1025,7 +1025,7 @@ pub mod ast {
|
||||||
check_found_path(
|
check_found_path(
|
||||||
r#"
|
r#"
|
||||||
mod bar {
|
mod bar {
|
||||||
mod foo { pub(super) struct S; }
|
mod foo { pub(crate) struct S; }
|
||||||
pub(crate) use foo::*;
|
pub(crate) use foo::*;
|
||||||
}
|
}
|
||||||
$0
|
$0
|
||||||
|
@ -1047,7 +1047,7 @@ $0
|
||||||
check_found_path(
|
check_found_path(
|
||||||
r#"
|
r#"
|
||||||
mod bar {
|
mod bar {
|
||||||
mod foo { pub(super) struct S; }
|
mod foo { pub(crate) struct S; }
|
||||||
pub(crate) use foo::S as U;
|
pub(crate) use foo::S as U;
|
||||||
}
|
}
|
||||||
$0
|
$0
|
||||||
|
|
|
@ -985,12 +985,8 @@ impl DefCollector<'_> {
|
||||||
for (name, res) in resolutions {
|
for (name, res) in resolutions {
|
||||||
match name {
|
match name {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
changed |= self.push_res_and_update_glob_vis(
|
changed |=
|
||||||
module_id,
|
self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
|
||||||
name,
|
|
||||||
res.with_visibility(vis),
|
|
||||||
import,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let tr = match res.take_types() {
|
let tr = match res.take_types() {
|
||||||
|
@ -1043,10 +1039,11 @@ impl DefCollector<'_> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for (glob_importing_module, glob_import_vis, use_) in glob_imports {
|
for (glob_importing_module, glob_import_vis, use_) in glob_imports {
|
||||||
|
let vis = glob_import_vis.min(vis, &self.def_map).unwrap_or(glob_import_vis);
|
||||||
self.update_recursive(
|
self.update_recursive(
|
||||||
glob_importing_module,
|
glob_importing_module,
|
||||||
resolutions,
|
resolutions,
|
||||||
glob_import_vis,
|
vis,
|
||||||
Some(ImportType::Glob(use_)),
|
Some(ImportType::Glob(use_)),
|
||||||
depth + 1,
|
depth + 1,
|
||||||
);
|
);
|
||||||
|
@ -1058,8 +1055,19 @@ impl DefCollector<'_> {
|
||||||
module_id: LocalModuleId,
|
module_id: LocalModuleId,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
mut defs: PerNs,
|
mut defs: PerNs,
|
||||||
|
vis: Visibility,
|
||||||
def_import_type: Option<ImportType>,
|
def_import_type: Option<ImportType>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
if let Some((_, v, _)) = defs.types.as_mut() {
|
||||||
|
*v = v.min(vis, &self.def_map).unwrap_or(vis);
|
||||||
|
}
|
||||||
|
if let Some((_, v, _)) = defs.values.as_mut() {
|
||||||
|
*v = v.min(vis, &self.def_map).unwrap_or(vis);
|
||||||
|
}
|
||||||
|
if let Some((_, v, _)) = defs.macros.as_mut() {
|
||||||
|
*v = v.min(vis, &self.def_map).unwrap_or(vis);
|
||||||
|
}
|
||||||
|
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
|
|
||||||
if let Some(ImportType::Glob(_)) = def_import_type {
|
if let Some(ImportType::Glob(_)) = def_import_type {
|
||||||
|
|
|
@ -412,3 +412,42 @@ use reexport::*;
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_18308() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
use outer::*;
|
||||||
|
|
||||||
|
mod outer {
|
||||||
|
mod inner_superglob {
|
||||||
|
pub use super::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The importing order matters!
|
||||||
|
pub use inner_superglob::*;
|
||||||
|
use super::glob_target::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod glob_target {
|
||||||
|
pub struct ShouldBePrivate;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
crate
|
||||||
|
glob_target: t
|
||||||
|
outer: t
|
||||||
|
|
||||||
|
crate::glob_target
|
||||||
|
ShouldBePrivate: t v
|
||||||
|
|
||||||
|
crate::outer
|
||||||
|
ShouldBePrivate: t v
|
||||||
|
inner_superglob: t
|
||||||
|
|
||||||
|
crate::outer::inner_superglob
|
||||||
|
ShouldBePrivate: t v
|
||||||
|
inner_superglob: t
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -191,6 +191,11 @@ impl Visibility {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let def_block = def_map.block_id();
|
||||||
|
if (mod_a.containing_block(), mod_b.containing_block()) != (def_block, def_block) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let mut a_ancestors =
|
let mut a_ancestors =
|
||||||
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
|
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
|
||||||
let mut b_ancestors =
|
let mut b_ancestors =
|
||||||
|
@ -210,6 +215,43 @@ impl Visibility {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the least permissive visibility of `self` and `other`.
|
||||||
|
///
|
||||||
|
/// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only
|
||||||
|
/// visible in unrelated modules).
|
||||||
|
pub(crate) fn min(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
||||||
|
match (self, other) {
|
||||||
|
(vis, Visibility::Public) | (Visibility::Public, vis) => Some(vis),
|
||||||
|
(Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => {
|
||||||
|
if mod_a.krate != mod_b.krate {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let def_block = def_map.block_id();
|
||||||
|
if (mod_a.containing_block(), mod_b.containing_block()) != (def_block, def_block) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut a_ancestors =
|
||||||
|
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
|
||||||
|
let mut b_ancestors =
|
||||||
|
iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent);
|
||||||
|
|
||||||
|
if a_ancestors.any(|m| m == mod_b.local_id) {
|
||||||
|
// B is above A
|
||||||
|
return Some(Visibility::Module(mod_a, expl_b));
|
||||||
|
}
|
||||||
|
|
||||||
|
if b_ancestors.any(|m| m == mod_a.local_id) {
|
||||||
|
// A is above B
|
||||||
|
return Some(Visibility::Module(mod_b, expl_a));
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
|
/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
|
||||||
|
|
Loading…
Reference in a new issue