From d11dbf648fa94bf04c92be274fa20f29f44868a5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 29 Apr 2025 10:49:41 +0200 Subject: [PATCH] Cleanup cfg check handling in expression store lowering --- crates/hir-def/src/attr.rs | 55 ++++-- crates/hir-def/src/expr_store/expander.rs | 18 +- crates/hir-def/src/expr_store/lower.rs | 93 ++++++----- .../hir-def/src/expr_store/lower/generics.rs | 2 +- crates/hir-def/src/item_tree.rs | 4 +- crates/hir-expand/src/attrs.rs | 158 +++++++++++------- crates/hir-expand/src/declarative.rs | 2 +- crates/ide-db/src/prime_caches.rs | 20 ++- crates/rust-analyzer/src/bin/main.rs | 6 +- crates/rust-analyzer/src/cli/diagnostics.rs | 12 +- .../src/cli/unresolved_references.rs | 12 +- crates/rust-analyzer/src/command.rs | 8 +- crates/rust-analyzer/src/flycheck.rs | 8 +- .../rust-analyzer/tests/slow-tests/support.rs | 3 +- crates/stdx/src/thread.rs | 13 +- crates/stdx/src/thread/pool.rs | 5 +- crates/vfs-notify/src/lib.rs | 3 +- 17 files changed, 234 insertions(+), 188 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index a80313aba3e4..bb6222b1d464 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -1,6 +1,6 @@ //! A higher level attributes based on TokenTree, with also some shortcuts. -use std::{borrow::Cow, hash::Hash, ops}; +use std::{borrow::Cow, convert::identity, hash::Hash, ops}; use base_db::Crate; use cfg::{CfgExpr, CfgOptions}; @@ -8,6 +8,7 @@ use either::Either; use hir_expand::{ HirFileId, InFile, attrs::{Attr, AttrId, RawAttrs, collect_attrs}, + span_map::SpanMapRef, }; use intern::{Symbol, sym}; use la_arena::{ArenaMap, Idx, RawIdx}; @@ -45,8 +46,27 @@ impl Attrs { (**self).iter().find(|attr| attr.id == id) } - pub(crate) fn filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs { - Attrs(raw_attrs.filter(db, krate)) + pub(crate) fn expand_cfg_attr( + db: &dyn DefDatabase, + krate: Crate, + raw_attrs: RawAttrs, + ) -> Attrs { + Attrs(raw_attrs.expand_cfg_attr(db, krate)) + } + + pub(crate) fn is_cfg_enabled_for( + db: &dyn DefDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, + ) -> Result<(), CfgExpr> { + RawAttrs::attrs_iter_expanded::(db, owner, span_map, cfg_options) + .filter_map(|attr| attr.cfg()) + .find_map(|cfg| match cfg_options.check(&cfg).is_none_or(identity) { + true => None, + false => Some(cfg), + }) + .map_or(Ok(()), Err) } } @@ -522,38 +542,41 @@ impl AttrsWithOwner { GenericParamId::ConstParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id()) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id()) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id()) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id()) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } GenericParamId::LifetimeParamId(it) => { let src = it.parent.child_source(db); // FIXME: We should be never getting `None` here. - match src.value.get(it.local_id) { - Some(val) => RawAttrs::from_attrs_owner( + return Attrs(match src.value.get(it.local_id) { + Some(val) => RawAttrs::new_expanded( db, - src.with_value(val), + val, db.span_map(src.file_id).as_ref(), + def.krate(db).cfg_options(db), ), None => RawAttrs::EMPTY, - } + }); } }, AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), @@ -561,7 +584,7 @@ impl AttrsWithOwner { AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), }; - let attrs = raw_attrs.filter(db, def.krate(db)); + let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db)); Attrs(attrs) } diff --git a/crates/hir-def/src/expr_store/expander.rs b/crates/hir-def/src/expr_store/expander.rs index 7eec913dd654..d24f4b7028d7 100644 --- a/crates/hir-def/src/expr_store/expander.rs +++ b/crates/hir-def/src/expr_store/expander.rs @@ -3,10 +3,11 @@ use std::mem; use base_db::Crate; +use cfg::CfgOptions; use drop_bomb::DropBomb; use hir_expand::{ ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, - attrs::RawAttrs, eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, + eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, }; use span::{AstIdMap, Edition, SyntaxContext}; use syntax::ast::HasAttrs; @@ -64,22 +65,13 @@ impl Expander { } } - pub(super) fn attrs( - &self, - db: &dyn DefDatabase, - krate: Crate, - has_attrs: &dyn HasAttrs, - ) -> Attrs { - Attrs::filter(db, krate, RawAttrs::new(db, has_attrs, self.span_map.as_ref())) - } - pub(super) fn is_cfg_enabled( &self, db: &dyn DefDatabase, - krate: Crate, has_attrs: &dyn HasAttrs, - ) -> bool { - self.attrs(db, krate, has_attrs).is_cfg_enabled(krate.cfg_options(db)) + cfg_options: &CfgOptions, + ) -> Result<(), cfg::CfgExpr> { + Attrs::is_cfg_enabled_for(db, has_attrs, self.span_map.as_ref(), cfg_options) } pub(super) fn call_syntax_ctx(&self) -> SyntaxContext { diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 7f907fdba8e3..50505d54ba2f 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -7,6 +7,7 @@ mod path; use std::mem; +use cfg::CfgOptions; use either::Either; use hir_expand::{ HirFileId, InFile, Lookup, MacroDefId, @@ -81,8 +82,6 @@ pub(super) fn lower_body( // even though they should be the same. Also, when the body comes from multiple expansions, their // hygiene is different. - let krate = module.krate(); - let mut self_param = None; let mut source_map_self_param = None; let mut params = vec![]; @@ -100,9 +99,8 @@ pub(super) fn lower_body( // and skip the body. if skip_body { if let Some(param_list) = parameters { - if let Some(self_param_syn) = param_list - .self_param() - .filter(|self_param| collector.expander.is_cfg_enabled(db, krate, self_param)) + if let Some(self_param_syn) = + param_list.self_param().filter(|self_param| collector.check_cfg(self_param)) { let is_mutable = self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); @@ -119,10 +117,7 @@ pub(super) fn lower_body( source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn))); } - let count = param_list - .params() - .filter(|it| collector.expander.is_cfg_enabled(db, krate, it)) - .count(); + let count = param_list.params().filter(|it| collector.check_cfg(it)).count(); params = (0..count).map(|_| collector.missing_pat()).collect(); }; let body_expr = collector.missing_expr(); @@ -138,9 +133,7 @@ pub(super) fn lower_body( } if let Some(param_list) = parameters { - if let Some(self_param_syn) = - param_list.self_param().filter(|it| collector.expander.is_cfg_enabled(db, krate, it)) - { + if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) { let is_mutable = self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none(); let hygiene = self_param_syn @@ -157,7 +150,7 @@ pub(super) fn lower_body( } for param in param_list.params() { - if collector.expander.is_cfg_enabled(db, krate, ¶m) { + if collector.check_cfg(¶m) { let param_pat = collector.collect_pat_top(param.pat()); params.push(param_pat); } @@ -346,7 +339,7 @@ pub(crate) fn lower_function( collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| { if let Some(param_list) = fn_.value.param_list() { if let Some(param) = param_list.self_param() { - let enabled = collector.expander.is_cfg_enabled(db, module.krate(), ¶m); + let enabled = collector.check_cfg(¶m); if enabled { has_self_param = true; params.push(match param.ty() { @@ -381,7 +374,7 @@ pub(crate) fn lower_function( } let p = param_list .params() - .filter(|param| collector.expander.is_cfg_enabled(db, module.krate(), param)) + .filter(|param| collector.check_cfg(param)) .filter(|param| { let is_variadic = param.dotdotdot_token().is_some(); has_variadic |= is_variadic; @@ -441,6 +434,7 @@ pub(crate) fn lower_function( pub struct ExprCollector<'db> { db: &'db dyn DefDatabase, + cfg_options: &'db CfgOptions, expander: Expander, def_map: Arc, local_def_map: Arc, @@ -553,6 +547,7 @@ impl ExprCollector<'_> { let expander = Expander::new(db, current_file_id, &def_map); ExprCollector { db, + cfg_options: module.krate().cfg_options(db), module, def_map, local_def_map, @@ -1026,7 +1021,9 @@ impl ExprCollector<'_> { /// Returns `None` if and only if the expression is `#[cfg]`d out. fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option { let syntax_ptr = AstPtr::new(&expr); - self.check_cfg(&expr)?; + if !self.check_cfg(&expr) { + return None; + } // FIXME: Move some of these arms out into separate methods for clarity Some(match expr { @@ -1114,6 +1111,7 @@ impl ExprCollector<'_> { ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e), ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e), ast::Expr::CallExpr(e) => { + // FIXME: Remove this once we drop support for <1.86, https://github.com/rust-lang/rust/commit/ac9cb908ac4301dfc25e7a2edee574320022ae2c let is_rustc_box = { let attrs = e.attrs(); attrs.filter_map(|it| it.as_simple_atom()).any(|it| it == "rustc_box") @@ -1156,13 +1154,17 @@ impl ExprCollector<'_> { match_arm_list .arms() .filter_map(|arm| { - self.check_cfg(&arm).map(|()| MatchArm { - pat: self.collect_pat_top(arm.pat()), - expr: self.collect_expr_opt(arm.expr()), - guard: arm - .guard() - .map(|guard| self.collect_expr_opt(guard.condition())), - }) + if self.check_cfg(&arm) { + Some(MatchArm { + pat: self.collect_pat_top(arm.pat()), + expr: self.collect_expr_opt(arm.expr()), + guard: arm + .guard() + .map(|guard| self.collect_expr_opt(guard.condition())), + }) + } else { + None + } }) .collect() } else { @@ -1230,7 +1232,9 @@ impl ExprCollector<'_> { let fields = nfl .fields() .filter_map(|field| { - self.check_cfg(&field)?; + if !self.check_cfg(&field) { + return None; + } let name = field.field_name()?.as_name(); @@ -1483,7 +1487,9 @@ impl ExprCollector<'_> { } fn maybe_collect_expr_as_pat(&mut self, expr: &ast::Expr) -> Option { - self.check_cfg(expr)?; + if !self.check_cfg(expr) { + return None; + } let syntax_ptr = AstPtr::new(expr); let result = match expr { @@ -1558,7 +1564,9 @@ impl ExprCollector<'_> { let args = record_field_list .fields() .filter_map(|f| { - self.check_cfg(&f)?; + if !self.check_cfg(&f) { + return None; + } let field_expr = f.expr()?; let pat = self.collect_expr_as_pat(field_expr); let name = f.field_name()?.as_name(); @@ -2044,7 +2052,7 @@ impl ExprCollector<'_> { fn collect_stmt(&mut self, statements: &mut Vec, s: ast::Stmt) { match s { ast::Stmt::LetStmt(stmt) => { - if self.check_cfg(&stmt).is_none() { + if !self.check_cfg(&stmt) { return; } let pat = self.collect_pat_top(stmt.pat()); @@ -2059,7 +2067,7 @@ impl ExprCollector<'_> { ast::Stmt::ExprStmt(stmt) => { let expr = stmt.expr(); match &expr { - Some(expr) if self.check_cfg(expr).is_none() => return, + Some(expr) if !self.check_cfg(expr) => return, _ => (), } let has_semi = stmt.semicolon_token().is_some(); @@ -2074,7 +2082,7 @@ impl ExprCollector<'_> { } } ast::Stmt::Item(ast::Item::MacroDef(macro_)) => { - if self.check_cfg(¯o_).is_none() { + if !self.check_cfg(¯o_) { return; } let Some(name) = macro_.name() else { @@ -2086,7 +2094,7 @@ impl ExprCollector<'_> { self.collect_macro_def(statements, macro_id); } ast::Stmt::Item(ast::Item::MacroRules(macro_)) => { - if self.check_cfg(¯o_).is_none() { + if !self.check_cfg(¯o_) { return; } let Some(name) = macro_.name() else { @@ -2360,7 +2368,9 @@ impl ExprCollector<'_> { let args = record_pat_field_list .fields() .filter_map(|f| { - self.check_cfg(&f)?; + if !self.check_cfg(&f) { + return None; + } let ast_pat = f.pat()?; let pat = self.collect_pat(ast_pat, binding_list); let name = f.field_name()?.as_name(); @@ -2536,25 +2546,18 @@ impl ExprCollector<'_> { /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when /// not. - fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> Option<()> { - let attrs = self.expander.attrs(self.db, self.module.krate(), owner); - match attrs.cfg() { - Some(cfg) => { - let cfg_options = self.module.krate().cfg_options(self.db); - - if cfg_options.check(&cfg) != Some(false) { - return Some(()); - } - + fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> bool { + let enabled = self.expander.is_cfg_enabled(self.db, owner, self.cfg_options); + match enabled { + Ok(()) => true, + Err(cfg) => { self.source_map.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode { node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())), cfg, - opts: cfg_options.clone(), + opts: self.cfg_options.clone(), }); - - None + false } - None => Some(()), } } diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 9485e703d9cb..42c85571f646 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -110,7 +110,7 @@ impl GenericParamsCollector { fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) { for generic_param in params.generic_params() { - let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param); + let enabled = ec.check_cfg(&generic_param); if !enabled { continue; } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 01d340cea6df..1b97eb72b6f2 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -179,7 +179,7 @@ impl ItemTree { /// Returns the inner attributes of the source file. pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs { - Attrs::filter( + Attrs::expand_cfg_attr( db, krate, self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(), @@ -191,7 +191,7 @@ impl ItemTree { } pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs { - Attrs::filter(db, krate, self.raw_attrs(of).clone()) + Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone()) } /// Returns a count of a few, expensive items. diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 5dae27f7a16c..107316239809 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, fmt, ops}; use base_db::Crate; -use cfg::CfgExpr; +use cfg::{CfgExpr, CfgOptions}; use either::Either; use intern::{Interned, Symbol, sym}; @@ -14,11 +14,10 @@ use syntax::{AstNode, AstToken, SyntaxNode, ast, match_ast}; use syntax_bridge::{DocCommentDesugarMode, desugar_doc_comment_text, syntax_node_to_token_tree}; use triomphe::ThinArc; -use crate::name::Name; use crate::{ - InFile, db::ExpandDatabase, mod_path::ModPath, + name::Name, span_map::SpanMapRef, tt::{self, TopSubtree, token_to_literal}, }; @@ -49,29 +48,7 @@ impl RawAttrs { owner: &dyn ast::HasAttrs, span_map: SpanMapRef<'_>, ) -> Self { - let entries: Vec<_> = collect_attrs(owner) - .filter_map(|(id, attr)| match attr { - Either::Left(attr) => { - attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id)) - } - Either::Right(comment) => comment.doc_comment().map(|doc| { - let span = span_map.span_for_range(comment.syntax().text_range()); - let (text, kind) = - desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro); - Attr { - id, - input: Some(Box::new(AttrInput::Literal(tt::Literal { - symbol: text, - span, - kind, - suffix: None, - }))), - path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), - ctxt: span.ctx, - } - }), - }) - .collect(); + let entries: Vec<_> = Self::attrs_iter::(db, owner, span_map).collect(); let entries = if entries.is_empty() { None @@ -82,12 +59,61 @@ impl RawAttrs { RawAttrs { entries } } - pub fn from_attrs_owner( + /// A [`RawAttrs`] that has its `#[cfg_attr(...)]` attributes expanded. + pub fn new_expanded( db: &dyn ExpandDatabase, - owner: InFile<&dyn ast::HasAttrs>, + owner: &dyn ast::HasAttrs, span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, ) -> Self { - Self::new(db, owner.value, span_map) + let entries: Vec<_> = + Self::attrs_iter_expanded::(db, owner, span_map, cfg_options).collect(); + + let entries = if entries.is_empty() { + None + } else { + Some(ThinArc::from_header_and_iter((), entries.into_iter())) + }; + + RawAttrs { entries } + } + + pub fn attrs_iter( + db: &dyn ExpandDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + ) -> impl Iterator { + collect_attrs(owner).filter_map(move |(id, attr)| match attr { + Either::Left(attr) => { + attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id)) + } + Either::Right(comment) if DESUGAR_COMMENTS => comment.doc_comment().map(|doc| { + let span = span_map.span_for_range(comment.syntax().text_range()); + let (text, kind) = desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro); + Attr { + id, + input: Some(Box::new(AttrInput::Literal(tt::Literal { + symbol: text, + span, + kind, + suffix: None, + }))), + path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), + ctxt: span.ctx, + } + }), + Either::Right(_) => None, + }) + } + + pub fn attrs_iter_expanded( + db: &dyn ExpandDatabase, + owner: &dyn ast::HasAttrs, + span_map: SpanMapRef<'_>, + cfg_options: &CfgOptions, + ) -> impl Iterator { + Self::attrs_iter::(db, owner, span_map) + .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options)) } pub fn merge(&self, other: Self) -> Self { @@ -114,9 +140,8 @@ impl RawAttrs { } } - /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. - // FIXME: This should return a different type, signaling it was filtered? - pub fn filter(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs { + /// Processes `cfg_attr`s + pub fn expand_cfg_attr(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs { let has_cfg_attrs = self.iter().any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr)); if !has_cfg_attrs { @@ -126,37 +151,8 @@ impl RawAttrs { let cfg_options = krate.cfg_options(db); let new_attrs = self .iter() - .flat_map(|attr| -> SmallVec<[_; 1]> { - let is_cfg_attr = attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr); - if !is_cfg_attr { - return smallvec![attr.clone()]; - } - - let subtree = match attr.token_tree_value() { - Some(it) => it, - _ => return smallvec![attr.clone()], - }; - - let (cfg, parts) = match parse_cfg_attr_input(subtree) { - Some(it) => it, - None => return smallvec![attr.clone()], - }; - let index = attr.id; - let attrs = parts - .enumerate() - .take(1 << AttrId::CFG_ATTR_BITS) - .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); - - let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); - let cfg = CfgExpr::parse(&cfg); - if cfg_options.check(&cfg) == Some(false) { - smallvec![] - } else { - cov_mark::hit!(cfg_attr_active); - - attrs.collect() - } - }) + .cloned() + .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options)) .collect::>(); let entries = if new_attrs.is_empty() { None @@ -316,6 +312,42 @@ impl Attr { pub fn path(&self) -> &ModPath { &self.path } + + pub fn expand_cfg_attr( + self, + db: &dyn ExpandDatabase, + cfg_options: &CfgOptions, + ) -> impl IntoIterator { + let is_cfg_attr = self.path.as_ident().is_some_and(|name| *name == sym::cfg_attr); + if !is_cfg_attr { + return smallvec![self.clone()]; + } + + let subtree = match self.token_tree_value() { + Some(it) => it, + _ => return smallvec![self.clone()], + }; + + let (cfg, parts) = match parse_cfg_attr_input(subtree) { + Some(it) => it, + None => return smallvec![self.clone()], + }; + let index = self.id; + let attrs = parts + .enumerate() + .take(1 << AttrId::CFG_ATTR_BITS) + .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); + + let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); + let cfg = CfgExpr::parse(&cfg); + if cfg_options.check(&cfg) == Some(false) { + smallvec![] + } else { + cov_mark::hit!(cfg_attr_active); + + attrs.collect::>() + } + } } impl Attr { diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs index 1fa682ce3a2d..0d100c1364ab 100644 --- a/crates/hir-expand/src/declarative.rs +++ b/crates/hir-expand/src/declarative.rs @@ -82,7 +82,7 @@ impl DeclarativeMacroExpander { let transparency = |node| { // ... would be nice to have the item tree here - let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate); + let attrs = RawAttrs::new_expanded(db, node, map.as_ref(), def_crate.cfg_options(db)); match attrs .iter() .find(|it| { diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs index 5e8d016bfb02..cbe31405ab78 100644 --- a/crates/ide-db/src/prime_caches.rs +++ b/crates/ide-db/src/prime_caches.rs @@ -90,15 +90,17 @@ pub fn parallel_prime_caches( }; for id in 0..num_worker_threads { - stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .allow_leak(true) - .name(format!("PrimeCaches#{id}")) - .spawn({ - let worker = prime_caches_worker.clone(); - let db = db.clone(); - move || worker(db) - }) - .expect("failed to spawn thread"); + stdx::thread::Builder::new( + stdx::thread::ThreadIntent::Worker, + format!("PrimeCaches#{id}"), + ) + .allow_leak(true) + .spawn({ + let worker = prime_caches_worker.clone(); + let db = db.clone(); + move || worker(db) + }) + .expect("failed to spawn thread"); } (work_sender, progress_receiver) diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index ea5a5eaa6a44..4dba97c8ec49 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -182,10 +182,8 @@ fn with_extra_thread( thread_intent: stdx::thread::ThreadIntent, f: impl FnOnce() -> anyhow::Result<()> + Send + 'static, ) -> anyhow::Result<()> { - let handle = stdx::thread::Builder::new(thread_intent) - .name(thread_name.into()) - .stack_size(STACK_SIZE) - .spawn(f)?; + let handle = + stdx::thread::Builder::new(thread_intent, thread_name).stack_size(STACK_SIZE).spawn(f)?; handle.join()?; diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 7c4eeebdfa31..7b12cb14009f 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs @@ -15,11 +15,13 @@ impl flags::Diagnostics { pub fn run(self) -> anyhow::Result<()> { const STACK_SIZE: usize = 1024 * 1024 * 8; - let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive) - .name("BIG_STACK_THREAD".into()) - .stack_size(STACK_SIZE) - .spawn(|| self.run_()) - .unwrap(); + let handle = stdx::thread::Builder::new( + stdx::thread::ThreadIntent::LatencySensitive, + "BIG_STACK_THREAD", + ) + .stack_size(STACK_SIZE) + .spawn(|| self.run_()) + .unwrap(); handle.join() } diff --git a/crates/rust-analyzer/src/cli/unresolved_references.rs b/crates/rust-analyzer/src/cli/unresolved_references.rs index bca7c8a098c2..1d4fbb942235 100644 --- a/crates/rust-analyzer/src/cli/unresolved_references.rs +++ b/crates/rust-analyzer/src/cli/unresolved_references.rs @@ -15,11 +15,13 @@ impl flags::UnresolvedReferences { pub fn run(self) -> anyhow::Result<()> { const STACK_SIZE: usize = 1024 * 1024 * 8; - let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive) - .name("BIG_STACK_THREAD".into()) - .stack_size(STACK_SIZE) - .spawn(|| self.run_()) - .unwrap(); + let handle = stdx::thread::Builder::new( + stdx::thread::ThreadIntent::LatencySensitive, + "BIG_STACK_THREAD", + ) + .stack_size(STACK_SIZE) + .spawn(|| self.run_()) + .unwrap(); handle.join() } diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs index 0035d941e2c6..d6c80c399ba2 100644 --- a/crates/rust-analyzer/src/command.rs +++ b/crates/rust-analyzer/src/command.rs @@ -148,10 +148,10 @@ impl CommandHandle { let stderr = child.0.stderr().take().unwrap(); let actor = CargoActor::::new(parser, sender, stdout, stderr); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("CommandHandle".to_owned()) - .spawn(move || actor.run()) - .expect("failed to spawn thread"); + let thread = + stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle") + .spawn(move || actor.run()) + .expect("failed to spawn thread"); Ok(CommandHandle { program, arguments, current_dir, child, thread, _phantom: PhantomData }) } diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs index 2778b311e1e3..fc312439d58c 100644 --- a/crates/rust-analyzer/src/flycheck.rs +++ b/crates/rust-analyzer/src/flycheck.rs @@ -133,10 +133,10 @@ impl FlycheckHandle { let actor = FlycheckActor::new(id, sender, config, sysroot_root, workspace_root, manifest_path); let (sender, receiver) = unbounded::(); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("Flycheck".to_owned()) - .spawn(move || actor.run(receiver)) - .expect("failed to spawn thread"); + let thread = + stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, format!("Flycheck{id}")) + .spawn(move || actor.run(receiver)) + .expect("failed to spawn thread"); FlycheckHandle { id, sender, _thread: thread } } diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index 3f97952365f3..7b5a53311217 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -298,8 +298,7 @@ impl Server { ) -> Server { let (connection, client) = Connection::memory(); - let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("test server".to_owned()) + let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "test server") .spawn(move || main_loop(config, connection).unwrap()) .expect("failed to spawn a thread"); diff --git a/crates/stdx/src/thread.rs b/crates/stdx/src/thread.rs index 3d1453831269..a34e9e4a6551 100644 --- a/crates/stdx/src/thread.rs +++ b/crates/stdx/src/thread.rs @@ -26,12 +26,12 @@ pub use pool::Pool; /// # Panics /// /// Panics if failed to spawn the thread. -pub fn spawn(intent: ThreadIntent, f: F) -> JoinHandle +pub fn spawn(intent: ThreadIntent, name: String, f: F) -> JoinHandle where F: (FnOnce() -> T) + Send + 'static, T: Send + 'static, { - Builder::new(intent).spawn(f).expect("failed to spawn thread") + Builder::new(intent, name).spawn(f).expect("failed to spawn thread") } pub struct Builder { @@ -42,13 +42,8 @@ pub struct Builder { impl Builder { #[must_use] - pub fn new(intent: ThreadIntent) -> Self { - Self { intent, inner: jod_thread::Builder::new(), allow_leak: false } - } - - #[must_use] - pub fn name(self, name: String) -> Self { - Self { inner: self.inner.name(name), ..self } + pub fn new(intent: ThreadIntent, name: impl Into) -> Self { + Self { intent, inner: jod_thread::Builder::new().name(name.into()), allow_leak: false } } #[must_use] diff --git a/crates/stdx/src/thread/pool.rs b/crates/stdx/src/thread/pool.rs index 074cd747dacc..a8de4db624f1 100644 --- a/crates/stdx/src/thread/pool.rs +++ b/crates/stdx/src/thread/pool.rs @@ -50,10 +50,9 @@ impl Pool { let extant_tasks = Arc::new(AtomicUsize::new(0)); let mut handles = Vec::with_capacity(threads); - for _ in 0..threads { - let handle = Builder::new(INITIAL_INTENT) + for idx in 0..threads { + let handle = Builder::new(INITIAL_INTENT, format!("Worker{idx}",)) .stack_size(STACK_SIZE) - .name("Worker".into()) .allow_leak(true) .spawn({ let extant_tasks = Arc::clone(&extant_tasks); diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index e918fd0887db..a03337dbc51e 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs @@ -38,8 +38,7 @@ impl loader::Handle for NotifyHandle { fn spawn(sender: loader::Sender) -> NotifyHandle { let actor = NotifyActor::new(sender); let (sender, receiver) = unbounded::(); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("VfsLoader".to_owned()) + let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "VfsLoader") .spawn(move || actor.run(receiver)) .expect("failed to spawn thread"); NotifyHandle { sender, _thread: thread }