Make basic use of spans for macro expansion errors

This commit is contained in:
Lukas Wirth 2024-07-29 14:52:40 +02:00
parent 7beac14cba
commit ae9c553902
24 changed files with 392 additions and 333 deletions

View file

@ -12,8 +12,7 @@ use crate::{
builtin::quote::{dollar_crate, quote},
db::ExpandDatabase,
hygiene::span_with_def_site_ctxt,
name,
name::{AsName, Name},
name::{self, AsName, Name},
span_map::ExpansionSpanMap,
tt, ExpandError, ExpandResult,
};
@ -129,13 +128,17 @@ impl VariantShape {
}
}
fn from(tm: &ExpansionSpanMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
fn from(
call_site: Span,
tm: &ExpansionSpanMap,
value: Option<FieldList>,
) -> Result<Self, ExpandError> {
let r = match value {
None => VariantShape::Unit,
Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
it.fields()
.map(|it| it.name())
.map(|it| name_to_token(tm, it))
.map(|it| name_to_token(call_site, tm, it))
.collect::<Result<_, _>>()?,
),
Some(FieldList::TupleFieldList(it)) => VariantShape::Tuple(it.fields().count()),
@ -212,16 +215,17 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
parser::Edition::CURRENT_FIXME,
);
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"))?;
.ok_or_else(|| ExpandError::other(call_site, "invalid item definition"))?;
let item =
macro_items.items().next().ok_or_else(|| ExpandError::other(call_site, "no item found"))?;
let adt = &ast::Adt::cast(item.syntax().clone())
.ok_or_else(|| ExpandError::other("expected struct, enum or union"))?;
.ok_or_else(|| ExpandError::other(call_site, "expected struct, enum or union"))?;
let (name, generic_param_list, where_clause, shape) = match adt {
ast::Adt::Struct(it) => (
it.name(),
it.generic_param_list(),
it.where_clause(),
AdtShape::Struct(VariantShape::from(tm, it.field_list())?),
AdtShape::Struct(VariantShape::from(call_site, tm, it.field_list())?),
),
ast::Adt::Enum(it) => {
let default_variant = it
@ -241,8 +245,8 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
.flat_map(|it| it.variants())
.map(|it| {
Ok((
name_to_token(tm, it.name())?,
VariantShape::from(tm, it.field_list())?,
name_to_token(call_site, tm, it.name())?,
VariantShape::from(call_site, tm, it.field_list())?,
))
})
.collect::<Result<_, ExpandError>>()?,
@ -357,17 +361,18 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
)
})
.collect();
let name_token = name_to_token(tm, name)?;
let name_token = name_to_token(call_site, tm, name)?;
Ok(BasicAdtInfo { name: name_token, shape, param_types, where_clause, associated_types })
}
fn name_to_token(
call_site: Span,
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")
ExpandError::other(call_site, "missing name")
})?;
let span = token_map.span_at(name.syntax().text_range().start());

View file

