mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-08 21:13:55 +00:00
Rollup merge of #132192 - petrochenkov:macfa, r=compiler-errors
expand: Stop using artificial `ast::Item` for macros loaded from metadata You don't need a full `Item` for that, and not using a piece of AST helps with https://github.com/rust-lang/rust/pull/131808.
This commit is contained in:
commit
b3ac6d339c
@ -3,12 +3,11 @@ use std::collections::hash_map::Entry;
|
|||||||
use std::{mem, slice};
|
use std::{mem, slice};
|
||||||
|
|
||||||
use ast::token::IdentIsRaw;
|
use ast::token::IdentIsRaw;
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_ast::token::NtPatKind::*;
|
use rustc_ast::token::NtPatKind::*;
|
||||||
use rustc_ast::token::TokenKind::*;
|
use rustc_ast::token::TokenKind::*;
|
||||||
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
|
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||||
use rustc_ast::{DUMMY_NODE_ID, NodeId};
|
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::{self as attr, TransparencyError};
|
use rustc_attr::{self as attr, TransparencyError};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||||
@ -370,34 +369,32 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
|
|||||||
pub fn compile_declarative_macro(
|
pub fn compile_declarative_macro(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
features: &Features,
|
features: &Features,
|
||||||
def: &ast::Item,
|
macro_def: &ast::MacroDef,
|
||||||
|
ident: Ident,
|
||||||
|
attrs: &[ast::Attribute],
|
||||||
|
span: Span,
|
||||||
|
node_id: NodeId,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
) -> (SyntaxExtension, Vec<(usize, Span)>) {
|
) -> (SyntaxExtension, Vec<(usize, Span)>) {
|
||||||
debug!("compile_declarative_macro: {:?}", def);
|
|
||||||
let mk_syn_ext = |expander| {
|
let mk_syn_ext = |expander| {
|
||||||
SyntaxExtension::new(
|
SyntaxExtension::new(
|
||||||
sess,
|
sess,
|
||||||
features,
|
features,
|
||||||
SyntaxExtensionKind::LegacyBang(expander),
|
SyntaxExtensionKind::LegacyBang(expander),
|
||||||
def.span,
|
span,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
edition,
|
edition,
|
||||||
def.ident.name,
|
ident.name,
|
||||||
&def.attrs,
|
attrs,
|
||||||
def.id != DUMMY_NODE_ID,
|
node_id != DUMMY_NODE_ID,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new());
|
let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new());
|
||||||
|
|
||||||
let dcx = sess.dcx();
|
let dcx = sess.dcx();
|
||||||
let lhs_nm = Ident::new(sym::lhs, def.span);
|
let lhs_nm = Ident::new(sym::lhs, span);
|
||||||
let rhs_nm = Ident::new(sym::rhs, def.span);
|
let rhs_nm = Ident::new(sym::rhs, span);
|
||||||
let tt_spec = Some(NonterminalKind::TT);
|
let tt_spec = Some(NonterminalKind::TT);
|
||||||
|
|
||||||
let macro_def = match &def.kind {
|
|
||||||
ast::ItemKind::MacroDef(def) => def,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let macro_rules = macro_def.macro_rules;
|
let macro_rules = macro_def.macro_rules;
|
||||||
|
|
||||||
// Parse the macro_rules! invocation
|
// Parse the macro_rules! invocation
|
||||||
@ -410,25 +407,22 @@ pub fn compile_declarative_macro(
|
|||||||
let argument_gram = vec![
|
let argument_gram = vec![
|
||||||
mbe::TokenTree::Sequence(DelimSpan::dummy(), mbe::SequenceRepetition {
|
mbe::TokenTree::Sequence(DelimSpan::dummy(), mbe::SequenceRepetition {
|
||||||
tts: vec![
|
tts: vec![
|
||||||
mbe::TokenTree::MetaVarDecl(def.span, lhs_nm, tt_spec),
|
mbe::TokenTree::MetaVarDecl(span, lhs_nm, tt_spec),
|
||||||
mbe::TokenTree::token(token::FatArrow, def.span),
|
mbe::TokenTree::token(token::FatArrow, span),
|
||||||
mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec),
|
mbe::TokenTree::MetaVarDecl(span, rhs_nm, tt_spec),
|
||||||
],
|
],
|
||||||
separator: Some(Token::new(
|
separator: Some(Token::new(if macro_rules { token::Semi } else { token::Comma }, span)),
|
||||||
if macro_rules { token::Semi } else { token::Comma },
|
kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, span),
|
||||||
def.span,
|
|
||||||
)),
|
|
||||||
kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span),
|
|
||||||
num_captures: 2,
|
num_captures: 2,
|
||||||
}),
|
}),
|
||||||
// to phase into semicolon-termination instead of semicolon-separation
|
// to phase into semicolon-termination instead of semicolon-separation
|
||||||
mbe::TokenTree::Sequence(DelimSpan::dummy(), mbe::SequenceRepetition {
|
mbe::TokenTree::Sequence(DelimSpan::dummy(), mbe::SequenceRepetition {
|
||||||
tts: vec![mbe::TokenTree::token(
|
tts: vec![mbe::TokenTree::token(
|
||||||
if macro_rules { token::Semi } else { token::Comma },
|
if macro_rules { token::Semi } else { token::Comma },
|
||||||
def.span,
|
span,
|
||||||
)],
|
)],
|
||||||
separator: None,
|
separator: None,
|
||||||
kleene: mbe::KleeneToken::new(mbe::KleeneOp::ZeroOrMore, def.span),
|
kleene: mbe::KleeneToken::new(mbe::KleeneOp::ZeroOrMore, span),
|
||||||
num_captures: 0,
|
num_captures: 0,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@ -460,7 +454,7 @@ pub fn compile_declarative_macro(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let s = parse_failure_msg(&token, track.get_expected_token());
|
let s = parse_failure_msg(&token, track.get_expected_token());
|
||||||
let sp = token.span.substitute_dummy(def.span);
|
let sp = token.span.substitute_dummy(span);
|
||||||
let mut err = sess.dcx().struct_span_err(sp, s);
|
let mut err = sess.dcx().struct_span_err(sp, s);
|
||||||
err.span_label(sp, msg);
|
err.span_label(sp, msg);
|
||||||
annotate_doc_comment(&mut err, sess.source_map(), sp);
|
annotate_doc_comment(&mut err, sess.source_map(), sp);
|
||||||
@ -468,7 +462,7 @@ pub fn compile_declarative_macro(
|
|||||||
return dummy_syn_ext(guar);
|
return dummy_syn_ext(guar);
|
||||||
}
|
}
|
||||||
Error(sp, msg) => {
|
Error(sp, msg) => {
|
||||||
let guar = sess.dcx().span_err(sp.substitute_dummy(def.span), msg);
|
let guar = sess.dcx().span_err(sp.substitute_dummy(span), msg);
|
||||||
return dummy_syn_ext(guar);
|
return dummy_syn_ext(guar);
|
||||||
}
|
}
|
||||||
ErrorReported(guar) => {
|
ErrorReported(guar) => {
|
||||||
@ -489,7 +483,7 @@ pub fn compile_declarative_macro(
|
|||||||
&TokenStream::new(vec![tt.clone()]),
|
&TokenStream::new(vec![tt.clone()]),
|
||||||
true,
|
true,
|
||||||
sess,
|
sess,
|
||||||
def.id,
|
node_id,
|
||||||
features,
|
features,
|
||||||
edition,
|
edition,
|
||||||
)
|
)
|
||||||
@ -497,13 +491,13 @@ pub fn compile_declarative_macro(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
// We don't handle errors here, the driver will abort
|
// We don't handle errors here, the driver will abort
|
||||||
// after parsing/expansion. We can report every error in every macro this way.
|
// after parsing/expansion. We can report every error in every macro this way.
|
||||||
check_emission(check_lhs_nt_follows(sess, def, &tt));
|
check_emission(check_lhs_nt_follows(sess, node_id, &tt));
|
||||||
return tt;
|
return tt;
|
||||||
}
|
}
|
||||||
sess.dcx().span_bug(def.span, "wrong-structured lhs")
|
sess.dcx().span_bug(span, "wrong-structured lhs")
|
||||||
})
|
})
|
||||||
.collect::<Vec<mbe::TokenTree>>(),
|
.collect::<Vec<mbe::TokenTree>>(),
|
||||||
_ => sess.dcx().span_bug(def.span, "wrong-structured lhs"),
|
_ => sess.dcx().span_bug(span, "wrong-structured lhs"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
|
let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] {
|
||||||
@ -515,17 +509,17 @@ pub fn compile_declarative_macro(
|
|||||||
&TokenStream::new(vec![tt.clone()]),
|
&TokenStream::new(vec![tt.clone()]),
|
||||||
false,
|
false,
|
||||||
sess,
|
sess,
|
||||||
def.id,
|
node_id,
|
||||||
features,
|
features,
|
||||||
edition,
|
edition,
|
||||||
)
|
)
|
||||||
.pop()
|
.pop()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
sess.dcx().span_bug(def.span, "wrong-structured rhs")
|
sess.dcx().span_bug(span, "wrong-structured rhs")
|
||||||
})
|
})
|
||||||
.collect::<Vec<mbe::TokenTree>>(),
|
.collect::<Vec<mbe::TokenTree>>(),
|
||||||
_ => sess.dcx().span_bug(def.span, "wrong-structured rhs"),
|
_ => sess.dcx().span_bug(span, "wrong-structured rhs"),
|
||||||
};
|
};
|
||||||
|
|
||||||
for rhs in &rhses {
|
for rhs in &rhses {
|
||||||
@ -537,15 +531,9 @@ pub fn compile_declarative_macro(
|
|||||||
check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(lhs)));
|
check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(lhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
check_emission(macro_check::check_meta_variables(
|
check_emission(macro_check::check_meta_variables(&sess.psess, node_id, span, &lhses, &rhses));
|
||||||
&sess.psess,
|
|
||||||
def.id,
|
|
||||||
def.span,
|
|
||||||
&lhses,
|
|
||||||
&rhses,
|
|
||||||
));
|
|
||||||
|
|
||||||
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
|
let (transparency, transparency_error) = attr::find_transparency(attrs, macro_rules);
|
||||||
match transparency_error {
|
match transparency_error {
|
||||||
Some(TransparencyError::UnknownTransparency(value, span)) => {
|
Some(TransparencyError::UnknownTransparency(value, span)) => {
|
||||||
dcx.span_err(span, format!("unknown macro transparency: `{value}`"));
|
dcx.span_err(span, format!("unknown macro transparency: `{value}`"));
|
||||||
@ -564,7 +552,7 @@ pub fn compile_declarative_macro(
|
|||||||
|
|
||||||
// Compute the spans of the macro rules for unused rule linting.
|
// Compute the spans of the macro rules for unused rule linting.
|
||||||
// Also, we are only interested in non-foreign macros.
|
// Also, we are only interested in non-foreign macros.
|
||||||
let rule_spans = if def.id != DUMMY_NODE_ID {
|
let rule_spans = if node_id != DUMMY_NODE_ID {
|
||||||
lhses
|
lhses
|
||||||
.iter()
|
.iter()
|
||||||
.zip(rhses.iter())
|
.zip(rhses.iter())
|
||||||
@ -590,15 +578,15 @@ pub fn compile_declarative_macro(
|
|||||||
mbe::TokenTree::Delimited(.., delimited) => {
|
mbe::TokenTree::Delimited(.., delimited) => {
|
||||||
mbe::macro_parser::compute_locs(&delimited.tts)
|
mbe::macro_parser::compute_locs(&delimited.tts)
|
||||||
}
|
}
|
||||||
_ => sess.dcx().span_bug(def.span, "malformed macro lhs"),
|
_ => sess.dcx().span_bug(span, "malformed macro lhs"),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let expander = Box::new(MacroRulesMacroExpander {
|
let expander = Box::new(MacroRulesMacroExpander {
|
||||||
name: def.ident,
|
name: ident,
|
||||||
span: def.span,
|
span,
|
||||||
node_id: def.id,
|
node_id,
|
||||||
transparency,
|
transparency,
|
||||||
lhses,
|
lhses,
|
||||||
rhses,
|
rhses,
|
||||||
@ -608,13 +596,13 @@ pub fn compile_declarative_macro(
|
|||||||
|
|
||||||
fn check_lhs_nt_follows(
|
fn check_lhs_nt_follows(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
def: &ast::Item,
|
node_id: NodeId,
|
||||||
lhs: &mbe::TokenTree,
|
lhs: &mbe::TokenTree,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||||
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
||||||
check_matcher(sess, def, &delimited.tts)
|
check_matcher(sess, node_id, &delimited.tts)
|
||||||
} else {
|
} else {
|
||||||
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
||||||
Err(sess.dcx().span_err(lhs.span(), msg))
|
Err(sess.dcx().span_err(lhs.span(), msg))
|
||||||
@ -686,12 +674,12 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed
|
|||||||
|
|
||||||
fn check_matcher(
|
fn check_matcher(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
def: &ast::Item,
|
node_id: NodeId,
|
||||||
matcher: &[mbe::TokenTree],
|
matcher: &[mbe::TokenTree],
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let first_sets = FirstSets::new(matcher);
|
let first_sets = FirstSets::new(matcher);
|
||||||
let empty_suffix = TokenSet::empty();
|
let empty_suffix = TokenSet::empty();
|
||||||
check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix)?;
|
check_matcher_core(sess, node_id, &first_sets, matcher, &empty_suffix)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1028,7 +1016,7 @@ impl<'tt> TokenSet<'tt> {
|
|||||||
// see `FirstSets::new`.
|
// see `FirstSets::new`.
|
||||||
fn check_matcher_core<'tt>(
|
fn check_matcher_core<'tt>(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
def: &ast::Item,
|
node_id: NodeId,
|
||||||
first_sets: &FirstSets<'tt>,
|
first_sets: &FirstSets<'tt>,
|
||||||
matcher: &'tt [mbe::TokenTree],
|
matcher: &'tt [mbe::TokenTree],
|
||||||
follow: &TokenSet<'tt>,
|
follow: &TokenSet<'tt>,
|
||||||
@ -1082,7 +1070,7 @@ fn check_matcher_core<'tt>(
|
|||||||
token::CloseDelim(d.delim),
|
token::CloseDelim(d.delim),
|
||||||
span.close,
|
span.close,
|
||||||
));
|
));
|
||||||
check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix)?;
|
check_matcher_core(sess, node_id, first_sets, &d.tts, &my_suffix)?;
|
||||||
// don't track non NT tokens
|
// don't track non NT tokens
|
||||||
last.replace_with_irrelevant();
|
last.replace_with_irrelevant();
|
||||||
|
|
||||||
@ -1114,7 +1102,7 @@ fn check_matcher_core<'tt>(
|
|||||||
// At this point, `suffix_first` is built, and
|
// At this point, `suffix_first` is built, and
|
||||||
// `my_suffix` is some TokenSet that we can use
|
// `my_suffix` is some TokenSet that we can use
|
||||||
// for checking the interior of `seq_rep`.
|
// for checking the interior of `seq_rep`.
|
||||||
let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix)?;
|
let next = check_matcher_core(sess, node_id, first_sets, &seq_rep.tts, my_suffix)?;
|
||||||
if next.maybe_empty {
|
if next.maybe_empty {
|
||||||
last.add_all(&next);
|
last.add_all(&next);
|
||||||
} else {
|
} else {
|
||||||
@ -1144,7 +1132,7 @@ fn check_matcher_core<'tt>(
|
|||||||
// macro. (See #86567.)
|
// macro. (See #86567.)
|
||||||
// Macros defined in the current crate have a real node id,
|
// Macros defined in the current crate have a real node id,
|
||||||
// whereas macros from an external crate have a dummy id.
|
// whereas macros from an external crate have a dummy id.
|
||||||
if def.id != DUMMY_NODE_ID
|
if node_id != DUMMY_NODE_ID
|
||||||
&& matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
|
&& matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
|
||||||
&& matches!(
|
&& matches!(
|
||||||
next_token,
|
next_token,
|
||||||
|
@ -28,7 +28,7 @@ use rustc_session::lint::{self, BuiltinLintDiag};
|
|||||||
use rustc_session::output::validate_crate_name;
|
use rustc_session::output::validate_crate_name;
|
||||||
use rustc_session::search_paths::PathKind;
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::symbol::{Symbol, sym};
|
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use rustc_target::spec::{PanicStrategy, Target, TargetTriple};
|
use rustc_target::spec::{PanicStrategy, Target, TargetTriple};
|
||||||
use tracing::{debug, info, trace};
|
use tracing::{debug, info, trace};
|
||||||
@ -97,7 +97,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum LoadedMacro {
|
pub enum LoadedMacro {
|
||||||
MacroDef(ast::Item, Edition),
|
MacroDef { def: MacroDef, ident: Ident, attrs: AttrVec, span: Span, edition: Edition },
|
||||||
ProcMacro(SyntaxExtension),
|
ProcMacro(SyntaxExtension),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_attr::Deprecation;
|
use rustc_attr::Deprecation;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
@ -592,27 +591,16 @@ impl CStore {
|
|||||||
|
|
||||||
let data = self.get_crate_data(id.krate);
|
let data = self.get_crate_data(id.krate);
|
||||||
if data.root.is_proc_macro_crate() {
|
if data.root.is_proc_macro_crate() {
|
||||||
return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, tcx));
|
LoadedMacro::ProcMacro(data.load_proc_macro(id.index, tcx))
|
||||||
}
|
} else {
|
||||||
|
LoadedMacro::MacroDef {
|
||||||
let span = data.get_span(id.index, sess);
|
def: data.get_macro(id.index, sess),
|
||||||
|
|
||||||
LoadedMacro::MacroDef(
|
|
||||||
ast::Item {
|
|
||||||
ident: data.item_ident(id.index, sess),
|
ident: data.item_ident(id.index, sess),
|
||||||
id: ast::DUMMY_NODE_ID,
|
|
||||||
span,
|
|
||||||
attrs: data.get_item_attrs(id.index, sess).collect(),
|
attrs: data.get_item_attrs(id.index, sess).collect(),
|
||||||
kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)),
|
span: data.get_span(id.index, sess),
|
||||||
vis: ast::Visibility {
|
edition: data.root.edition,
|
||||||
span: span.shrink_to_lo(),
|
}
|
||||||
kind: ast::VisibilityKind::Inherited,
|
}
|
||||||
tokens: None,
|
|
||||||
},
|
|
||||||
tokens: None,
|
|
||||||
},
|
|
||||||
data.root.edition,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
|
pub fn def_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
|
||||||
|
@ -177,7 +177,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
let loaded_macro = self.cstore().load_macro_untracked(def_id, self.tcx);
|
let loaded_macro = self.cstore().load_macro_untracked(def_id, self.tcx);
|
||||||
let macro_data = match loaded_macro {
|
let macro_data = match loaded_macro {
|
||||||
LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition),
|
LoadedMacro::MacroDef { def, ident, attrs, span, edition } => {
|
||||||
|
self.compile_macro(&def, ident, &attrs, span, ast::DUMMY_NODE_ID, edition)
|
||||||
|
}
|
||||||
LoadedMacro::ProcMacro(ext) => MacroData::new(Lrc::new(ext)),
|
LoadedMacro::ProcMacro(ext) => MacroData::new(Lrc::new(ext)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,8 +199,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
|||||||
},
|
},
|
||||||
ItemKind::Const(..) => DefKind::Const,
|
ItemKind::Const(..) => DefKind::Const,
|
||||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||||
ItemKind::MacroDef(..) => {
|
ItemKind::MacroDef(def) => {
|
||||||
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
|
let edition = self.resolver.tcx.sess.edition();
|
||||||
|
let macro_data =
|
||||||
|
self.resolver.compile_macro(def, i.ident, &i.attrs, i.span, i.id, edition);
|
||||||
let macro_kind = macro_data.ext.macro_kind();
|
let macro_kind = macro_data.ext.macro_kind();
|
||||||
opt_macro_data = Some(macro_data);
|
opt_macro_data = Some(macro_data);
|
||||||
DefKind::Macro(macro_kind)
|
DefKind::Macro(macro_kind)
|
||||||
|
@ -1122,9 +1122,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
/// Compile the macro into a `SyntaxExtension` and its rule spans.
|
/// Compile the macro into a `SyntaxExtension` and its rule spans.
|
||||||
///
|
///
|
||||||
/// Possibly replace its expander to a pre-defined one for built-in macros.
|
/// Possibly replace its expander to a pre-defined one for built-in macros.
|
||||||
pub(crate) fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> MacroData {
|
pub(crate) fn compile_macro(
|
||||||
let (mut ext, mut rule_spans) =
|
&mut self,
|
||||||
compile_declarative_macro(self.tcx.sess, self.tcx.features(), item, edition);
|
macro_def: &ast::MacroDef,
|
||||||
|
ident: Ident,
|
||||||
|
attrs: &[ast::Attribute],
|
||||||
|
span: Span,
|
||||||
|
node_id: NodeId,
|
||||||
|
edition: Edition,
|
||||||
|
) -> MacroData {
|
||||||
|
let (mut ext, mut rule_spans) = compile_declarative_macro(
|
||||||
|
self.tcx.sess,
|
||||||
|
self.tcx.features(),
|
||||||
|
macro_def,
|
||||||
|
ident,
|
||||||
|
attrs,
|
||||||
|
span,
|
||||||
|
node_id,
|
||||||
|
edition,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(builtin_name) = ext.builtin_name {
|
if let Some(builtin_name) = ext.builtin_name {
|
||||||
// The macro was marked with `#[rustc_builtin_macro]`.
|
// The macro was marked with `#[rustc_builtin_macro]`.
|
||||||
@ -1132,28 +1148,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// The macro is a built-in, replace its expander function
|
// The macro is a built-in, replace its expander function
|
||||||
// while still taking everything else from the source code.
|
// while still taking everything else from the source code.
|
||||||
// If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
|
// If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
|
||||||
match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) {
|
match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(span)) {
|
||||||
BuiltinMacroState::NotYetSeen(builtin_ext) => {
|
BuiltinMacroState::NotYetSeen(builtin_ext) => {
|
||||||
ext.kind = builtin_ext;
|
ext.kind = builtin_ext;
|
||||||
rule_spans = Vec::new();
|
rule_spans = Vec::new();
|
||||||
}
|
}
|
||||||
BuiltinMacroState::AlreadySeen(span) => {
|
BuiltinMacroState::AlreadySeen(note_span) => {
|
||||||
self.dcx().emit_err(errors::AttemptToDefineBuiltinMacroTwice {
|
self.dcx()
|
||||||
span: item.span,
|
.emit_err(errors::AttemptToDefineBuiltinMacroTwice { span, note_span });
|
||||||
note_span: span,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName {
|
self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
|
||||||
span: item.span,
|
|
||||||
ident: item.ident,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ItemKind::MacroDef(def) = &item.kind else { unreachable!() };
|
MacroData { ext: Lrc::new(ext), rule_spans, macro_rules: macro_def.macro_rules }
|
||||||
MacroData { ext: Lrc::new(ext), rule_spans, macro_rules: def.macro_rules }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_accessible(
|
fn path_accessible(
|
||||||
|
@ -248,9 +248,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
|
|||||||
// Check to see if it is a macro 2.0 or built-in macro
|
// Check to see if it is a macro 2.0 or built-in macro
|
||||||
if matches!(
|
if matches!(
|
||||||
CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx),
|
CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx),
|
||||||
LoadedMacro::MacroDef(def, _)
|
LoadedMacro::MacroDef { def, .. } if !def.macro_rules
|
||||||
if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
|
|
||||||
if !ast_def.macro_rules)
|
|
||||||
) {
|
) {
|
||||||
once(crate_name).chain(relative).collect()
|
once(crate_name).chain(relative).collect()
|
||||||
} else {
|
} else {
|
||||||
@ -747,24 +745,12 @@ fn build_macro(
|
|||||||
is_doc_hidden: bool,
|
is_doc_hidden: bool,
|
||||||
) -> clean::ItemKind {
|
) -> clean::ItemKind {
|
||||||
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
|
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
|
||||||
LoadedMacro::MacroDef(item_def, _) => match macro_kind {
|
LoadedMacro::MacroDef { def, .. } => match macro_kind {
|
||||||
MacroKind::Bang => {
|
MacroKind::Bang => {
|
||||||
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
|
let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
|
||||||
let vis =
|
clean::MacroItem(clean::Macro {
|
||||||
cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
|
source: utils::display_macro_source(cx, name, &def, def_id, vis, is_doc_hidden),
|
||||||
clean::MacroItem(clean::Macro {
|
})
|
||||||
source: utils::display_macro_source(
|
|
||||||
cx,
|
|
||||||
name,
|
|
||||||
def,
|
|
||||||
def_id,
|
|
||||||
vis,
|
|
||||||
is_doc_hidden,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
MacroKind::Derive | MacroKind::Attr => {
|
MacroKind::Derive | MacroKind::Attr => {
|
||||||
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
|
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
|
||||||
|
@ -16,6 +16,7 @@ use itertools::Itertools;
|
|||||||
use rustc_attr::{ConstStability, StabilityLevel, StableSince};
|
use rustc_attr::{ConstStability, StabilityLevel, StableSince};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_metadata::creader::{CStore, LoadedMacro};
|
use rustc_metadata::creader::{CStore, LoadedMacro};
|
||||||
@ -25,7 +26,6 @@ use rustc_span::symbol::kw;
|
|||||||
use rustc_span::{Symbol, sym};
|
use rustc_span::{Symbol, sym};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
use {rustc_ast as ast, rustc_hir as hir};
|
|
||||||
|
|
||||||
use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
|
use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
|
||||||
use crate::clean::types::ExternalLocation;
|
use crate::clean::types::ExternalLocation;
|
||||||
@ -554,10 +554,8 @@ fn generate_macro_def_id_path(
|
|||||||
// Check to see if it is a macro 2.0 or built-in macro.
|
// Check to see if it is a macro 2.0 or built-in macro.
|
||||||
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
|
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
|
||||||
let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) {
|
let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) {
|
||||||
LoadedMacro::MacroDef(def, _) => {
|
// If `def.macro_rules` is `true`, then it's not a macro 2.0.
|
||||||
// If `ast_def.macro_rules` is `true`, then it's not a macro 2.0.
|
LoadedMacro::MacroDef { def, .. } => !def.macro_rules,
|
||||||
matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules)
|
|
||||||
}
|
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user