Auto merge of #108221 - petrochenkov:cratecfg, r=michaelwoerister
rustc_interface: Add a new query `pre_configure` It partially expands crate attributes before the main expansion pass (without modifying the crate), and the produced preliminary crate attribute list is used for querying a few attributes that are required very early. Crate-level cfg attributes on the crate itself are then expanded normally during the main expansion pass, like attributes on any other nodes. This is a continuation of https://github.com/rust-lang/rust/pull/92473 and one more step to very unstable crate-level proc macro attributes maybe actually working. Previously crate attributes were pre-configured simultaneously with feature extraction, and then written directly into `ast::Crate`.
This commit is contained in:
commit
df7fd9995f
20 changed files with 207 additions and 128 deletions
|
@ -6,7 +6,7 @@ use rustc_ast::{self as ast, AttrItem, AttrStyle};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::FileName;
|
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 {
|
for raw_attr in attrs {
|
||||||
let mut parser = rustc_parse::new_parser_from_source_str(
|
let mut parser = rustc_parse::new_parser_from_source_str(
|
||||||
parse_sess,
|
parse_sess,
|
||||||
|
@ -36,6 +36,4 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
||||||
start_span.to(end_span),
|
start_span.to(end_span),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
krate
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,14 @@ struct CollectProcMacros<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inject(
|
pub fn inject(
|
||||||
|
krate: &mut ast::Crate,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
resolver: &mut dyn ResolverExpand,
|
resolver: &mut dyn ResolverExpand,
|
||||||
mut krate: ast::Crate,
|
|
||||||
is_proc_macro_crate: bool,
|
is_proc_macro_crate: bool,
|
||||||
has_proc_macro_decls: bool,
|
has_proc_macro_decls: bool,
|
||||||
is_test_crate: bool,
|
is_test_crate: bool,
|
||||||
handler: &rustc_errors::Handler,
|
handler: &rustc_errors::Handler,
|
||||||
) -> ast::Crate {
|
) {
|
||||||
let ecfg = ExpansionConfig::default("proc_macro".to_string());
|
let ecfg = ExpansionConfig::default("proc_macro".to_string());
|
||||||
let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);
|
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 {
|
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;
|
let macros = collect.macros;
|
||||||
|
|
||||||
if !is_proc_macro_crate {
|
if !is_proc_macro_crate {
|
||||||
return krate;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_test_crate {
|
if is_test_crate {
|
||||||
return krate;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let decls = mk_decls(&mut cx, ¯os);
|
let decls = mk_decls(&mut cx, ¯os);
|
||||||
krate.items.push(decls);
|
krate.items.push(decls);
|
||||||
|
|
||||||
krate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CollectProcMacros<'a> {
|
impl<'a> CollectProcMacros<'a> {
|
||||||
|
|
|
@ -9,17 +9,19 @@ use rustc_span::DUMMY_SP;
|
||||||
use thin_vec::thin_vec;
|
use thin_vec::thin_vec;
|
||||||
|
|
||||||
pub fn inject(
|
pub fn inject(
|
||||||
mut krate: ast::Crate,
|
krate: &mut ast::Crate,
|
||||||
|
pre_configured_attrs: &[ast::Attribute],
|
||||||
resolver: &mut dyn ResolverExpand,
|
resolver: &mut dyn ResolverExpand,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
) -> ast::Crate {
|
) -> usize {
|
||||||
|
let orig_num_items = krate.items.len();
|
||||||
let edition = sess.parse_sess.edition;
|
let edition = sess.parse_sess.edition;
|
||||||
|
|
||||||
// the first name in this list is the crate name of the crate with the prelude
|
// 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) {
|
let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
|
||||||
return krate;
|
return 0;
|
||||||
} else if attr::contains_name(&krate.attrs, sym::no_std) {
|
} else if attr::contains_name(pre_configured_attrs, sym::no_std) {
|
||||||
if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
|
if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) {
|
||||||
&[sym::core]
|
&[sym::core]
|
||||||
} else {
|
} else {
|
||||||
&[sym::core, sym::compiler_builtins]
|
&[sym::core, sym::compiler_builtins]
|
||||||
|
@ -88,6 +90,5 @@ pub fn inject(
|
||||||
);
|
);
|
||||||
|
|
||||||
krate.items.insert(0, use_item);
|
krate.items.insert(0, use_item);
|
||||||
|
krate.items.len() - orig_num_items
|
||||||
krate
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct TestCtxt<'a> {
|
||||||
|
|
||||||
/// Traverse the crate, collecting all the test functions, eliding any
|
/// Traverse the crate, collecting all the test functions, eliding any
|
||||||
/// existing main functions, and synthesizing a main test harness
|
/// 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 span_diagnostic = sess.diagnostic();
|
||||||
let panic_strategy = sess.panic_strategy();
|
let panic_strategy = sess.panic_strategy();
|
||||||
let platform_panic_strategy = sess.target.panic_strategy;
|
let platform_panic_strategy = sess.target.panic_strategy;
|
||||||
|
|
|
@ -353,7 +353,7 @@ fn run_compiler(
|
||||||
|
|
||||||
{
|
{
|
||||||
let plugins = queries.register_plugins()?;
|
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.
|
// Lint plugins are registered; now we can process command line flags.
|
||||||
if sess.opts.describe_lints {
|
if sess.opts.describe_lints {
|
||||||
|
|
|
@ -1002,6 +1002,7 @@ pub struct ExpansionData {
|
||||||
pub struct ExtCtxt<'a> {
|
pub struct ExtCtxt<'a> {
|
||||||
pub sess: &'a Session,
|
pub sess: &'a Session,
|
||||||
pub ecfg: expand::ExpansionConfig<'a>,
|
pub ecfg: expand::ExpansionConfig<'a>,
|
||||||
|
pub num_standard_library_imports: usize,
|
||||||
pub reduced_recursion_limit: Option<Limit>,
|
pub reduced_recursion_limit: Option<Limit>,
|
||||||
pub root_path: PathBuf,
|
pub root_path: PathBuf,
|
||||||
pub resolver: &'a mut dyn ResolverExpand,
|
pub resolver: &'a mut dyn ResolverExpand,
|
||||||
|
@ -1030,6 +1031,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
ExtCtxt {
|
ExtCtxt {
|
||||||
sess,
|
sess,
|
||||||
ecfg,
|
ecfg,
|
||||||
|
num_standard_library_imports: 0,
|
||||||
reduced_recursion_limit: None,
|
reduced_recursion_limit: None,
|
||||||
resolver,
|
resolver,
|
||||||
lint_store,
|
lint_store,
|
||||||
|
|
|
@ -24,7 +24,6 @@ use rustc_session::Session;
|
||||||
use rustc_span::edition::{Edition, ALL_EDITIONS};
|
use rustc_span::edition::{Edition, ALL_EDITIONS};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use thin_vec::ThinVec;
|
|
||||||
|
|
||||||
/// A folder that strips out items that do not belong in the current configuration.
|
/// A folder that strips out items that do not belong in the current configuration.
|
||||||
pub struct StripUnconfigured<'a> {
|
pub struct StripUnconfigured<'a> {
|
||||||
|
@ -37,7 +36,7 @@ pub struct StripUnconfigured<'a> {
|
||||||
pub lint_node_id: NodeId,
|
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>) {
|
fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
|
||||||
sess.emit_err(FeatureRemoved {
|
sess.emit_err(FeatureRemoved {
|
||||||
span,
|
span,
|
||||||
|
@ -191,39 +190,16 @@ fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec {
|
||||||
pub fn features(
|
let strip_unconfigured = StripUnconfigured {
|
||||||
sess: &Session,
|
sess,
|
||||||
mut krate: ast::Crate,
|
features: None,
|
||||||
lint_node_id: NodeId,
|
config_tokens: false,
|
||||||
) -> (ast::Crate, Features) {
|
lint_node_id: ast::CRATE_NODE_ID,
|
||||||
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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
(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]
|
#[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`.
|
/// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
|
||||||
/// This is only used during the invocation of `derive` proc-macros,
|
/// This is only used during the invocation of `derive` proc-macros,
|
||||||
/// which require that we cfg-expand their entire input.
|
/// which require that we cfg-expand their entire input.
|
||||||
|
@ -281,7 +252,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|tree| match tree.clone() {
|
.flat_map(|tree| match tree.clone() {
|
||||||
AttrTokenTree::Attributes(mut data) => {
|
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) {
|
if self.in_cfg(&data.attrs) {
|
||||||
data.tokens = LazyAttrTokenStream::new(
|
data.tokens = LazyAttrTokenStream::new(
|
||||||
|
@ -319,12 +290,16 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
/// the syntax of any `cfg_attr` is incorrect.
|
/// the syntax of any `cfg_attr` is incorrect.
|
||||||
fn process_cfg_attrs<T: HasAttrs>(&self, node: &mut T) {
|
fn process_cfg_attrs<T: HasAttrs>(&self, node: &mut T) {
|
||||||
node.visit_attrs(|attrs| {
|
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> {
|
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] }
|
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
|
/// 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
|
/// 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
|
/// is in the original source file. Gives a compiler error if the syntax of
|
||||||
/// the attribute is incorrect.
|
/// 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)) =
|
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![];
|
return vec![];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -365,10 +340,10 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
|
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
|
||||||
expanded_attrs
|
expanded_attrs
|
||||||
.into_iter()
|
.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()
|
.collect()
|
||||||
} else {
|
} 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1038,6 +1038,9 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
|
||||||
) -> Result<Self::OutputTy, Self> {
|
) -> Result<Self::OutputTy, Self> {
|
||||||
Ok(noop_flat_map(node, collector))
|
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> {
|
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) {
|
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||||
noop_visit_crate(self, visitor)
|
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> {
|
impl InvocationCollectorNode for P<ast::Ty> {
|
||||||
|
@ -1688,7 +1696,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
res
|
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| {
|
node.visit_attrs(|attrs| {
|
||||||
// Repeated `insert` calls is inefficient, but the number of
|
// Repeated `insert` calls is inefficient, but the number of
|
||||||
// insertions is almost always 0 or 1 in practice.
|
// insertions is almost always 0 or 1 in practice.
|
||||||
|
@ -1712,7 +1720,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
sym::cfg_attr => {
|
sym::cfg_attr => {
|
||||||
self.expand_cfg_attr(&mut node, attr, pos);
|
self.expand_cfg_attr(&mut node, &attr, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1756,11 +1764,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
|
node.expand_cfg_false(self, span);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sym::cfg_attr => {
|
sym::cfg_attr => {
|
||||||
self.expand_cfg_attr(node, attr, pos);
|
self.expand_cfg_attr(node, &attr, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => visit_clobber(node, |node| {
|
_ => visit_clobber(node, |node| {
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::interface::{Compiler, Result};
|
||||||
use crate::proc_macro_decls;
|
use crate::proc_macro_decls;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
use ast::CRATE_NODE_ID;
|
|
||||||
use rustc_ast::{self as ast, visit};
|
use rustc_ast::{self as ast, visit};
|
||||||
use rustc_borrowck as mir_borrowck;
|
use rustc_borrowck as mir_borrowck;
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
|
@ -76,22 +75,14 @@ pub fn register_plugins<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
metadata_loader: &'a dyn MetadataLoader,
|
metadata_loader: &'a dyn MetadataLoader,
|
||||||
register_lints: impl Fn(&Session, &mut LintStore),
|
register_lints: impl Fn(&Session, &mut LintStore),
|
||||||
mut krate: ast::Crate,
|
pre_configured_attrs: &[ast::Attribute],
|
||||||
crate_name: Symbol,
|
crate_name: Symbol,
|
||||||
) -> Result<(ast::Crate, LintStore)> {
|
) -> Result<LintStore> {
|
||||||
krate = sess.time("attributes_injection", || {
|
|
||||||
rustc_builtin_macros::cmdline_attrs::inject(
|
|
||||||
krate,
|
|
||||||
&sess.parse_sess,
|
|
||||||
&sess.opts.unstable_opts.crate_attr,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
let (krate, features) = rustc_expand::config::features(sess, krate, CRATE_NODE_ID);
|
|
||||||
// these need to be set "early" so that expansion sees `quote` if enabled.
|
// these need to be set "early" so that expansion sees `quote` if enabled.
|
||||||
|
let features = rustc_expand::config::features(sess, pre_configured_attrs);
|
||||||
sess.init_features(features);
|
sess.init_features(features);
|
||||||
|
|
||||||
let crate_types = util::collect_crate_types(sess, &krate.attrs);
|
let crate_types = util::collect_crate_types(sess, pre_configured_attrs);
|
||||||
sess.init_crate_types(crate_types);
|
sess.init_crate_types(crate_types);
|
||||||
|
|
||||||
let stable_crate_id = StableCrateId::new(
|
let stable_crate_id = StableCrateId::new(
|
||||||
|
@ -117,8 +108,9 @@ pub fn register_plugins<'a>(
|
||||||
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
|
let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
|
||||||
register_lints(sess, &mut lint_store);
|
register_lints(sess, &mut lint_store);
|
||||||
|
|
||||||
let registrars =
|
let registrars = sess.time("plugin_loading", || {
|
||||||
sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate));
|
plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs)
|
||||||
|
});
|
||||||
sess.time("plugin_registration", || {
|
sess.time("plugin_registration", || {
|
||||||
let mut registry = plugin::Registry { lint_store: &mut lint_store };
|
let mut registry = plugin::Registry { lint_store: &mut lint_store };
|
||||||
for registrar in registrars {
|
for registrar in registrars {
|
||||||
|
@ -126,7 +118,7 @@ pub fn register_plugins<'a>(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok((krate, lint_store))
|
Ok(lint_store)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pre_expansion_lint<'a>(
|
fn pre_expansion_lint<'a>(
|
||||||
|
@ -173,19 +165,29 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
||||||
/// harness if one is to be provided, injection of a dependency on the
|
/// harness if one is to be provided, injection of a dependency on the
|
||||||
/// standard library and prelude, and name resolution.
|
/// standard library and prelude, and name resolution.
|
||||||
#[instrument(level = "trace", skip(krate, resolver))]
|
#[instrument(level = "trace", skip(krate, resolver))]
|
||||||
fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>) -> ast::Crate {
|
fn configure_and_expand(
|
||||||
|
mut krate: ast::Crate,
|
||||||
|
pre_configured_attrs: &[ast::Attribute],
|
||||||
|
resolver: &mut Resolver<'_, '_>,
|
||||||
|
) -> ast::Crate {
|
||||||
let tcx = resolver.tcx();
|
let tcx = resolver.tcx();
|
||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
let lint_store = unerased_lint_store(tcx);
|
let lint_store = unerased_lint_store(tcx);
|
||||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), &krate, crate_name);
|
let lint_check_node = (&krate, pre_configured_attrs);
|
||||||
|
pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), lint_check_node, crate_name);
|
||||||
rustc_builtin_macros::register_builtin_macros(resolver);
|
rustc_builtin_macros::register_builtin_macros(resolver);
|
||||||
|
|
||||||
krate = sess.time("crate_injection", || {
|
let num_standard_library_imports = sess.time("crate_injection", || {
|
||||||
rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess)
|
rustc_builtin_macros::standard_library_imports::inject(
|
||||||
|
&mut krate,
|
||||||
|
pre_configured_attrs,
|
||||||
|
resolver,
|
||||||
|
sess,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer());
|
util::check_attr_crate_type(sess, pre_configured_attrs, &mut resolver.lint_buffer());
|
||||||
|
|
||||||
// Expand all macros
|
// Expand all macros
|
||||||
krate = sess.time("macro_expand_crate", || {
|
krate = sess.time("macro_expand_crate", || {
|
||||||
|
@ -222,7 +224,7 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
||||||
|
|
||||||
// Create the config for macro expansion
|
// Create the config for macro expansion
|
||||||
let features = sess.features_untracked();
|
let features = sess.features_untracked();
|
||||||
let recursion_limit = get_recursion_limit(&krate.attrs, sess);
|
let recursion_limit = get_recursion_limit(pre_configured_attrs, sess);
|
||||||
let cfg = rustc_expand::expand::ExpansionConfig {
|
let cfg = rustc_expand::expand::ExpansionConfig {
|
||||||
features: Some(features),
|
features: Some(features),
|
||||||
recursion_limit,
|
recursion_limit,
|
||||||
|
@ -235,6 +237,7 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
||||||
|
|
||||||
let lint_store = LintStoreExpandImpl(lint_store);
|
let lint_store = LintStoreExpandImpl(lint_store);
|
||||||
let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store));
|
let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store));
|
||||||
|
ecx.num_standard_library_imports = num_standard_library_imports;
|
||||||
// Expand macros now!
|
// Expand macros now!
|
||||||
let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
|
let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
|
||||||
|
|
||||||
|
@ -263,7 +266,7 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
||||||
});
|
});
|
||||||
|
|
||||||
sess.time("maybe_building_test_harness", || {
|
sess.time("maybe_building_test_harness", || {
|
||||||
rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate)
|
rustc_builtin_macros::test_harness::inject(&mut krate, sess, resolver)
|
||||||
});
|
});
|
||||||
|
|
||||||
let has_proc_macro_decls = sess.time("AST_validation", || {
|
let has_proc_macro_decls = sess.time("AST_validation", || {
|
||||||
|
@ -287,12 +290,12 @@ fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>)
|
||||||
sess.emit_warning(errors::ProcMacroCratePanicAbort);
|
sess.emit_warning(errors::ProcMacroCratePanicAbort);
|
||||||
}
|
}
|
||||||
|
|
||||||
krate = sess.time("maybe_create_a_macro_crate", || {
|
sess.time("maybe_create_a_macro_crate", || {
|
||||||
let is_test_crate = sess.opts.test;
|
let is_test_crate = sess.opts.test;
|
||||||
rustc_builtin_macros::proc_macro_harness::inject(
|
rustc_builtin_macros::proc_macro_harness::inject(
|
||||||
|
&mut krate,
|
||||||
sess,
|
sess,
|
||||||
resolver,
|
resolver,
|
||||||
krate,
|
|
||||||
is_proc_macro_crate,
|
is_proc_macro_crate,
|
||||||
has_proc_macro_decls,
|
has_proc_macro_decls,
|
||||||
is_test_crate,
|
is_test_crate,
|
||||||
|
@ -356,7 +359,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
|
||||||
tcx.registered_tools(()),
|
tcx.registered_tools(()),
|
||||||
Some(lint_buffer),
|
Some(lint_buffer),
|
||||||
rustc_lint::BuiltinCombinedEarlyLintPass::new(),
|
rustc_lint::BuiltinCombinedEarlyLintPass::new(),
|
||||||
&**krate,
|
(&**krate, &*krate.attrs),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,9 +560,9 @@ fn resolver_for_lowering<'tcx>(
|
||||||
) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
|
) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
|
||||||
let arenas = Resolver::arenas();
|
let arenas = Resolver::arenas();
|
||||||
let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
|
let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
|
||||||
let krate = tcx.crate_for_resolver(()).steal();
|
let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
|
||||||
let mut resolver = Resolver::new(tcx, &krate, &arenas);
|
let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas);
|
||||||
let krate = configure_and_expand(krate, &mut resolver);
|
let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);
|
||||||
|
|
||||||
// Make sure we don't mutate the cstore from here on.
|
// Make sure we don't mutate the cstore from here on.
|
||||||
tcx.untracked().cstore.leak();
|
tcx.untracked().cstore.leak();
|
||||||
|
|
|
@ -88,8 +88,9 @@ pub struct Queries<'tcx> {
|
||||||
|
|
||||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||||
parse: Query<ast::Crate>,
|
parse: Query<ast::Crate>,
|
||||||
|
pre_configure: Query<(ast::Crate, ast::AttrVec)>,
|
||||||
crate_name: Query<Symbol>,
|
crate_name: Query<Symbol>,
|
||||||
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
|
register_plugins: Query<(ast::Crate, ast::AttrVec, Lrc<LintStore>)>,
|
||||||
dep_graph: Query<DepGraph>,
|
dep_graph: Query<DepGraph>,
|
||||||
// This just points to what's in `gcx_cell`.
|
// This just points to what's in `gcx_cell`.
|
||||||
gcx: Query<&'tcx GlobalCtxt<'tcx>>,
|
gcx: Query<&'tcx GlobalCtxt<'tcx>>,
|
||||||
|
@ -106,6 +107,7 @@ impl<'tcx> Queries<'tcx> {
|
||||||
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
|
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
|
||||||
dep_graph_future: Default::default(),
|
dep_graph_future: Default::default(),
|
||||||
parse: Default::default(),
|
parse: Default::default(),
|
||||||
|
pre_configure: Default::default(),
|
||||||
crate_name: Default::default(),
|
crate_name: Default::default(),
|
||||||
register_plugins: Default::default(),
|
register_plugins: Default::default(),
|
||||||
dep_graph: Default::default(),
|
dep_graph: Default::default(),
|
||||||
|
@ -133,17 +135,36 @@ impl<'tcx> Queries<'tcx> {
|
||||||
.compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
|
.compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_plugins(&self) -> Result<QueryResult<'_, (ast::Crate, Lrc<LintStore>)>> {
|
pub fn pre_configure(&self) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec)>> {
|
||||||
|
self.pre_configure.compute(|| {
|
||||||
|
let mut krate = self.parse()?.steal();
|
||||||
|
|
||||||
|
let sess = self.session();
|
||||||
|
rustc_builtin_macros::cmdline_attrs::inject(
|
||||||
|
&mut krate,
|
||||||
|
&sess.parse_sess,
|
||||||
|
&sess.opts.unstable_opts.crate_attr,
|
||||||
|
);
|
||||||
|
|
||||||
|
let pre_configured_attrs =
|
||||||
|
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||||
|
Ok((krate, pre_configured_attrs))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_plugins(
|
||||||
|
&self,
|
||||||
|
) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec, Lrc<LintStore>)>> {
|
||||||
self.register_plugins.compute(|| {
|
self.register_plugins.compute(|| {
|
||||||
let crate_name = *self.crate_name()?.borrow();
|
let crate_name = *self.crate_name()?.borrow();
|
||||||
let krate = self.parse()?.steal();
|
let (krate, pre_configured_attrs) = self.pre_configure()?.steal();
|
||||||
|
|
||||||
let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
|
let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {};
|
||||||
let (krate, lint_store) = passes::register_plugins(
|
let lint_store = passes::register_plugins(
|
||||||
self.session(),
|
self.session(),
|
||||||
&*self.codegen_backend().metadata_loader(),
|
&*self.codegen_backend().metadata_loader(),
|
||||||
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
|
||||||
krate,
|
&pre_configured_attrs,
|
||||||
crate_name,
|
crate_name,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -154,17 +175,17 @@ impl<'tcx> Queries<'tcx> {
|
||||||
// called, which happens within passes::register_plugins().
|
// called, which happens within passes::register_plugins().
|
||||||
self.dep_graph_future().ok();
|
self.dep_graph_future().ok();
|
||||||
|
|
||||||
Ok((krate, Lrc::new(lint_store)))
|
Ok((krate, pre_configured_attrs, Lrc::new(lint_store)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
|
fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> {
|
||||||
self.crate_name.compute(|| {
|
self.crate_name.compute(|| {
|
||||||
Ok({
|
Ok({
|
||||||
let parse_result = self.parse()?;
|
let pre_configure_result = self.pre_configure()?;
|
||||||
let krate = parse_result.borrow();
|
let (_, pre_configured_attrs) = &*pre_configure_result.borrow();
|
||||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
||||||
find_crate_name(self.session(), &krate.attrs)
|
find_crate_name(self.session(), pre_configured_attrs)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -188,7 +209,7 @@ impl<'tcx> Queries<'tcx> {
|
||||||
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
||||||
self.gcx.compute(|| {
|
self.gcx.compute(|| {
|
||||||
let crate_name = *self.crate_name()?.borrow();
|
let crate_name = *self.crate_name()?.borrow();
|
||||||
let (krate, lint_store) = self.register_plugins()?.steal();
|
let (krate, pre_configured_attrs, lint_store) = self.register_plugins()?.steal();
|
||||||
|
|
||||||
let sess = self.session();
|
let sess = self.session();
|
||||||
|
|
||||||
|
@ -215,7 +236,7 @@ impl<'tcx> Queries<'tcx> {
|
||||||
feed.crate_name(crate_name);
|
feed.crate_name(crate_name);
|
||||||
|
|
||||||
let feed = tcx.feed_unit_query();
|
let feed = tcx.feed_unit_query();
|
||||||
feed.crate_for_resolver(tcx.arena.alloc(Steal::new(krate)));
|
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
|
||||||
feed.metadata_loader(
|
feed.metadata_loader(
|
||||||
tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())),
|
tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())),
|
||||||
);
|
);
|
||||||
|
|
|
@ -341,7 +341,7 @@ pub trait EarlyCheckNode<'a>: Copy {
|
||||||
'a: 'b;
|
'a: 'b;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
|
impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) {
|
||||||
fn id(self) -> ast::NodeId {
|
fn id(self) -> ast::NodeId {
|
||||||
ast::CRATE_NODE_ID
|
ast::CRATE_NODE_ID
|
||||||
}
|
}
|
||||||
|
@ -349,15 +349,15 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
&self.attrs
|
&self.1
|
||||||
}
|
}
|
||||||
fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
|
fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
|
||||||
where
|
where
|
||||||
'a: 'b,
|
'a: 'b,
|
||||||
{
|
{
|
||||||
lint_callback!(cx, check_crate, self);
|
lint_callback!(cx, check_crate, self.0);
|
||||||
ast_visit::walk_crate(cx, self);
|
ast_visit::walk_crate(cx, self.0);
|
||||||
lint_callback!(cx, check_crate_post, self);
|
lint_callback!(cx, check_crate_post, self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ macro_rules! arena_types {
|
||||||
)>,
|
)>,
|
||||||
[] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
|
[] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
|
||||||
[] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
|
[] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
|
||||||
[] crate_for_resolver: rustc_data_structures::steal::Steal<rustc_ast::ast::Crate>,
|
[] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>,
|
||||||
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
|
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
|
||||||
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
|
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
|
||||||
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
|
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
|
||||||
|
|
|
@ -2116,7 +2116,7 @@ rustc_queries! {
|
||||||
desc { "raw operations for metadata file access" }
|
desc { "raw operations for metadata file access" }
|
||||||
}
|
}
|
||||||
|
|
||||||
query crate_for_resolver((): ()) -> &'tcx Steal<rustc_ast::ast::Crate> {
|
query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> {
|
||||||
feedable
|
feedable
|
||||||
no_hash
|
no_hash
|
||||||
desc { "the ast before macro expansion and name resolution" }
|
desc { "the ast before macro expansion and name resolution" }
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use crate::errors::{LoadPluginError, MalformedPluginAttribute};
|
use crate::errors::{LoadPluginError, MalformedPluginAttribute};
|
||||||
use crate::Registry;
|
use crate::Registry;
|
||||||
use libloading::Library;
|
use libloading::Library;
|
||||||
use rustc_ast::Crate;
|
use rustc_ast::Attribute;
|
||||||
use rustc_metadata::locator;
|
use rustc_metadata::locator;
|
||||||
use rustc_session::cstore::MetadataLoader;
|
use rustc_session::cstore::MetadataLoader;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
@ -20,11 +20,11 @@ type PluginRegistrarFn = fn(&mut Registry<'_>);
|
||||||
pub fn load_plugins(
|
pub fn load_plugins(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
metadata_loader: &dyn MetadataLoader,
|
metadata_loader: &dyn MetadataLoader,
|
||||||
krate: &Crate,
|
attrs: &[Attribute],
|
||||||
) -> Vec<PluginRegistrarFn> {
|
) -> Vec<PluginRegistrarFn> {
|
||||||
let mut plugins = Vec::new();
|
let mut plugins = Vec::new();
|
||||||
|
|
||||||
for attr in &krate.attrs {
|
for attr in attrs {
|
||||||
if !attr.has_name(sym::plugin) {
|
if !attr.has_name(sym::plugin) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1180,7 +1180,8 @@ impl<'tcx> Resolver<'_, 'tcx> {
|
||||||
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
krate: &Crate,
|
attrs: &[ast::Attribute],
|
||||||
|
crate_span: Span,
|
||||||
arenas: &'a ResolverArenas<'a>,
|
arenas: &'a ResolverArenas<'a>,
|
||||||
) -> Resolver<'a, 'tcx> {
|
) -> Resolver<'a, 'tcx> {
|
||||||
let root_def_id = CRATE_DEF_ID.to_def_id();
|
let root_def_id = CRATE_DEF_ID.to_def_id();
|
||||||
|
@ -1189,8 +1190,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
|
ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
|
||||||
ExpnId::root(),
|
ExpnId::root(),
|
||||||
krate.spans.inner_span,
|
crate_span,
|
||||||
attr::contains_name(&krate.attrs, sym::no_implicit_prelude),
|
attr::contains_name(attrs, sym::no_implicit_prelude),
|
||||||
&mut module_map,
|
&mut module_map,
|
||||||
);
|
);
|
||||||
let empty_module = arenas.new_module(
|
let empty_module = arenas.new_module(
|
||||||
|
@ -1222,9 +1223,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
.map(|(name, _)| (Ident::from_str(name), Default::default()))
|
.map(|(name, _)| (Ident::from_str(name), Default::default()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !attr::contains_name(&krate.attrs, sym::no_core) {
|
if !attr::contains_name(attrs, sym::no_core) {
|
||||||
extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default());
|
extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default());
|
||||||
if !attr::contains_name(&krate.attrs, sym::no_std) {
|
if !attr::contains_name(attrs, sym::no_std) {
|
||||||
extern_prelude.insert(Ident::with_dummy_span(sym::std), Default::default());
|
extern_prelude.insert(Ident::with_dummy_span(sym::std), Default::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,8 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
|
||||||
|
|
||||||
pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
|
pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
|
||||||
let mut registered_tools = RegisteredTools::default();
|
let mut registered_tools = RegisteredTools::default();
|
||||||
let krate = tcx.crate_for_resolver(()).borrow();
|
let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
|
||||||
for attr in attr::filter_by_name(&krate.attrs, sym::register_tool) {
|
for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) {
|
||||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||||
match nested_meta.ident() {
|
match nested_meta.ident() {
|
||||||
Some(ident) => {
|
Some(ident) => {
|
||||||
|
|
6
tests/ui/cfg/auxiliary/cfg_false_lib.rs
Normal file
6
tests/ui/cfg/auxiliary/cfg_false_lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// It is unclear whether a fully unconfigured crate should link to standard library,
|
||||||
|
// or what its `no_std`/`no_core`/`compiler_builtins` status, more precisely.
|
||||||
|
// Currently the usual standard library prelude is added to such crates,
|
||||||
|
// and therefore they link to libstd.
|
||||||
|
|
||||||
|
#![cfg(FALSE)]
|
20
tests/ui/cfg/cfg-false-feature.rs
Normal file
20
tests/ui/cfg/cfg-false-feature.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// It is unclear which features should be in effect in a fully unconfigured crate (issue #104633).
|
||||||
|
// Currently none on the features are in effect, so we get the feature gates reported.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: --crate-type lib
|
||||||
|
|
||||||
|
#![feature(decl_macro)]
|
||||||
|
#![cfg(FALSE)]
|
||||||
|
#![feature(box_syntax)]
|
||||||
|
|
||||||
|
macro mac() {} //~ WARN `macro` is experimental
|
||||||
|
//~| WARN unstable syntax can change at any point in the future
|
||||||
|
|
||||||
|
trait A = Clone; //~ WARN trait aliases are experimental
|
||||||
|
//~| WARN unstable syntax can change at any point in the future
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let box _ = Box::new(0); //~ WARN box pattern syntax is experimental
|
||||||
|
//~| WARN unstable syntax can change at any point in the future
|
||||||
|
}
|
35
tests/ui/cfg/cfg-false-feature.stderr
Normal file
35
tests/ui/cfg/cfg-false-feature.stderr
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
warning: trait aliases are experimental
|
||||||
|
--> $DIR/cfg-false-feature.rs:14:1
|
||||||
|
|
|
||||||
|
LL | trait A = Clone;
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #41517 <https://github.com/rust-lang/rust/issues/41517> for more information
|
||||||
|
= help: add `#![feature(trait_alias)]` to the crate attributes to enable
|
||||||
|
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||||
|
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||||
|
|
||||||
|
warning: `macro` is experimental
|
||||||
|
--> $DIR/cfg-false-feature.rs:11:1
|
||||||
|
|
|
||||||
|
LL | macro mac() {}
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
|
||||||
|
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||||
|
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||||
|
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||||
|
|
||||||
|
warning: box pattern syntax is experimental
|
||||||
|
--> $DIR/cfg-false-feature.rs:18:9
|
||||||
|
|
|
||||||
|
LL | let box _ = Box::new(0);
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
|
||||||
|
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||||
|
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||||
|
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||||
|
|
||||||
|
warning: 3 warnings emitted
|
||||||
|
|
11
tests/ui/cfg/cfg_false_no_std.rs
Normal file
11
tests/ui/cfg/cfg_false_no_std.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Currently no error because the panic handler is supplied by libstd linked though the empty
|
||||||
|
// library, but the desirable behavior is unclear (see comments in cfg_false_lib.rs).
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// aux-build: cfg_false_lib.rs
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate cfg_false_lib as _;
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Reference in a new issue