@ -460,15 +460,11 @@ fn compile_error_expand(
let err = match &*tt.token_trees {
[tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span: _,
span,
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
suffix: _,
}))] =>
// FIXME: Use the span here!
{
ExpandError::other(Box::from(unescape_str(text).as_str()))
}
_ => ExpandError::other("`compile_error!` argument must be a string"),
}))] => ExpandError::other(*span, Box::from(unescape_str(text).as_str())),
_ => ExpandError::other(span, "`compile_error!` argument must be a string"),
};
ExpandResult { value: quote! {span =>}, err: Some(err) }
@ -478,7 +474,7 @@ fn concat_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
tt: &tt::Subtree,
_: Span,
call_site: Span,
) -> ExpandResult<tt::Subtree> {
let mut err = None;
let mut text = String::new();
@ -527,7 +523,9 @@ fn concat_expand(
| tt::LitKind::ByteStrRaw(_)
| tt::LitKind::CStr
| tt::LitKind::CStrRaw(_)
| tt::LitKind::Err(_) => err = Some(ExpandError::other("unexpected literal")),
| tt::LitKind::Err(_) => {
err = Some(ExpandError::other(it.span, "unexpected literal"))
}
}
}
// handle boolean literals
@ -539,7 +537,7 @@ fn concat_expand(
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
}
}
}
@ -551,7 +549,7 @@ fn concat_bytes_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
tt: &tt::Subtree,
_: Span,
call_site: Span,
) -> ExpandResult<tt::Subtree> {
let mut bytes = String::new();
let mut err = None;
@ -585,20 +583,22 @@ fn concat_bytes_expand(
bytes.extend(text.as_str().escape_debug());
}
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
err.get_or_insert(ExpandError::other(*span, "unexpected token"));
break;
}
}
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
tt::TokenTree::Subtree(tree) if tree.delimiter.kind == tt::DelimiterKind::Bracket => {
if let Err(e) = concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span) {
if let Err(e) =
concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span, call_site)
{
err.get_or_insert(e);
break;
}
}
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
break;
}
}
@ -623,6 +623,7 @@ fn concat_bytes_expand_subtree(
tree: &tt::Subtree,
bytes: &mut String,
mut record_span: impl FnMut(Span),
err_span: Span,
) -> Result<(), ExpandError> {
for (ti, tt) in tree.token_trees.iter().enumerate() {
match tt {
@ -650,7 +651,7 @@ fn concat_bytes_expand_subtree(
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
_ => {
return Err(mbe::ExpandError::UnexpectedToken.into());
return Err(ExpandError::other(err_span, "unexpected token"));
}
}
}
@ -672,7 +673,7 @@ fn concat_idents_expand(
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
err.get_or_insert(ExpandError::other(span, "unexpected token"));
}
}
}
@ -686,16 +687,17 @@ fn relative_file(
call_id: MacroCallId,
path_str: &str,
allow_recursion: bool,
err_span: Span,
) -> Result<EditionedFileId, ExpandError> {
let lookup = call_id.lookup(db);
let call_site = lookup.kind.file_id().original_file_respecting_includes(db).file_id();
let path = AnchoredPath { anchor: call_site, path: path_str };
let res = db
.resolve_path(path)
.ok_or_else(|| ExpandError::other(format!("failed to load file `{path_str}`")))?;
.ok_or_else(|| ExpandError::other(err_span, format!("failed to load file `{path_str}`")))?;
// Prevent include itself
if res == call_site && !allow_recursion {
Err(ExpandError::other(format!("recursive inclusion of `{path_str}`")))
Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`")))
} else {
Ok(EditionedFileId::new(res, db.crate_graph()[lookup.krate].edition))
}
@ -727,7 +729,7 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
}
_ => None,
})
.ok_or(mbe::ExpandError::ConversionError.into())
.ok_or(ExpandError::other(tt.delimiter.open, "expected string literal"))
}
fn include_expand(
@ -751,7 +753,7 @@ fn include_expand(
Some(it) => ExpandResult::ok(it),
None => ExpandResult::new(
tt::Subtree::empty(DelimSpan { open: span, close: span }),
ExpandError::other("failed to parse included file"),
ExpandError::other(span, "failed to parse included file"),
),
}
}
@ -761,7 +763,7 @@ pub fn include_input_to_file_id(
arg_id: MacroCallId,
arg: &tt::Subtree,
) -> Result<EditionedFileId, ExpandError> {
relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false)
relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false, arg.delimiter.open)
}
fn include_bytes_expand(
@ -800,7 +802,7 @@ fn include_str_expand(
// it's unusual to `include_str!` a Rust file), but we can return an empty string.
// Ideally, we'd be able to offer a precise expansion if the user asks for macro
// expansion.
let file_id = match relative_file(db, arg_id, path.as_str(), true) {
let file_id = match relative_file(db, arg_id, path.as_str(), true, span) {
Ok(file_id) => file_id,
Err(_) => {
return ExpandResult::ok(quote!(span =>""));
@ -836,7 +838,10 @@ fn env_expand(
// The only variable rust-analyzer ever sets is `OUT_DIR`, so only diagnose that to avoid
// unnecessary diagnostics for eg. `CARGO_PKG_NAME`.
if key.as_str() == "OUT_DIR" {
err = Some(ExpandError::other(r#"`OUT_DIR` not set, enable "build scripts" to fix"#));
err = Some(ExpandError::other(
span,
r#"`OUT_DIR` not set, enable "build scripts" to fix"#,
));
}
// If the variable is unset, still return a dummy string to help type inference along.
@ -885,7 +890,7 @@ fn quote_expand(
) -> ExpandResult<tt::Subtree> {
ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: span, close: span }),
ExpandError::other("quote! is not implemented"),
ExpandError::other(span, "quote! is not implemented"),
)
}

View file

@ -259,39 +259,38 @@ pub fn expand_speculative(
// Do the actual expansion, we need to directly expand the proc macro due to the attribute args
// Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
let mut speculative_expansion =
match loc.def.kind {
MacroDefKind::ProcMacro(ast, expander, _) => {
let span = db.proc_macro_span(ast);
tt.delimiter = tt::Delimiter::invisible_spanned(span);
expander.expand(
db,
loc.def.krate,
loc.krate,
&tt,
attr_arg.as_ref(),
span_with_def_site_ctxt(db, span, actual_macro_call),
span_with_call_site_ctxt(db, span, actual_macro_call),
span_with_mixed_site_ctxt(db, span, actual_macro_call),
)
}
MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span)
}
MacroDefKind::Declarative(it) => db
.decl_macro_expander(loc.krate, it)
.expand_unhygienic(db, tt, loc.def.krate, span, loc.def.edition),
MacroDefKind::BuiltIn(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInDerive(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInEager(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
};
let mut speculative_expansion = match loc.def.kind {
MacroDefKind::ProcMacro(ast, expander, _) => {
let span = db.proc_macro_span(ast);
tt.delimiter = tt::Delimiter::invisible_spanned(span);
expander.expand(
db,
loc.def.krate,
loc.krate,
&tt,
attr_arg.as_ref(),
span_with_def_site_ctxt(db, span, actual_macro_call),
span_with_call_site_ctxt(db, span, actual_macro_call),
span_with_mixed_site_ctxt(db, span, actual_macro_call),
)
}
MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span)
}
MacroDefKind::Declarative(it) => {
db.decl_macro_expander(loc.krate, it).expand_unhygienic(tt, span, loc.def.edition)
}
MacroDefKind::BuiltIn(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInDerive(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInEager(_, it) => {
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
};
let expand_to = loc.expand_to();
@ -735,11 +734,14 @@ fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
if TOKEN_LIMIT.check(count).is_err() {
Err(ExpandResult {
value: (),
err: Some(ExpandError::other(format!(
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
count,
TOKEN_LIMIT.inner(),
))),
err: Some(ExpandError::other(
tt.delimiter.open,
format!(
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
count,
TOKEN_LIMIT.inner(),
),
)),
})
} else {
Ok(())

View file

@ -1,7 +1,6 @@
//! Compiled declarative macro expanders (`macro_rules!`` and `macro`)
use std::sync::OnceLock;
use base_db::{CrateId, VersionReq};
use base_db::CrateId;
use intern::sym;
use mbe::DocCommentDesugarMode;
use span::{Edition, MacroCallId, Span, SyntaxContextId};
@ -13,7 +12,7 @@ use crate::{
attrs::RawAttrs,
db::ExpandDatabase,
hygiene::{apply_mark, Transparency},
tt, AstId, ExpandError, ExpandResult, Lookup,
tt, AstId, ExpandError, ExpandErrorKind, ExpandResult, Lookup,
};
/// Old-style `macro_rules` or the new macros 2.0
@ -23,9 +22,6 @@ pub struct DeclarativeMacroExpander {
pub transparency: Transparency,
}
// FIXME: Remove this once we drop support for 1.76
static REQUIREMENT: OnceLock<VersionReq> = OnceLock::new();
impl DeclarativeMacroExpander {
pub fn expand(
&self,
@ -35,29 +31,16 @@ impl DeclarativeMacroExpander {
span: Span,
) -> ExpandResult<(tt::Subtree, Option<u32>)> {
let loc = db.lookup_intern_macro_call(call_id);
let toolchain = db.toolchain(loc.def.krate);
let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
&base_db::Version {
pre: base_db::Prerelease::EMPTY,
build: base_db::BuildMetadata::EMPTY,
major: version.major,
minor: version.minor,
patch: version.patch,
},
)
});
match self.mac.err() {
Some(_) => ExpandResult::new(
(tt::Subtree::empty(tt::DelimSpan { open: span, close: span }), None),
ExpandError::MacroDefinition,
ExpandError::new(span, ExpandErrorKind::MacroDefinition),
),
None => self
.mac
.expand(
&tt,
|s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency),
new_meta_vars,
span,
loc.def.edition,
)
@ -67,32 +50,18 @@ impl DeclarativeMacroExpander {
pub fn expand_unhygienic(
&self,
db: &dyn ExpandDatabase,
tt: tt::Subtree,
krate: CrateId,
call_site: Span,
def_site_edition: Edition,
) -> ExpandResult<tt::Subtree> {
let toolchain = db.toolchain(krate);
let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
&base_db::Version {
pre: base_db::Prerelease::EMPTY,
build: base_db::BuildMetadata::EMPTY,
major: version.major,
minor: version.minor,
patch: version.patch,
},
)
});
match self.mac.err() {
Some(_) => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
ExpandError::MacroDefinition,
ExpandError::new(call_site, ExpandErrorKind::MacroDefinition),
),
None => self
.mac
.expand(&tt, |_| (), new_meta_vars, call_site, def_site_edition)
.expand(&tt, |_| (), call_site, def_site_edition)
.map(TupleExt::head)
.map_err(Into::into),
}

