Unnamed repository; edit this file 'description' to name the repository.
internal: remove accidental code re-use
FragmentKind played two roles: * entry point to the parser * syntactic category of a macro call These are different use-cases, and warrant different types. For example, macro can't expand to visibility, but we have such fragment today. This PR introduces `ExpandsTo` enum to separate this two use-cases. I suspect we might further split `FragmentKind` into `$x:specifier` enum specific to MBE, and a general parser entry point, but that's for another PR!
Aleksey Kladov 2021-09-06
parent 847d0fa · commit dbb702c
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir_def/src/attr.rs3
-rw-r--r--crates/hir_def/src/item_tree.rs4
-rw-r--r--crates/hir_def/src/item_tree/lower.rs4
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs2
-rw-r--r--crates/hir_def/src/lib.rs10
-rw-r--r--crates/hir_def/src/nameres/collector.rs71
-rw-r--r--crates/hir_expand/Cargo.toml1
-rw-r--r--crates/hir_expand/src/builtin_derive.rs3
-rw-r--r--crates/hir_expand/src/builtin_macro.rs24
-rw-r--r--crates/hir_expand/src/db.rs38
-rw-r--r--crates/hir_expand/src/eager.rs29
-rw-r--r--crates/hir_expand/src/hygiene.rs3
-rw-r--r--crates/hir_expand/src/lib.rs96
-rw-r--r--crates/mbe/src/lib.rs8
-rw-r--r--crates/mbe/src/syntax_bridge.rs7
-rw-r--r--crates/mbe/src/tests.rs3
-rw-r--r--crates/parser/src/lib.rs4
18 files changed, 172 insertions, 139 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d47e92c9e9..3b08782375 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -525,7 +525,6 @@ dependencies = [
"la-arena",
"limit",
"mbe",
- "parser",
"profile",
"rustc-hash",
"syntax",
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 163a45ca14..9f09666e97 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -695,8 +695,7 @@ impl Attr {
hygiene: &Hygiene,
id: AttrId,
) -> Option<Attr> {
- let (parse, _) =
- mbe::token_tree_to_syntax_node(tt, hir_expand::FragmentKind::MetaItem).ok()?;
+ let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::FragmentKind::MetaItem).ok()?;
let ast = ast::Meta::cast(parse.syntax_node())?;
Self::from_src(db, ast, hygiene, id)
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index aa462f2b97..26621b8c7e 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -51,7 +51,7 @@ use hir_expand::{
ast_id_map::FileAstId,
hygiene::Hygiene,
name::{name, AsName, Name},
- FragmentKind, HirFileId, InFile,
+ ExpandTo, HirFileId, InFile,
};
use la_arena::{Arena, Idx, RawIdx};
use profile::Count;
@@ -739,7 +739,7 @@ pub struct MacroCall {
/// Path to the called macro.
pub path: Interned<ModPath>,
pub ast_id: FileAstId<ast::MacroCall>,
- pub fragment: FragmentKind,
+ pub expand_to: ExpandTo,
}
#[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index d385bcaf66..7bed19a792 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -573,8 +573,8 @@ impl<'a> Ctx<'a> {
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
let ast_id = self.source_ast_id_map.ast_id(m);
- let fragment = hir_expand::to_fragment_kind(m);
- let res = MacroCall { path, ast_id, fragment };
+ let expand_to = hir_expand::ExpandTo::from_call_site(m);
+ let res = MacroCall { path, ast_id, expand_to };
Some(id(self.data().macro_calls.alloc(res)))
}
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 24cc2408de..3e33b0c46c 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -440,7 +440,7 @@ impl<'a> Printer<'a> {
}
}
ModItem::MacroCall(it) => {
- let MacroCall { path, ast_id: _, fragment: _ } = &self.tree[it];
+ let MacroCall { path, ast_id: _, expand_to: _ } = &self.tree[it];
wln!(self, "{}!(...);", path);
}
ModItem::MacroRules(it) => {
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index ea6a2b4a6f..4904ebfd63 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -61,7 +61,7 @@ use hir_expand::{
ast_id_map::FileAstId,
eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
hygiene::Hygiene,
- AstId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
+ AstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
};
use la_arena::Idx;
use nameres::DefMap;
@@ -667,7 +667,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
mut error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
- let fragment = hir_expand::to_fragment_kind(self.value);
+ let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
let h = Hygiene::new(db.upcast(), self.file_id);
let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
@@ -683,7 +683,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
macro_call_as_call_id(
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
- fragment,
+ expands_to,
db,
krate,
resolver,
@@ -712,7 +712,7 @@ pub struct UnresolvedMacro {
fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>,
- fragment: FragmentKind,
+ expand_to: ExpandTo,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -738,7 +738,7 @@ fn macro_call_as_call_id(
Ok(def.as_lazy_macro(
db.upcast(),
krate,
- MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
+ MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
))
};
Ok(res)
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index b376f9a253..165cdcba00 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -14,7 +14,7 @@ use hir_expand::{
builtin_macro::find_builtin_macro,
name::{name, AsName, Name},
proc_macro::ProcMacroExpander,
- FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
+ ExpandTo, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
};
use hir_expand::{InFile, MacroCallLoc};
use itertools::Itertools;
@@ -223,7 +223,7 @@ struct MacroDirective {
#[derive(Clone, Debug, Eq, PartialEq)]
enum MacroDirectiveKind {
- FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
+ FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
}
@@ -1021,10 +1021,10 @@ impl DefCollector<'_> {
};
match &directive.kind {
- MacroDirectiveKind::FnLike { ast_id, fragment } => {
+ MacroDirectiveKind::FnLike { ast_id, expand_to } => {
match macro_call_as_call_id(
ast_id,
- *fragment,
+ *expand_to,
self.db,
self.def_map.krate,
&resolver,
@@ -1223,32 +1223,34 @@ impl DefCollector<'_> {
for directive in &self.unresolved_macros {
match &directive.kind {
- MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
- ast_id,
- *fragment,
- self.db,
- self.def_map.krate,
- |path| {
- let resolved_res = self.def_map.resolve_path_fp_with_macro(
- self.db,
- ResolveMode::Other,
- directive.module_id,
- &path,
- BuiltinShadowMode::Module,
- );
- resolved_res.resolved_def.take_macros()
- },
- &mut |_| (),
- ) {
- Ok(_) => (),
- Err(UnresolvedMacro { path }) => {
- self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
- directive.module_id,
- ast_id.ast_id,
- path,
- ));
+ MacroDirectiveKind::FnLike { ast_id, expand_to } => {
+ match macro_call_as_call_id(
+ ast_id,
+ *expand_to,
+ self.db,
+ self.def_map.krate,
+ |path| {
+ let resolved_res = self.def_map.resolve_path_fp_with_macro(
+ self.db,
+ ResolveMode::Other,
+ directive.module_id,
+ &path,
+ BuiltinShadowMode::Module,
+ );
+ resolved_res.resolved_def.take_macros()
+ },
+ &mut |_| (),
+ ) {
+ Ok(_) => (),
+ Err(UnresolvedMacro { path }) => {
+ self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+ directive.module_id,
+ ast_id.ast_id,
+ path,
+ ));
+ }
}
- },
+ }
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
// FIXME: we might want to diagnose this too
}
@@ -1899,7 +1901,7 @@ impl ModCollector<'_, '_> {
let mut error = None;
match macro_call_as_call_id(
&ast_id,
- mac.fragment,
+ mac.expand_to,
self.def_collector.db,
self.def_collector.def_map.krate,
|path| {
@@ -1930,12 +1932,11 @@ impl ModCollector<'_, '_> {
// Built-in macro failed eager expansion.
// FIXME: don't parse the file here
- let fragment = hir_expand::to_fragment_kind(
- &ast_id.ast_id.to_node(self.def_collector.db.upcast()),
- );
+ let macro_call = ast_id.ast_id.to_node(self.def_collector.db.upcast());
+ let expand_to = hir_expand::ExpandTo::from_call_site(&macro_call);
self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
self.module_id,
- MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
+ MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to },
error.unwrap().to_string(),
));
return;
@@ -1947,7 +1948,7 @@ impl ModCollector<'_, '_> {
self.def_collector.unresolved_macros.push(MacroDirective {
module_id: self.module_id,
depth: self.macro_depth + 1,
- kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
+ kind: MacroDirectiveKind::FnLike { ast_id, expand_to: mac.expand_to },
});
}
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml
index 9cd2768106..5655a8fdff 100644
--- a/crates/hir_expand/Cargo.toml
+++ b/crates/hir_expand/Cargo.toml
@@ -19,7 +19,6 @@ itertools = "0.10.0"
base_db = { path = "../base_db", version = "0.0.0" }
cfg = { path = "../cfg", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
-parser = { path = "../parser", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
tt = { path = "../tt", version = "0.0.0" }
mbe = { path = "../mbe", version = "0.0.0" }
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index 9ab61ce7ce..de846a5cc6 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -3,7 +3,6 @@
use tracing::debug;
use mbe::ExpandResult;
-use parser::FragmentKind;
use syntax::{
ast::{self, AstNode, GenericParamsOwner, ModuleItemOwner, NameOwner},
match_ast,
@@ -73,7 +72,7 @@ struct BasicAdtInfo {
}
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> {
- let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, FragmentKind::Items)?; // FragmentKind::Items doesn't parse attrs?
+ let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::FragmentKind::Items)?; // FragmentKind::Items doesn't parse attrs?
let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| {
debug!("derive node didn't parse");
mbe::ExpandError::UnexpectedToken
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index f3bfd65987..a4b5632e32 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -554,17 +554,19 @@ fn option_env_expand(
#[cfg(test)]
mod tests {
- use super::*;
- use crate::{
- name::AsName, test_db::TestDB, AstNode, EagerCallInfo, MacroCallId, MacroCallKind,
- MacroCallLoc,
- };
+ use std::sync::Arc;
+
use base_db::{fixture::WithFixture, SourceDatabase};
use expect_test::{expect, Expect};
- use parser::FragmentKind;
- use std::sync::Arc;
use syntax::ast::NameOwner;
+ use crate::{
+ name::AsName, test_db::TestDB, AstNode, EagerCallInfo, ExpandTo, MacroCallId,
+ MacroCallKind, MacroCallLoc,
+ };
+
+ use super::*;
+
fn expand_builtin_macro(ra_fixture: &str) -> String {
let (db, file_id) = TestDB::with_single_file(ra_fixture);
let parsed = db.parse(file_id);
@@ -599,7 +601,7 @@ mod tests {
eager: None,
kind: MacroCallKind::FnLike {
ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
- fragment: FragmentKind::Expr,
+ expand_to: ExpandTo::Expr,
},
};
@@ -614,7 +616,6 @@ mod tests {
local_inner: false,
};
- let fragment = crate::to_fragment_kind(&macro_call);
let args = macro_call.token_tree().unwrap();
let parsed_args = mbe::syntax_node_to_token_tree(args.syntax()).0;
let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
@@ -626,10 +627,11 @@ mod tests {
arg_or_expansion: Arc::new(parsed_args.clone()),
included_file: None,
}),
- kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr },
+ kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr },
});
let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
+ let expand_to = crate::ExpandTo::from_call_site(&macro_call);
let loc = MacroCallLoc {
def,
krate,
@@ -637,7 +639,7 @@ mod tests {
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
- kind: MacroCallKind::FnLike { ast_id: call_id, fragment },
+ kind: MacroCallKind::FnLike { ast_id: call_id, expand_to },
};
let id: MacroCallId = db.intern_macro(loc);
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index af98084f4c..84bf5aea90 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -6,17 +6,16 @@ use base_db::{salsa, SourceDatabase};
use itertools::Itertools;
use limit::Limit;
use mbe::{ExpandError, ExpandResult};
-use parser::{FragmentKind, T};
use syntax::{
algo::diff,
ast::{self, AttrsOwner, NameOwner},
- AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, TextRange,
+ AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, TextRange, T,
};
use crate::{
ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander,
- BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc,
- MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
+ BuiltinFnLikeExpander, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
+ MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
};
/// Total limit on the number of tokens produced by any macro invocation.
@@ -157,10 +156,9 @@ pub fn expand_speculative(
let speculative_expansion = macro_def.expand(db, actual_macro_call, &tt);
- let fragment_kind = macro_fragment_kind(db, actual_macro_call);
+ let expand_to = macro_expand_to(db, actual_macro_call);
- let (node, tmap_2) =
- mbe::token_tree_to_syntax_node(&speculative_expansion.value, fragment_kind).ok()?;
+ let (node, tmap_2) = token_tree_to_syntax_node(&speculative_expansion.value, expand_to).ok()?;
let token_id = macro_def.map_id_down(token_id);
let range = tmap_2.first_range_by_token(token_id, token_to_map.kind())?;
@@ -215,17 +213,17 @@ fn parse_macro_expansion(
None => return ExpandResult { value: None, err: result.err },
};
- let fragment_kind = macro_fragment_kind(db, macro_file.macro_call_id);
+ let expand_to = macro_expand_to(db, macro_file.macro_call_id);
tracing::debug!("expanded = {}", tt.as_debug_string());
- tracing::debug!("kind = {:?}", fragment_kind);
+ tracing::debug!("kind = {:?}", expand_to);
- let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) {
+ 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 {:?} = {}",
- fragment_kind,
+ expand_to,
tt.as_debug_string()
);
return ExpandResult::only_err(err);
@@ -437,7 +435,21 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
Arc::new(HygieneFrame::new(db, file_id))
}
-fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
+fn macro_expand_to(db: &dyn AstDatabase, id: MacroCallId) -> ExpandTo {
let loc: MacroCallLoc = db.lookup_intern_macro(id);
- loc.kind.fragment_kind()
+ loc.kind.expand_to()
+}
+
+fn token_tree_to_syntax_node(
+ tt: &tt::Subtree,
+ expand_to: ExpandTo,
+) -> Result<(Parse<SyntaxNode>, mbe::TokenMap), ExpandError> {
+ let fragment = match expand_to {
+ ExpandTo::Statements => mbe::FragmentKind::Statements,
+ ExpandTo::Items => mbe::FragmentKind::Items,
+ ExpandTo::Pattern => mbe::FragmentKind::Pattern,
+ ExpandTo::Type => mbe::FragmentKind::Type,
+ ExpandTo::Expr => mbe::FragmentKind::Expr,
+ };
+ mbe::token_tree_to_syntax_node(tt, fragment)
}
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 81a40185bc..e5cf1a5d23 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -18,19 +18,19 @@
//!
//!
//! See the full discussion : <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Eager.20expansion.20of.20built-in.20macros>
+use std::sync::Arc;
+
+use base_db::CrateId;
+use mbe::ExpandResult;
+use syntax::{ted, SyntaxNode};
use crate::{
ast::{self, AstNode},
db::AstDatabase,
- EagerCallInfo, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
+ EagerCallInfo, ExpandTo, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
+ MacroDefKind,
};
-use base_db::CrateId;
-use mbe::ExpandResult;
-use parser::FragmentKind;
-use std::sync::Arc;
-use syntax::{ted, SyntaxNode};
-
#[derive(Debug)]
pub struct ErrorEmitted {
_private: (),
@@ -113,7 +113,7 @@ pub fn expand_eager_macro(
let ast_map = db.ast_id_map(macro_call.file_id);
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(&macro_call.value));
- let fragment = crate::to_fragment_kind(&macro_call.value);
+ let expand_to = ExpandTo::from_call_site(&macro_call.value);
// Note:
// When `lazy_expand` is called, its *parent* file must be already exists.
@@ -126,12 +126,13 @@ pub fn expand_eager_macro(
arg_or_expansion: Arc::new(parsed_args.clone()),
included_file: None,
}),
- kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr },
+ kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr },
});
let arg_file_id = arg_id;
- let parsed_args =
- diagnostic_sink.result(mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr))?.0;
+ let parsed_args = diagnostic_sink
+ .result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::FragmentKind::Expr))?
+ .0;
let result = eager_macro_recur(
db,
InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
@@ -153,7 +154,7 @@ pub fn expand_eager_macro(
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
- kind: MacroCallKind::FnLike { ast_id: call_id, fragment },
+ kind: MacroCallKind::FnLike { ast_id: call_id, expand_to },
};
Ok(db.intern_macro(loc))
@@ -176,11 +177,11 @@ fn lazy_expand(
) -> ExpandResult<Option<InFile<SyntaxNode>>> {
let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
- let fragment = crate::to_fragment_kind(&macro_call.value);
+ let expand_to = ExpandTo::from_call_site(&macro_call.value);
let id = def.as_lazy_macro(
db,
krate,
- MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment },
+ MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), expand_to },
);
let err = db.macro_expand_error(id);
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index cac484a325..959cd73b5d 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -8,10 +8,9 @@ use base_db::CrateId;
use db::TokenExpander;
use either::Either;
use mbe::Origin;
-use parser::SyntaxKind;
use syntax::{
ast::{self, AttrsOwner},
- AstNode, SyntaxNode, TextRange, TextSize,
+ AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize,
};
use crate::{
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index f982679b64..a814a2886d 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -19,7 +19,6 @@ use base_db::ProcMacroKind;
use either::Either;
pub use mbe::{ExpandError, ExpandResult};
-pub use parser::FragmentKind;
use std::{hash::Hash, iter, sync::Arc};
@@ -268,7 +267,7 @@ pub struct MacroCallLoc {
pub enum MacroCallKind {
FnLike {
ast_id: AstId<ast::MacroCall>,
- fragment: FragmentKind,
+ expand_to: ExpandTo,
},
Derive {
ast_id: AstId<ast::Item>,
@@ -327,11 +326,11 @@ impl MacroCallKind {
}
}
- fn fragment_kind(&self) -> FragmentKind {
+ fn expand_to(&self) -> ExpandTo {
match self {
- MacroCallKind::FnLike { fragment, .. } => *fragment,
- MacroCallKind::Derive { .. } => FragmentKind::Items,
- MacroCallKind::Attr { .. } => FragmentKind::Items, // is this always correct?
+ MacroCallKind::FnLike { expand_to, .. } => *expand_to,
+ MacroCallKind::Derive { .. } => ExpandTo::Items,
+ MacroCallKind::Attr { .. } => ExpandTo::Items, // is this always correct?
}
}
}
@@ -653,38 +652,61 @@ impl<N: AstNode> InFile<N> {
}
}
-/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
-/// FIXME: Not completed
-pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind {
- use syntax::SyntaxKind::*;
-
- let syn = call.syntax();
-
- let parent = match syn.parent() {
- Some(it) => it,
- None => return FragmentKind::Statements,
- };
-
- match parent.kind() {
- MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => FragmentKind::Items,
- MACRO_STMTS | EXPR_STMT | BLOCK_EXPR => FragmentKind::Statements,
- MACRO_PAT => FragmentKind::Pattern,
- MACRO_TYPE => FragmentKind::Type,
-
- ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
- | CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
- | MATCH_GUARD | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR
- | FIELD_EXPR | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR => {
- FragmentKind::Expr
- }
- LET_STMT => {
- // FIXME: Handle LHS Pattern
- FragmentKind::Expr
- }
+/// In Rust, macros expand token trees to token trees. When we want to turn a
+/// token tree into an AST node, we need to figure out what kind of AST node we
+/// want: something like `foo` can be a type, an expression, or a pattern.
+///
+/// Naively, one would think that "what this expands to" is a property of a
+/// particular macro: macro `m1` returns an item, while macro `m2` returns an
+/// expression, etc. That's not the case -- macros are polymorphic in the
+/// result, and can expand to any type of the AST node.
+///
+/// What defines the actual AST node is the syntactic context of the macro
+/// invocation. As a contrived example, in `let T![*] = T![*];` the first `T`
+/// expands to a pattern, while the second one expands to an expression.
+///
+/// `ExpandTo` captures this bit of information about a particular macro call
+/// site.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ExpandTo {
+ Statements,
+ Items,
+ Pattern,
+ Type,
+ Expr,
+}
- _ => {
- // Unknown , Just guess it is `Items`
- FragmentKind::Items
+impl ExpandTo {
+ pub fn from_call_site(call: &ast::MacroCall) -> ExpandTo {
+ use syntax::SyntaxKind::*;
+
+ let syn = call.syntax();
+
+ let parent = match syn.parent() {
+ Some(it) => it,
+ None => return ExpandTo::Statements,
+ };
+
+ match parent.kind() {
+ MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => ExpandTo::Items,
+ MACRO_STMTS | EXPR_STMT | BLOCK_EXPR => ExpandTo::Statements,
+ MACRO_PAT => ExpandTo::Pattern,
+ MACRO_TYPE => ExpandTo::Type,
+
+ ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
+ | CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
+ | MATCH_GUARD | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR
+ | FIELD_EXPR | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR
+ | BIN_EXPR => ExpandTo::Expr,
+ LET_STMT => {
+ // FIXME: Handle LHS Pattern
+ ExpandTo::Expr
+ }
+
+ _ => {
+ // Unknown , Just guess it is `Items`
+ ExpandTo::Items
+ }
}
}
}
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index f490d75c3f..13fec269fa 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -18,13 +18,15 @@ mod token_map;
use std::fmt;
-pub use tt::{Delimiter, DelimiterKind, Punct};
-
use crate::{
parser::{parse_pattern, parse_template, MetaTemplate, Op},
tt_iter::TtIter,
};
+// FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces
+pub use ::parser::FragmentKind;
+pub use tt::{Delimiter, DelimiterKind, Punct};
+
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
UnexpectedToken(String),
@@ -39,7 +41,7 @@ pub enum ExpandError {
UnexpectedToken,
BindingError(String),
ConversionError,
- // FXME: no way mbe should know about proc macros.
+ // FIXME: no way mbe should know about proc macros.
UnresolvedProcMacro,
Other(String),
}
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 6aa034abdc..2d3c612146 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -2,7 +2,7 @@
use std::iter;
-use parser::{FragmentKind, ParseError, TreeSink};
+use parser::{ParseError, TreeSink};
use rustc_hash::FxHashMap;
use syntax::{
ast::{self, make::tokens::doc_comment},
@@ -12,8 +12,9 @@ use syntax::{
};
use tt::buffer::{Cursor, TokenBuffer};
-use crate::{subtree_source::SubtreeTokenSource, tt_iter::TtIter};
-use crate::{ExpandError, TokenMap};
+use crate::{
+ subtree_source::SubtreeTokenSource, tt_iter::TtIter, ExpandError, FragmentKind, TokenMap,
+};
/// Convert the syntax node to a `TokenTree` (what macro
/// will consume).
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index bf85186609..30cafdac7b 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -3,10 +3,11 @@ mod rule;
use std::fmt::Write;
-use ::parser::FragmentKind;
use syntax::{ast, AstNode, NodeOrToken, SyntaxNode, WalkEvent};
use test_utils::assert_eq_text;
+use crate::FragmentKind;
+
use super::*;
pub(crate) struct MacroFixture {
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 44537e380a..d883e72301 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -98,12 +98,8 @@ pub enum FragmentKind {
Block,
Visibility,
MetaItem,
-
- // These kinds are used when parsing the result of expansion
- // FIXME: use separate fragment kinds for macro inputs and outputs?
Items,
Statements,
-
Attr,
}