diff --git a/Cargo.lock b/Cargo.lock index de6258502a3..897a4f6adfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3805,6 +3805,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_expand", + "rustc_feature", "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 79fc9e4382f..bd3e676daa4 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,6 +13,7 @@ use rustc_ast::{walk_list, StaticItem}; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; +use rustc_feature::Features; use rustc_macros::Subdiagnostic; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ @@ -45,6 +46,7 @@ enum DisallowTildeConstContext<'a> { struct AstValidator<'a> { session: &'a Session, + features: &'a Features, /// The span of the `extern` in an `extern { ... }` block, if any. extern_mod: Option<&'a Item>, @@ -1023,7 +1025,7 @@ fn visit_item(&mut self, item: &'a Item) { } self.check_type_no_bounds(bounds, "this context"); - if self.session.features_untracked().lazy_type_alias { + if self.features.lazy_type_alias { if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) { self.err_handler().emit_err(err); } @@ -1500,9 +1502,15 @@ fn deny_equality_constraints( this.err_handler().emit_err(err); } -pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool { +pub fn check_crate( + session: &Session, + features: &Features, + krate: &Crate, + lints: &mut LintBuffer, +) -> bool { let mut validator = AstValidator { session, + features, extern_mod: None, in_trait_impl: false, in_const_trait_impl: false, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index c4efad7caf2..10c9c3ef111 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -514,10 +514,10 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { } } -pub fn check_crate(krate: &ast::Crate, sess: &Session) { - maybe_stage_features(sess, krate); - check_incompatible_features(sess); - let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() }; +pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { + maybe_stage_features(sess, features, krate); + check_incompatible_features(sess, features); + let mut visitor = PostExpansionVisitor { sess, features }; let spans = sess.parse_sess.gated_spans.spans.borrow(); macro_rules! gate_all { @@ -600,12 +600,12 @@ macro_rules! gate_all { visit::walk_crate(&mut visitor, krate); } -fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { +fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate) { // checks if `#![feature]` has been used to enable any lang feature // does not check the same for lib features unless there's at least one // declared lang feature if !sess.opts.unstable_features.is_nightly_build() { - let lang_features = &sess.features_untracked().declared_lang_features; + let lang_features = &features.declared_lang_features; if lang_features.len() == 0 { return; } @@ -640,9 +640,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { } } -fn check_incompatible_features(sess: &Session) { - let features = sess.features_untracked(); - +fn check_incompatible_features(sess: &Session, features: &Features) { let declared_features = features .declared_lang_features .iter() diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 6ed5fc77d75..3592287b95c 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -800,18 +800,15 @@ pub struct Deprecation { } /// Finds the deprecation attribute. `None` if none exists. -pub fn find_deprecation(sess: &Session, attrs: &[Attribute]) -> Option<(Deprecation, Span)> { - find_deprecation_generic(sess, attrs.iter()) -} - -fn find_deprecation_generic<'a, I>(sess: &Session, attrs_iter: I) -> Option<(Deprecation, Span)> -where - I: Iterator, -{ +pub fn find_deprecation( + sess: &Session, + features: &Features, + attrs: &[Attribute], +) -> Option<(Deprecation, Span)> { let mut depr: Option<(Deprecation, Span)> = None; - let is_rustc = sess.features_untracked().staged_api; + let is_rustc = features.staged_api; - 'outer: for attr in attrs_iter { + 'outer: for attr in attrs { if !attr.has_name(sym::deprecated) { continue; } @@ -872,7 +869,7 @@ fn find_deprecation_generic<'a, I>(sess: &Session, attrs_iter: I) -> Option<(Dep } } sym::suggestion => { - if !sess.features_untracked().deprecated_suggestion { + if !features.deprecated_suggestion { sess.emit_err(session_diagnostics::DeprecatedItemSuggestion { span: mi.span, is_nightly: sess.is_nightly_build().then_some(()), @@ -890,7 +887,7 @@ fn find_deprecation_generic<'a, I>(sess: &Session, attrs_iter: I) -> Option<(Dep meta.span(), AttrError::UnknownMetaItem( pprust::path_to_string(&mi.path), - if sess.features_untracked().deprecated_suggestion { + if features.deprecated_suggestion { &["since", "note", "suggestion"] } else { &["since", "note"] diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 3e90ae6907f..9302db104b6 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -69,7 +69,7 @@ pub fn expand_assert<'cx>( // If `generic_assert` is enabled, generates rich captured outputs // // FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949 - else if let Some(features) = cx.ecfg.features && features.generic_assert { + else if cx.ecfg.features.generic_assert { context::Context::new(cx, call_site_span).build(cond_expr, panic_path()) } // If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..." diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 1397cee7af8..31cac51845f 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -24,7 +24,7 @@ pub fn expand_cfg( &cfg, &cx.sess.parse_sess, cx.current_expansion.lint_node_id, - cx.ecfg.features, + Some(cx.ecfg.features), ); MacEager::expr(cx.expr_bool(sp, matches_cfg)) } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 49401e9ca94..f826c6e7712 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -31,10 +31,11 @@ pub(crate) fn expand( pub(crate) fn cfg_eval( sess: &Session, - features: Option<&Features>, + features: &Features, annotatable: Annotatable, lint_node_id: NodeId, ) -> Annotatable { + let features = Some(features); CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } } .configure_annotatable(annotatable) // Since the item itself has already been configured by the `InvocationCollector`, diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 7c0b36ced96..dae1bc5bfe5 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -5,6 +5,7 @@ use rustc_ast_pretty::pprust; use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; +use rustc_feature::Features; use rustc_session::Session; use rustc_span::hygiene::AstPass; use rustc_span::source_map::SourceMap; @@ -46,13 +47,14 @@ struct CollectProcMacros<'a> { pub fn inject( krate: &mut ast::Crate, sess: &Session, + features: &Features, resolver: &mut dyn ResolverExpand, is_proc_macro_crate: bool, has_proc_macro_decls: bool, is_test_crate: bool, handler: &rustc_errors::Handler, ) { - let ecfg = ExpansionConfig::default("proc_macro".to_string()); + let ecfg = ExpansionConfig::default("proc_macro".to_string(), features); let mut cx = ExtCtxt::new(sess, ecfg, resolver, None); let mut collect = CollectProcMacros { diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 07e6288ed8c..3ee3112f021 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -1,6 +1,7 @@ use rustc_ast::{self as ast, attr}; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::ExpansionConfig; +use rustc_feature::Features; use rustc_session::Session; use rustc_span::edition::Edition::*; use rustc_span::hygiene::AstPass; @@ -13,6 +14,7 @@ pub fn inject( pre_configured_attrs: &[ast::Attribute], resolver: &mut dyn ResolverExpand, sess: &Session, + features: &Features, ) -> usize { let orig_num_items = krate.items.len(); let edition = sess.parse_sess.edition; @@ -39,7 +41,7 @@ pub fn inject( let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id()); - let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); + let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features); let cx = ExtCtxt::new(sess, ecfg, resolver, None); // .rev() to preserve ordering above in combination with insert(0, ...) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 507b74c2437..d8846a9f0aa 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -41,7 +41,12 @@ 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(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn ResolverExpand) { +pub fn inject( + krate: &mut ast::Crate, + sess: &Session, + features: &Features, + resolver: &mut dyn ResolverExpand, +) { let span_diagnostic = sess.diagnostic(); let panic_strategy = sess.panic_strategy(); let platform_panic_strategy = sess.target.panic_strategy; @@ -76,7 +81,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve resolver, reexport_test_harness_main, krate, - &sess.features_untracked(), + features, panic_strategy, test_runner, ) @@ -243,9 +248,7 @@ fn generate_test_harness( panic_strategy: PanicStrategy, test_runner: Option, ) { - let mut econfig = ExpansionConfig::default("test".to_string()); - econfig.features = Some(features); - + let econfig = ExpansionConfig::default("test".to_string(), features); let ext_cx = ExtCtxt::new(sess, econfig, resolver, None); let expn_id = ext_cx.resolver.expansion_for_ast_pass( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 12473a2bb0b..c4d2a374f0c 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -18,6 +18,7 @@ Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult, }; +use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; @@ -767,6 +768,7 @@ pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { /// and other properties converted from attributes. pub fn new( sess: &Session, + features: &Features, kind: SyntaxExtensionKind, span: Span, helper_attrs: Vec, @@ -816,7 +818,7 @@ pub fn new( allow_internal_unstable: (!allow_internal_unstable.is_empty()) .then(|| allow_internal_unstable.into()), stability: stability.map(|(s, _)| s), - deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d), + deprecation: attr::find_deprecation(&sess, features, attrs).map(|(d, _)| d), helper_attrs, edition, builtin_name, @@ -957,6 +959,7 @@ pub trait LintStoreExpand { fn pre_expansion_lint( &self, sess: &Session, + features: &Features, registered_tools: &RegisteredTools, node_id: NodeId, attrs: &[Attribute], diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 165c6d47c8a..34d16bf00cd 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -796,7 +796,7 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { | Annotatable::FieldDef(..) | Annotatable::Variant(..) => panic!("unexpected annotatable"), }; - if self.cx.ecfg.proc_macro_hygiene() { + if self.cx.ecfg.features.proc_macro_hygiene { return; } feature_err( @@ -834,7 +834,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) { } } - if !self.cx.ecfg.proc_macro_hygiene() { + if !self.cx.ecfg.features.proc_macro_hygiene { annotatable .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess }); } @@ -1122,6 +1122,7 @@ fn wrap_flat_map_node_noop_flat_map( if let Some(lint_store) = ecx.lint_store { lint_store.pre_expansion_lint( ecx.sess, + ecx.ecfg.features, ecx.resolver.registered_tools(), ecx.current_expansion.lint_node_id, &attrs, @@ -1580,7 +1581,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn cfg(&self) -> StripUnconfigured<'_> { StripUnconfigured { sess: &self.cx.sess, - features: self.cx.ecfg.features, + features: Some(self.cx.ecfg.features), config_tokens: false, lint_node_id: self.cx.current_expansion.lint_node_id, } @@ -1676,7 +1677,7 @@ fn take_first_attr( // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { - let features = self.cx.ecfg.features.unwrap(); + let features = self.cx.ecfg.features; let mut attrs = attrs.iter().peekable(); let mut span: Option = None; while let Some(attr) = attrs.next() { @@ -1976,7 +1977,7 @@ fn visit_id(&mut self, id: &mut NodeId) { pub struct ExpansionConfig<'feat> { pub crate_name: String, - pub features: Option<&'feat Features>, + pub features: &'feat Features, pub recursion_limit: Limit, pub trace_mac: bool, /// If false, strip `#[test]` nodes @@ -1987,11 +1988,11 @@ pub struct ExpansionConfig<'feat> { pub proc_macro_backtrace: bool, } -impl<'feat> ExpansionConfig<'feat> { - pub fn default(crate_name: String) -> ExpansionConfig<'static> { +impl ExpansionConfig<'_> { + pub fn default(crate_name: String, features: &Features) -> ExpansionConfig<'_> { ExpansionConfig { crate_name, - features: None, + features, recursion_limit: Limit::new(1024), trace_mac: false, should_test: false, @@ -1999,8 +2000,4 @@ pub fn default(crate_name: String) -> ExpansionConfig<'static> { proc_macro_backtrace: false, } } - - fn proc_macro_hygiene(&self) -> bool { - self.features.is_some_and(|features| features.proc_macro_hygiene) - } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1b935058c04..ce8b4621720 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -16,6 +16,7 @@ use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{Applicability, ErrorGuaranteed}; +use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, }; @@ -375,6 +376,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( /// Converts a macro item into a syntax extension. pub fn compile_declarative_macro( sess: &Session, + features: &Features, def: &ast::Item, edition: Edition, ) -> (SyntaxExtension, Vec<(usize, Span)>) { @@ -382,6 +384,7 @@ pub fn compile_declarative_macro( let mk_syn_ext = |expander| { SyntaxExtension::new( sess, + features, SyntaxExtensionKind::LegacyBang(expander), def.span, Vec::new(), @@ -503,7 +506,7 @@ pub fn compile_declarative_macro( true, &sess.parse_sess, def.id, - sess.features_untracked(), + features, edition, ) .pop() @@ -527,7 +530,7 @@ pub fn compile_declarative_macro( false, &sess.parse_sess, def.id, - sess.features_untracked(), + features, edition, ) .pop() diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 2c7438ed9db..ae008674d01 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -15,6 +15,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_expand = { path = "../rustc_expand" } +rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index def9fdcd3c7..18a669175b9 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -11,6 +11,7 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::PResult; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; +use rustc_feature::Features; use rustc_fs_util::try_canonicalize; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; @@ -98,6 +99,7 @@ pub(crate) fn create_lint_store( fn pre_expansion_lint<'a>( sess: &Session, + features: &Features, lint_store: &LintStore, registered_tools: &RegisteredTools, check_node: impl EarlyCheckNode<'a>, @@ -107,6 +109,7 @@ fn pre_expansion_lint<'a>( || { rustc_lint::check_ast_node( sess, + features, true, lint_store, registered_tools, @@ -125,13 +128,14 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { fn pre_expansion_lint( &self, sess: &Session, + features: &Features, registered_tools: &RegisteredTools, node_id: ast::NodeId, attrs: &[ast::Attribute], items: &[rustc_ast::ptr::P], name: Symbol, ) { - pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); + pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, attrs, items), name); } } @@ -147,10 +151,18 @@ fn configure_and_expand( ) -> ast::Crate { let tcx = resolver.tcx(); let sess = tcx.sess; + let features = tcx.features(); let lint_store = unerased_lint_store(tcx); let crate_name = tcx.crate_name(LOCAL_CRATE); let lint_check_node = (&krate, pre_configured_attrs); - pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), lint_check_node, crate_name); + pre_expansion_lint( + sess, + features, + lint_store, + tcx.registered_tools(()), + lint_check_node, + crate_name, + ); rustc_builtin_macros::register_builtin_macros(resolver); let num_standard_library_imports = sess.time("crate_injection", || { @@ -159,6 +171,7 @@ fn configure_and_expand( pre_configured_attrs, resolver, sess, + features, ) }); @@ -198,16 +211,15 @@ fn configure_and_expand( } // Create the config for macro expansion - let features = sess.features_untracked(); let recursion_limit = get_recursion_limit(pre_configured_attrs, sess); let cfg = rustc_expand::expand::ExpansionConfig { - features: Some(features), + crate_name: crate_name.to_string(), + features, recursion_limit, trace_mac: sess.opts.unstable_opts.trace_macros, should_test: sess.is_test_crate(), span_debug: sess.opts.unstable_opts.span_debug, proc_macro_backtrace: sess.opts.unstable_opts.proc_macro_backtrace, - ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; let lint_store = LintStoreExpandImpl(lint_store); @@ -241,11 +253,16 @@ fn configure_and_expand( }); sess.time("maybe_building_test_harness", || { - rustc_builtin_macros::test_harness::inject(&mut krate, sess, resolver) + rustc_builtin_macros::test_harness::inject(&mut krate, sess, features, resolver) }); let has_proc_macro_decls = sess.time("AST_validation", || { - rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer()) + rustc_ast_passes::ast_validation::check_crate( + sess, + features, + &krate, + resolver.lint_buffer(), + ) }); let crate_types = tcx.crate_types(); @@ -270,6 +287,7 @@ fn configure_and_expand( rustc_builtin_macros::proc_macro_harness::inject( &mut krate, sess, + features, resolver, is_proc_macro_crate, has_proc_macro_decls, @@ -300,7 +318,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { // Needs to go *after* expansion to be able to check the results of macro expansion. sess.time("complete_gated_feature_checking", || { - rustc_ast_passes::feature_gate::check_crate(&krate, sess); + rustc_ast_passes::feature_gate::check_crate(&krate, sess, tcx.features()); }); // Add all buffered lints from the `ParseSess` to the `Session`. @@ -329,6 +347,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let lint_store = unerased_lint_store(tcx); rustc_lint::check_ast_node( sess, + tcx.features(), false, lint_store, tcx.registered_tools(()), diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 7687e83da76..5d38cf770a2 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -234,9 +234,6 @@ pub fn global_ctxt(&'tcx self) -> Result> debug_assert_eq!(_id, CRATE_DEF_ID); let untracked = Untracked { cstore, source_span, definitions }; - // FIXME: Move features from session to tcx and make them immutable. - sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs)); - let qcx = passes::create_global_ctxt( self.compiler, crate_types, @@ -254,11 +251,13 @@ pub fn global_ctxt(&'tcx self) -> Result> feed.crate_name(crate_name); let feed = tcx.feed_unit_query(); + feed.features_query( + tcx.arena.alloc(rustc_expand::config::features(sess, &pre_configured_attrs)), + ); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.metadata_loader( tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())), ); - feed.features_query(tcx.sess.features_untracked()); }); Ok(qcx) }) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2c9d212a6a6..7a430c1df85 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2237,7 +2237,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { impl EarlyLintPass for IncompleteInternalFeatures { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { - let features = cx.sess().features_untracked(); + let features = cx.builder.features(); features .declared_lang_features .iter() diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index f7e56b30553..f73797415bc 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -27,6 +27,7 @@ use rustc_data_structures::sync; use rustc_errors::{add_elided_lifetime_in_path_suggestion, DiagnosticBuilder, DiagnosticMessage}; use rustc_errors::{Applicability, DecorateLint, MultiSpan, SuggestionStyle}; +use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -1071,6 +1072,7 @@ fn fulfill_expectation(&self, expectation: LintExpectationId) { impl<'a> EarlyContext<'a> { pub(crate) fn new( sess: &'a Session, + features: &'a Features, warn_about_weird_lints: bool, lint_store: &'a LintStore, registered_tools: &'a RegisteredTools, @@ -1079,6 +1081,7 @@ pub(crate) fn new( EarlyContext { builder: LintLevelsBuilder::new( sess, + features, warn_about_weird_lints, lint_store, registered_tools, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 9f1f5a26ee5..211ea8f4347 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -20,6 +20,7 @@ use rustc_ast::visit::{self as ast_visit, Visitor}; use rustc_ast::{self as ast, walk_list, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_feature::Features; use rustc_middle::ty::RegisteredTools; use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_session::Session; @@ -381,6 +382,7 @@ fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) pub fn check_ast_node<'a>( sess: &Session, + features: &Features, pre_expansion: bool, lint_store: &LintStore, registered_tools: &RegisteredTools, @@ -390,6 +392,7 @@ pub fn check_ast_node<'a>( ) { let context = EarlyContext::new( sess, + features, !pre_expansion, lint_store, registered_tools, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 18b178d8882..1f4e5fa4d3b 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -12,6 +12,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; +use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; @@ -119,6 +120,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp let mut builder = LintLevelsBuilder { sess: tcx.sess, + features: tcx.features(), provider: QueryMapExpectationsWrapper { tcx, cur: hir::CRATE_HIR_ID, @@ -148,6 +150,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe let mut levels = LintLevelsBuilder { sess: tcx.sess, + features: tcx.features(), provider: LintLevelQueryMap { tcx, cur: owner.into(), @@ -435,6 +438,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { pub struct LintLevelsBuilder<'s, P> { sess: &'s Session, + features: &'s Features, provider: P, warn_about_weird_lints: bool, store: &'s LintStore, @@ -448,12 +452,14 @@ pub(crate) struct BuilderPush { impl<'s> LintLevelsBuilder<'s, TopDown> { pub(crate) fn new( sess: &'s Session, + features: &'s Features, warn_about_weird_lints: bool, store: &'s LintStore, registered_tools: &'s RegisteredTools, ) -> Self { let mut builder = LintLevelsBuilder { sess, + features, provider: TopDown { sets: LintLevelSets::new(), cur: COMMAND_LINE }, warn_about_weird_lints, store, @@ -526,6 +532,10 @@ pub(crate) fn sess(&self) -> &Session { self.sess } + pub(crate) fn features(&self) -> &Features { + self.features + } + pub(crate) fn lint_store(&self) -> &LintStore { self.store } @@ -716,7 +726,7 @@ fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: ast::MetaItemKind::NameValue(ref name_value) => { if item.path == sym::reason { if let ast::LitKind::Str(rationale, _) = name_value.kind { - if !self.sess.features_untracked().lint_reasons { + if !self.features.lint_reasons { feature_err( &self.sess.parse_sess, sym::lint_reasons, @@ -992,7 +1002,7 @@ fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: #[track_caller] fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool { if let Some(feature) = lint_id.lint.feature_gate { - if !self.sess.features_untracked().enabled(feature) { + if !self.features.enabled(feature) { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); struct_lint_level( diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 9e67bb655d4..e8f66c36a86 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -842,7 +842,7 @@ fn get_span(self, index: DefIndex, sess: &Session) -> Span { .decode((self, sess)) } - fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension { + fn load_proc_macro(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = @@ -861,9 +861,11 @@ fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension { } }; + let sess = tcx.sess; let attrs: Vec<_> = self.get_item_attrs(id, sess).collect(); SyntaxExtension::new( sess, + tcx.features(), kind, self.get_span(id, sess), helper_attrs, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7dbfe0e0cb0..aeda8af6d2c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -6,6 +6,7 @@ use rustc_ast as ast; use rustc_attr::Deprecation; +use rustc_data_structures::sync::Lrc; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; @@ -23,7 +24,6 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use rustc_data_structures::sync::Lrc; use std::any::Any; use super::{Decodable, DecodeContext, DecodeIterator}; @@ -522,12 +522,13 @@ pub fn ctor_untracked(&self, def: DefId) -> Option<(CtorKind, DefId)> { self.get_crate_data(def.krate).get_ctor(def.index) } - pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { + pub fn load_macro_untracked(&self, id: DefId, tcx: TyCtxt<'_>) -> LoadedMacro { + let sess = tcx.sess; let _prof_timer = sess.prof.generic_activity("metadata_load_macro"); let data = self.get_crate_data(id.krate); if data.root.is_proc_macro_crate() { - return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); + return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, tcx)); } let span = data.get_span(id.index, sess); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 5a320865c95..b056ae420ab 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -131,6 +131,7 @@ macro_rules! arena_types { [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>), [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem, [] mod_child: rustc_middle::metadata::ModChild, + [] features: rustc_feature::Features, ]); ) } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3950ac9dd31..bd2336410b9 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -115,7 +115,7 @@ fn annotate( let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)); debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs); - let depr = attr::find_deprecation(&self.tcx.sess, attrs); + let depr = attr::find_deprecation(self.tcx.sess, self.tcx.features(), attrs); let mut is_deprecated = false; if let Some((depr, span)) = &depr { is_deprecated = true; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index a655667d01d..127bec22c17 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -171,7 +171,7 @@ pub(crate) fn get_macro_by_def_id(&mut self, def_id: DefId) -> MacroData { return macro_data.clone(); } - let load_macro_untracked = self.cstore().load_macro_untracked(def_id, &self.tcx.sess); + let load_macro_untracked = self.cstore().load_macro_untracked(def_id, self.tcx); let (ext, macro_rules) = match load_macro_untracked { LoadedMacro::MacroDef(item, edition) => ( Lrc::new(self.compile_macro(&item, edition).0), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e403386e60c..76e54e60d14 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1282,7 +1282,7 @@ pub fn new( let registered_tools = tcx.registered_tools(()); - let features = tcx.sess.features_untracked(); + let features = tcx.features(); let mut resolver = Resolver { tcx, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 614a29e7578..6a5b675b4bb 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -920,7 +920,8 @@ pub(crate) fn compile_macro( item: &ast::Item, edition: Edition, ) -> (SyntaxExtension, Vec<(usize, Span)>) { - let (mut result, mut rule_spans) = compile_declarative_macro(self.tcx.sess, item, edition); + let (mut result, mut rule_spans) = + compile_declarative_macro(self.tcx.sess, self.tcx.features(), item, edition); if let Some(builtin_name) = result.builtin_name { // The macro was marked with `#[rustc_builtin_macro]`. diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5d7572f65a5..086ce4e6964 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -17,7 +17,7 @@ use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ - self, AtomicU64, AtomicUsize, Lock, Lrc, OnceCell, OneThread, Ordering, Ordering::SeqCst, + self, AtomicU64, AtomicUsize, Lock, Lrc, OneThread, Ordering, Ordering::SeqCst, }; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; @@ -152,8 +152,6 @@ pub struct Session { /// Input, input file path and output file path to this compilation process. pub io: CompilerIO, - features: OnceCell, - incr_comp_session: OneThread>, /// Used for incremental compilation tests. Will only be populated if /// `-Zquery-dep-graph` is specified. @@ -705,21 +703,6 @@ pub fn instrument_coverage_except_unused_functions(&self) -> bool { self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedFunctions } - /// Gets the features enabled for the current compilation session. - /// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents - /// dependency tracking. Use tcx.features() instead. - #[inline] - pub fn features_untracked(&self) -> &rustc_feature::Features { - self.features.get().unwrap() - } - - pub fn init_features(&self, features: rustc_feature::Features) { - match self.features.set(features) { - Ok(()) => {} - Err(_) => panic!("`features` was initialized twice"), - } - } - pub fn is_sanitizer_cfi_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) } @@ -1464,7 +1447,6 @@ pub fn build_session( parse_sess, sysroot, io, - features: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 384010034e6..389bac0f09d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -200,7 +200,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT let fqn = if let ItemType::Macro = kind { // Check to see if it is a macro 2.0 or built-in macro if matches!( - CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.sess()), + CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx), LoadedMacro::MacroDef(def, _) if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules) @@ -680,7 +680,7 @@ fn build_macro( import_def_id: Option, macro_kind: MacroKind, ) -> clean::ItemKind { - match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) { + match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) { LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index eb5d3c88570..58022046294 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -604,7 +604,7 @@ fn generate_macro_def_id_path( } // Check to see if it is a macro 2.0 or built-in macro. // More information in . - let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx.sess) { + let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) { LoadedMacro::MacroDef(def, _) => { // If `ast_def.macro_rules` is `true`, then it's not a macro 2.0. matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules)