about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 f36f48baaee..66dec7d89e5 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 3a65bc7c6ea..6f69ee15aca 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 4a60a948560..ef86be67096 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 {