Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/builtin_derive_macro.rs')
-rw-r--r--crates/hir-expand/src/builtin_derive_macro.rs460
1 files changed, 247 insertions, 213 deletions
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index ecc8b407a9..410aa4d289 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -1,16 +1,16 @@
//! Builtin derives.
-use ::tt::Ident;
-use base_db::{CrateOrigin, LangCrateOrigin};
+use base_db::{span::SpanData, CrateOrigin, LangCrateOrigin};
use itertools::izip;
-use mbe::TokenMap;
use rustc_hash::FxHashSet;
use stdx::never;
use tracing::debug;
use crate::{
+ hygiene::span_with_def_site_ctxt,
name::{AsName, Name},
- tt::{self, TokenId},
+ span::SpanMapRef,
+ tt,
};
use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
@@ -29,12 +29,15 @@ macro_rules! register_builtin {
db: &dyn ExpandDatabase,
id: MacroCallId,
tt: &ast::Adt,
- token_map: &TokenMap,
+ token_map: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
let expander = match *self {
$( BuiltinDeriveExpander::$trait => $expand, )*
};
- expander(db, id, tt, token_map)
+
+ let span = db.lookup_intern_macro_call(id).span(db);
+ let span = span_with_def_site_ctxt(db, span, id);
+ expander(db, id, span, tt, token_map)
}
fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -70,19 +73,19 @@ enum VariantShape {
Unit,
}
-fn tuple_field_iterator(n: usize) -> impl Iterator<Item = tt::Ident> {
- (0..n).map(|it| Ident::new(format!("f{it}"), tt::TokenId::unspecified()))
+fn tuple_field_iterator(span: SpanData, n: usize) -> impl Iterator<Item = tt::Ident> {
+ (0..n).map(move |it| tt::Ident::new(format!("f{it}"), span))
}
impl VariantShape {
- fn as_pattern(&self, path: tt::Subtree) -> tt::Subtree {
- self.as_pattern_map(path, |it| quote!(#it))
+ fn as_pattern(&self, path: tt::Subtree, span: SpanData) -> tt::Subtree {
+ self.as_pattern_map(path, span, |it| quote!(span => #it))
}
- fn field_names(&self) -> Vec<tt::Ident> {
+ fn field_names(&self, span: SpanData) -> Vec<tt::Ident> {
match self {
VariantShape::Struct(s) => s.clone(),
- VariantShape::Tuple(n) => tuple_field_iterator(*n).collect(),
+ VariantShape::Tuple(n) => tuple_field_iterator(span, *n).collect(),
VariantShape::Unit => vec![],
}
}
@@ -90,26 +93,27 @@ impl VariantShape {
fn as_pattern_map(
&self,
path: tt::Subtree,
+ span: SpanData,
field_map: impl Fn(&tt::Ident) -> tt::Subtree,
) -> tt::Subtree {
match self {
VariantShape::Struct(fields) => {
let fields = fields.iter().map(|it| {
let mapped = field_map(it);
- quote! { #it : #mapped , }
+ quote! {span => #it : #mapped , }
});
- quote! {
+ quote! {span =>
#path { ##fields }
}
}
&VariantShape::Tuple(n) => {
- let fields = tuple_field_iterator(n).map(|it| {
+ let fields = tuple_field_iterator(span, n).map(|it| {
let mapped = field_map(&it);
- quote! {
+ quote! {span =>
#mapped ,
}
});
- quote! {
+ quote! {span =>
#path ( ##fields )
}
}
@@ -117,7 +121,7 @@ impl VariantShape {
}
}
- fn from(tm: &TokenMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
+ fn from(tm: SpanMapRef<'_>, value: Option<FieldList>) -> Result<Self, ExpandError> {
let r = match value {
None => VariantShape::Unit,
Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
@@ -139,17 +143,17 @@ enum AdtShape {
}
impl AdtShape {
- fn as_pattern(&self, name: &tt::Ident) -> Vec<tt::Subtree> {
- self.as_pattern_map(name, |it| quote!(#it))
+ fn as_pattern(&self, span: SpanData, name: &tt::Ident) -> Vec<tt::Subtree> {
+ self.as_pattern_map(name, |it| quote!(span =>#it), span)
}
- fn field_names(&self) -> Vec<Vec<tt::Ident>> {
+ fn field_names(&self, span: SpanData) -> Vec<Vec<tt::Ident>> {
match self {
AdtShape::Struct(s) => {
- vec![s.field_names()]
+ vec![s.field_names(span)]
}
AdtShape::Enum { variants, .. } => {
- variants.iter().map(|(_, fields)| fields.field_names()).collect()
+ variants.iter().map(|(_, fields)| fields.field_names(span)).collect()
}
AdtShape::Union => {
never!("using fields of union in derive is always wrong");
@@ -162,18 +166,21 @@ impl AdtShape {
&self,
name: &tt::Ident,
field_map: impl Fn(&tt::Ident) -> tt::Subtree,
+ span: SpanData,
) -> Vec<tt::Subtree> {
match self {
AdtShape::Struct(s) => {
- vec![s.as_pattern_map(quote! { #name }, field_map)]
+ vec![s.as_pattern_map(quote! {span => #name }, span, field_map)]
}
AdtShape::Enum { variants, .. } => variants
.iter()
- .map(|(v, fields)| fields.as_pattern_map(quote! { #name :: #v }, &field_map))
+ .map(|(v, fields)| {
+ fields.as_pattern_map(quote! {span => #name :: #v }, span, &field_map)
+ })
.collect(),
AdtShape::Union => {
never!("pattern matching on union is always wrong");
- vec![quote! { un }]
+ vec![quote! {span => un }]
}
}
}
@@ -189,8 +196,12 @@ struct BasicAdtInfo {
associated_types: Vec<tt::Subtree>,
}
-fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError> {
- let (name, generic_param_list, shape) = match &adt {
+fn parse_adt(
+ tm: SpanMapRef<'_>,
+ adt: &ast::Adt,
+ call_site: SpanData,
+) -> Result<BasicAdtInfo, ExpandError> {
+ let (name, generic_param_list, shape) = match adt {
ast::Adt::Struct(it) => (
it.name(),
it.generic_param_list(),
@@ -234,22 +245,26 @@ fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError>
match this {
Some(it) => {
param_type_set.insert(it.as_name());
- mbe::syntax_node_to_token_tree(it.syntax()).0
+ mbe::syntax_node_to_token_tree(it.syntax(), tm)
+ }
+ None => {
+ tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
}
- None => tt::Subtree::empty(),
}
};
let bounds = match &param {
ast::TypeOrConstParam::Type(it) => {
- it.type_bound_list().map(|it| mbe::syntax_node_to_token_tree(it.syntax()).0)
+ it.type_bound_list().map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm))
}
ast::TypeOrConstParam::Const(_) => None,
};
let ty = if let ast::TypeOrConstParam::Const(param) = param {
let ty = param
.ty()
- .map(|ty| mbe::syntax_node_to_token_tree(ty.syntax()).0)
- .unwrap_or_else(tt::Subtree::empty);
+ .map(|ty| mbe::syntax_node_to_token_tree(ty.syntax(), tm))
+ .unwrap_or_else(|| {
+ tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
+ });
Some(ty)
} else {
None
@@ -282,20 +297,22 @@ fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError>
let name = p.path()?.qualifier()?.as_single_name_ref()?.as_name();
param_type_set.contains(&name).then_some(p)
})
- .map(|it| mbe::syntax_node_to_token_tree(it.syntax()).0)
+ .map(|it| mbe::syntax_node_to_token_tree(it.syntax(), tm))
.collect();
- let name_token = name_to_token(&tm, name)?;
+ let name_token = name_to_token(tm, name)?;
Ok(BasicAdtInfo { name: name_token, shape, param_types, associated_types })
}
-fn name_to_token(token_map: &TokenMap, name: Option<ast::Name>) -> Result<tt::Ident, ExpandError> {
+fn name_to_token(
+ token_map: SpanMapRef<'_>,
+ 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 name_token_id =
- token_map.token_by_range(name.syntax().text_range()).unwrap_or_else(TokenId::unspecified);
- let name_token = tt::Ident { span: name_token_id, text: name.text().into() };
+ let span = token_map.span_for_range(name.syntax().text_range());
+ let name_token = tt::Ident { span, text: name.text().into() };
Ok(name_token)
}
@@ -331,14 +348,21 @@ fn name_to_token(token_map: &TokenMap, name: Option<ast::Name>) -> Result<tt::Id
/// 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: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
trait_path: tt::Subtree,
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
) -> ExpandResult<tt::Subtree> {
- let info = match parse_adt(tm, tt) {
+ let info = match parse_adt(tm, tt, invoc_span) {
Ok(info) => info,
- Err(e) => return ExpandResult::new(tt::Subtree::empty(), e),
+ Err(e) => {
+ return ExpandResult::new(
+ tt::Subtree::empty(tt::DelimSpan { open: invoc_span, close: invoc_span }),
+ e,
+ )
+ }
};
let trait_body = make_trait_body(&info);
let mut where_block = vec![];
@@ -349,13 +373,13 @@ fn expand_simple_derive(
let ident_ = ident.clone();
if let Some(b) = bound {
let ident = ident.clone();
- where_block.push(quote! { #ident : #b , });
+ where_block.push(quote! {invoc_span => #ident : #b , });
}
if let Some(ty) = param_ty {
- (quote! { const #ident : #ty , }, quote! { #ident_ , })
+ (quote! {invoc_span => const #ident : #ty , }, quote! {invoc_span => #ident_ , })
} else {
let bound = trait_path.clone();
- (quote! { #ident : #bound , }, quote! { #ident_ , })
+ (quote! {invoc_span => #ident : #bound , }, quote! {invoc_span => #ident_ , })
}
})
.unzip();
@@ -363,17 +387,17 @@ fn expand_simple_derive(
where_block.extend(info.associated_types.iter().map(|it| {
let it = it.clone();
let bound = trait_path.clone();
- quote! { #it : #bound , }
+ quote! {invoc_span => #it : #bound , }
}));
let name = info.name;
- let expanded = quote! {
+ let expanded = quote! {invoc_span =>
impl < ##params > #trait_path for #name < ##args > where ##where_block { #trait_body }
};
ExpandResult::ok(expanded)
}
-fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId) -> tt::TokenTree {
+fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: SpanData) -> tt::TokenTree {
// FIXME: make hygiene works for builtin derive macro
// such that $crate can be used here.
let cg = db.crate_graph();
@@ -381,9 +405,9 @@ fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId) -> tt::TokenTree
let tt = if matches!(cg[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) {
cov_mark::hit!(test_copy_expand_in_core);
- quote! { crate }
+ quote! {span => crate }
} else {
- quote! { core }
+ quote! {span => core }
};
tt.token_trees[0].clone()
@@ -392,56 +416,50 @@ fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId) -> tt::TokenTree
fn copy_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::marker::Copy }, |_| quote! {})
+ let krate = find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
}
fn clone_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::clone::Clone }, |adt| {
+ let krate = find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
- let star = tt::Punct {
- char: '*',
- spacing: ::tt::Spacing::Alone,
- span: tt::TokenId::unspecified(),
- };
- return quote! {
+ let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
+ return quote! {span =>
fn clone(&self) -> Self {
#star self
}
};
}
if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) {
- let star = tt::Punct {
- char: '*',
- spacing: ::tt::Spacing::Alone,
- span: tt::TokenId::unspecified(),
- };
- return quote! {
+ let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
+ return quote! {span =>
fn clone(&self) -> Self {
match #star self {}
}
};
}
let name = &adt.name;
- let patterns = adt.shape.as_pattern(name);
- let exprs = adt.shape.as_pattern_map(name, |it| quote! { #it .clone() });
+ let patterns = adt.shape.as_pattern(span, name);
+ let exprs = adt.shape.as_pattern_map(name, |it| quote! {span => #it .clone() }, span);
let arms = patterns.into_iter().zip(exprs.into_iter()).map(|(pat, expr)| {
- let fat_arrow = fat_arrow();
- quote! {
+ let fat_arrow = fat_arrow(span);
+ quote! {span =>
#pat #fat_arrow #expr,
}
});
- quote! {
+ quote! {span =>
fn clone(&self) -> Self {
match self {
##arms
@@ -451,53 +469,56 @@ fn clone_expand(
})
}
-/// This function exists since `quote! { => }` doesn't work.
-fn fat_arrow() -> ::tt::Subtree<TokenId> {
- let eq =
- tt::Punct { char: '=', spacing: ::tt::Spacing::Joint, span: tt::TokenId::unspecified() };
- quote! { #eq> }
+/// This function exists since `quote! {span => => }` doesn't work.
+fn fat_arrow(span: SpanData) -> tt::Subtree {
+ let eq = tt::Punct { char: '=', spacing: ::tt::Spacing::Joint, span };
+ quote! {span => #eq> }
}
-/// This function exists since `quote! { && }` doesn't work.
-fn and_and() -> ::tt::Subtree<TokenId> {
- let and =
- tt::Punct { char: '&', spacing: ::tt::Spacing::Joint, span: tt::TokenId::unspecified() };
- quote! { #and& }
+/// This function exists since `quote! {span => && }` doesn't work.
+fn and_and(span: SpanData) -> tt::Subtree {
+ let and = tt::Punct { char: '&', spacing: ::tt::Spacing::Joint, span };
+ quote! {span => #and& }
}
fn default_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = &find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::default::Default }, |adt| {
+ let krate = &find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| {
let body = match &adt.shape {
AdtShape::Struct(fields) => {
let name = &adt.name;
- fields
- .as_pattern_map(quote!(#name), |_| quote!(#krate::default::Default::default()))
+ fields.as_pattern_map(
+ quote!(span =>#name),
+ span,
+ |_| quote!(span =>#krate::default::Default::default()),
+ )
}
AdtShape::Enum { default_variant, variants } => {
if let Some(d) = default_variant {
let (name, fields) = &variants[*d];
let adt_name = &adt.name;
fields.as_pattern_map(
- quote!(#adt_name :: #name),
- |_| quote!(#krate::default::Default::default()),
+ quote!(span =>#adt_name :: #name),
+ span,
+ |_| quote!(span =>#krate::default::Default::default()),
)
} else {
// FIXME: Return expand error here
- quote!()
+ quote!(span =>)
}
}
AdtShape::Union => {
// FIXME: Return expand error here
- quote!()
+ quote!(span =>)
}
};
- quote! {
+ quote! {span =>
fn default() -> Self {
#body
}
@@ -508,44 +529,41 @@ fn default_expand(
fn debug_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = &find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::fmt::Debug }, |adt| {
+ let krate = &find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, 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| {
let x_string = it.to_string();
- quote! {
+ quote! {span =>
.field(#x_string, & #it)
}
});
- quote! {
+ quote! {span =>
f.debug_struct(#name) ##for_fields .finish()
}
}
VariantShape::Tuple(n) => {
- let for_fields = tuple_field_iterator(*n).map(|it| {
- quote! {
+ let for_fields = tuple_field_iterator(span, *n).map(|it| {
+ quote! {span =>
.field( & #it)
}
});
- quote! {
+ quote! {span =>
f.debug_tuple(#name) ##for_fields .finish()
}
}
- VariantShape::Unit => quote! {
+ VariantShape::Unit => quote! {span =>
f.write_str(#name)
},
};
if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) {
- let star = tt::Punct {
- char: '*',
- spacing: ::tt::Spacing::Alone,
- span: tt::TokenId::unspecified(),
- };
- return quote! {
+ let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
+ return quote! {span =>
fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result {
match #star self {}
}
@@ -553,20 +571,20 @@ fn debug_expand(
}
let arms = match &adt.shape {
AdtShape::Struct(fields) => {
- let fat_arrow = fat_arrow();
+ let fat_arrow = fat_arrow(span);
let name = &adt.name;
- let pat = fields.as_pattern(quote!(#name));
+ let pat = fields.as_pattern(quote!(span =>#name), span);
let expr = for_variant(name.to_string(), fields);
- vec![quote! { #pat #fat_arrow #expr }]
+ vec![quote! {span => #pat #fat_arrow #expr }]
}
AdtShape::Enum { variants, .. } => variants
.iter()
.map(|(name, v)| {
- let fat_arrow = fat_arrow();
+ let fat_arrow = fat_arrow(span);
let adt_name = &adt.name;
- let pat = v.as_pattern(quote!(#adt_name :: #name));
+ let pat = v.as_pattern(quote!(span =>#adt_name :: #name), span);
let expr = for_variant(name.to_string(), v);
- quote! {
+ quote! {span =>
#pat #fat_arrow #expr ,
}
})
@@ -576,7 +594,7 @@ fn debug_expand(
vec![]
}
};
- quote! {
+ quote! {span =>
fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result {
match self {
##arms
@@ -589,47 +607,46 @@ fn debug_expand(
fn hash_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = &find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::hash::Hash }, |adt| {
+ let krate = &find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
- return quote! {};
+ return quote! {span =>};
}
if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) {
- let star = tt::Punct {
- char: '*',
- spacing: ::tt::Spacing::Alone,
- span: tt::TokenId::unspecified(),
- };
- return quote! {
+ let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
+ return quote! {span =>
fn hash<H: #krate::hash::Hasher>(&self, ra_expand_state: &mut H) {
match #star self {}
}
};
}
- let arms = adt.shape.as_pattern(&adt.name).into_iter().zip(adt.shape.field_names()).map(
- |(pat, names)| {
- let expr = {
- let it = names.iter().map(|it| quote! { #it . hash(ra_expand_state); });
- quote! { {
- ##it
- } }
- };
- let fat_arrow = fat_arrow();
- quote! {
- #pat #fat_arrow #expr ,
- }
- },
- );
+ let arms =
+ adt.shape.as_pattern(span, &adt.name).into_iter().zip(adt.shape.field_names(span)).map(
+ |(pat, names)| {
+ let expr = {
+ let it =
+ names.iter().map(|it| quote! {span => #it . hash(ra_expand_state); });
+ quote! {span => {
+ ##it
+ } }
+ };
+ let fat_arrow = fat_arrow(span);
+ quote! {span =>
+ #pat #fat_arrow #expr ,
+ }
+ },
+ );
let check_discriminant = if matches!(&adt.shape, AdtShape::Enum { .. }) {
- quote! { #krate::mem::discriminant(self).hash(ra_expand_state); }
+ quote! {span => #krate::mem::discriminant(self).hash(ra_expand_state); }
} else {
- quote! {}
+ quote! {span =>}
};
- quote! {
+ quote! {span =>
fn hash<H: #krate::hash::Hasher>(&self, ra_expand_state: &mut H) {
#check_discriminant
match self {
@@ -643,56 +660,58 @@ fn hash_expand(
fn eq_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::cmp::Eq }, |_| quote! {})
+ let krate = find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
}
fn partial_eq_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialEq }, |adt| {
+ let krate = find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| {
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
- return quote! {};
+ return quote! {span =>};
}
let name = &adt.name;
- let (self_patterns, other_patterns) = self_and_other_patterns(adt, name);
- let arms = izip!(self_patterns, other_patterns, adt.shape.field_names()).map(
+ let (self_patterns, other_patterns) = self_and_other_patterns(adt, name, span);
+ let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map(
|(pat1, pat2, names)| {
- let fat_arrow = fat_arrow();
+ let fat_arrow = fat_arrow(span);
let body = match &*names {
[] => {
- quote!(true)
+ quote!(span =>true)
}
[first, rest @ ..] => {
let rest = rest.iter().map(|it| {
- let t1 = Ident::new(format!("{}_self", it.text), it.span);
- let t2 = Ident::new(format!("{}_other", it.text), it.span);
- let and_and = and_and();
- quote!(#and_and #t1 .eq( #t2 ))
+ let t1 = tt::Ident::new(format!("{}_self", it.text), it.span);
+ let t2 = tt::Ident::new(format!("{}_other", it.text), it.span);
+ let and_and = and_and(span);
+ quote!(span =>#and_and #t1 .eq( #t2 ))
});
let first = {
- let t1 = Ident::new(format!("{}_self", first.text), first.span);
- let t2 = Ident::new(format!("{}_other", first.text), first.span);
- quote!(#t1 .eq( #t2 ))
+ let t1 = tt::Ident::new(format!("{}_self", first.text), first.span);
+ let t2 = tt::Ident::new(format!("{}_other", first.text), first.span);
+ quote!(span =>#t1 .eq( #t2 ))
};
- quote!(#first ##rest)
+ quote!(span =>#first ##rest)
}
};
- quote! { ( #pat1 , #pat2 ) #fat_arrow #body , }
+ quote! {span => ( #pat1 , #pat2 ) #fat_arrow #body , }
},
);
- let fat_arrow = fat_arrow();
- quote! {
+ let fat_arrow = fat_arrow(span);
+ quote! {span =>
fn eq(&self, other: &Self) -> bool {
match (self, other) {
##arms
@@ -706,35 +725,46 @@ fn partial_eq_expand(
fn self_and_other_patterns(
adt: &BasicAdtInfo,
name: &tt::Ident,
+ span: SpanData,
) -> (Vec<tt::Subtree>, Vec<tt::Subtree>) {
- let self_patterns = adt.shape.as_pattern_map(name, |it| {
- let t = Ident::new(format!("{}_self", it.text), it.span);
- quote!(#t)
- });
- let other_patterns = adt.shape.as_pattern_map(name, |it| {
- let t = Ident::new(format!("{}_other", it.text), it.span);
- quote!(#t)
- });
+ let self_patterns = adt.shape.as_pattern_map(
+ name,
+ |it| {
+ let t = tt::Ident::new(format!("{}_self", it.text), it.span);
+ quote!(span =>#t)
+ },
+ span,
+ );
+ let other_patterns = adt.shape.as_pattern_map(
+ name,
+ |it| {
+ let t = tt::Ident::new(format!("{}_other", it.text), it.span);
+ quote!(span =>#t)
+ },
+ span,
+ );
(self_patterns, other_patterns)
}
fn ord_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = &find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::cmp::Ord }, |adt| {
+ let krate = &find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| {
fn compare(
krate: &tt::TokenTree,
left: tt::Subtree,
right: tt::Subtree,
rest: tt::Subtree,
+ span: SpanData,
) -> tt::Subtree {
- let fat_arrow1 = fat_arrow();
- let fat_arrow2 = fat_arrow();
- quote! {
+ let fat_arrow1 = fat_arrow(span);
+ let fat_arrow2 = fat_arrow(span);
+ quote! {span =>
match #left.cmp(&#right) {
#krate::cmp::Ordering::Equal #fat_arrow1 {
#rest
@@ -745,34 +775,34 @@ fn ord_expand(
}
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
- return quote!();
+ return quote!(span =>);
}
- let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name);
- let arms = izip!(self_patterns, other_patterns, adt.shape.field_names()).map(
+ let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name, span);
+ let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map(
|(pat1, pat2, fields)| {
- let mut body = quote!(#krate::cmp::Ordering::Equal);
+ let mut body = quote!(span =>#krate::cmp::Ordering::Equal);
for f in fields.into_iter().rev() {
- let t1 = Ident::new(format!("{}_self", f.text), f.span);
- let t2 = Ident::new(format!("{}_other", f.text), f.span);
- body = compare(krate, quote!(#t1), quote!(#t2), body);
+ let t1 = tt::Ident::new(format!("{}_self", f.text), f.span);
+ let t2 = tt::Ident::new(format!("{}_other", f.text), f.span);
+ body = compare(krate, quote!(span =>#t1), quote!(span =>#t2), body, span);
}
- let fat_arrow = fat_arrow();
- quote! { ( #pat1 , #pat2 ) #fat_arrow #body , }
+ let fat_arrow = fat_arrow(span);
+ quote! {span => ( #pat1 , #pat2 ) #fat_arrow #body , }
},
);
- let fat_arrow = fat_arrow();
- let mut body = quote! {
+ let fat_arrow = fat_arrow(span);
+ let mut body = quote! {span =>
match (self, other) {
##arms
_unused #fat_arrow #krate::cmp::Ordering::Equal
}
};
if matches!(&adt.shape, AdtShape::Enum { .. }) {
- let left = quote!(#krate::intrinsics::discriminant_value(self));
- let right = quote!(#krate::intrinsics::discriminant_value(other));
- body = compare(krate, left, right, body);
+ let left = quote!(span =>#krate::intrinsics::discriminant_value(self));
+ let right = quote!(span =>#krate::intrinsics::discriminant_value(other));
+ body = compare(krate, left, right, body, span);
}
- quote! {
+ quote! {span =>
fn cmp(&self, other: &Self) -> #krate::cmp::Ordering {
#body
}
@@ -783,20 +813,22 @@ fn ord_expand(
fn partial_ord_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
+ span: SpanData,
tt: &ast::Adt,
- tm: &TokenMap,
+ tm: SpanMapRef<'_>,
) -> ExpandResult<tt::Subtree> {
- let krate = &find_builtin_crate(db, id);
- expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialOrd }, |adt| {
+ let krate = &find_builtin_crate(db, id, span);
+ expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| {
fn compare(
krate: &tt::TokenTree,
left: tt::Subtree,
right: tt::Subtree,
rest: tt::Subtree,
+ span: SpanData,
) -> tt::Subtree {
- let fat_arrow1 = fat_arrow();
- let fat_arrow2 = fat_arrow();
- quote! {
+ let fat_arrow1 = fat_arrow(span);
+ let fat_arrow2 = fat_arrow(span);
+ quote! {span =>
match #left.partial_cmp(&#right) {
#krate::option::Option::Some(#krate::cmp::Ordering::Equal) #fat_arrow1 {
#rest
@@ -807,37 +839,39 @@ fn partial_ord_expand(
}
if matches!(adt.shape, AdtShape::Union) {
// FIXME: Return expand error here
- return quote!();
+ return quote!(span =>);
}
- let left = quote!(#krate::intrinsics::discriminant_value(self));
- let right = quote!(#krate::intrinsics::discriminant_value(other));
+ let left = quote!(span =>#krate::intrinsics::discriminant_value(self));
+ let right = quote!(span =>#krate::intrinsics::discriminant_value(other));
- let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name);
- let arms = izip!(self_patterns, other_patterns, adt.shape.field_names()).map(
+ let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name, span);
+ let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map(
|(pat1, pat2, fields)| {
- let mut body = quote!(#krate::option::Option::Some(#krate::cmp::Ordering::Equal));
+ let mut body =
+ quote!(span =>#krate::option::Option::Some(#krate::cmp::Ordering::Equal));
for f in fields.into_iter().rev() {
- let t1 = Ident::new(format!("{}_self", f.text), f.span);
- let t2 = Ident::new(format!("{}_other", f.text), f.span);
- body = compare(krate, quote!(#t1), quote!(#t2), body);
+ let t1 = tt::Ident::new(format!("{}_self", f.text), f.span);
+ let t2 = tt::Ident::new(format!("{}_other", f.text), f.span);
+ body = compare(krate, quote!(span =>#t1), quote!(span =>#t2), body, span);
}
- let fat_arrow = fat_arrow();
- quote! { ( #pat1 , #pat2 ) #fat_arrow #body , }
+ let fat_arrow = fat_arrow(span);
+ quote! {span => ( #pat1 , #pat2 ) #fat_arrow #body , }
},
);
- let fat_arrow = fat_arrow();
+ let fat_arrow = fat_arrow(span);
let body = compare(
krate,
left,
right,
- quote! {
+ quote! {span =>
match (self, other) {
##arms
_unused #fat_arrow #krate::option::Option::Some(#krate::cmp::Ordering::Equal)
}
},
+ span,
);
- quote! {
+ quote! {span =>
fn partial_cmp(&self, other: &Self) -> #krate::option::Option::Option<#krate::cmp::Ordering> {
#body
}