Unify assoc item visibility queries

This commit is contained in:
Lukas Wirth 2025-06-15 09:59:56 +02:00
parent bceeb6a3c7
commit 4b38ea5abd
5 changed files with 59 additions and 78 deletions

View file

@ -11,10 +11,10 @@ use syntax::{AstPtr, ast};
use triomphe::Arc;
use crate::{
AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc,
ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc,
GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, MacroId,
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId,
AssocItemId, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId,
EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander,
MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId,
StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId,
TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
attr::{Attrs, AttrsWithOwner},
@ -298,16 +298,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
#[salsa::invoke(visibility::field_visibilities_query)]
fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>;
// FIXME: unify function_visibility and const_visibility?
#[salsa::invoke(visibility::function_visibility_query)]
fn function_visibility(&self, def: FunctionId) -> Visibility;
#[salsa::invoke(visibility::const_visibility_query)]
fn const_visibility(&self, def: ConstId) -> Visibility;
#[salsa::invoke(visibility::type_alias_visibility_query)]
fn type_alias_visibility(&self, def: TypeAliasId) -> Visibility;
#[salsa::invoke(visibility::assoc_visibility_query)]
fn assoc_visibility(&self, def: AssocItemId) -> Visibility;
// endregion:visibilities

View file

@ -793,7 +793,7 @@ impl DefWithBodyId {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, salsa_macros::Supertype)]
pub enum AssocItemId {
FunctionId(FunctionId),
ConstId(ConstId),

View file

@ -8,12 +8,8 @@ use syntax::ast::{self, HasVisibility};
use triomphe::Arc;
use crate::{
ConstId, FunctionId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId,
TraitId, TypeAliasId, VariantId,
db::DefDatabase,
nameres::DefMap,
resolver::{HasResolver, Resolver},
src::HasSource,
AssocItemId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, TraitId,
VariantId, db::DefDatabase, nameres::DefMap, resolver::HasResolver, src::HasSource,
};
pub use crate::item_tree::{RawVisibility, VisibilityExplicitness};
@ -225,63 +221,56 @@ pub(crate) fn field_visibilities_query(
pub fn visibility_from_ast(
db: &dyn DefDatabase,
resolver: &Resolver<'_>,
has_resolver: impl HasResolver,
ast_vis: InFile<Option<ast::Visibility>>,
) -> Visibility {
let mut span_map = None;
let raw_vis = crate::item_tree::visibility_from_ast(db, ast_vis.value, &mut |range| {
span_map.get_or_insert_with(|| db.span_map(ast_vis.file_id)).span_for_range(range).ctx
});
Visibility::resolve(db, resolver, &raw_vis)
if raw_vis == RawVisibility::Public {
return Visibility::Public;
}
Visibility::resolve(db, &has_resolver.resolver(db), &raw_vis)
}
fn trait_item_visibility(
db: &dyn DefDatabase,
resolver: &Resolver<'_>,
container: ItemContainerId,
) -> Option<Visibility> {
/// Resolve visibility of a type alias.
pub(crate) fn assoc_visibility_query(db: &dyn DefDatabase, def: AssocItemId) -> Visibility {
match def {
AssocItemId::FunctionId(function_id) => {
let loc = function_id.lookup(db);
trait_item_visibility(db, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, function_id, source.map(|src| src.visibility()))
})
}
AssocItemId::ConstId(const_id) => {
let loc = const_id.lookup(db);
trait_item_visibility(db, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, const_id, source.map(|src| src.visibility()))
})
}
AssocItemId::TypeAliasId(type_alias_id) => {
let loc = type_alias_id.lookup(db);
trait_item_visibility(db, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, type_alias_id, source.map(|src| src.visibility()))
})
}
}
}
fn trait_item_visibility(db: &dyn DefDatabase, container: ItemContainerId) -> Option<Visibility> {
match container {
ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, resolver, trait_)),
ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, trait_)),
_ => None,
}
}
/// Resolve visibility of a function.
pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility {
let loc = def.lookup(db);
let resolver = def.resolver(db);
trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, &resolver, source.map(|src| src.visibility()))
})
}
/// Resolve visibility of a const.
pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility {
let loc = def.lookup(db);
let resolver = def.resolver(db);
trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, &resolver, source.map(|src| src.visibility()))
})
}
/// Resolve visibility of a type alias.
pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility {
let loc = def.lookup(db);
let resolver = def.resolver(db);
trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| {
let source = loc.source(db);
visibility_from_ast(db, &resolver, source.map(|src| src.visibility()))
})
}
pub(crate) fn trait_visibility(
db: &dyn DefDatabase,
resolver: &Resolver<'_>,
def: TraitId,
) -> Visibility {
fn trait_visibility(db: &dyn DefDatabase, def: TraitId) -> Visibility {
let loc = def.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, resolver, source.map(|src| src.visibility()))
visibility_from_ast(db, def, source.map(|src| src.visibility()))
}

View file

@ -1550,7 +1550,7 @@ fn is_valid_impl_method_candidate(
check_that!(name.is_none_or(|n| n == item_name));
if let Some(from_module) = visible_from_module {
if !db.const_visibility(c).is_visible_from(db, from_module) {
if !db.assoc_visibility(c.into()).is_visible_from(db, from_module) {
cov_mark::hit!(const_candidate_not_visible);
return IsValidCandidate::NotVisible;
}
@ -1639,7 +1639,7 @@ fn is_valid_impl_fn_candidate(
let data = db.function_signature(fn_id);
if let Some(from_module) = visible_from_module {
if !db.function_visibility(fn_id).is_visible_from(db, from_module) {
if !db.assoc_visibility(fn_id.into()).is_visible_from(db, from_module) {
cov_mark::hit!(autoderef_candidate_not_visible);
return IsValidCandidate::NotVisible;
}

View file

@ -1431,7 +1431,7 @@ impl HasVisibility for Struct {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -1485,7 +1485,7 @@ impl HasVisibility for Union {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -1574,7 +1574,7 @@ impl HasVisibility for Enum {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -2632,7 +2632,7 @@ impl SelfParam {
impl HasVisibility for Function {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
db.function_visibility(self.id)
db.assoc_visibility(self.id.into())
}
}
@ -2692,7 +2692,7 @@ impl HasVisibility for ExternCrateDecl {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -2727,7 +2727,7 @@ impl Const {
impl HasVisibility for Const {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
db.const_visibility(self.id)
db.assoc_visibility(self.id.into())
}
}
@ -2813,7 +2813,7 @@ impl HasVisibility for Static {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -2915,7 +2915,7 @@ impl HasVisibility for Trait {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -2938,7 +2938,7 @@ impl HasVisibility for TraitAlias {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
let loc = self.id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
}
}
@ -2976,7 +2976,7 @@ impl TypeAlias {
impl HasVisibility for TypeAlias {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
db.type_alias_visibility(self.id)
db.assoc_visibility(self.id.into())
}
}
@ -3200,7 +3200,7 @@ impl HasVisibility for Macro {
MacroId::Macro2Id(id) => {
let loc = id.lookup(db);
let source = loc.source(db);
visibility_from_ast(db, &id.resolver(db), source.map(|src| src.visibility()))
visibility_from_ast(db, id, source.map(|src| src.visibility()))
}
MacroId::MacroRulesId(_) => Visibility::Public,
MacroId::ProcMacroId(_) => Visibility::Public,