use crate::expand::{self, AstFragment, Invocation};
+use crate::module::DirectoryOwnership;
use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind};
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
-use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
+use rustc_parse::{self, parser, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
}
}
-// `meta_item` is the annotation, and `item` is the item being modified.
-// FIXME Decorators should follow the same pattern too.
+/// Result of an expansion that may need to be retried.
+/// Consider using this for non-`MultiItemModifier` expanders as well.
+pub enum ExpandResult<T, U> {
+ /// Expansion produced a result (possibly dummy).
+ Ready(T),
+ /// Expansion could not produce a result and needs to be retried.
+ /// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
+ Retry(U, String),
+}
+
+// `meta_item` is the attribute, and `item` is the item being modified.
pub trait MultiItemModifier {
fn expand(
&self,
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable,
- ) -> Vec<Annotatable>;
+ ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
}
-impl<F, T> MultiItemModifier for F
+impl<F> MultiItemModifier for F
where
- F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T,
- T: Into<Vec<Annotatable>>,
+ F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec<Annotatable>,
{
fn expand(
&self,
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable,
- ) -> Vec<Annotatable> {
- (*self)(ecx, span, meta_item, item).into()
- }
-}
-
-impl Into<Vec<Annotatable>> for Annotatable {
- fn into(self) -> Vec<Annotatable> {
- vec![self]
+ ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
+ ExpandResult::Ready(self(ecx, span, meta_item, item))
}
}
mut_visit::noop_visit_tt(tt, self)
}
- fn visit_mac(&mut self, mac: &mut ast::Mac) {
+ fn visit_mac(&mut self, mac: &mut ast::MacCall) {
mut_visit::noop_visit_mac(mac, self)
}
}
fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
fn add_derive_copy(&mut self, expn_id: ExpnId);
+ fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
}
#[derive(Clone)]
pub resolver: &'a mut dyn Resolver,
pub current_expansion: ExpansionData,
pub expansions: FxHashMap<Span, Vec<String>>,
+ /// Called directly after having parsed an external `mod foo;` in expansion.
+ pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
}
impl<'a> ExtCtxt<'a> {
parse_sess: &'a ParseSess,
ecfg: expand::ExpansionConfig<'a>,
resolver: &'a mut dyn Resolver,
+ extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
) -> ExtCtxt<'a> {
ExtCtxt {
parse_sess,
ecfg,
- root_path: PathBuf::new(),
resolver,
+ extern_mod_loaded,
+ root_path: PathBuf::new(),
current_expansion: ExpansionData {
id: ExpnId::root(),
depth: 0,