Fix associated item visibility in block-local impls

This commit is contained in:
Ryo Yoshida 2023-02-19 23:30:49 +09:00
parent 443801755c
commit 83e24fec98
No known key found for this signature in database
GPG key ID: E25698A930586171
5 changed files with 52 additions and 8 deletions

View file

@ -666,8 +666,10 @@ impl DefCollector<'_> {
macro_: Macro2Id, macro_: Macro2Id,
vis: &RawVisibility, vis: &RawVisibility,
) { ) {
let vis = let vis = self
self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public); .def_map
.resolve_visibility(self.db, module_id, vis, false)
.unwrap_or(Visibility::Public);
self.def_map.modules[module_id].scope.declare(macro_.into()); self.def_map.modules[module_id].scope.declare(macro_.into());
self.update( self.update(
module_id, module_id,
@ -831,7 +833,7 @@ impl DefCollector<'_> {
let mut def = directive.status.namespaces(); let mut def = directive.status.namespaces();
let vis = self let vis = self
.def_map .def_map
.resolve_visibility(self.db, module_id, &directive.import.visibility) .resolve_visibility(self.db, module_id, &directive.import.visibility, false)
.unwrap_or(Visibility::Public); .unwrap_or(Visibility::Public);
match import.kind { match import.kind {
@ -1547,7 +1549,7 @@ impl ModCollector<'_, '_> {
}; };
let resolve_vis = |def_map: &DefMap, visibility| { let resolve_vis = |def_map: &DefMap, visibility| {
def_map def_map
.resolve_visibility(db, self.module_id, visibility) .resolve_visibility(db, self.module_id, visibility, false)
.unwrap_or(Visibility::Public) .unwrap_or(Visibility::Public)
}; };
@ -1823,7 +1825,7 @@ impl ModCollector<'_, '_> {
) -> LocalModuleId { ) -> LocalModuleId {
let def_map = &mut self.def_collector.def_map; let def_map = &mut self.def_collector.def_map;
let vis = def_map let vis = def_map
.resolve_visibility(self.def_collector.db, self.module_id, visibility) .resolve_visibility(self.def_collector.db, self.module_id, visibility, false)
.unwrap_or(Visibility::Public); .unwrap_or(Visibility::Public);
let modules = &mut def_map.modules; let modules = &mut def_map.modules;
let origin = match definition { let origin = match definition {

View file

@ -78,6 +78,7 @@ impl DefMap {
// pub(path) // pub(path)
// ^^^^ this // ^^^^ this
visibility: &RawVisibility, visibility: &RawVisibility,
within_impl: bool,
) -> Option<Visibility> { ) -> Option<Visibility> {
let mut vis = match visibility { let mut vis = match visibility {
RawVisibility::Module(path) => { RawVisibility::Module(path) => {
@ -102,7 +103,8 @@ impl DefMap {
// `super` to its parent (etc.). However, visibilities must only refer to a module in the // `super` to its parent (etc.). However, visibilities must only refer to a module in the
// DefMap they're written in, so we restrict them when that happens. // DefMap they're written in, so we restrict them when that happens.
if let Visibility::Module(m) = vis { if let Visibility::Module(m) = vis {
if self.block_id() != m.block { // ...unless we're resolving visibility for an associated item in an impl.
if self.block_id() != m.block && !within_impl {
cov_mark::hit!(adjust_vis_in_block_def_map); cov_mark::hit!(adjust_vis_in_block_def_map);
vis = Visibility::Module(self.module_id(self.root())); vis = Visibility::Module(self.module_id(self.root()));
tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);

View file

@ -214,10 +214,12 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
visibility: &RawVisibility, visibility: &RawVisibility,
) -> Option<Visibility> { ) -> Option<Visibility> {
let within_impl =
self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
match visibility { match visibility {
RawVisibility::Module(_) => { RawVisibility::Module(_) => {
let (item_map, module) = self.item_scope(); let (item_map, module) = self.item_scope();
item_map.resolve_visibility(db, module, visibility) item_map.resolve_visibility(db, module, visibility, within_impl)
} }
RawVisibility::Public => Some(Visibility::Public), RawVisibility::Public => Some(Visibility::Public),
} }

View file

@ -120,7 +120,7 @@ impl Visibility {
self, self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
def_map: &DefMap, def_map: &DefMap,
mut from_module: crate::LocalModuleId, mut from_module: LocalModuleId,
) -> bool { ) -> bool {
let mut to_module = match self { let mut to_module = match self {
Visibility::Module(m) => m, Visibility::Module(m) => m,

View file

@ -115,6 +115,44 @@ mod module {
fn main(s: module::Struct) { fn main(s: module::Struct) {
s.method(); s.method();
} }
"#,
);
}
#[test]
fn can_see_through_top_level_anonymous_const() {
// regression test for #14046.
check_diagnostics(
r#"
struct S;
mod m {
const _: () = {
impl crate::S {
pub(crate) fn method(self) {}
pub(crate) const A: usize = 42;
}
};
mod inner {
const _: () = {
impl crate::S {
pub(crate) fn method2(self) {}
pub(crate) const B: usize = 42;
pub(super) fn private(self) {}
pub(super) const PRIVATE: usize = 42;
}
};
}
}
fn main() {
S.method();
S::A;
S.method2();
S::B;
S.private();
//^^^^^^^^^^^ error: function `private` is private
S::PRIVATE;
//^^^^^^^^^^ error: const `PRIVATE` is private
}
"#, "#,
); );
} }