Unnamed repository; edit this file 'description' to name the repository.
Remove accidental dependency between `parse_macro_expansion` and `parse`
Lukas Wirth 2024-03-07
parent 9c2fa76 · commit bd0ffb0
-rw-r--r--crates/hir-expand/src/builtin_derive_macro.rs73
-rw-r--r--crates/hir-expand/src/db.rs22
-rw-r--r--crates/hir-expand/src/span_map.rs2
3 files changed, 46 insertions, 51 deletions
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index f36f48baae..66dec7d89e 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -10,10 +10,12 @@ use crate::{
hygiene::span_with_def_site_ctxt,
name::{AsName, Name},
quote::dollar_crate,
- span_map::SpanMapRef,
+ span_map::ExpansionSpanMap,
tt,
};
-use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
+use syntax::ast::{
+ self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
+};
use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult};
@@ -25,7 +27,7 @@ macro_rules! register_builtin {
}
impl BuiltinDeriveExpander {
- pub fn expander(&self) -> fn(Span, &ast::Adt, SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+ pub fn expander(&self) -> fn(Span, &tt::Subtree) -> ExpandResult<tt::Subtree> {
match *self {
$( BuiltinDeriveExpander::$trait => $expand, )*
}
@@ -47,12 +49,11 @@ impl BuiltinDeriveExpander {
&self,
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &ast::Adt,
- token_map: SpanMapRef<'_>,
+ tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
let span = db.lookup_intern_macro_call(id).call_site;
let span = span_with_def_site_ctxt(db, span, id);
- self.expander()(span, tt, token_map)
+ self.expander()(span, tt)
}
}
@@ -126,7 +127,7 @@ impl VariantShape {
}
}
- fn from(tm: SpanMapRef<'_>, value: Option<FieldList>) -> Result<Self, ExpandError> {
+ fn from(tm: &ExpansionSpanMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
let r = match value {
None => VariantShape::Unit,
Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
@@ -202,11 +203,13 @@ struct BasicAdtInfo {
associated_types: Vec<tt::Subtree>,
}
-fn parse_adt(
- tm: SpanMapRef<'_>,
- adt: &ast::Adt,
- call_site: Span,
-) -> Result<BasicAdtInfo, ExpandError> {
+fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
+ let (parsed, tm) = &mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
+ let macro_items = ast::MacroItems::cast(parsed.syntax_node())
+ .ok_or_else(|| ExpandError::other("invalid item definition"))?;
+ let item = macro_items.items().next().ok_or_else(|| ExpandError::other("no item found"))?;
+ let adt = &ast::Adt::cast(item.syntax().clone())
+ .ok_or_else(|| ExpandError::other("expected struct, enum or union"))?;
let (name, generic_param_list, where_clause, shape) = match adt {
ast::Adt::Struct(it) => (
it.name(),
@@ -322,14 +325,14 @@ fn parse_adt(
}
fn name_to_token(
- token_map: SpanMapRef<'_>,
+ token_map: &ExpansionSpanMap,
name: Option<ast::Name>,
) -> Result<tt::Ident, ExpandError> {
let name = name.ok_or_else(|| {
debug!("parsed item has no name");
ExpandError::other("missing name")
})?;
- let span = token_map.span_for_range(name.syntax().text_range());
+ let span = token_map.span_at(name.syntax().text_range().start());
let name_token = tt::Ident { span, text: name.text().into() };
Ok(name_token)
}
@@ -366,14 +369,12 @@ fn name_to_token(
/// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
/// therefore does not get bound by the derived trait.
fn expand_simple_derive(
- // FIXME: use
invoc_span: Span,
- tt: &ast::Adt,
- tm: SpanMapRef<'_>,
+ tt: &tt::Subtree,
trait_path: tt::Subtree,
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
) -> ExpandResult<tt::Subtree> {
- let info = match parse_adt(tm, tt, invoc_span) {
+ let info = match parse_adt(tt, invoc_span) {
Ok(info) => info,
Err(e) => {
return ExpandResult::new(
@@ -416,14 +417,14 @@ fn expand_simple_derive(
ExpandResult::ok(expanded)
}
-fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn copy_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
+ expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
}
-fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn clone_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
return quote! {span =>
@@ -472,9 +473,9 @@ fn and_and(span: Span) -> tt::Subtree {
quote! {span => #and& }
}
-fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn default_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = &dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| {
let body = match &adt.shape {
AdtShape::Struct(fields) => {
let name = &adt.name;
@@ -511,9 +512,9 @@ fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult
})
}
-fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn debug_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = &dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
let for_variant = |name: String, v: &VariantShape| match v {
VariantShape::Struct(fields) => {
let for_fields = fields.iter().map(|it| {
@@ -583,9 +584,9 @@ fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<t
})
}
-fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn hash_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = &dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
return quote! {span =>};
@@ -630,14 +631,14 @@ fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt
})
}
-fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
+ expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
}
-fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn partial_eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
return quote! {span =>};
@@ -707,9 +708,9 @@ fn self_and_other_patterns(
(self_patterns, other_patterns)
}
-fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = &dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
fn compare(
krate: &tt::Ident,
left: tt::Subtree,
@@ -765,9 +766,9 @@ fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt:
})
}
-fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
let krate = &dollar_crate(span);
- expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| {
+ expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
fn compare(
krate: &tt::Ident,
left: tt::Subtree,
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 3a65bc7c6e..6f69ee15ac 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -215,11 +215,6 @@ pub fn expand_speculative(
MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, loc.call_site)
}
- MacroDefKind::BuiltInDerive(expander, ..) => {
- // this cast is a bit sus, can we avoid losing the typedness here?
- let adt = ast::Adt::cast(speculative_args.clone()).unwrap();
- expander.expand(db, actual_macro_call, &adt, span_map)
- }
MacroDefKind::Declarative(it) => db.decl_macro_expander(loc.krate, it).expand_unhygienic(
db,
tt,
@@ -227,6 +222,9 @@ pub fn expand_speculative(
loc.call_site,
),
MacroDefKind::BuiltIn(it, _) => it.expand(db, actual_macro_call, &tt).map_err(Into::into),
+ MacroDefKind::BuiltInDerive(it, ..) => {
+ it.expand(db, actual_macro_call, &tt).map_err(Into::into)
+ }
MacroDefKind::BuiltInEager(it, _) => {
it.expand(db, actual_macro_call, &tt).map_err(Into::into)
}
@@ -321,6 +319,7 @@ pub(crate) fn parse_with_map(
}
}
+// FIXME: for derive attributes, this will return separate copies of the same structures!
fn macro_arg(
db: &dyn ExpandDatabase,
id: MacroCallId,
@@ -526,16 +525,6 @@ fn macro_expand(
let ExpandResult { value: tt, mut err } = match loc.def.kind {
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
- MacroDefKind::BuiltInDerive(expander, ..) => {
- let (root, map) = parse_with_map(db, loc.kind.file_id());
- let root = root.syntax_node();
- let MacroCallKind::Derive { ast_id, .. } = loc.kind else { unreachable!() };
- let node = ast_id.to_ptr(db).to_node(&root);
-
- // FIXME: Use censoring
- let _censor = censor_for_macro_input(&loc, node.syntax());
- expander.expand(db, macro_call_id, &node, map.as_ref())
- }
_ => {
let ValueResult { value: (macro_arg, undo_info), err } = db.macro_arg(macro_call_id);
let format_parse_err = |err: Arc<Box<[SyntaxError]>>| {
@@ -569,6 +558,9 @@ fn macro_expand(
err: err.map(format_parse_err),
};
}
+ MacroDefKind::BuiltInDerive(it, _) => {
+ it.expand(db, macro_call_id, arg).map_err(Into::into)
+ }
MacroDefKind::BuiltInEager(it, _) => {
it.expand(db, macro_call_id, arg).map_err(Into::into)
}
diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs
index 4a60a94856..ef86be6709 100644
--- a/crates/hir-expand/src/span_map.rs
+++ b/crates/hir-expand/src/span_map.rs
@@ -31,11 +31,13 @@ impl mbe::SpanMapper<Span> for SpanMap {
self.span_for_range(range)
}
}
+
impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
fn span_for(&self, range: TextRange) -> Span {
self.span_for_range(range)
}
}
+
impl SpanMap {
pub fn span_for_range(&self, range: TextRange) -> Span {
match self {