Skip to content

rustc_interface: Add a new query pre_configure #108221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 23, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions compiler/rustc_builtin_macros/src/cmdline_attrs.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use rustc_ast::{self as ast, AttrItem, AttrStyle};
use rustc_session::parse::ParseSess;
use rustc_span::FileName;

pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate {
pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) {
for raw_attr in attrs {
let mut parser = rustc_parse::new_parser_from_source_str(
parse_sess,
@@ -36,6 +36,4 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
start_span.to(end_span),
));
}

krate
}
12 changes: 5 additions & 7 deletions compiler/rustc_builtin_macros/src/proc_macro_harness.rs
Original file line number Diff line number Diff line change
@@ -43,14 +43,14 @@ struct CollectProcMacros<'a> {
}

pub fn inject(
krate: &mut ast::Crate,
sess: &Session,
resolver: &mut dyn ResolverExpand,
mut krate: ast::Crate,
is_proc_macro_crate: bool,
has_proc_macro_decls: bool,
is_test_crate: bool,
handler: &rustc_errors::Handler,
) -> ast::Crate {
) {
let ecfg = ExpansionConfig::default("proc_macro".to_string());
let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);

@@ -64,22 +64,20 @@ pub fn inject(
};

if has_proc_macro_decls || is_proc_macro_crate {
visit::walk_crate(&mut collect, &krate);
visit::walk_crate(&mut collect, krate);
}
let macros = collect.macros;

if !is_proc_macro_crate {
return krate;
return;
}

if is_test_crate {
return krate;
return;
}

let decls = mk_decls(&mut cx, &macros);
krate.items.push(decls);

krate
}

impl<'a> CollectProcMacros<'a> {
17 changes: 9 additions & 8 deletions compiler/rustc_builtin_macros/src/standard_library_imports.rs
Original file line number Diff line number Diff line change
@@ -9,17 +9,19 @@ use rustc_span::DUMMY_SP;
use thin_vec::thin_vec;

pub fn inject(
mut krate: ast::Crate,
krate: &mut ast::Crate,
pre_configured_attrs: &[ast::Attribute],
resolver: &mut dyn ResolverExpand,
sess: &Session,
) -> ast::Crate {
) -> usize {
let orig_num_items = krate.items.len();
let edition = sess.parse_sess.edition;

// the first name in this list is the crate name of the crate with the prelude
let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) {
return krate;
} else if attr::contains_name(&krate.attrs, sym::no_std) {
if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
return 0;
} else if attr::contains_name(pre_configured_attrs, sym::no_std) {
if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) {
&[sym::core]
} else {
&[sym::core, sym::compiler_builtins]
@@ -88,6 +90,5 @@ pub fn inject(
);

krate.items.insert(0, use_item);

krate
krate.items.len() - orig_num_items
}
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/test_harness.rs
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ struct TestCtxt<'a> {

/// Traverse the crate, collecting all the test functions, eliding any
/// existing main functions, and synthesizing a main test harness
pub fn inject(sess: &Session, resolver: &mut dyn ResolverExpand, krate: &mut ast::Crate) {
pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn ResolverExpand) {
let span_diagnostic = sess.diagnostic();
let panic_strategy = sess.panic_strategy();
let platform_panic_strategy = sess.target.panic_strategy;
2 changes: 1 addition & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -353,7 +353,7 @@ fn run_compiler(

{
let plugins = queries.register_plugins()?;
let (_, lint_store) = &*plugins.borrow();
let (.., lint_store) = &*plugins.borrow();

// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
2 changes: 2 additions & 0 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
@@ -1002,6 +1002,7 @@ pub struct ExpansionData {
pub struct ExtCtxt<'a> {
pub sess: &'a Session,
pub ecfg: expand::ExpansionConfig<'a>,
pub num_standard_library_imports: usize,
pub reduced_recursion_limit: Option<Limit>,
pub root_path: PathBuf,
pub resolver: &'a mut dyn ResolverExpand,
@@ -1030,6 +1031,7 @@ impl<'a> ExtCtxt<'a> {
ExtCtxt {
sess,
ecfg,
num_standard_library_imports: 0,
reduced_recursion_limit: None,
resolver,
lint_store,
69 changes: 22 additions & 47 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@ use rustc_session::Session;
use rustc_span::edition::{Edition, ALL_EDITIONS};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use thin_vec::ThinVec;

/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
@@ -37,7 +36,7 @@ pub struct StripUnconfigured<'a> {
pub lint_node_id: NodeId,
}

fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
sess.emit_err(FeatureRemoved {
span,
@@ -191,39 +190,16 @@ fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
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) {
let mut strip_unconfigured =
StripUnconfigured { sess, features: None, config_tokens: false, lint_node_id };

let 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()
}
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
}
pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec {
let strip_unconfigured = StripUnconfigured {
sess,
features: None,
config_tokens: false,
lint_node_id: ast::CRATE_NODE_ID,
};
(krate, features)
let attrs: ast::AttrVec =
attrs.iter().flat_map(|attr| strip_unconfigured.process_cfg_attr(attr)).collect();
if strip_unconfigured.in_cfg(&attrs) { attrs } else { ast::AttrVec::new() }
}

#[macro_export]
@@ -254,11 +230,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 +252,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 +290,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 +309,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 +340,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()
}
}

16 changes: 12 additions & 4 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
@@ -1038,6 +1038,9 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
) -> Result<Self::OutputTy, Self> {
Ok(noop_flat_map(node, collector))
}
fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, span: Span) {
collector.cx.emit_err(RemoveNodeNotSupported { span, descr: Self::descr() });
}
}

impl InvocationCollectorNode for P<ast::Item> {
@@ -1378,6 +1381,11 @@ impl InvocationCollectorNode for ast::Crate {
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
noop_visit_crate(self, visitor)
}
fn expand_cfg_false(&mut self, collector: &mut InvocationCollector<'_, '_>, _span: Span) {
self.attrs.clear();
// Standard prelude imports are left in the crate for backward compatibility.
self.items.truncate(collector.cx.num_standard_library_imports);
}
}

impl InvocationCollectorNode for P<ast::Ty> {
@@ -1688,7 +1696,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
res
}

fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) {
fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: &ast::Attribute, pos: usize) {
node.visit_attrs(|attrs| {
// Repeated `insert` calls is inefficient, but the number of
// insertions is almost always 0 or 1 in practice.
@@ -1712,7 +1720,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
Default::default()
}
sym::cfg_attr => {
self.expand_cfg_attr(&mut node, attr, pos);
self.expand_cfg_attr(&mut node, &attr, pos);
continue;
}
_ => {
@@ -1756,11 +1764,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
continue;
}

self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
node.expand_cfg_false(self, span);
continue;
}
sym::cfg_attr => {
self.expand_cfg_attr(node, attr, pos);
self.expand_cfg_attr(node, &attr, pos);
continue;
}
_ => visit_clobber(node, |node| {
Loading