Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/db.rs')
| -rw-r--r-- | crates/hir-expand/src/db.rs | 159 |
1 files changed, 69 insertions, 90 deletions
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 8dddddfabb..beae6e843e 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -3,6 +3,7 @@ use base_db::{Crate, SourceDatabase}; use mbe::MatchedArmIndex; use span::{AstIdMap, Edition, Span, SyntaxContext}; +use std::borrow::Cow; use syntax::{AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, ast}; use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree}; use triomphe::Arc; @@ -17,11 +18,11 @@ use crate::{ fixup::{self, SyntaxFixupUndoInfo}, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt}, proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros}, - span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, + span_map::{ExpansionSpanMap, RealSpanMap, SpanMap}, tt, }; /// This is just to ensure the types of smart_macro_arg and macro_arg are the same -type MacroArgResult = (Arc<tt::TopSubtree>, SyntaxFixupUndoInfo, Span); +type MacroArgResult = (tt::TopSubtree, SyntaxFixupUndoInfo, Span); /// Total limit on the number of tokens produced by any macro invocation. /// /// If an invocation produces more tokens than this limit, it will not be stored in the database and @@ -30,10 +31,10 @@ type MacroArgResult = (Arc<tt::TopSubtree>, SyntaxFixupUndoInfo, Span); /// Actual max for `analysis-stats .` at some point: 30672. const TOKEN_LIMIT: usize = 2_097_152; -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum TokenExpander { +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum TokenExpander<'db> { /// Old-style `macro_rules` or the new macros 2.0 - DeclarativeMacro(Arc<DeclarativeMacroExpander>), + DeclarativeMacro(&'db DeclarativeMacroExpander), /// Stuff like `line!` and `file!`. BuiltIn(BuiltinFnLikeExpander), /// Built-in eagerly expanded fn-like macros (`include!`, `concat!`, etc.) @@ -67,65 +68,59 @@ pub trait ExpandDatabase: SourceDatabase { fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode; /// Implementation for the macro case. - #[salsa::lru(512)] + #[salsa::transparent] fn parse_macro_expansion( &self, macro_file: MacroCallId, - ) -> ExpandResult<(Parse<SyntaxNode>, Arc<ExpansionSpanMap>)>; + ) -> &ExpandResult<(Parse<SyntaxNode>, ExpansionSpanMap)>; #[salsa::transparent] #[salsa::invoke(SpanMap::new)] - fn span_map(&self, file_id: HirFileId) -> SpanMap; + fn span_map(&self, file_id: HirFileId) -> SpanMap<'_>; #[salsa::transparent] #[salsa::invoke(crate::span_map::expansion_span_map)] - fn expansion_span_map(&self, file_id: MacroCallId) -> Arc<ExpansionSpanMap>; + fn expansion_span_map(&self, file_id: MacroCallId) -> &ExpansionSpanMap; #[salsa::invoke(crate::span_map::real_span_map)] - fn real_span_map(&self, file_id: EditionedFileId) -> Arc<RealSpanMap>; - - /// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the - /// reason why we use salsa at all. - /// - /// We encode macro definitions into ids of macro calls, this what allows us - /// to be incremental. - #[salsa::transparent] - fn intern_macro_call(&self, macro_call: MacroCallLoc) -> MacroCallId; #[salsa::transparent] - fn lookup_intern_macro_call(&self, macro_call: MacroCallId) -> MacroCallLoc; + fn real_span_map(&self, file_id: EditionedFileId) -> &RealSpanMap; /// Lowers syntactic macro call to a token tree representation. That's a firewall /// query, only typing in the macro call itself changes the returned /// subtree. #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"] #[salsa::invoke(macro_arg)] - fn macro_arg(&self, id: MacroCallId) -> MacroArgResult; + #[salsa::transparent] + fn macro_arg(&self, id: MacroCallId) -> &MacroArgResult; #[salsa::transparent] - fn macro_arg_considering_derives( - &self, + fn macro_arg_considering_derives<'db>( + &'db self, id: MacroCallId, kind: &MacroCallKind, - ) -> MacroArgResult; + ) -> &'db MacroArgResult; /// Fetches the expander for this macro. #[salsa::transparent] #[salsa::invoke(TokenExpander::macro_expander)] - fn macro_expander(&self, id: MacroDefId) -> TokenExpander; + fn macro_expander(&self, id: MacroDefId) -> TokenExpander<'_>; /// Fetches (and compiles) the expander of this decl macro. #[salsa::invoke(DeclarativeMacroExpander::expander)] + #[salsa::transparent] fn decl_macro_expander( &self, def_crate: Crate, id: AstId<ast::Macro>, - ) -> Arc<DeclarativeMacroExpander>; + ) -> &DeclarativeMacroExpander; /// Special case of the previous query for procedural macros. We can't LRU /// proc macros, since they are not deterministic in general, and /// non-determinism breaks salsa in a very, very, very bad way. /// @edwin0cheng heroically debugged this once! See #4315 for details #[salsa::invoke(expand_proc_macro)] - fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<Arc<tt::TopSubtree>>; + #[salsa::transparent] + fn expand_proc_macro(&self, call: MacroCallId) -> &ExpandResult<tt::TopSubtree>; /// Retrieves the span to be used for a proc-macro expansions spans. /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to /// directly depend on as that would cause to frequent invalidations, mainly because of the @@ -134,12 +129,12 @@ pub trait ExpandDatabase: SourceDatabase { #[salsa::invoke_interned(proc_macro_span)] fn proc_macro_span(&self, fun: AstId<ast::Fn>) -> Span; - /// Firewall query that returns the errors from the `parse_macro_expansion` query. #[salsa::invoke(parse_macro_expansion_error)] + #[salsa::transparent] fn parse_macro_expansion_error( &self, macro_call: MacroCallId, - ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>; + ) -> Option<ExpandResult<Arc<[SyntaxError]>>>; #[salsa::transparent] fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; @@ -154,7 +149,7 @@ fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> match file { HirFileId::FileId(_) => SyntaxContext::root(edition), HirFileId::MacroFile(m) => { - let kind = db.lookup_intern_macro_call(m).kind; + let kind = m.loc(db).kind; db.macro_arg_considering_derives(m, &kind).2.ctx } } @@ -177,11 +172,11 @@ pub fn expand_speculative( speculative_args: &SyntaxNode, token_to_map: SyntaxToken, ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { - let loc = db.lookup_intern_macro_call(actual_macro_call); - let (_, _, span) = db.macro_arg_considering_derives(actual_macro_call, &loc.kind); + let loc = actual_macro_call.loc(db); + let (_, _, span) = *db.macro_arg_considering_derives(actual_macro_call, &loc.kind); let span_map = RealSpanMap::absolute(span.anchor.file_id); - let span_map = SpanMapRef::RealSpanMap(&span_map); + let span_map = SpanMap::RealSpanMap(&span_map); // Build the subtree and token mapping for the speculative args let (mut tt, undo_info) = match &loc.kind { @@ -358,48 +353,42 @@ fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode { // FIXME: We should verify that the parsed node is one of the many macro node variants we expect // instead of having it be untyped +#[salsa_macros::tracked(returns(ref), lru = 512)] fn parse_macro_expansion( db: &dyn ExpandDatabase, macro_file: MacroCallId, -) -> ExpandResult<(Parse<SyntaxNode>, Arc<ExpansionSpanMap>)> { +) -> ExpandResult<(Parse<SyntaxNode>, ExpansionSpanMap)> { let _p = tracing::info_span!("parse_macro_expansion").entered(); - let loc = db.lookup_intern_macro_call(macro_file); + let loc = macro_file.loc(db); let expand_to = loc.expand_to(); let mbe::ValueResult { value: (tt, matched_arm), err } = macro_expand(db, macro_file, loc); - let (parse, mut rev_token_map) = token_tree_to_syntax_node( - db, - match &tt { - CowArc::Arc(it) => it, - CowArc::Owned(it) => it, - }, - expand_to, - ); + let (parse, mut rev_token_map) = token_tree_to_syntax_node(db, &tt, expand_to); rev_token_map.matched_arm = matched_arm; - ExpandResult { value: (parse, Arc::new(rev_token_map)), err } + ExpandResult { value: (parse, rev_token_map), err } } fn parse_macro_expansion_error( db: &dyn ExpandDatabase, macro_call_id: MacroCallId, -) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>> { +) -> Option<ExpandResult<Arc<[SyntaxError]>>> { let e: ExpandResult<Arc<[SyntaxError]>> = - db.parse_macro_expansion(macro_call_id).map(|it| Arc::from(it.0.errors())); - if e.value.is_empty() && e.err.is_none() { None } else { Some(Arc::new(e)) } + db.parse_macro_expansion(macro_call_id).as_ref().map(|it| Arc::from(it.0.errors())); + if e.value.is_empty() && e.err.is_none() { None } else { Some(e) } } pub(crate) fn parse_with_map( db: &dyn ExpandDatabase, file_id: HirFileId, -) -> (Parse<SyntaxNode>, SpanMap) { +) -> (Parse<SyntaxNode>, SpanMap<'_>) { match file_id { HirFileId::FileId(file_id) => { (file_id.parse(db).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id))) } HirFileId::MacroFile(macro_file) => { - let (parse, map) = db.parse_macro_expansion(macro_file).value; - (parse, SpanMap::ExpansionSpanMap(map)) + let (parse, map) = &db.parse_macro_expansion(macro_file).value; + (parse.clone(), SpanMap::ExpansionSpanMap(map)) } } } @@ -409,11 +398,11 @@ pub(crate) fn parse_with_map( /// /// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is #[allow(deprecated)] // we are macro_arg_considering_derives -fn macro_arg_considering_derives( - db: &dyn ExpandDatabase, +fn macro_arg_considering_derives<'db>( + db: &'db dyn ExpandDatabase, id: MacroCallId, kind: &MacroCallKind, -) -> MacroArgResult { +) -> &'db MacroArgResult { match kind { // Get the macro arg for the derive macro MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(*derive_macro_id), @@ -422,8 +411,9 @@ fn macro_arg_considering_derives( } } +#[salsa_macros::tracked(returns(ref))] fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { - let loc = db.lookup_intern_macro_call(id); + let loc = id.loc(db); if let MacroCallLoc { def: MacroDefId { kind: MacroDefKind::BuiltInEager(..), .. }, @@ -447,10 +437,10 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { let dummy_tt = |kind| { ( - Arc::new(tt::TopSubtree::from_token_trees( + tt::TopSubtree::from_token_trees( tt::Delimiter { open: span, close: span, kind }, tt::TokenTreesView::empty(), - )), + ), SyntaxFixupUndoInfo::default(), span, ) @@ -487,7 +477,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { let mut tt = syntax_bridge::syntax_node_to_token_tree( tt.syntax(), - map.as_ref(), + map, span, if loc.def.is_proc_macro() { DocCommentDesugarMode::ProcMacro @@ -499,7 +489,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { // proc macros expect their inputs without parentheses, MBEs expect it with them included tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); } - return (Arc::new(tt), SyntaxFixupUndoInfo::NONE, span); + return (tt, SyntaxFixupUndoInfo::NONE, span); } // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro MacroCallKind::Derive { .. } => { @@ -522,7 +512,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { let (mut tt, undo_info) = attr_macro_input_to_token_tree( db, item_node.syntax(), - map.as_ref(), + map, span, is_derive, censor_item_tree_attr_ids, @@ -534,11 +524,11 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult { tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); } - (Arc::new(tt), undo_info, span) + (tt, undo_info, span) } -impl TokenExpander { - fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { +impl<'db> TokenExpander<'db> { + fn macro_expander(db: &'db dyn ExpandDatabase, id: MacroDefId) -> TokenExpander<'db> { match id.kind { MacroDefKind::Declarative(ast_id, _) => { TokenExpander::DeclarativeMacro(db.decl_macro_expander(id.krate, ast_id)) @@ -552,27 +542,26 @@ impl TokenExpander { } } -enum CowArc<T> { - Arc(Arc<T>), - Owned(T), -} - fn macro_expand( db: &dyn ExpandDatabase, macro_call_id: MacroCallId, loc: MacroCallLoc, -) -> ExpandResult<(CowArc<tt::TopSubtree>, MatchedArmIndex)> { +) -> ExpandResult<(Cow<'_, tt::TopSubtree>, MatchedArmIndex)> { let _p = tracing::info_span!("macro_expand").entered(); let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind { MacroDefKind::ProcMacro(..) => { - return db.expand_proc_macro(macro_call_id).map(CowArc::Arc).zip_val(None); + return db + .expand_proc_macro(macro_call_id) + .as_ref() + .map(|it| (Cow::Borrowed(it), None)); } _ => { let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(macro_call_id, &loc.kind); + let span = *span; - let arg = &*macro_arg; + let arg = macro_arg; let res = match loc.def.kind { MacroDefKind::Declarative(id, _) => db .decl_macro_expander(loc.def.krate, id) @@ -592,7 +581,7 @@ fn macro_expand( // As such we just return the input subtree here. let eager = match &loc.kind { MacroCallKind::FnLike { eager: None, .. } => { - return ExpandResult::ok(CowArc::Arc(macro_arg.clone())).zip_val(None); + return ExpandResult::ok(Cow::Borrowed(macro_arg)).zip_val(None); } MacroCallKind::FnLike { eager: Some(eager), .. } => Some(&**eager), _ => None, @@ -608,7 +597,7 @@ fn macro_expand( } MacroDefKind::BuiltInAttr(_, it) => { let mut res = it.expand(db, macro_call_id, arg, span); - fixup::reverse_fixups(&mut res.value, &undo_info); + fixup::reverse_fixups(&mut res.value, undo_info); res.zip_val(None) } MacroDefKind::ProcMacro(_, _, _) => unreachable!(), @@ -622,12 +611,12 @@ fn macro_expand( // Set a hard limit for the expanded tt if let Err(value) = check_tt_count(&tt) { return value - .map(|()| CowArc::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)))) + .map(|()| Cow::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)))) .zip_val(matched_arm); } } - ExpandResult { value: (CowArc::Owned(tt), matched_arm), err } + ExpandResult { value: (Cow::Owned(tt), matched_arm), err } } fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span { @@ -641,11 +630,9 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span { span_map.span_for_range(range) } -fn expand_proc_macro( - db: &dyn ExpandDatabase, - id: MacroCallId, -) -> ExpandResult<Arc<tt::TopSubtree>> { - let loc = db.lookup_intern_macro_call(id); +#[salsa_macros::tracked(returns(ref))] +fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::TopSubtree> { + let loc = id.loc(db); let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(id, &loc.kind); let (ast, expander) = match loc.def.kind { @@ -664,7 +651,7 @@ fn expand_proc_macro( db, loc.def.krate, loc.krate, - ¯o_arg, + macro_arg, attr_arg, span_with_def_site_ctxt(db, span, id.into(), loc.def.edition), span_with_call_site_ctxt(db, span, id.into(), loc.def.edition), @@ -674,12 +661,12 @@ fn expand_proc_macro( // Set a hard limit for the expanded tt if let Err(value) = check_tt_count(&tt) { - return value.map(|()| Arc::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)))); + return value.map(|()| tt::TopSubtree::empty(tt::DelimSpan::from_single(*span))); } - fixup::reverse_fixups(&mut tt, &undo_info); + fixup::reverse_fixups(&mut tt, undo_info); - ExpandResult { value: Arc::new(tt), err } + ExpandResult { value: tt, err } } pub(crate) fn token_tree_to_syntax_node( @@ -714,11 +701,3 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { }) } } - -fn intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallLoc) -> MacroCallId { - MacroCallId::new(db, macro_call) -} - -fn lookup_intern_macro_call(db: &dyn ExpandDatabase, macro_call: MacroCallId) -> MacroCallLoc { - macro_call.loc(db) -} |