1
Fork 0

expand: Pass ast::Crate by reference to AST transforming passes

Also some more attributes are passed by reference.
This commit is contained in:
Vadim Petrochenkov 2023-02-18 16:23:57 +04:00
parent 84dd6dfd9d
commit 6cc33b7691
9 changed files with 62 additions and 79 deletions

View file

@ -192,38 +192,32 @@ fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
}
/// `cfg_attr`-process the crate's attributes and compute the crate's features.
pub fn features(
sess: &Session,
mut krate: ast::Crate,
lint_node_id: NodeId,
) -> (ast::Crate, Features) {
pub fn features(sess: &Session, krate: &mut ast::Crate, lint_node_id: NodeId) -> Features {
let mut strip_unconfigured =
StripUnconfigured { sess, features: None, config_tokens: false, lint_node_id };
let unconfigured_attrs = krate.attrs.clone();
let mut unconfigured_attrs = krate.attrs.clone();
let diag = &sess.parse_sess.span_diagnostic;
let err_count = diag.err_count();
let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) {
None => {
// The entire crate is unconfigured.
krate.attrs = ast::AttrVec::new();
krate.items = ThinVec::new();
Features::default()
krate.attrs.flat_map_in_place(|attr| strip_unconfigured.process_cfg_attr(&attr));
if !strip_unconfigured.in_cfg(&krate.attrs) {
// The entire crate is unconfigured.
krate.attrs = ast::AttrVec::new();
krate.items = ThinVec::new();
Features::default()
} else {
let features = get_features(sess, &krate.attrs);
if err_count == diag.err_count() {
// Avoid reconfiguring malformed `cfg_attr`s.
strip_unconfigured.features = Some(&features);
// Run configuration again, this time with features available
// so that we can perform feature-gating.
unconfigured_attrs.flat_map_in_place(|attr| strip_unconfigured.process_cfg_attr(&attr));
strip_unconfigured.in_cfg(&unconfigured_attrs);
}
Some(attrs) => {
krate.attrs = attrs;
let features = get_features(sess, &krate.attrs);
if err_count == diag.err_count() {
// Avoid reconfiguring malformed `cfg_attr`s.
strip_unconfigured.features = Some(&features);
// Run configuration again, this time with features available
// so that we can perform feature-gating.
strip_unconfigured.configure_krate_attrs(unconfigured_attrs);
}
features
}
};
(krate, features)
features
}
}
#[macro_export]
@ -254,11 +248,6 @@ impl<'a> StripUnconfigured<'a> {
}
}
fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
self.in_cfg(&attrs).then_some(attrs)
}
/// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
/// This is only used during the invocation of `derive` proc-macros,
/// which require that we cfg-expand their entire input.
@ -281,7 +270,7 @@ impl<'a> StripUnconfigured<'a> {
.iter()
.flat_map(|tree| match tree.clone() {
AttrTokenTree::Attributes(mut data) => {
data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
if self.in_cfg(&data.attrs) {
data.tokens = LazyAttrTokenStream::new(
@ -319,12 +308,16 @@ impl<'a> StripUnconfigured<'a> {
/// the syntax of any `cfg_attr` is incorrect.
fn process_cfg_attrs<T: HasAttrs>(&self, node: &mut T) {
node.visit_attrs(|attrs| {
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
});
}
fn process_cfg_attr(&self, attr: Attribute) -> Vec<Attribute> {
if attr.has_name(sym::cfg_attr) { self.expand_cfg_attr(attr, true) } else { vec![attr] }
fn process_cfg_attr(&self, attr: &Attribute) -> Vec<Attribute> {
if attr.has_name(sym::cfg_attr) {
self.expand_cfg_attr(attr, true)
} else {
vec![attr.clone()]
}
}
/// Parse and expand a single `cfg_attr` attribute into a list of attributes
@ -334,9 +327,9 @@ impl<'a> StripUnconfigured<'a> {
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
pub(crate) fn expand_cfg_attr(&self, attr: Attribute, recursive: bool) -> Vec<Attribute> {
pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
let Some((cfg_predicate, expanded_attrs)) =
rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) else {
rustc_parse::parse_cfg_attr(attr, &self.sess.parse_sess) else {
return vec![];
};
@ -365,10 +358,10 @@ impl<'a> StripUnconfigured<'a> {
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
expanded_attrs
.into_iter()
.flat_map(|item| self.process_cfg_attr(self.expand_cfg_attr_item(&attr, item)))
.flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(attr, item)))
.collect()
} else {
expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(&attr, item)).collect()
expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(attr, item)).collect()
}
}