mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Auto merge of #17221 - Veykril:lazier-validation, r=Veykril
internal: Lazier macro parse tree validation
This commit is contained in:
commit
b98690ba74
14 changed files with 151 additions and 140 deletions
|
@ -8,7 +8,7 @@ mod input;
|
||||||
use std::panic;
|
use std::panic;
|
||||||
|
|
||||||
use salsa::Durability;
|
use salsa::Durability;
|
||||||
use syntax::{ast, Parse, SourceFile};
|
use syntax::{ast, Parse, SourceFile, SyntaxError};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -62,6 +62,9 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
||||||
/// Parses the file into the syntax tree.
|
/// Parses the file into the syntax tree.
|
||||||
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
|
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
|
||||||
|
|
||||||
|
/// Returns the set of errors obtained from parsing the file including validation errors.
|
||||||
|
fn parse_errors(&self, file_id: FileId) -> Option<Arc<[SyntaxError]>>;
|
||||||
|
|
||||||
/// The crate graph.
|
/// The crate graph.
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
fn crate_graph(&self) -> Arc<CrateGraph>;
|
fn crate_graph(&self) -> Arc<CrateGraph>;
|
||||||
|
@ -88,6 +91,14 @@ fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
|
||||||
SourceFile::parse(&text, span::Edition::CURRENT)
|
SourceFile::parse(&text, span::Edition::CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_errors(db: &dyn SourceDatabase, file_id: FileId) -> Option<Arc<[SyntaxError]>> {
|
||||||
|
let errors = db.parse(file_id).errors();
|
||||||
|
match &*errors {
|
||||||
|
[] => None,
|
||||||
|
[..] => Some(errors.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// We don't want to give HIR knowledge of source roots, hence we extract these
|
/// We don't want to give HIR knowledge of source roots, hence we extract these
|
||||||
/// methods into a separate DB.
|
/// methods into a separate DB.
|
||||||
#[salsa::query_group(SourceDatabaseExtStorage)]
|
#[salsa::query_group(SourceDatabaseExtStorage)]
|
||||||
|
|
|
@ -10,9 +10,10 @@ use std::ops::Index;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use hir_expand::{name::Name, HirFileId, InFile};
|
use hir_expand::{name::Name, InFile};
|
||||||
use la_arena::{Arena, ArenaMap};
|
use la_arena::{Arena, ArenaMap};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use span::MacroFileId;
|
||||||
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
use syntax::{ast, AstPtr, SyntaxNodePtr};
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ pub struct BodySourceMap {
|
||||||
|
|
||||||
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
||||||
|
|
||||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
|
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
|
||||||
|
|
||||||
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
|
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
|
||||||
/// the source map (since they're just as volatile).
|
/// the source map (since they're just as volatile).
|
||||||
|
@ -349,11 +350,17 @@ impl BodySourceMap {
|
||||||
self.expr_map.get(&src).cloned()
|
self.expr_map.get(&src).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
|
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<MacroFileId> {
|
||||||
let src = node.map(AstPtr::new);
|
let src = node.map(AstPtr::new);
|
||||||
self.expansions.get(&src).cloned()
|
self.expansions.get(&src).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn macro_calls(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = (InFile<AstPtr<ast::MacroCall>>, MacroFileId)> + '_ {
|
||||||
|
self.expansions.iter().map(|(&a, &b)| (a, b))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
|
pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
|
||||||
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
|
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1006,7 +1006,9 @@ impl ExprCollector<'_> {
|
||||||
Some((mark, expansion)) => {
|
Some((mark, expansion)) => {
|
||||||
// Keep collecting even with expansion errors so we can provide completions and
|
// Keep collecting even with expansion errors so we can provide completions and
|
||||||
// other services in incomplete macro expressions.
|
// other services in incomplete macro expressions.
|
||||||
self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id());
|
self.source_map
|
||||||
|
.expansions
|
||||||
|
.insert(macro_call_ptr, self.expander.current_file_id().macro_file().unwrap());
|
||||||
let prev_ast_id_map = mem::replace(
|
let prev_ast_id_map = mem::replace(
|
||||||
&mut self.ast_id_map,
|
&mut self.ast_id_map,
|
||||||
self.db.ast_id_map(self.expander.current_file_id()),
|
self.db.ast_id_map(self.expander.current_file_id()),
|
||||||
|
|
|
@ -229,7 +229,7 @@ pub struct TraitData {
|
||||||
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
||||||
/// 2015 or 2018.
|
/// 2015 or 2018.
|
||||||
// box it as the vec is usually empty anyways
|
// box it as the vec is usually empty anyways
|
||||||
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitData {
|
impl TraitData {
|
||||||
|
@ -258,12 +258,12 @@ impl TraitData {
|
||||||
let mut collector =
|
let mut collector =
|
||||||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
|
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
|
||||||
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
|
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
|
||||||
let (items, attribute_calls, diagnostics) = collector.finish();
|
let (items, macro_calls, diagnostics) = collector.finish();
|
||||||
|
|
||||||
(
|
(
|
||||||
Arc::new(TraitData {
|
Arc::new(TraitData {
|
||||||
name,
|
name,
|
||||||
attribute_calls,
|
macro_calls,
|
||||||
items,
|
items,
|
||||||
is_auto,
|
is_auto,
|
||||||
is_unsafe,
|
is_unsafe,
|
||||||
|
@ -298,7 +298,7 @@ impl TraitData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
||||||
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
|
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ impl TraitAliasData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ImplData {
|
pub struct ImplData {
|
||||||
pub target_trait: Option<Interned<TraitRef>>,
|
pub target_trait: Option<Interned<TraitRef>>,
|
||||||
pub self_ty: Interned<TypeRef>,
|
pub self_ty: Interned<TypeRef>,
|
||||||
|
@ -327,7 +327,7 @@ pub struct ImplData {
|
||||||
pub is_negative: bool,
|
pub is_negative: bool,
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
// box it as the vec is usually empty anyways
|
// box it as the vec is usually empty anyways
|
||||||
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImplData {
|
impl ImplData {
|
||||||
|
@ -354,7 +354,7 @@ impl ImplData {
|
||||||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
|
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
|
||||||
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
|
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
|
||||||
|
|
||||||
let (items, attribute_calls, diagnostics) = collector.finish();
|
let (items, macro_calls, diagnostics) = collector.finish();
|
||||||
let items = items.into_iter().map(|(_, item)| item).collect();
|
let items = items.into_iter().map(|(_, item)| item).collect();
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -364,14 +364,14 @@ impl ImplData {
|
||||||
items,
|
items,
|
||||||
is_negative,
|
is_negative,
|
||||||
is_unsafe,
|
is_unsafe,
|
||||||
attribute_calls,
|
macro_calls,
|
||||||
}),
|
}),
|
||||||
DefDiagnostics::new(diagnostics),
|
DefDiagnostics::new(diagnostics),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
||||||
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
|
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +573,7 @@ struct AssocItemCollector<'a> {
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
|
|
||||||
items: Vec<(Name, AssocItemId)>,
|
items: Vec<(Name, AssocItemId)>,
|
||||||
attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
|
macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AssocItemCollector<'a> {
|
impl<'a> AssocItemCollector<'a> {
|
||||||
|
@ -590,7 +590,7 @@ impl<'a> AssocItemCollector<'a> {
|
||||||
container,
|
container,
|
||||||
expander: Expander::new(db, file_id, module_id),
|
expander: Expander::new(db, file_id, module_id),
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
attr_calls: Vec::new(),
|
macro_calls: Vec::new(),
|
||||||
diagnostics: Vec::new(),
|
diagnostics: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,7 +604,7 @@ impl<'a> AssocItemCollector<'a> {
|
||||||
) {
|
) {
|
||||||
(
|
(
|
||||||
self.items,
|
self.items,
|
||||||
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
|
if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
|
||||||
self.diagnostics,
|
self.diagnostics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -662,11 +662,11 @@ impl<'a> AssocItemCollector<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.attr_calls.push((ast_id, call_id));
|
self.macro_calls.push((ast_id, call_id));
|
||||||
|
|
||||||
let res =
|
let res =
|
||||||
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
||||||
self.collect_macro_items(res, &|| loc.kind.clone());
|
self.collect_macro_items(res);
|
||||||
continue 'items;
|
continue 'items;
|
||||||
}
|
}
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
|
@ -743,11 +743,8 @@ impl<'a> AssocItemCollector<'a> {
|
||||||
Ok(Some(call_id)) => {
|
Ok(Some(call_id)) => {
|
||||||
let res =
|
let res =
|
||||||
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
||||||
self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike {
|
self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id));
|
||||||
ast_id: InFile::new(file_id, ast_id),
|
self.collect_macro_items(res);
|
||||||
expand_to: hir_expand::ExpandTo::Items,
|
|
||||||
eager: None,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -766,39 +763,8 @@ impl<'a> AssocItemCollector<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_macro_items(
|
fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) {
|
||||||
&mut self,
|
let Some((mark, _parse)) = res.value else { return };
|
||||||
ExpandResult { value, err }: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>,
|
|
||||||
error_call_kind: &dyn Fn() -> hir_expand::MacroCallKind,
|
|
||||||
) {
|
|
||||||
let Some((mark, parse)) = value else { return };
|
|
||||||
|
|
||||||
if let Some(err) = err {
|
|
||||||
let diag = match err {
|
|
||||||
// why is this reported here?
|
|
||||||
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
|
||||||
DefDiagnostic::unresolved_proc_macro(
|
|
||||||
self.module_id.local_id,
|
|
||||||
error_call_kind(),
|
|
||||||
krate,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => DefDiagnostic::macro_error(
|
|
||||||
self.module_id.local_id,
|
|
||||||
error_call_kind(),
|
|
||||||
err.to_string(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
self.diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
let errors = parse.errors();
|
|
||||||
if !errors.is_empty() {
|
|
||||||
self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
|
|
||||||
self.module_id.local_id,
|
|
||||||
error_call_kind(),
|
|
||||||
errors.into_boxed_slice(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
|
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
|
||||||
let item_tree = tree_id.item_tree(self.db);
|
let item_tree = tree_id.item_tree(self.db);
|
||||||
|
|
|
@ -234,6 +234,14 @@ impl ItemScope {
|
||||||
self.impls.iter().copied()
|
self.impls.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
|
||||||
|
self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
|
||||||
|
self.derive_macros.values().flat_map(|it| {
|
||||||
|
it.iter().flat_map(|it| it.derive_call_ids.iter().copied().flatten())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
|
pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
|
||||||
self.types.values().copied().filter_map(|(def, vis, _)| match def {
|
self.types.values().copied().filter_map(|(def, vis, _)| match def {
|
||||||
ModuleDefId::ModuleId(module) => Some((module, vis)),
|
ModuleDefId::ModuleId(module) => Some((module, vis)),
|
||||||
|
|
|
@ -15,15 +15,13 @@ use hir_expand::{
|
||||||
builtin_fn_macro::find_builtin_macro,
|
builtin_fn_macro::find_builtin_macro,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
proc_macro::CustomProcMacroExpander,
|
proc_macro::CustomProcMacroExpander,
|
||||||
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc,
|
ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||||
MacroDefId, MacroDefKind,
|
|
||||||
};
|
};
|
||||||
use itertools::{izip, Itertools};
|
use itertools::{izip, Itertools};
|
||||||
use la_arena::Idx;
|
use la_arena::Idx;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
|
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
|
||||||
use stdx::always;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
|
@ -1412,31 +1410,6 @@ impl DefCollector<'_> {
|
||||||
}
|
}
|
||||||
let file_id = macro_call_id.as_file();
|
let file_id = macro_call_id.as_file();
|
||||||
|
|
||||||
// First, fetch the raw expansion result for purposes of error reporting. This goes through
|
|
||||||
// `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve
|
|
||||||
// incrementality).
|
|
||||||
// FIXME: This kind of error fetching feels a bit odd?
|
|
||||||
let ExpandResult { value: errors, err } =
|
|
||||||
self.db.parse_macro_expansion_error(macro_call_id);
|
|
||||||
if let Some(err) = err {
|
|
||||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
|
|
||||||
let diag = match err {
|
|
||||||
// why is this reported here?
|
|
||||||
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
|
||||||
always!(krate == loc.def.krate);
|
|
||||||
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
|
|
||||||
}
|
|
||||||
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.def_map.diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
if !errors.is_empty() {
|
|
||||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
|
|
||||||
let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors);
|
|
||||||
self.def_map.diagnostics.push(diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then, fetch and process the item tree. This will reuse the expansion result from above.
|
// Then, fetch and process the item tree. This will reuse the expansion result from above.
|
||||||
let item_tree = self.db.file_item_tree(file_id);
|
let item_tree = self.db.file_item_tree(file_id);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use base_db::CrateId;
|
||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
|
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
|
||||||
use la_arena::Idx;
|
use la_arena::Idx;
|
||||||
use syntax::{ast, SyntaxError};
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
item_tree::{self, ItemTreeId},
|
item_tree::{self, ItemTreeId},
|
||||||
|
@ -23,8 +23,6 @@ pub enum DefDiagnosticKind {
|
||||||
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
|
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
|
||||||
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
|
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
|
||||||
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
|
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
|
||||||
MacroError { ast: MacroCallKind, message: String },
|
|
||||||
MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
|
|
||||||
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
|
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
|
||||||
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
|
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
|
||||||
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
|
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
|
||||||
|
@ -98,7 +96,7 @@ impl DefDiagnostic {
|
||||||
// FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc
|
// FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc
|
||||||
// yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
|
// yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
|
||||||
// struct loses all that information!
|
// struct loses all that information!
|
||||||
pub(crate) fn unresolved_proc_macro(
|
pub fn unresolved_proc_macro(
|
||||||
container: LocalModuleId,
|
container: LocalModuleId,
|
||||||
ast: MacroCallKind,
|
ast: MacroCallKind,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
|
@ -106,25 +104,6 @@ impl DefDiagnostic {
|
||||||
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
|
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn macro_error(
|
|
||||||
container: LocalModuleId,
|
|
||||||
ast: MacroCallKind,
|
|
||||||
message: String,
|
|
||||||
) -> Self {
|
|
||||||
Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, message } }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn macro_expansion_parse_error(
|
|
||||||
container: LocalModuleId,
|
|
||||||
ast: MacroCallKind,
|
|
||||||
errors: Box<[SyntaxError]>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
in_module: container,
|
|
||||||
kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Whats the difference between this and unresolved_proc_macro
|
// FIXME: Whats the difference between this and unresolved_proc_macro
|
||||||
pub(crate) fn unresolved_macro_call(
|
pub(crate) fn unresolved_macro_call(
|
||||||
container: LocalModuleId,
|
container: LocalModuleId,
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub trait ExpandDatabase: SourceDatabase {
|
||||||
fn parse_macro_expansion_error(
|
fn parse_macro_expansion_error(
|
||||||
&self,
|
&self,
|
||||||
macro_call: MacroCallId,
|
macro_call: MacroCallId,
|
||||||
) -> ExpandResult<Box<[SyntaxError]>>;
|
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This expands the given macro call, but with different arguments. This is
|
/// This expands the given macro call, but with different arguments. This is
|
||||||
|
@ -357,9 +357,14 @@ fn parse_macro_expansion(
|
||||||
fn parse_macro_expansion_error(
|
fn parse_macro_expansion_error(
|
||||||
db: &dyn ExpandDatabase,
|
db: &dyn ExpandDatabase,
|
||||||
macro_call_id: MacroCallId,
|
macro_call_id: MacroCallId,
|
||||||
) -> ExpandResult<Box<[SyntaxError]>> {
|
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>> {
|
||||||
db.parse_macro_expansion(MacroFileId { macro_call_id })
|
let e: ExpandResult<Arc<[SyntaxError]>> =
|
||||||
.map(|it| it.0.errors().into_boxed_slice())
|
db.parse_macro_expansion(MacroFileId { macro_call_id }).map(|it| Arc::from(it.0.errors()));
|
||||||
|
if e.value.is_empty() && e.err.is_none() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Arc::new(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_with_map(
|
pub(crate) fn parse_with_map(
|
||||||
|
|
|
@ -132,13 +132,13 @@ pub enum ExpandError {
|
||||||
MacroDefinition,
|
MacroDefinition,
|
||||||
Mbe(mbe::ExpandError),
|
Mbe(mbe::ExpandError),
|
||||||
RecursionOverflow,
|
RecursionOverflow,
|
||||||
Other(Box<Box<str>>),
|
Other(Arc<Box<str>>),
|
||||||
ProcMacroPanic(Box<Box<str>>),
|
ProcMacroPanic(Arc<Box<str>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpandError {
|
impl ExpandError {
|
||||||
pub fn other(msg: impl Into<Box<str>>) -> Self {
|
pub fn other(msg: impl Into<Box<str>>) -> Self {
|
||||||
ExpandError::Other(Box::new(msg.into()))
|
ExpandError::Other(Arc::new(msg.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use rustc_hash::FxHashMap;
|
||||||
use span::Span;
|
use span::Span;
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
|
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ impl CustomProcMacroExpander {
|
||||||
ProcMacroExpansionError::System(text)
|
ProcMacroExpansionError::System(text)
|
||||||
| ProcMacroExpansionError::Panic(text) => ExpandResult::new(
|
| ProcMacroExpansionError::Panic(text) => ExpandResult::new(
|
||||||
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
|
tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
|
||||||
ExpandError::ProcMacroPanic(Box::new(text.into_boxed_str())),
|
ExpandError::ProcMacroPanic(Arc::new(text.into_boxed_str())),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub use hir_def::VariantId;
|
||||||
use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
|
use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId};
|
||||||
use hir_expand::{name::Name, HirFileId, InFile};
|
use hir_expand::{name::Name, HirFileId, InFile};
|
||||||
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
|
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
|
use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
|
||||||
|
|
||||||
|
@ -172,7 +173,7 @@ pub struct MacroError {
|
||||||
pub struct MacroExpansionParseError {
|
pub struct MacroExpansionParseError {
|
||||||
pub node: InFile<SyntaxNodePtr>,
|
pub node: InFile<SyntaxNodePtr>,
|
||||||
pub precise_location: Option<TextRange>,
|
pub precise_location: Option<TextRange>,
|
||||||
pub errors: Box<[SyntaxError]>,
|
pub errors: Arc<[SyntaxError]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
|
|
@ -59,7 +59,9 @@ use hir_def::{
|
||||||
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId,
|
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId,
|
||||||
TypeParamId, UnionId,
|
TypeParamId, UnionId,
|
||||||
};
|
};
|
||||||
use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind};
|
use hir_expand::{
|
||||||
|
attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
|
||||||
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
all_super_traits, autoderef, check_orphan_rules,
|
all_super_traits, autoderef, check_orphan_rules,
|
||||||
consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
|
consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
|
||||||
|
@ -79,7 +81,7 @@ use hir_ty::{
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nameres::diagnostics::DefDiagnosticKind;
|
use nameres::diagnostics::DefDiagnosticKind;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use span::Edition;
|
use span::{Edition, MacroCallId};
|
||||||
use stdx::{impl_from, never};
|
use stdx::{impl_from, never};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasAttrs as _, HasName},
|
ast::{self, HasAttrs as _, HasName},
|
||||||
|
@ -559,6 +561,12 @@ impl Module {
|
||||||
emit_def_diagnostic(db, acc, diag);
|
emit_def_diagnostic(db, acc, diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.id.is_block_module() {
|
||||||
|
// These are reported by the body of block modules
|
||||||
|
let scope = &def_map[self.id.local_id].scope;
|
||||||
|
scope.all_macro_calls().for_each(|it| macro_call_diagnostics(db, it, acc));
|
||||||
|
}
|
||||||
|
|
||||||
for def in self.declarations(db) {
|
for def in self.declarations(db) {
|
||||||
match def {
|
match def {
|
||||||
ModuleDef::Module(m) => {
|
ModuleDef::Module(m) => {
|
||||||
|
@ -577,6 +585,10 @@ impl Module {
|
||||||
item.diagnostics(db, acc, style_lints);
|
item.diagnostics(db, acc, style_lints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.all_macro_calls(db)
|
||||||
|
.iter()
|
||||||
|
.for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
|
||||||
|
|
||||||
acc.extend(def.diagnostics(db, style_lints))
|
acc.extend(def.diagnostics(db, style_lints))
|
||||||
}
|
}
|
||||||
ModuleDef::Adt(adt) => {
|
ModuleDef::Adt(adt) => {
|
||||||
|
@ -621,6 +633,11 @@ impl Module {
|
||||||
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
|
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
impl_def
|
||||||
|
.all_macro_calls(db)
|
||||||
|
.iter()
|
||||||
|
.for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
|
||||||
|
|
||||||
let ast_id_map = db.ast_id_map(file_id);
|
let ast_id_map = db.ast_id_map(file_id);
|
||||||
|
|
||||||
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
|
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
|
||||||
|
@ -809,6 +826,37 @@ impl Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn macro_call_diagnostics(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
macro_call_id: MacroCallId,
|
||||||
|
acc: &mut Vec<AnyDiagnostic>,
|
||||||
|
) {
|
||||||
|
let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ValueResult { value: parse_errors, err } = &*e;
|
||||||
|
if let Some(err) = err {
|
||||||
|
let loc = db.lookup_intern_macro_call(macro_call_id);
|
||||||
|
let (node, precise_location, macro_name, kind) = precise_macro_call_location(&loc.kind, db);
|
||||||
|
let diag = match err {
|
||||||
|
&hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
|
||||||
|
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate }.into()
|
||||||
|
}
|
||||||
|
err => MacroError { node, precise_location, message: err.to_string() }.into(),
|
||||||
|
};
|
||||||
|
acc.push(diag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !parse_errors.is_empty() {
|
||||||
|
let loc = db.lookup_intern_macro_call(macro_call_id);
|
||||||
|
let (node, precise_location, _, _) = precise_macro_call_location(&loc.kind, db);
|
||||||
|
acc.push(
|
||||||
|
MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
|
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
|
||||||
let id = db.macro_def(m.id);
|
let id = db.macro_def(m.id);
|
||||||
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
|
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
|
||||||
|
@ -888,16 +936,6 @@ fn emit_def_diagnostic_(
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
DefDiagnosticKind::MacroError { ast, message } => {
|
|
||||||
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
|
||||||
acc.push(MacroError { node, precise_location, message: message.clone() }.into());
|
|
||||||
}
|
|
||||||
DefDiagnosticKind::MacroExpansionParseError { ast, errors } => {
|
|
||||||
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
|
||||||
acc.push(
|
|
||||||
MacroExpansionParseError { node, precise_location, errors: errors.clone() }.into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
||||||
let node = ast.to_node(db.upcast());
|
let node = ast.to_node(db.upcast());
|
||||||
// Must have a name, otherwise we wouldn't emit it.
|
// Must have a name, otherwise we wouldn't emit it.
|
||||||
|
@ -1644,6 +1682,10 @@ impl DefWithBody {
|
||||||
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
|
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_map
|
||||||
|
.macro_calls()
|
||||||
|
.for_each(|(_ast_id, call_id)| macro_call_diagnostics(db, call_id.macro_call_id, acc));
|
||||||
|
|
||||||
for diag in source_map.diagnostics() {
|
for diag in source_map.diagnostics() {
|
||||||
acc.push(match diag {
|
acc.push(match diag {
|
||||||
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
|
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
|
||||||
|
@ -2445,6 +2487,14 @@ impl Trait {
|
||||||
.filter(|(_, ty)| !count_required_only || !ty.has_default())
|
.filter(|(_, ty)| !count_required_only || !ty.has_default())
|
||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
||||||
|
db.trait_data(self.id)
|
||||||
|
.macro_calls
|
||||||
|
.as_ref()
|
||||||
|
.map(|it| it.as_ref().clone().into_boxed_slice())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasVisibility for Trait {
|
impl HasVisibility for Trait {
|
||||||
|
@ -3765,6 +3815,14 @@ impl Impl {
|
||||||
pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
|
pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
|
||||||
check_orphan_rules(db, self.id)
|
check_orphan_rules(db, self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
|
||||||
|
db.impl_data(self.id)
|
||||||
|
.macro_calls
|
||||||
|
.as_ref()
|
||||||
|
.map(|it| it.as_ref().clone().into_boxed_slice())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
|
|
|
@ -28,7 +28,7 @@ use hir_expand::{
|
||||||
mod_path::path,
|
mod_path::path,
|
||||||
name,
|
name,
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
HirFileId, InFile, MacroFileId, MacroFileIdExt,
|
HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt,
|
||||||
};
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
diagnostics::{
|
diagnostics::{
|
||||||
|
@ -118,7 +118,7 @@ impl SourceAnalyzer {
|
||||||
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprId> {
|
||||||
let src = match expr {
|
let src = match expr {
|
||||||
ast::Expr::MacroExpr(expr) => {
|
ast::Expr::MacroExpr(expr) => {
|
||||||
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?))?
|
self.expand_expr(db, InFile::new(self.file_id, expr.macro_call()?))?.into()
|
||||||
}
|
}
|
||||||
_ => InFile::new(self.file_id, expr.clone()),
|
_ => InFile::new(self.file_id, expr.clone()),
|
||||||
};
|
};
|
||||||
|
@ -145,20 +145,20 @@ impl SourceAnalyzer {
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
expr: InFile<ast::MacroCall>,
|
expr: InFile<ast::MacroCall>,
|
||||||
) -> Option<InFile<ast::Expr>> {
|
) -> Option<InMacroFile<ast::Expr>> {
|
||||||
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
|
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
|
||||||
let expanded = db.parse_or_expand(macro_file);
|
let expanded = db.parse_macro_expansion(macro_file).value.0.syntax_node();
|
||||||
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
|
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
|
||||||
match stmts.expr()? {
|
match stmts.expr()? {
|
||||||
ast::Expr::MacroExpr(mac) => {
|
ast::Expr::MacroExpr(mac) => {
|
||||||
self.expand_expr(db, InFile::new(macro_file, mac.macro_call()?))?
|
self.expand_expr(db, InFile::new(macro_file.into(), mac.macro_call()?))?
|
||||||
}
|
}
|
||||||
expr => InFile::new(macro_file, expr),
|
expr => InMacroFile::new(macro_file, expr),
|
||||||
}
|
}
|
||||||
} else if let Some(call) = ast::MacroCall::cast(expanded.clone()) {
|
} else if let Some(call) = ast::MacroCall::cast(expanded.clone()) {
|
||||||
self.expand_expr(db, InFile::new(macro_file, call))?
|
self.expand_expr(db, InFile::new(macro_file.into(), call))?
|
||||||
} else {
|
} else {
|
||||||
InFile::new(macro_file, ast::Expr::cast(expanded)?)
|
InMacroFile::new(macro_file, ast::Expr::cast(expanded)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(res)
|
Some(res)
|
||||||
|
|
|
@ -299,11 +299,10 @@ pub fn diagnostics(
|
||||||
) -> Vec<Diagnostic> {
|
) -> Vec<Diagnostic> {
|
||||||
let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered();
|
let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered();
|
||||||
let sema = Semantics::new(db);
|
let sema = Semantics::new(db);
|
||||||
let parse = db.parse(file_id);
|
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
|
|
||||||
// [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
|
// [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
|
||||||
res.extend(parse.errors().into_iter().take(128).map(|err| {
|
res.extend(db.parse_errors(file_id).as_deref().into_iter().flatten().take(128).map(|err| {
|
||||||
Diagnostic::new(
|
Diagnostic::new(
|
||||||
DiagnosticCode::RustcHardError("syntax-error"),
|
DiagnosticCode::RustcHardError("syntax-error"),
|
||||||
format!("Syntax Error: {err}"),
|
format!("Syntax Error: {err}"),
|
||||||
|
@ -342,7 +341,8 @@ pub fn diagnostics(
|
||||||
AnyDiagnostic::MacroDefError(d) => handlers::macro_error::macro_def_error(&ctx, &d),
|
AnyDiagnostic::MacroDefError(d) => handlers::macro_error::macro_def_error(&ctx, &d),
|
||||||
AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d),
|
AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d),
|
||||||
AnyDiagnostic::MacroExpansionParseError(d) => {
|
AnyDiagnostic::MacroExpansionParseError(d) => {
|
||||||
res.extend(d.errors.iter().take(32).map(|err| {
|
// FIXME: Point to the correct error span here, not just the macro-call name
|
||||||
|
res.extend(d.errors.iter().take(16).map(|err| {
|
||||||
{
|
{
|
||||||
Diagnostic::new(
|
Diagnostic::new(
|
||||||
DiagnosticCode::RustcHardError("syntax-error"),
|
DiagnosticCode::RustcHardError("syntax-error"),
|
||||||
|
|
Loading…
Reference in a new issue