X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir_expand%2Fsrc%2Fdb.rs;h=d6d33b4cd724f144e336c27e9fb91e67863a4cdc;hb=7b89d5ede23cbbbf4bef37b43e0d2d99752ddb51;hp=c39825b591c2af1a26a72726d363550064098672;hpb=81163b8cd4a03ac0d37807e02de20ad2605e26dd;p=rust.git diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index c39825b591c..d6d33b4cd72 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs @@ -5,7 +5,7 @@ use base_db::{salsa, SourceDatabase}; use either::Either; use limit::Limit; -use mbe::{syntax_node_to_token_tree, ExpandError, ExpandResult}; +use mbe::syntax_node_to_token_tree; use rustc_hash::FxHashSet; use syntax::{ algo::diff, @@ -14,9 +14,10 @@ }; use crate::{ - ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander, - BuiltinFnLikeExpander, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, - MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, + ast_id_map::AstIdMap, fixup, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander, + BuiltinFnLikeExpander, ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, + MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, + ProcMacroExpander, }; /// Total limit on the number of tokens produced by any macro invocation. @@ -47,10 +48,10 @@ fn expand( db: &dyn AstDatabase, id: MacroCallId, tt: &tt::Subtree, - ) -> mbe::ExpandResult { + ) -> ExpandResult { match self { - TokenExpander::DeclarativeMacro { mac, .. } => mac.expand(tt), - TokenExpander::Builtin(it) => it.expand(db, id, tt), + TokenExpander::DeclarativeMacro { mac, .. } => mac.expand(tt).map_err(Into::into), + TokenExpander::Builtin(it) => it.expand(db, id, tt).map_err(Into::into), TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt), TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt), TokenExpander::ProcMacro(_) => { @@ -108,7 +109,10 @@ fn parse_macro_expansion( /// Lowers syntactic macro call to a token tree representation. #[salsa::transparent] - fn macro_arg(&self, id: MacroCallId) -> Option>; + fn macro_arg( + &self, + id: MacroCallId, + ) -> Option>; /// Extracts syntax node, corresponding to a macro call. That's a firewall /// query, only typing in the macro call itself changes the returned /// subtree. @@ -146,8 +150,15 @@ pub fn expand_speculative( // Build the subtree and token mapping for the speculative args let censor = censor_for_macro_input(&loc, &speculative_args); - let (mut tt, spec_args_tmap) = - mbe::syntax_node_to_token_tree_censored(&speculative_args, &censor); + let mut fixups = fixup::fixup_syntax(&speculative_args); + fixups.replace.extend(censor.into_iter().map(|node| (node, Vec::new()))); + let (mut tt, spec_args_tmap, _) = mbe::syntax_node_to_token_tree_with_modifications( + &speculative_args, + fixups.token_map, + fixups.next_id, + fixups.replace, + fixups.append, + ); let (attr_arg, token_id) = match loc.kind { MacroCallKind::Attr { invoc_attr_index, .. } => { @@ -157,7 +168,7 @@ pub fn expand_speculative( let attr = item .doc_comments_and_attrs() .nth(invoc_attr_index as usize) - .and_then(Either::right)?; + .and_then(Either::left)?; match attr.token_tree() { Some(token_tree) => { let (mut tree, map) = syntax_node_to_token_tree(attr.token_tree()?.syntax()); @@ -194,7 +205,7 @@ pub fn expand_speculative( // Do the actual expansion, we need to directly expand the proc macro due to the attribute args // Otherwise the expand query will fetch the non speculative attribute args and pass those instead. - let speculative_expansion = if let MacroDefKind::ProcMacro(expander, ..) = loc.def.kind { + let mut speculative_expansion = if let MacroDefKind::ProcMacro(expander, ..) = loc.def.kind { tt.delimiter = None; expander.expand(db, loc.krate, &tt, attr_arg.as_ref()) } else { @@ -202,8 +213,8 @@ pub fn expand_speculative( }; let expand_to = macro_expand_to(db, actual_macro_call); - let (node, rev_tmap) = - token_tree_to_syntax_node(&speculative_expansion.value, expand_to).ok()?; + fixup::reverse_fixups(&mut speculative_expansion.value, &spec_args_tmap, &fixups.undo_info); + let (node, rev_tmap) = token_tree_to_syntax_node(&speculative_expansion.value, expand_to); let range = rev_tmap.first_range_by_token(token_id, token_to_map.kind())?; let token = node.syntax_node().covering_element(range).into_token()?; @@ -264,17 +275,7 @@ fn parse_macro_expansion( tracing::debug!("expanded = {}", tt.as_debug_string()); tracing::debug!("kind = {:?}", expand_to); - let (parse, rev_token_map) = match token_tree_to_syntax_node(&tt, expand_to) { - Ok(it) => it, - Err(err) => { - tracing::debug!( - "failed to parse expansion to {:?} = {}", - expand_to, - tt.as_debug_string() - ); - return ExpandResult::only_err(err); - } - }; + let (parse, rev_token_map) = token_tree_to_syntax_node(&tt, expand_to); match result.err { Some(err) => { @@ -300,20 +301,31 @@ fn parse_macro_expansion( } } -fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option> { +fn macro_arg( + db: &dyn AstDatabase, + id: MacroCallId, +) -> Option> { let arg = db.macro_arg_text(id)?; let loc = db.lookup_intern_macro_call(id); let node = SyntaxNode::new_root(arg); let censor = censor_for_macro_input(&loc, &node); - let (mut tt, tmap) = mbe::syntax_node_to_token_tree_censored(&node, &censor); + let mut fixups = fixup::fixup_syntax(&node); + fixups.replace.extend(censor.into_iter().map(|node| (node, Vec::new()))); + let (mut tt, tmap, _) = mbe::syntax_node_to_token_tree_with_modifications( + &node, + fixups.token_map, + fixups.next_id, + fixups.replace, + fixups.append, + ); if loc.def.is_proc_macro() { // proc macros expect their inputs without parentheses, MBEs expect it with them included tt.delimiter = None; } - Some(Arc::new((tt, tmap))) + Some(Arc::new((tt, tmap, fixups.undo_info))) } fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet { @@ -325,16 +337,18 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet return None, MacroCallKind::Attr { invoc_attr_index, .. } => { cov_mark::hit!(attribute_macro_attr_censoring); ast::Item::cast(node.clone())? .doc_comments_and_attrs() .nth(invoc_attr_index as usize) - .and_then(Either::right) + .and_then(Either::left) .map(|attr| attr.syntax().clone()) .into_iter() .collect() @@ -401,7 +415,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Result, MacroDefKind::BuiltInEager(..) => { // FIXME: Return a random error here just to make the types align. // This obviously should do something real instead. - Err(mbe::ParseError::UnexpectedToken("unexpected eager macro".to_string())) + Err(mbe::ParseError::UnexpectedToken("unexpected eager macro".into())) } MacroDefKind::ProcMacro(expander, ..) => Ok(Arc::new(TokenExpander::ProcMacro(expander))), } @@ -420,7 +434,11 @@ fn macro_expand(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult it, - None => return ExpandResult::str_err("Failed to lower macro args to token tree".into()), + None => { + return ExpandResult::only_err(ExpandError::Other( + "Failed to lower macro args to token tree".into(), + )) + } }; let expander = match db.macro_def(loc.def) { @@ -428,20 +446,28 @@ fn macro_expand(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult return ExpandResult::str_err(format!("invalid macro definition: {}", err)), + Err(err) => { + return ExpandResult::only_err(ExpandError::Other( + format!("invalid macro definition: {}", err).into(), + )) + } }; - let ExpandResult { value: tt, err } = expander.expand(db, id, ¯o_arg.0); + let ExpandResult { value: mut tt, err } = expander.expand(db, id, ¯o_arg.0); // Set a hard limit for the expanded tt let count = tt.count(); - // XXX: Make ExpandResult a real error and use .map_err instead? if TOKEN_LIMIT.check(count).is_err() { - return ExpandResult::str_err(format!( - "macro invocation exceeds token limit: produced {} tokens, limit is {}", - count, - TOKEN_LIMIT.inner(), + return ExpandResult::only_err(ExpandError::Other( + format!( + "macro invocation exceeds token limit: produced {} tokens, limit is {}", + count, + TOKEN_LIMIT.inner(), + ) + .into(), )); } + fixup::reverse_fixups(&mut tt, ¯o_arg.1, ¯o_arg.2); + ExpandResult { value: Some(Arc::new(tt)), err } } @@ -453,7 +479,9 @@ fn expand_proc_macro(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult it, - None => return ExpandResult::str_err("No arguments for proc-macro".to_string()), + None => { + return ExpandResult::only_err(ExpandError::Other("No arguments for proc-macro".into())) + } }; let expander = match loc.def.kind { @@ -502,7 +530,7 @@ fn macro_expand_to(db: &dyn AstDatabase, id: MacroCallId) -> ExpandTo { fn token_tree_to_syntax_node( tt: &tt::Subtree, expand_to: ExpandTo, -) -> Result<(Parse, mbe::TokenMap), ExpandError> { +) -> (Parse, mbe::TokenMap) { let entry_point = match expand_to { ExpandTo::Statements => mbe::TopEntryPoint::MacroStmts, ExpandTo::Items => mbe::TopEntryPoint::MacroItems,