hir_def: refactor expand_macro_type and cleanups

This commit is contained in:
cynecx 2021-04-17 17:38:38 +02:00
parent 14918a3870
commit 7ed42a3a52
3 changed files with 34 additions and 124 deletions

View File

@ -19,7 +19,7 @@ use hir_expand::{
use la_arena::{Arena, ArenaMap};
use profile::Count;
use rustc_hash::FxHashMap;
use syntax::{ast, AstNode, AstPtr, SyntaxNode};
use syntax::{ast, AstNode, AstPtr};
pub use lower::LowerCtx;
@ -98,14 +98,11 @@ impl Expander {
}
}
fn enter_expand_intern(
pub(crate) fn enter_expand<T: ast::AstNode>(
&mut self,
db: &dyn DefDatabase,
macro_call: ast::MacroCall,
) -> Result<
ExpandResult<Option<(SyntaxNode, impl FnMut(&dyn DefDatabase) -> Mark + '_)>>,
UnresolvedMacro,
> {
) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> {
if self.recursion_limit + 1 > EXPANSION_RECURSION_LIMIT {
cov_mark::hit!(your_stack_belongs_to_me);
return Ok(ExpandResult::str_err(
@ -150,55 +147,6 @@ impl Expander {
}
};
let this = self;
let advance_state = move |db: &dyn DefDatabase| {
this.recursion_limit += 1;
let mark = Mark {
file_id: this.current_file_id,
ast_id_map: mem::take(&mut this.ast_id_map),
bomb: DropBomb::new("expansion mark dropped"),
};
this.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
this.current_file_id = file_id;
this.ast_id_map = db.ast_id_map(file_id);
mark
};
Ok(ExpandResult { value: Some((raw_node, advance_state)), err })
}
pub(crate) fn enter_expand_raw(
&mut self,
db: &dyn DefDatabase,
macro_call: ast::MacroCall,
) -> Result<ExpandResult<Option<(Mark, SyntaxNode)>>, UnresolvedMacro> {
let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? {
ExpandResult { value: Some((raw_node, advance_state)), err } => {
(raw_node, advance_state, err)
}
ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }),
};
log::debug!("macro expansion {:#?}", raw_node);
let mark = advance_state(db);
Ok(ExpandResult { value: Some((mark, raw_node)), err })
}
pub(crate) fn enter_expand<T: ast::AstNode>(
&mut self,
db: &dyn DefDatabase,
macro_call: ast::MacroCall,
) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> {
let (raw_node, mut advance_state, err) = match self.enter_expand_intern(db, macro_call)? {
ExpandResult { value: Some((raw_node, advance_state)), err } => {
(raw_node, advance_state, err)
}
ExpandResult { value: None, err } => return Ok(ExpandResult { value: None, err }),
};
let node = match T::cast(raw_node) {
Some(it) => it,
None => {
@ -209,7 +157,15 @@ impl Expander {
log::debug!("macro expansion {:#?}", node.syntax());
let mark = advance_state(db);
self.recursion_limit += 1;
let mark = Mark {
file_id: self.current_file_id,
ast_id_map: mem::take(&mut self.ast_id_map),
bomb: DropBomb::new("expansion mark dropped"),
};
self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
self.current_file_id = file_id;
self.ast_id_map = db.ast_id_map(file_id);
Ok(ExpandResult { value: Some((mark, node)), err })
}
@ -234,6 +190,10 @@ impl Expander {
&self.cfg_expander.cfg_options
}
pub(crate) fn current_file_id(&self) -> HirFileId {
self.current_file_id
}
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene);
Path::from_src(path, &ctx)

View File

@ -1,9 +1,8 @@
//! HIR for references to types. Paths in these are not yet resolved. They can
//! be directly created from an ast::TypeRef, without further queries.
use std::borrow::Cow;
use hir_expand::{ast_id_map::FileAstId, name::Name, ExpandResult, InFile};
use syntax::{algo::SyntaxRewriter, ast, AstNode, SyntaxKind, SyntaxNode};
use syntax::ast;
use crate::{
body::{Expander, LowerCtx},
@ -207,16 +206,6 @@ impl TypeRef {
TypeRef::Tuple(Vec::new())
}
pub fn has_macro_calls(&self) -> bool {
let mut has_macro_call = false;
self.walk(&mut |ty_ref| {
if let TypeRef::Macro(_) = ty_ref {
has_macro_call |= true
}
});
has_macro_call
}
pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) {
go(self, f);
@ -315,68 +304,29 @@ impl TypeBound {
}
}
pub fn expand_type_ref<'a>(
pub fn expand_macro_type(
db: &dyn DefDatabase,
module_id: ModuleId,
type_ref: &'a TypeRef,
) -> Option<Cow<'a, TypeRef>> {
let macro_call = match type_ref {
macro_type: &TypeRef,
) -> Option<TypeRef> {
let macro_call = match macro_type {
TypeRef::Macro(macro_call) => macro_call,
_ => return Some(Cow::Borrowed(type_ref)),
_ => panic!("expected TypeRef::Macro"),
};
let file_id = macro_call.file_id;
let macro_call = macro_call.to_node(db.upcast());
let mut expander = Expander::new(db, file_id, module_id);
let expanded = expand(db, &mut expander, &macro_call, true)?;
let node = ast::Type::cast(expanded)?;
let (file_id, expanded) = match expander.enter_expand::<ast::Type>(db, macro_call.clone()) {
Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
let file_id = expander.current_file_id();
expander.exit(db, mark);
(file_id, expanded)
}
_ => return None,
};
let ctx = LowerCtx::new(db, file_id);
return Some(Cow::Owned(TypeRef::from_ast(&ctx, node)));
fn expand(
db: &dyn DefDatabase,
expander: &mut Expander,
macro_call: &ast::MacroCall,
expect_type: bool,
) -> Option<SyntaxNode> {
let (mark, mut expanded) = match expander.enter_expand_raw(db, macro_call.clone()) {
Ok(ExpandResult { value: Some((mark, expanded)), .. }) => (mark, expanded),
_ => return None,
};
if expect_type && !ast::Type::can_cast(expanded.kind()) {
expander.exit(db, mark);
return None;
}
if ast::MacroType::can_cast(expanded.kind()) {
expanded = expanded.first_child()?; // MACRO_CALL
}
let mut rewriter = SyntaxRewriter::default();
let children = expanded.descendants().filter_map(ast::MacroCall::cast);
for child in children {
if let Some(new_node) = expand(db, expander, &child, false) {
if expanded == *child.syntax() {
expanded = new_node;
} else {
let parent = child.syntax().parent();
let old_node = match &parent {
Some(node) if node.kind() == SyntaxKind::MACRO_TYPE => node,
_ => child.syntax(),
};
rewriter.replace(old_node, &new_node)
}
}
}
expander.exit(db, mark);
let res = rewriter.rewrite(&expanded);
Some(res)
}
return Some(TypeRef::from_ast(&ctx, expanded));
}

View File

@ -15,7 +15,7 @@ use hir_def::{
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{expand_type_ref, TraitRef as HirTraitRef, TypeBound, TypeRef},
type_ref::{expand_macro_type, TraitRef as HirTraitRef, TypeBound, TypeRef},
AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId,
GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
TypeAliasId, TypeParamId, UnionId, VariantId,
@ -289,8 +289,8 @@ impl<'a> TyLoweringContext<'a> {
}
mt @ TypeRef::Macro(_) => {
if let Some(module_id) = self.resolver.module() {
match expand_type_ref(self.db.upcast(), module_id, mt) {
Some(type_ref) => self.lower_ty(type_ref.as_ref()),
match expand_macro_type(self.db.upcast(), module_id, mt) {
Some(type_ref) => self.lower_ty(&type_ref),
None => TyKind::Error.intern(&Interner),
}
} else {