summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_expand
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_expand
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_expand')
-rw-r--r--compiler/rustc_expand/Cargo.toml6
-rw-r--r--compiler/rustc_expand/messages.ftl1
-rw-r--r--compiler/rustc_expand/src/config.rs211
-rw-r--r--compiler/rustc_expand/src/errors.rs1
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs24
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs14
-rw-r--r--compiler/rustc_expand/src/module.rs4
-rw-r--r--compiler/rustc_expand/src/placeholders.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs5
-rw-r--r--compiler/rustc_expand/src/tests.rs4
11 files changed, 140 insertions, 134 deletions
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 02da5b5dc..9189a501a 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -8,9 +8,10 @@ build = false
doctest = false
[dependencies]
+# tidy-alphabetical-start
crossbeam-channel = "0.5.0"
-rustc_ast_passes = { path = "../rustc_ast_passes" }
rustc_ast = { path = "../rustc_ast" }
+rustc_ast_passes = { path = "../rustc_ast_passes" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -25,6 +26,7 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+termcolor = "1.2"
thin-vec = "0.2.12"
tracing = "0.1"
-termcolor = "1.2"
+# tidy-alphabetical-end
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 6c7e68246..8b9382962 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -86,6 +86,7 @@ expand_module_circular =
expand_module_file_not_found =
file not found for module `{$name}`
.help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+ .note = if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead
expand_module_in_block =
cannot declare a non-inline module inside a block unless it has a path attribute
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 8658cea13..bef487659 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -13,17 +13,16 @@ use rustc_ast::NodeId;
use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem};
use rustc_attr as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_feature::{Feature, Features, State as FeatureState};
-use rustc_feature::{
- ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
-};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_feature::Features;
+use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
use rustc_parse::validate_attr;
use rustc_session::parse::feature_err;
use rustc_session::Session;
-use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::edition::ALL_EDITIONS;
use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
+use thin_vec::ThinVec;
/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
@@ -36,85 +35,56 @@ pub struct StripUnconfigured<'a> {
pub lint_node_id: NodeId,
}
-pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
- fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
- sess.emit_err(FeatureRemoved {
- span,
- reason: reason.map(|reason| FeatureRemovedReason { reason }),
- });
- }
-
- fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
- ACTIVE_FEATURES.iter().filter(move |feature| {
- if let Some(feature_edition) = feature.edition {
- feature_edition <= edition
- } else {
- false
- }
- })
+pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features {
+ fn feature_list(attr: &Attribute) -> ThinVec<ast::NestedMetaItem> {
+ if attr.has_name(sym::feature)
+ && let Some(list) = attr.meta_item_list()
+ {
+ list
+ } else {
+ ThinVec::new()
+ }
}
let mut features = Features::default();
- let mut edition_enabled_features = FxHashMap::default();
- let crate_edition = sess.edition();
-
- for &edition in ALL_EDITIONS {
- if edition <= crate_edition {
- // The `crate_edition` implies its respective umbrella feature-gate
- // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
- edition_enabled_features.insert(edition.feature_name(), edition);
- }
- }
- for feature in active_features_up_to(crate_edition) {
- feature.set(&mut features, DUMMY_SP);
- edition_enabled_features.insert(feature.name, crate_edition);
- }
+ // The edition from `--edition`.
+ let crate_edition = sess.edition();
- // Process the edition umbrella feature-gates first, to ensure
- // `edition_enabled_features` is completed before it's queried.
+ // The maximum of (a) the edition from `--edition` and (b) any edition
+ // umbrella feature-gates declared in the code.
+ // - E.g. if `crate_edition` is 2015 but `rust_2018_preview` is present,
+ // `feature_edition` is 2018
+ let mut features_edition = crate_edition;
for attr in krate_attrs {
- if !attr.has_name(sym::feature) {
- continue;
- }
-
- let Some(list) = attr.meta_item_list() else {
- continue;
- };
-
- for mi in list {
- if !mi.is_word() {
- continue;
- }
-
- let name = mi.name_or_empty();
-
- let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
- if let Some(edition) = edition {
- if edition <= crate_edition {
- continue;
- }
-
- for feature in active_features_up_to(edition) {
- // FIXME(Manishearth) there is currently no way to set
- // lib features by edition
- feature.set(&mut features, DUMMY_SP);
- edition_enabled_features.insert(feature.name, edition);
+ for mi in feature_list(attr) {
+ if mi.is_word() {
+ let name = mi.name_or_empty();
+ let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
+ if let Some(edition) = edition
+ && edition > features_edition
+ {
+ features_edition = edition;
}
}
}
}
- for attr in krate_attrs {
- if !attr.has_name(sym::feature) {
- continue;
+ // Enable edition-dependent features based on `features_edition`.
+ // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher
+ let mut edition_enabled_features = FxHashSet::default();
+ for f in UNSTABLE_FEATURES {
+ if let Some(edition) = f.feature.edition && edition <= features_edition {
+ // FIXME(Manishearth) there is currently no way to set lib features by
+ // edition.
+ edition_enabled_features.insert(f.feature.name);
+ (f.set_enabled)(&mut features);
}
+ }
- let Some(list) = attr.meta_item_list() else {
- continue;
- };
-
- for mi in list {
+ // Process all features declared in the code.
+ for attr in krate_attrs {
+ for mi in feature_list(attr) {
let name = match mi.ident() {
Some(ident) if mi.is_word() => ident.name,
Some(ident) => {
@@ -136,38 +106,57 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
}
};
- if let Some(&edition) = edition_enabled_features.get(&name) {
+ // If the declared feature is an edition umbrella feature-gate,
+ // warn if it was redundant w.r.t. `crate_edition`.
+ // - E.g. warn if `rust_2018_preview` is declared when
+ // `crate_edition` is 2018
+ // - E.g. don't warn if `rust_2018_preview` is declared when
+ // `crate_edition` is 2015.
+ if let Some(&edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
+ if edition <= crate_edition {
+ sess.emit_warning(FeatureIncludedInEdition {
+ span: mi.span(),
+ feature: name,
+ edition,
+ });
+ }
+ features.set_declared_lang_feature(name, mi.span(), None);
+ continue;
+ }
+
+ // If the declared feature is edition-dependent and was already
+ // enabled due to `feature_edition`, give a warning.
+ // - E.g. warn if `test_2018_feature` is declared when
+ // `feature_edition` is 2018 or higher.
+ if edition_enabled_features.contains(&name) {
sess.emit_warning(FeatureIncludedInEdition {
span: mi.span(),
feature: name,
- edition,
+ edition: features_edition,
});
+ features.set_declared_lang_feature(name, mi.span(), None);
continue;
}
- if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
- // Handled in the separate loop above.
+ // If the declared feature has been removed, issue an error.
+ if let Some(f) = REMOVED_FEATURES.iter().find(|f| name == f.feature.name) {
+ sess.emit_err(FeatureRemoved {
+ span: mi.span(),
+ reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
+ });
continue;
}
- let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
- let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
- if let Some(Feature { state, .. }) = removed.or(stable_removed) {
- if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
- state
- {
- feature_removed(sess, mi.span(), *reason);
- continue;
- }
- }
-
- if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
- let since = Some(Symbol::intern(since));
- features.declared_lang_features.push((name, mi.span(), since));
- features.active_features.insert(name);
+ // If the declared feature is stable, record it.
+ if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+ let since = Some(Symbol::intern(f.since));
+ features.set_declared_lang_feature(name, mi.span(), since);
continue;
}
+ // If `-Z allow-features` is used and the declared feature is
+ // unstable and not also listed as one of the allowed features,
+ // issue an error.
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
if allowed.iter().all(|f| name.as_str() != f) {
sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
@@ -175,15 +164,25 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
}
}
- if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
- f.set(&mut features, mi.span());
- features.declared_lang_features.push((name, mi.span(), None));
- features.active_features.insert(name);
+ // If the declared feature is unstable, record it.
+ if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
+ (f.set_enabled)(&mut features);
+ // When the ICE comes from core, alloc or std (approximation of the standard library), there's a chance
+ // that the person hitting the ICE may be using -Zbuild-std or similar with an untested target.
+ // The bug is probably in the standard library and not the compiler in that case, but that doesn't
+ // really matter - we want a bug report.
+ if features.internal(name)
+ && ![sym::core, sym::alloc, sym::std].contains(&crate_name)
+ {
+ sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
+ }
+ features.set_declared_lang_feature(name, mi.span(), None);
continue;
}
- features.declared_lib_features.push((name, mi.span()));
- features.active_features.insert(name);
+ // Otherwise, the feature is unknown. Record it as a lib feature.
+ // It will be checked later.
+ features.set_declared_lib_feature(name, mi.span());
}
}
@@ -252,7 +251,8 @@ impl<'a> StripUnconfigured<'a> {
let trees: Vec<_> = stream
.0
.iter()
- .flat_map(|tree| match tree.clone() {
+ .flat_map(|tree| {
+ match tree.clone() {
AttrTokenTree::Attributes(mut data) => {
data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
@@ -267,18 +267,17 @@ impl<'a> StripUnconfigured<'a> {
}
AttrTokenTree::Delimited(sp, delim, mut inner) => {
inner = self.configure_tokens(&inner);
- Some(AttrTokenTree::Delimited(sp, delim, inner))
- .into_iter()
+ Some(AttrTokenTree::Delimited(sp, delim, inner)).into_iter()
}
- AttrTokenTree::Token(ref token, _) if let TokenKind::Interpolated(nt) = &token.kind => {
- panic!(
- "Nonterminal should have been flattened at {:?}: {:?}",
- token.span, nt
- );
+ AttrTokenTree::Token(ref token, _)
+ if let TokenKind::Interpolated(nt) = &token.kind =>
+ {
+ panic!("Nonterminal should have been flattened at {:?}: {:?}", token.span, nt);
}
AttrTokenTree::Token(token, spacing) => {
Some(AttrTokenTree::Token(token, spacing)).into_iter()
}
+ }
})
.collect();
AttrTokenStream::new(trees)
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index e3a0ae357..d86632c47 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -350,6 +350,7 @@ pub(crate) struct ModuleInBlockName {
#[derive(Diagnostic)]
#[diag(expand_module_file_not_found, code = "E0583")]
#[help]
+#[note]
pub(crate) struct ModuleFileNotFound {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 8b1fc5b90..5a774164a 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![feature(array_windows)]
#![feature(associated_type_bounds)]
#![feature(associated_type_defaults)]
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index a5959d68f..ebdd3cb54 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -716,18 +716,18 @@ fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
match rhs {
mbe::TokenTree::Delimited(_sp, d) => {
let has_compile_error = d.tts.array_windows::<3>().any(|[ident, bang, args]| {
- if let mbe::TokenTree::Token(ident) = ident &&
- let TokenKind::Ident(ident, _) = ident.kind &&
- ident == sym::compile_error &&
- let mbe::TokenTree::Token(bang) = bang &&
- let TokenKind::Not = bang.kind &&
- let mbe::TokenTree::Delimited(_, del) = args &&
- del.delim != Delimiter::Invisible
- {
- true
- } else {
- false
- }
+ if let mbe::TokenTree::Token(ident) = ident
+ && let TokenKind::Ident(ident, _) = ident.kind
+ && ident == sym::compile_error
+ && let mbe::TokenTree::Token(bang) = bang
+ && let TokenKind::Not = bang.kind
+ && let mbe::TokenTree::Delimited(_, del) = args
+ && del.delim != Delimiter::Invisible
+ {
+ true
+ } else {
+ false
+ }
});
if has_compile_error { true } else { d.tts.iter().any(has_compile_error_macro) }
}
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 7c37aadc6..7cb279a98 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -124,8 +124,7 @@ fn parse_depth<'sess>(
&& let Ok(n_usize) = usize::try_from(n_u128)
{
Ok(n_usize)
- }
- else {
+ } else {
let msg = "only unsuffixes integer literals are supported in meta-variable expressions";
Err(sess.span_diagnostic.struct_span_err(span, msg))
}
@@ -137,15 +136,16 @@ fn parse_ident<'sess>(
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, Ident> {
- if let Some(tt) = iter.next() && let TokenTree::Token(token, _) = tt {
+ if let Some(tt) = iter.next()
+ && let TokenTree::Token(token, _) = tt
+ {
if let Some((elem, false)) = token.ident() {
return Ok(elem);
}
let token_str = pprust::token_to_string(token);
- let mut err = sess.span_diagnostic.struct_span_err(
- span,
- format!("expected identifier, found `{}`", &token_str)
- );
+ let mut err = sess
+ .span_diagnostic
+ .struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
err.span_suggestion(
token.span,
format!("try removing `{}`", &token_str),
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 3779af19e..df6bdc695 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -91,7 +91,9 @@ pub(crate) fn mod_dir_path(
inline: Inline,
) -> (PathBuf, DirOwnership) {
match inline {
- Inline::Yes if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) => {
+ Inline::Yes
+ if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) =>
+ {
// For inline modules file path from `#[path]` is actually the directory path
// for historical reasons, so we don't pop the last segment here.
(file_path, DirOwnership::Owned { relative: None })
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 82cac2292..1292a8552 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -4,8 +4,8 @@ use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::token::Delimiter;
use rustc_data_structures::fx::FxHashMap;
-use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Ident;
+use rustc_span::DUMMY_SP;
use smallvec::{smallvec, SmallVec};
use thin_vec::ThinVec;
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 2dc9b51a3..aa4c7a531 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -226,9 +226,8 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
}));
}
- Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => {
- trees.push(TokenTree::Ident(Ident { sym: ident.name, is_raw, span: ident.span }))
- }
+ Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => trees
+ .push(TokenTree::Ident(Ident { sym: ident.name, is_raw, span: ident.span })),
Interpolated(nt) => {
let stream = TokenStream::from_nonterminal_ast(&nt);
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 8e3219c13..9f52669e1 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -2,7 +2,7 @@ use rustc_ast as ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
use rustc_session::parse::ParseSess;
-use rustc_span::create_default_session_if_not_set_then;
+use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{BytePos, Span};
@@ -181,7 +181,7 @@ impl<T: Write> Write for Shared<T> {
}
fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
- create_default_session_if_not_set_then(|_| {
+ create_default_session_globals_then(|| {
let (handler, source_map, output) = create_test_handler();
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());