Skip to content

feat: make trait assoc items become inactive due to cfg #12965

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 22, 2022
Merged
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
70 changes: 53 additions & 17 deletions crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::sync::Arc;

use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind};
use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
use smallvec::SmallVec;
use syntax::ast;

Expand All @@ -12,7 +12,10 @@ use crate::{
db::DefDatabase,
intern::Interned,
item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap},
nameres::{
attr_resolution::ResolvedAttr, diagnostics::DefDiagnostic, proc_macro::ProcMacroKind,
DefMap,
},
type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
Expand Down Expand Up @@ -210,6 +213,13 @@ pub struct TraitData {

impl TraitData {
pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
db.trait_data_with_diagnostics(tr).0
}

pub(crate) fn trait_data_with_diagnostics_query(
db: &dyn DefDatabase,
tr: TraitId,
) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
let item_tree = tree_id.item_tree(db);
let tr_def = &item_tree[tree_id.value];
Expand All @@ -229,17 +239,20 @@ impl TraitData {
let mut collector =
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
let (items, attribute_calls) = collector.finish();

Arc::new(TraitData {
name,
attribute_calls,
items,
is_auto,
is_unsafe,
visibility,
skip_array_during_method_dispatch,
})
let (items, attribute_calls, diagnostics) = collector.finish();

(
Arc::new(TraitData {
name,
attribute_calls,
items,
is_auto,
is_unsafe,
visibility,
skip_array_during_method_dispatch,
}),
Arc::new(diagnostics),
)
}

pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
Expand Down Expand Up @@ -280,7 +293,14 @@ pub struct ImplData {

impl ImplData {
pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
let _p = profile::span("impl_data_query");
db.impl_data_with_diagnostics(id).0
}

pub(crate) fn impl_data_with_diagnostics_query(
db: &dyn DefDatabase,
id: ImplId,
) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
let _p = profile::span("impl_data_with_diagnostics_query");
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);

let item_tree = tree_id.item_tree(db);
Expand All @@ -293,10 +313,13 @@ impl ImplData {
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);

let (items, attribute_calls) = collector.finish();
let (items, attribute_calls, diagnostics) = collector.finish();
let items = items.into_iter().map(|(_, item)| item).collect();

Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls })
(
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
Arc::new(diagnostics),
)
}

pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
Expand Down Expand Up @@ -437,6 +460,7 @@ struct AssocItemCollector<'a> {
db: &'a dyn DefDatabase,
module_id: ModuleId,
def_map: Arc<DefMap>,
inactive_diagnostics: Vec<DefDiagnostic>,
container: ItemContainerId,
expander: Expander,

Expand All @@ -459,15 +483,21 @@ impl<'a> AssocItemCollector<'a> {
expander: Expander::new(db, file_id, module_id),
items: Vec::new(),
attr_calls: Vec::new(),
inactive_diagnostics: Vec::new(),
}
}

fn finish(
self,
) -> (Vec<(Name, AssocItemId)>, Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>) {
) -> (
Vec<(Name, AssocItemId)>,
Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
Vec<DefDiagnostic>,
) {
(
self.items,
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
self.inactive_diagnostics,
)
}

Expand All @@ -479,6 +509,12 @@ impl<'a> AssocItemCollector<'a> {
'items: for &item in assoc_items {
let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
self.inactive_diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id.local_id,
InFile::new(self.expander.current_file_id(), item.ast_id(&item_tree).upcast()),
attrs.cfg().unwrap(),
self.expander.cfg_options().clone(),
));
continue;
}

Expand Down
9 changes: 8 additions & 1 deletion crates/hir-def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
intern::Interned,
item_tree::{AttrOwner, ItemTree},
lang_item::{LangItemTarget, LangItems},
nameres::DefMap,
nameres::{diagnostics::DefDiagnostic, DefMap},
visibility::{self, Visibility},
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
Expand Down Expand Up @@ -106,9 +106,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
#[salsa::invoke(ImplData::impl_data_query)]
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;

#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);

#[salsa::invoke(TraitData::trait_data_query)]
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;

#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
fn trait_data_with_diagnostics(&self, tr: TraitId)
-> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);

#[salsa::invoke(TypeAliasData::type_alias_data_query)]
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;

Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/nameres/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl DefDiagnostic {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
}

pub(super) fn unconfigured_code(
pub fn unconfigured_code(
container: LocalModuleId,
ast: AstId<ast::Item>,
cfg: CfgExpr,
Expand Down
11 changes: 11 additions & 0 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ impl Module {
.collect()
}

/// Fills `acc` with the module's diagnostics.
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
let _p = profile::span("Module::diagnostics").detail(|| {
format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
Expand All @@ -531,11 +532,21 @@ impl Module {
m.diagnostics(db, acc)
}
}
ModuleDef::Trait(t) => {
for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
emit_def_diagnostic(db, acc, diag);
}
acc.extend(decl.diagnostics(db))
}
_ => acc.extend(decl.diagnostics(db)),
}
}

for impl_def in self.impl_defs(db) {
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
emit_def_diagnostic(db, acc, diag);
}

for item in impl_def.items(db) {
let def: DefWithBody = match item {
AssocItem::Function(it) => it.into(),
Expand Down
5 changes: 2 additions & 3 deletions crates/ide-diagnostics/src/handlers/inactive_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,17 @@ fn f() {

#[test]
fn inactive_assoc_item() {
// FIXME these currently don't work, hence the *
check(
r#"
struct Foo;
impl Foo {
#[cfg(any())] pub fn f() {}
//*************************** weak: code is inactive due to #[cfg] directives
//^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
}

trait Bar {
#[cfg(any())] pub fn f() {}
//*************************** weak: code is inactive due to #[cfg] directives
//^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives
}
"#,
);
Expand Down