mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 17:53:56 +00:00
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!
This commit is contained in:
parent
847d0faf92
commit
dbb702cfc1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -525,7 +525,6 @@ dependencies = [
|
|||||||
"la-arena",
|
"la-arena",
|
||||||
"limit",
|
"limit",
|
||||||
"mbe",
|
"mbe",
|
||||||
"parser",
|
|
||||||
"profile",
|
"profile",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"syntax",
|
"syntax",
|
||||||
|
@ -695,8 +695,7 @@ impl Attr {
|
|||||||
hygiene: &Hygiene,
|
hygiene: &Hygiene,
|
||||||
id: AttrId,
|
id: AttrId,
|
||||||
) -> Option<Attr> {
|
) -> Option<Attr> {
|
||||||
let (parse, _) =
|
let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::FragmentKind::MetaItem).ok()?;
|
||||||
mbe::token_tree_to_syntax_node(tt, hir_expand::FragmentKind::MetaItem).ok()?;
|
|
||||||
let ast = ast::Meta::cast(parse.syntax_node())?;
|
let ast = ast::Meta::cast(parse.syntax_node())?;
|
||||||
|
|
||||||
Self::from_src(db, ast, hygiene, id)
|
Self::from_src(db, ast, hygiene, id)
|
||||||
|
@ -51,7 +51,7 @@ use hir_expand::{
|
|||||||
ast_id_map::FileAstId,
|
ast_id_map::FileAstId,
|
||||||
hygiene::Hygiene,
|
hygiene::Hygiene,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
FragmentKind, HirFileId, InFile,
|
ExpandTo, HirFileId, InFile,
|
||||||
};
|
};
|
||||||
use la_arena::{Arena, Idx, RawIdx};
|
use la_arena::{Arena, Idx, RawIdx};
|
||||||
use profile::Count;
|
use profile::Count;
|
||||||
@ -739,7 +739,7 @@ pub struct MacroCall {
|
|||||||
/// Path to the called macro.
|
/// Path to the called macro.
|
||||||
pub path: Interned<ModPath>,
|
pub path: Interned<ModPath>,
|
||||||
pub ast_id: FileAstId<ast::MacroCall>,
|
pub ast_id: FileAstId<ast::MacroCall>,
|
||||||
pub fragment: FragmentKind,
|
pub expand_to: ExpandTo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -573,8 +573,8 @@ impl<'a> Ctx<'a> {
|
|||||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
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 path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
|
||||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||||
let fragment = hir_expand::to_fragment_kind(m);
|
let expand_to = hir_expand::ExpandTo::from_call_site(m);
|
||||||
let res = MacroCall { path, ast_id, fragment };
|
let res = MacroCall { path, ast_id, expand_to };
|
||||||
Some(id(self.data().macro_calls.alloc(res)))
|
Some(id(self.data().macro_calls.alloc(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ impl<'a> Printer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModItem::MacroCall(it) => {
|
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);
|
wln!(self, "{}!(...);", path);
|
||||||
}
|
}
|
||||||
ModItem::MacroRules(it) => {
|
ModItem::MacroRules(it) => {
|
||||||
|
@ -61,7 +61,7 @@ use hir_expand::{
|
|||||||
ast_id_map::FileAstId,
|
ast_id_map::FileAstId,
|
||||||
eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
|
eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
|
||||||
hygiene::Hygiene,
|
hygiene::Hygiene,
|
||||||
AstId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
AstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||||
};
|
};
|
||||||
use la_arena::Idx;
|
use la_arena::Idx;
|
||||||
use nameres::DefMap;
|
use nameres::DefMap;
|
||||||
@ -667,7 +667,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
|||||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||||
mut error_sink: &mut dyn FnMut(mbe::ExpandError),
|
mut error_sink: &mut dyn FnMut(mbe::ExpandError),
|
||||||
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
|
) -> 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 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 h = Hygiene::new(db.upcast(), self.file_id);
|
||||||
let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
|
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(
|
macro_call_as_call_id(
|
||||||
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
|
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
|
||||||
fragment,
|
expands_to,
|
||||||
db,
|
db,
|
||||||
krate,
|
krate,
|
||||||
resolver,
|
resolver,
|
||||||
@ -712,7 +712,7 @@ pub struct UnresolvedMacro {
|
|||||||
|
|
||||||
fn macro_call_as_call_id(
|
fn macro_call_as_call_id(
|
||||||
call: &AstIdWithPath<ast::MacroCall>,
|
call: &AstIdWithPath<ast::MacroCall>,
|
||||||
fragment: FragmentKind,
|
expand_to: ExpandTo,
|
||||||
db: &dyn db::DefDatabase,
|
db: &dyn db::DefDatabase,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||||
@ -738,7 +738,7 @@ fn macro_call_as_call_id(
|
|||||||
Ok(def.as_lazy_macro(
|
Ok(def.as_lazy_macro(
|
||||||
db.upcast(),
|
db.upcast(),
|
||||||
krate,
|
krate,
|
||||||
MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
|
MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
@ -14,7 +14,7 @@ use hir_expand::{
|
|||||||
builtin_macro::find_builtin_macro,
|
builtin_macro::find_builtin_macro,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
proc_macro::ProcMacroExpander,
|
proc_macro::ProcMacroExpander,
|
||||||
FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
ExpandTo, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||||
};
|
};
|
||||||
use hir_expand::{InFile, MacroCallLoc};
|
use hir_expand::{InFile, MacroCallLoc};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@ -223,7 +223,7 @@ struct MacroDirective {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
enum MacroDirectiveKind {
|
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 },
|
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
|
||||||
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
|
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem },
|
||||||
}
|
}
|
||||||
@ -1021,10 +1021,10 @@ impl DefCollector<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match &directive.kind {
|
match &directive.kind {
|
||||||
MacroDirectiveKind::FnLike { ast_id, fragment } => {
|
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
||||||
match macro_call_as_call_id(
|
match macro_call_as_call_id(
|
||||||
ast_id,
|
ast_id,
|
||||||
*fragment,
|
*expand_to,
|
||||||
self.db,
|
self.db,
|
||||||
self.def_map.krate,
|
self.def_map.krate,
|
||||||
&resolver,
|
&resolver,
|
||||||
@ -1223,32 +1223,34 @@ impl DefCollector<'_> {
|
|||||||
|
|
||||||
for directive in &self.unresolved_macros {
|
for directive in &self.unresolved_macros {
|
||||||
match &directive.kind {
|
match &directive.kind {
|
||||||
MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
|
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
||||||
ast_id,
|
match macro_call_as_call_id(
|
||||||
*fragment,
|
ast_id,
|
||||||
self.db,
|
*expand_to,
|
||||||
self.def_map.krate,
|
self.db,
|
||||||
|path| {
|
self.def_map.krate,
|
||||||
let resolved_res = self.def_map.resolve_path_fp_with_macro(
|
|path| {
|
||||||
self.db,
|
let resolved_res = self.def_map.resolve_path_fp_with_macro(
|
||||||
ResolveMode::Other,
|
self.db,
|
||||||
directive.module_id,
|
ResolveMode::Other,
|
||||||
&path,
|
directive.module_id,
|
||||||
BuiltinShadowMode::Module,
|
&path,
|
||||||
);
|
BuiltinShadowMode::Module,
|
||||||
resolved_res.resolved_def.take_macros()
|
);
|
||||||
},
|
resolved_res.resolved_def.take_macros()
|
||||||
&mut |_| (),
|
},
|
||||||
) {
|
&mut |_| (),
|
||||||
Ok(_) => (),
|
) {
|
||||||
Err(UnresolvedMacro { path }) => {
|
Ok(_) => (),
|
||||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
Err(UnresolvedMacro { path }) => {
|
||||||
directive.module_id,
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
||||||
ast_id.ast_id,
|
directive.module_id,
|
||||||
path,
|
ast_id.ast_id,
|
||||||
));
|
path,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
|
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
|
||||||
// FIXME: we might want to diagnose this too
|
// FIXME: we might want to diagnose this too
|
||||||
}
|
}
|
||||||
@ -1899,7 +1901,7 @@ impl ModCollector<'_, '_> {
|
|||||||
let mut error = None;
|
let mut error = None;
|
||||||
match macro_call_as_call_id(
|
match macro_call_as_call_id(
|
||||||
&ast_id,
|
&ast_id,
|
||||||
mac.fragment,
|
mac.expand_to,
|
||||||
self.def_collector.db,
|
self.def_collector.db,
|
||||||
self.def_collector.def_map.krate,
|
self.def_collector.def_map.krate,
|
||||||
|path| {
|
|path| {
|
||||||
@ -1930,12 +1932,11 @@ impl ModCollector<'_, '_> {
|
|||||||
// Built-in macro failed eager expansion.
|
// Built-in macro failed eager expansion.
|
||||||
|
|
||||||
// FIXME: don't parse the file here
|
// FIXME: don't parse the file here
|
||||||
let fragment = hir_expand::to_fragment_kind(
|
let macro_call = ast_id.ast_id.to_node(self.def_collector.db.upcast());
|
||||||
&ast_id.ast_id.to_node(self.def_collector.db.upcast()),
|
let expand_to = hir_expand::ExpandTo::from_call_site(¯o_call);
|
||||||
);
|
|
||||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
|
self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
|
||||||
self.module_id,
|
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(),
|
error.unwrap().to_string(),
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
@ -1947,7 +1948,7 @@ impl ModCollector<'_, '_> {
|
|||||||
self.def_collector.unresolved_macros.push(MacroDirective {
|
self.def_collector.unresolved_macros.push(MacroDirective {
|
||||||
module_id: self.module_id,
|
module_id: self.module_id,
|
||||||
depth: self.macro_depth + 1,
|
depth: self.macro_depth + 1,
|
||||||
kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
|
kind: MacroDirectiveKind::FnLike { ast_id, expand_to: mac.expand_to },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ itertools = "0.10.0"
|
|||||||
base_db = { path = "../base_db", version = "0.0.0" }
|
base_db = { path = "../base_db", version = "0.0.0" }
|
||||||
cfg = { path = "../cfg", version = "0.0.0" }
|
cfg = { path = "../cfg", version = "0.0.0" }
|
||||||
syntax = { path = "../syntax", 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" }
|
profile = { path = "../profile", version = "0.0.0" }
|
||||||
tt = { path = "../tt", version = "0.0.0" }
|
tt = { path = "../tt", version = "0.0.0" }
|
||||||
mbe = { path = "../mbe", version = "0.0.0" }
|
mbe = { path = "../mbe", version = "0.0.0" }
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use mbe::ExpandResult;
|
use mbe::ExpandResult;
|
||||||
use parser::FragmentKind;
|
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode, GenericParamsOwner, ModuleItemOwner, NameOwner},
|
ast::{self, AstNode, GenericParamsOwner, ModuleItemOwner, NameOwner},
|
||||||
match_ast,
|
match_ast,
|
||||||
@ -73,7 +72,7 @@ struct BasicAdtInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> {
|
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(|| {
|
let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| {
|
||||||
debug!("derive node didn't parse");
|
debug!("derive node didn't parse");
|
||||||
mbe::ExpandError::UnexpectedToken
|
mbe::ExpandError::UnexpectedToken
|
||||||
|
@ -554,17 +554,19 @@ fn option_env_expand(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use std::sync::Arc;
|
||||||
use crate::{
|
|
||||||
name::AsName, test_db::TestDB, AstNode, EagerCallInfo, MacroCallId, MacroCallKind,
|
|
||||||
MacroCallLoc,
|
|
||||||
};
|
|
||||||
use base_db::{fixture::WithFixture, SourceDatabase};
|
use base_db::{fixture::WithFixture, SourceDatabase};
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use parser::FragmentKind;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use syntax::ast::NameOwner;
|
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 {
|
fn expand_builtin_macro(ra_fixture: &str) -> String {
|
||||||
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
let (db, file_id) = TestDB::with_single_file(ra_fixture);
|
||||||
let parsed = db.parse(file_id);
|
let parsed = db.parse(file_id);
|
||||||
@ -599,7 +601,7 @@ mod tests {
|
|||||||
eager: None,
|
eager: None,
|
||||||
kind: MacroCallKind::FnLike {
|
kind: MacroCallKind::FnLike {
|
||||||
ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)),
|
ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)),
|
||||||
fragment: FragmentKind::Expr,
|
expand_to: ExpandTo::Expr,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -614,7 +616,6 @@ mod tests {
|
|||||||
local_inner: false,
|
local_inner: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fragment = crate::to_fragment_kind(¯o_call);
|
|
||||||
let args = macro_call.token_tree().unwrap();
|
let args = macro_call.token_tree().unwrap();
|
||||||
let parsed_args = mbe::syntax_node_to_token_tree(args.syntax()).0;
|
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(¯o_call));
|
let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call));
|
||||||
@ -626,10 +627,11 @@ mod tests {
|
|||||||
arg_or_expansion: Arc::new(parsed_args.clone()),
|
arg_or_expansion: Arc::new(parsed_args.clone()),
|
||||||
included_file: None,
|
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 expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
|
||||||
|
let expand_to = crate::ExpandTo::from_call_site(¯o_call);
|
||||||
let loc = MacroCallLoc {
|
let loc = MacroCallLoc {
|
||||||
def,
|
def,
|
||||||
krate,
|
krate,
|
||||||
@ -637,7 +639,7 @@ mod tests {
|
|||||||
arg_or_expansion: Arc::new(expanded.subtree),
|
arg_or_expansion: Arc::new(expanded.subtree),
|
||||||
included_file: expanded.included_file,
|
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);
|
let id: MacroCallId = db.intern_macro(loc);
|
||||||
|
@ -6,17 +6,16 @@ use base_db::{salsa, SourceDatabase};
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
use mbe::{ExpandError, ExpandResult};
|
use mbe::{ExpandError, ExpandResult};
|
||||||
use parser::{FragmentKind, T};
|
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::diff,
|
algo::diff,
|
||||||
ast::{self, AttrsOwner, NameOwner},
|
ast::{self, AttrsOwner, NameOwner},
|
||||||
AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, TextRange,
|
AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, TextRange, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander,
|
ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander,
|
||||||
BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc,
|
BuiltinFnLikeExpander, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
|
||||||
MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
|
MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Total limit on the number of tokens produced by any macro invocation.
|
/// 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 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) =
|
let (node, tmap_2) = token_tree_to_syntax_node(&speculative_expansion.value, expand_to).ok()?;
|
||||||
mbe::token_tree_to_syntax_node(&speculative_expansion.value, fragment_kind).ok()?;
|
|
||||||
|
|
||||||
let token_id = macro_def.map_id_down(token_id);
|
let token_id = macro_def.map_id_down(token_id);
|
||||||
let range = tmap_2.first_range_by_token(token_id, token_to_map.kind())?;
|
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 },
|
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!("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,
|
Ok(it) => it,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"failed to parse expansion to {:?} = {}",
|
"failed to parse expansion to {:?} = {}",
|
||||||
fragment_kind,
|
expand_to,
|
||||||
tt.as_debug_string()
|
tt.as_debug_string()
|
||||||
);
|
);
|
||||||
return ExpandResult::only_err(err);
|
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))
|
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);
|
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)
|
||||||
}
|
}
|
||||||
|
@ -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>
|
//! 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::{
|
use crate::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
db::AstDatabase,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ErrorEmitted {
|
pub struct ErrorEmitted {
|
||||||
_private: (),
|
_private: (),
|
||||||
@ -113,7 +113,7 @@ pub fn expand_eager_macro(
|
|||||||
|
|
||||||
let ast_map = db.ast_id_map(macro_call.file_id);
|
let ast_map = db.ast_id_map(macro_call.file_id);
|
||||||
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value));
|
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value));
|
||||||
let fragment = crate::to_fragment_kind(¯o_call.value);
|
let expand_to = ExpandTo::from_call_site(¯o_call.value);
|
||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
// When `lazy_expand` is called, its *parent* file must be already exists.
|
// 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()),
|
arg_or_expansion: Arc::new(parsed_args.clone()),
|
||||||
included_file: None,
|
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 arg_file_id = arg_id;
|
||||||
|
|
||||||
let parsed_args =
|
let parsed_args = diagnostic_sink
|
||||||
diagnostic_sink.result(mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr))?.0;
|
.result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::FragmentKind::Expr))?
|
||||||
|
.0;
|
||||||
let result = eager_macro_recur(
|
let result = eager_macro_recur(
|
||||||
db,
|
db,
|
||||||
InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
|
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),
|
arg_or_expansion: Arc::new(expanded.subtree),
|
||||||
included_file: expanded.included_file,
|
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))
|
Ok(db.intern_macro(loc))
|
||||||
@ -176,11 +177,11 @@ fn lazy_expand(
|
|||||||
) -> ExpandResult<Option<InFile<SyntaxNode>>> {
|
) -> ExpandResult<Option<InFile<SyntaxNode>>> {
|
||||||
let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value);
|
let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value);
|
||||||
|
|
||||||
let fragment = crate::to_fragment_kind(¯o_call.value);
|
let expand_to = ExpandTo::from_call_site(¯o_call.value);
|
||||||
let id = def.as_lazy_macro(
|
let id = def.as_lazy_macro(
|
||||||
db,
|
db,
|
||||||
krate,
|
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);
|
let err = db.macro_expand_error(id);
|
||||||
|
@ -8,10 +8,9 @@ use base_db::CrateId;
|
|||||||
use db::TokenExpander;
|
use db::TokenExpander;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use mbe::Origin;
|
use mbe::Origin;
|
||||||
use parser::SyntaxKind;
|
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AttrsOwner},
|
ast::{self, AttrsOwner},
|
||||||
AstNode, SyntaxNode, TextRange, TextSize,
|
AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -19,7 +19,6 @@ use base_db::ProcMacroKind;
|
|||||||
use either::Either;
|
use either::Either;
|
||||||
|
|
||||||
pub use mbe::{ExpandError, ExpandResult};
|
pub use mbe::{ExpandError, ExpandResult};
|
||||||
pub use parser::FragmentKind;
|
|
||||||
|
|
||||||
use std::{hash::Hash, iter, sync::Arc};
|
use std::{hash::Hash, iter, sync::Arc};
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ pub struct MacroCallLoc {
|
|||||||
pub enum MacroCallKind {
|
pub enum MacroCallKind {
|
||||||
FnLike {
|
FnLike {
|
||||||
ast_id: AstId<ast::MacroCall>,
|
ast_id: AstId<ast::MacroCall>,
|
||||||
fragment: FragmentKind,
|
expand_to: ExpandTo,
|
||||||
},
|
},
|
||||||
Derive {
|
Derive {
|
||||||
ast_id: AstId<ast::Item>,
|
ast_id: AstId<ast::Item>,
|
||||||
@ -327,11 +326,11 @@ impl MacroCallKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fragment_kind(&self) -> FragmentKind {
|
fn expand_to(&self) -> ExpandTo {
|
||||||
match self {
|
match self {
|
||||||
MacroCallKind::FnLike { fragment, .. } => *fragment,
|
MacroCallKind::FnLike { expand_to, .. } => *expand_to,
|
||||||
MacroCallKind::Derive { .. } => FragmentKind::Items,
|
MacroCallKind::Derive { .. } => ExpandTo::Items,
|
||||||
MacroCallKind::Attr { .. } => FragmentKind::Items, // is this always correct?
|
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.
|
/// In Rust, macros expand token trees to token trees. When we want to turn a
|
||||||
/// FIXME: Not completed
|
/// token tree into an AST node, we need to figure out what kind of AST node we
|
||||||
pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind {
|
/// want: something like `foo` can be a type, an expression, or a pattern.
|
||||||
use syntax::SyntaxKind::*;
|
///
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
|
||||||
let syn = call.syntax();
|
impl ExpandTo {
|
||||||
|
pub fn from_call_site(call: &ast::MacroCall) -> ExpandTo {
|
||||||
|
use syntax::SyntaxKind::*;
|
||||||
|
|
||||||
let parent = match syn.parent() {
|
let syn = call.syntax();
|
||||||
Some(it) => it,
|
|
||||||
None => return FragmentKind::Statements,
|
|
||||||
};
|
|
||||||
|
|
||||||
match parent.kind() {
|
let parent = match syn.parent() {
|
||||||
MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => FragmentKind::Items,
|
Some(it) => it,
|
||||||
MACRO_STMTS | EXPR_STMT | BLOCK_EXPR => FragmentKind::Statements,
|
None => return ExpandTo::Statements,
|
||||||
MACRO_PAT => FragmentKind::Pattern,
|
};
|
||||||
MACRO_TYPE => FragmentKind::Type,
|
|
||||||
|
|
||||||
ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
|
match parent.kind() {
|
||||||
| CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
|
MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => ExpandTo::Items,
|
||||||
| MATCH_GUARD | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR
|
MACRO_STMTS | EXPR_STMT | BLOCK_EXPR => ExpandTo::Statements,
|
||||||
| FIELD_EXPR | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR => {
|
MACRO_PAT => ExpandTo::Pattern,
|
||||||
FragmentKind::Expr
|
MACRO_TYPE => ExpandTo::Type,
|
||||||
}
|
|
||||||
LET_STMT => {
|
|
||||||
// FIXME: Handle LHS Pattern
|
|
||||||
FragmentKind::Expr
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
|
||||||
// Unknown , Just guess it is `Items`
|
| CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
|
||||||
FragmentKind::Items
|
| 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,15 @@ mod token_map;
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub use tt::{Delimiter, DelimiterKind, Punct};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parser::{parse_pattern, parse_template, MetaTemplate, Op},
|
parser::{parse_pattern, parse_template, MetaTemplate, Op},
|
||||||
tt_iter::TtIter,
|
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)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
UnexpectedToken(String),
|
UnexpectedToken(String),
|
||||||
@ -39,7 +41,7 @@ pub enum ExpandError {
|
|||||||
UnexpectedToken,
|
UnexpectedToken,
|
||||||
BindingError(String),
|
BindingError(String),
|
||||||
ConversionError,
|
ConversionError,
|
||||||
// FXME: no way mbe should know about proc macros.
|
// FIXME: no way mbe should know about proc macros.
|
||||||
UnresolvedProcMacro,
|
UnresolvedProcMacro,
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use parser::{FragmentKind, ParseError, TreeSink};
|
use parser::{ParseError, TreeSink};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, make::tokens::doc_comment},
|
ast::{self, make::tokens::doc_comment},
|
||||||
@ -12,8 +12,9 @@ use syntax::{
|
|||||||
};
|
};
|
||||||
use tt::buffer::{Cursor, TokenBuffer};
|
use tt::buffer::{Cursor, TokenBuffer};
|
||||||
|
|
||||||
use crate::{subtree_source::SubtreeTokenSource, tt_iter::TtIter};
|
use crate::{
|
||||||
use crate::{ExpandError, TokenMap};
|
subtree_source::SubtreeTokenSource, tt_iter::TtIter, ExpandError, FragmentKind, TokenMap,
|
||||||
|
};
|
||||||
|
|
||||||
/// Convert the syntax node to a `TokenTree` (what macro
|
/// Convert the syntax node to a `TokenTree` (what macro
|
||||||
/// will consume).
|
/// will consume).
|
||||||
|
@ -3,10 +3,11 @@ mod rule;
|
|||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use ::parser::FragmentKind;
|
|
||||||
use syntax::{ast, AstNode, NodeOrToken, SyntaxNode, WalkEvent};
|
use syntax::{ast, AstNode, NodeOrToken, SyntaxNode, WalkEvent};
|
||||||
use test_utils::assert_eq_text;
|
use test_utils::assert_eq_text;
|
||||||
|
|
||||||
|
use crate::FragmentKind;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub(crate) struct MacroFixture {
|
pub(crate) struct MacroFixture {
|
||||||
|
@ -98,12 +98,8 @@ pub enum FragmentKind {
|
|||||||
Block,
|
Block,
|
||||||
Visibility,
|
Visibility,
|
||||||
MetaItem,
|
MetaItem,
|
||||||
|
|
||||||
// These kinds are used when parsing the result of expansion
|
|
||||||
// FIXME: use separate fragment kinds for macro inputs and outputs?
|
|
||||||
Items,
|
Items,
|
||||||
Statements,
|
Statements,
|
||||||
|
|
||||||
Attr,
|
Attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user