View file

@ -176,14 +176,19 @@ fn eager_macro_recur(
Some(path) => match macro_resolver(&path) {
Some(def) => def,
None => {
error =
Some(ExpandError::other(format!("unresolved macro {}", path.display(db))));
error = Some(ExpandError::other(
span_map.span_at(call.syntax().text_range().start()),
format!("unresolved macro {}", path.display(db)),
));
offset += call.syntax().text_range().len();
continue;
}
},
None => {
error = Some(ExpandError::other("malformed macro invocation"));
error = Some(ExpandError::other(
span_map.span_at(call.syntax().text_range().start()),
"malformed macro invocation",
));
offset += call.syntax().text_range().len();
continue;
}

View file

@ -124,47 +124,77 @@ impl_intern_lookup!(
pub type ExpandResult<T> = ValueResult<T, ExpandError>;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum ExpandError {
ProcMacroAttrExpansionDisabled,
MissingProcMacroExpander(CrateId),
/// The macro expansion is disabled.
MacroDisabled,
MacroDefinition,
Mbe(mbe::ExpandError),
RecursionOverflow,
Other(Arc<Box<str>>),
ProcMacroPanic(Arc<Box<str>>),
pub struct ExpandError {
inner: Arc<(ExpandErrorKind, Span)>,
}
impl ExpandError {
pub fn other(msg: impl Into<Box<str>>) -> Self {
ExpandError::Other(Arc::new(msg.into()))
pub fn new(span: Span, kind: ExpandErrorKind) -> Self {
ExpandError { inner: Arc::new((kind, span)) }
}
pub fn other(span: Span, msg: impl Into<Box<str>>) -> Self {
ExpandError { inner: Arc::new((ExpandErrorKind::Other(msg.into()), span)) }
}
pub fn kind(&self) -> &ExpandErrorKind {
&self.inner.0
}
pub fn span(&self) -> Span {
self.inner.1
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum ExpandErrorKind {
/// Attribute macro expansion is disabled.
ProcMacroAttrExpansionDisabled,
MissingProcMacroExpander(CrateId),
/// The macro for this call is disabled.
MacroDisabled,
/// The macro definition has errors.
MacroDefinition,
Mbe(mbe::ExpandErrorKind),
RecursionOverflow,
Other(Box<str>),
ProcMacroPanic(Box<str>),
}
impl ExpandError {
pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> (String, bool) {
self.inner.0.render_to_string(db)
}
}
impl ExpandErrorKind {
pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> (String, bool) {
match self {
Self::ProcMacroAttrExpansionDisabled => {
ExpandErrorKind::ProcMacroAttrExpansionDisabled => {
("procedural attribute macro expansion is disabled".to_owned(), false)
}
Self::MacroDisabled => ("proc-macro is explicitly disabled".to_owned(), false),
&Self::MissingProcMacroExpander(def_crate) => {
ExpandErrorKind::MacroDisabled => {
("proc-macro is explicitly disabled".to_owned(), false)
}
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
match db.proc_macros().get_error_for_crate(def_crate) {
Some((e, hard_err)) => (e.to_owned(), hard_err),
None => ("missing expander".to_owned(), true),
}
}
Self::MacroDefinition => ("macro definition has parse errors".to_owned(), true),
Self::Mbe(e) => (e.to_string(), true),
Self::RecursionOverflow => ("overflow expanding the original macro".to_owned(), true),
Self::Other(e) => ((***e).to_owned(), true),
Self::ProcMacroPanic(e) => ((***e).to_owned(), true),
ExpandErrorKind::MacroDefinition => {
("macro definition has parse errors".to_owned(), true)
}
ExpandErrorKind::Mbe(e) => (e.to_string(), true),
ExpandErrorKind::RecursionOverflow => {
("overflow expanding the original macro".to_owned(), true)
}
ExpandErrorKind::Other(e) => ((**e).to_owned(), true),
ExpandErrorKind::ProcMacroPanic(e) => ((**e).to_owned(), true),
}
}
}
impl From<mbe::ExpandError> for ExpandError {
fn from(mbe: mbe::ExpandError) -> Self {
Self::Mbe(mbe)
ExpandError { inner: Arc::new((ExpandErrorKind::Mbe(mbe.inner.1.clone()), mbe.inner.0)) }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -7,9 +7,8 @@ use base_db::{CrateId, Env};
use intern::Symbol;
use rustc_hash::FxHashMap;
use span::Span;
use triomphe::Arc;
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult};
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub enum ProcMacroKind {
@ -76,15 +75,18 @@ impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros {
}
impl ProcMacros {
fn get(&self, krate: CrateId, idx: u32) -> Result<&ProcMacro, ExpandError> {
fn get(&self, krate: CrateId, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> {
let proc_macros = match self.0.get(&krate) {
Some(Ok(proc_macros)) => proc_macros,
Some(Err(_)) | None => {
return Err(ExpandError::other("internal error: no proc macros for crate"));
return Err(ExpandError::other(
err_span,
"internal error: no proc macros for crate",
));
}
};
proc_macros.get(idx as usize).ok_or_else(|| {
ExpandError::other(
ExpandError::other(err_span,
format!(
"internal error: proc-macro index out of bounds: the length is {} but the index is {}",
proc_macros.len(),
@ -184,11 +186,11 @@ impl CustomProcMacroExpander {
}
/// The macro is explicitly disabled due to proc-macro attribute expansion being disabled.
pub const fn as_expand_error(&self, def_crate: CrateId) -> Option<ExpandError> {
pub fn as_expand_error(&self, def_crate: CrateId) -> Option<ExpandErrorKind> {
match self.proc_macro_id {
Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandError::ProcMacroAttrExpansionDisabled),
Self::DISABLED_ID => Some(ExpandError::MacroDisabled),
Self::MISSING_EXPANDER => Some(ExpandError::MissingProcMacroExpander(def_crate)),
Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled),
Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled),
Self::MISSING_EXPANDER => Some(ExpandErrorKind::MissingProcMacroExpander(def_crate)),
_ => None,
}
}
@ -207,19 +209,19 @@ impl CustomProcMacroExpander {
match self.proc_macro_id {
Self::PROC_MACRO_ATTR_DISABLED => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
ExpandError::ProcMacroAttrExpansionDisabled,
ExpandError::new(call_site, ExpandErrorKind::ProcMacroAttrExpansionDisabled),
),
Self::MISSING_EXPANDER => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
ExpandError::MissingProcMacroExpander(def_crate),
ExpandError::new(call_site, ExpandErrorKind::MissingProcMacroExpander(def_crate)),
),
Self::DISABLED_ID => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
ExpandError::MacroDisabled,
ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
),
id => {
let proc_macros = db.proc_macros();
let proc_macro = match proc_macros.get(def_crate, id) {
let proc_macro = match proc_macros.get(def_crate, id, call_site) {
Ok(proc_macro) => proc_macro,
Err(e) => {
return ExpandResult::new(
@ -240,12 +242,18 @@ impl CustomProcMacroExpander {
ProcMacroExpansionError::System(text)
if proc_macro.kind == ProcMacroKind::Attr =>
{
ExpandResult { value: tt.clone(), err: Some(ExpandError::other(text)) }
ExpandResult {
value: tt.clone(),
err: Some(ExpandError::other(call_site, text)),
}
}
ProcMacroExpansionError::System(text)
| ProcMacroExpansionError::Panic(text) => ExpandResult::new(
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
ExpandError::ProcMacroPanic(Arc::new(text.into_boxed_str())),
ExpandError::new(
call_site,
ExpandErrorKind::ProcMacroPanic(text.into_boxed_str()),
),
),
},
}