diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index aa678ba788a5bb9e8d3220d13a4f039638c99beb..5f6a7c452c4c457db7e9bff5bd2cdb59a20176e8 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -436,6 +436,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { } define_dep_nodes!( <'tcx> + // We use this for most things when incr. comp. is turned off. + [] Null, + // Represents the `Krate` as a whole (the `hir::Krate` value) (as // distinct from the krate module). This is basically a hash of // the entire krate, so if you read from `Krate` (e.g., by calling @@ -605,8 +608,8 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), [input] PostorderCnums, - [input] HasCloneClosures(CrateNum), - [input] HasCopyClosures(CrateNum), + [] HasCloneClosures(CrateNum), + [] HasCopyClosures(CrateNum), // This query is not expected to have inputs -- as a result, it's // not a good candidate for "replay" because it's essentially a @@ -630,8 +633,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { [] CompileCodegenUnit(InternedString), [input] OutputFilenames, [anon] NormalizeTy, - // We use this for most things when incr. comp. is turned off. - [] Null, [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, @@ -642,6 +643,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { [] GetSymbolExportLevel(DefId), + [input] Features, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index fa745bf165577cc3de2d14e6f1b7e8877c61ced6..877027a21a22189a1721f20e8ecb1a31e457eace 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -550,7 +550,7 @@ fn collect_in_band_defs( { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); - self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes; + self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes; assert!(self.in_band_ty_params.is_empty()); @@ -964,7 +964,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { let span = t.span; match itctx { ImplTraitContext::Existential => { - let has_feature = self.sess.features.borrow().conservative_impl_trait; + let has_feature = self.sess.features_untracked().conservative_impl_trait; if !t.span.allows_unstable() && !has_feature { emit_feature_err(&self.sess.parse_sess, "conservative_impl_trait", t.span, GateIssue::Language, @@ -988,7 +988,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { }, lifetimes) }, ImplTraitContext::Universal(def_id) => { - let has_feature = self.sess.features.borrow().universal_impl_trait; + let has_feature = self.sess.features_untracked().universal_impl_trait; if !t.span.allows_unstable() && !has_feature { emit_feature_err(&self.sess.parse_sess, "universal_impl_trait", t.span, GateIssue::Language, @@ -3713,7 +3713,7 @@ fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime { } fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { - if self.sess.features.borrow().dyn_trait { + if self.sess.features_untracked().dyn_trait { self.sess.buffer_lint_with_diagnostic( builtin::BARE_TRAIT_OBJECT, id, span, "trait objects without an explicit `dyn` are deprecated", diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c31a5c9d86d7763c19d554c1f2d7b4fd7aaf4a71..f935cbfcde992d394f95f844e86d8f2f2a4b74e3 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -17,6 +17,7 @@ use std::mem; use syntax::ast; +use syntax::feature_gate; use syntax::parse::token; use syntax::symbol::InternedString; use syntax::tokenstream; @@ -460,3 +461,21 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar, (pos.0 - filemap_start.0, width as u32) } + + + +impl<'gcx> HashStable> for feature_gate::Features { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + // Unfortunately we cannot exhaustively list fields here, since the + // struct is macro generated. + self.declared_stable_lang_features.hash_stable(hcx, hasher); + self.declared_lib_features.hash_stable(hcx, hasher); + + self.walk_feature_fields(|feature_name, value| { + feature_name.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); + } +} diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 37a84361aea2d0d8ad56200781e31846ab5ae49f..559b2720076f447030d042710fa0a698c55ddc3a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -289,11 +289,11 @@ pub fn report_region_errors( ) { debug!("report_region_errors(): {} errors to start", errors.len()); - if will_later_be_reported_by_nll && self.tcx.sess.nll() { + if will_later_be_reported_by_nll && self.tcx.nll() { // With `#![feature(nll)]`, we want to present a nice user // experience, so don't even mention the errors from the // AST checker. - if self.tcx.sess.features.borrow().nll { + if self.tcx.features().nll { return; } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e80ea16f565abc64dbda58cbcd0aa602c9066316..16c33d6bd837da03f301396a7eb42a43b11d2ac9 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -131,7 +131,7 @@ fn annotate(&mut self, id: NodeId, attrs: &[Attribute], item_sp: Span, kind: AnnotationKind, visit_children: F) where F: FnOnce(&mut Self) { - if self.tcx.sess.features.borrow().staged_api { + if self.tcx.features().staged_api { // This crate explicitly wants staged API. debug!("annotate(id = {:?}, attrs = {:?})", id, attrs); if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) { @@ -398,7 +398,7 @@ impl<'a, 'tcx> Index<'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> { let is_staged_api = tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || - tcx.sess.features.borrow().staged_api; + tcx.features().staged_api; let mut staged_api = FxHashMap(); staged_api.insert(LOCAL_CRATE, is_staged_api); let mut index = Index { @@ -408,7 +408,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> { active_features: FxHashSet(), }; - let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features; + let ref active_lib_features = tcx.features().declared_lib_features; // Put the active features into a map for quick lookup index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); @@ -677,7 +677,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) { // There's no good place to insert stability check for non-Copy unions, // so semi-randomly perform it here in stability.rs - hir::ItemUnion(..) if !self.tcx.sess.features.borrow().untagged_unions => { + hir::ItemUnion(..) if !self.tcx.features().untagged_unions => { let def_id = self.tcx.hir.local_def_id(item.id); let adt_def = self.tcx.adt_def(def_id); let ty = self.tcx.type_of(def_id); @@ -721,8 +721,6 @@ pub fn lookup_deprecation(self, id: DefId) -> Option { /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let sess = &tcx.sess; - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); if tcx.stability().staged_api[&LOCAL_CRATE] { @@ -736,12 +734,12 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } - let ref declared_lib_features = sess.features.borrow().declared_lib_features; + let ref declared_lib_features = tcx.features().declared_lib_features; let mut remaining_lib_features: FxHashMap = declared_lib_features.clone().into_iter().collect(); remaining_lib_features.remove(&Symbol::intern("proc_macro")); - for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { + for &(ref stable_lang_feature, span) in &tcx.features().declared_stable_lang_features { let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) .expect("unexpectedly couldn't find version feature was stabilized"); tcx.lint_node(lint::builtin::STABLE_FEATURES, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd87a8f918ab37b767817917206466712dcb6df7..f6da4b55301e40d444e80930f0091ca4e2d3a7c9 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch}; +use session::config::{DebugInfoLevel, OutputType, Epoch}; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; @@ -93,7 +93,8 @@ pub struct Session { /// multiple crates with the same name to coexist. See the /// trans::back::symbol_names module for more information. pub crate_disambiguator: RefCell>, - pub features: RefCell, + + features: RefCell>, /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. @@ -194,6 +195,7 @@ pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { None => bug!("accessing disambiguator before initialization"), } } + pub fn struct_span_warn<'a, S: Into>(&'a self, sp: S, msg: &str) @@ -456,16 +458,22 @@ pub fn print_llvm_passes(&self) -> bool { self.opts.debugging_opts.print_llvm_passes } - /// If true, we should use NLL-style region checking instead of - /// lexical style. - pub fn nll(&self) -> bool { - self.features.borrow().nll || self.opts.debugging_opts.nll + /// Get the features enabled for the current compilation session. Do not use + /// 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) -> cell::Ref { + let features = self.features.borrow(); + + if features.is_none() { + bug!("Access to Session::features before it is initialized"); + } + + cell::Ref::map(features, |r| r.as_ref().unwrap()) } - /// If true, we should use the MIR-based borrowck (we may *also* use - /// the AST-based borrowck). - pub fn use_mir(&self) -> bool { - self.borrowck_mode().use_mir() + pub fn init_features(&self, features: feature_gate::Features) { + *(self.features.borrow_mut()) = Some(features); } /// If true, we should gather causal information during NLL @@ -475,42 +483,6 @@ pub fn nll_dump_cause(&self) -> bool { self.opts.debugging_opts.nll_dump_cause } - /// If true, we should enable two-phase borrows checks. This is - /// done with either `-Ztwo-phase-borrows` or with - /// `#![feature(nll)]`. - pub fn two_phase_borrows(&self) -> bool { - self.features.borrow().nll || self.opts.debugging_opts.two_phase_borrows - } - - /// What mode(s) of borrowck should we run? AST? MIR? both? - /// (Also considers the `#![feature(nll)]` setting.) - pub fn borrowck_mode(&self) -> BorrowckMode { - match self.opts.borrowck_mode { - mode @ BorrowckMode::Mir | - mode @ BorrowckMode::Compare => mode, - - mode @ BorrowckMode::Ast => { - if self.nll() { - BorrowckMode::Mir - } else { - mode - } - } - - } - } - - /// Should we emit EndRegion MIR statements? These are consumed by - /// MIR borrowck, but not when NLL is used. They are also consumed - /// by the validation stuff. - pub fn emit_end_regions(&self) -> bool { - // FIXME(#46875) -- we should not emit end regions when NLL is enabled, - // but for now we can't stop doing so because it causes false positives - self.opts.debugging_opts.emit_end_regions || - self.opts.debugging_opts.mir_emit_validate > 0 || - self.use_mir() - } - /// Calculates the flavor of LTO to use for this compilation. pub fn lto(&self) -> config::Lto { // If our target has codegen requirements ignore the command line @@ -1029,7 +1001,7 @@ pub fn build_session_(sopts: config::Options, crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FxHashMap()), crate_disambiguator: RefCell::new(None), - features: RefCell::new(feature_gate::Features::new()), + features: RefCell::new(None), recursion_limit: Cell::new(64), type_length_limit: Cell::new(1048576), next_node_id: Cell::new(NodeId::new(1)), diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 43940d7cea3ed6a24a5cf841c2374f87f02dd64e..d11565618a687ede894f069fa6f841c4ab38599c 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -164,7 +164,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. - if !tcx.sess.features.borrow().specialization && + if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) { return false; } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d04c4771017318cda43639e45c5b80c7feeef420..a7f065d57aeed645a3e06676a8220d9f3a4ccb78 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,7 +14,7 @@ use dep_graph::{DepNode, DepConstructor}; use errors::DiagnosticBuilder; use session::Session; -use session::config::OutputFilenames; +use session::config::{BorrowckMode, OutputFilenames}; use middle; use hir::{TraitCandidate, HirId, ItemLocalId}; use hir::def::{Def, Export}; @@ -71,6 +71,7 @@ use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::codemap::MultiSpan; +use syntax::feature_gate; use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; @@ -1255,6 +1256,10 @@ pub fn crates(self) -> Lrc> { self.all_crate_nums(LOCAL_CRATE) } + pub fn features(self) -> Lrc { + self.features_query(LOCAL_CRATE) + } + pub fn def_key(self, id: DefId) -> hir_map::DefKey { if id.is_local() { self.hir.def_key(id) @@ -1362,6 +1367,53 @@ pub fn serialize_query_result_cache(self, self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder) } + /// If true, we should use NLL-style region checking instead of + /// lexical style. + pub fn nll(self) -> bool { + self.features().nll || self.sess.opts.debugging_opts.nll + } + + /// If true, we should use the MIR-based borrowck (we may *also* use + /// the AST-based borrowck). + pub fn use_mir(self) -> bool { + self.borrowck_mode().use_mir() + } + + /// If true, we should enable two-phase borrows checks. This is + /// done with either `-Ztwo-phase-borrows` or with + /// `#![feature(nll)]`. + pub fn two_phase_borrows(self) -> bool { + self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows + } + + /// What mode(s) of borrowck should we run? AST? MIR? both? + /// (Also considers the `#![feature(nll)]` setting.) + pub fn borrowck_mode(&self) -> BorrowckMode { + match self.sess.opts.borrowck_mode { + mode @ BorrowckMode::Mir | + mode @ BorrowckMode::Compare => mode, + + mode @ BorrowckMode::Ast => { + if self.nll() { + BorrowckMode::Mir + } else { + mode + } + } + + } + } + + /// Should we emit EndRegion MIR statements? These are consumed by + /// MIR borrowck, but not when NLL is used. They are also consumed + /// by the validation stuff. + pub fn emit_end_regions(self) -> bool { + // FIXME(#46875) -- we should not emit end regions when NLL is enabled, + // but for now we can't stop doing so because it causes false positives + self.sess.opts.debugging_opts.emit_end_regions || + self.sess.opts.debugging_opts.mir_emit_validate > 0 || + self.use_mir() + } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { @@ -2020,7 +2072,7 @@ pub fn mk_nil(self) -> Ty<'tcx> { } pub fn mk_diverging_default(self) -> Ty<'tcx> { - if self.sess.features.borrow().never_type { + if self.features().never_type { self.types.never } else { self.intern_tup(&[], true) @@ -2395,13 +2447,17 @@ pub fn provide(providers: &mut ty::maps::Providers) { }; providers.has_copy_closures = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - tcx.sess.features.borrow().copy_closures + tcx.features().copy_closures }; providers.has_clone_closures = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - tcx.sess.features.borrow().clone_closures + tcx.features().clone_closures }; providers.fully_normalize_monormophic_ty = |tcx, ty| { tcx.fully_normalize_associated_types_in(&ty) }; + providers.features_query = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Lrc::new(tcx.sess.features_untracked().clone()) + }; } diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index eb07876b05f26cb408e9cc86ae7329b42d128401..c91b30440e5e31ff0d506ca5e5e4b03a83a4a82f 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -593,6 +593,12 @@ fn describe(_tcx: TyCtxt, _: Ty) -> String { } } +impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up enabled feature gates") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> { #[inline] fn cache_on_disk(def_id: Self::Key) -> bool { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 6edb1d9be35db855baf1678756634ba05c282eab..c211713db6bc091a324930c65968238eb7aa9e2a 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -52,6 +52,7 @@ use syntax_pos::symbol::InternedString; use syntax::attr; use syntax::ast; +use syntax::feature_gate; use syntax::symbol::Symbol; #[macro_use] @@ -374,12 +375,19 @@ // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>) -> usize, + + [] fn features_query: features_node(CrateNum) -> Lrc, } ////////////////////////////////////////////////////////////////////// // These functions are little shims used to find the dep-node for a // given query when there is not a *direct* mapping: + +fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::Features +} + fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { DepConstructor::EraseRegionsTy { ty } } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index b654b6bc42a122896c018319b39efcaf5c0e07da..3443b9b61b2156ba718864b0497371cb5a03a8cd 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -936,6 +936,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); } DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); } + DepKind::Features => { force!(features_query, LOCAL_CRATE); } } true diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9ba33a57c20505329bfba80b2283ccfbd76d573b..f6f4e1ceb1563a05c9a69326f32fcf09fdd2a62e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2335,7 +2335,7 @@ pub fn associated_items(self, def_id: DefId) /// Returns true if the impls are the same polarity and are implementing /// a trait which contains no items pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool { - if !self.sess.features.borrow().overlapping_marker_traits { + if !self.features().overlapping_marker_traits { return false; } let trait1_is_empty = self.impl_trait_ref(def_id1) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 4fe6ee45295a3c06b5210194f641056f53bc056b..bb198adea4a6a6c88a0c304163a1da053747a04b 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -276,7 +276,7 @@ fn cancel_if_wrong_origin<'a>(&'a self, o: Origin) -> DiagnosticBuilder<'a> { - if !o.should_emit_errors(self.tcx.sess.borrowck_mode()) { + if !o.should_emit_errors(self.tcx.borrowck_mode()) { self.tcx.sess.diagnostic().cancel(&mut diag); } diag diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 54e3418d4f0178fb1ba1f93b860b8bb67c2fb4bd..8e3b99f2dbfee86a13c3007ff5e18877ce50fa76 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -201,7 +201,7 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt } fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { - if self.tcx.sess.features.borrow().never_type { + if self.tcx.features().never_type { self.tcx.is_ty_uninhabited_from(self.module, ty) } else { false @@ -227,7 +227,7 @@ fn is_variant_uninhabited(&self, substs: &'tcx ty::subst::Substs<'tcx>) -> bool { - if self.tcx.sess.features.borrow().never_type { + if self.tcx.features().never_type { self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs) } else { false diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index ae53ed0e1140d1226e4ba29f8ba45041ad13c40e..6f7143c185cb3ad2718ae1463fee873fd8ea77ff 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -212,7 +212,7 @@ fn check_match( let pat_ty = self.tables.node_id_to_type(scrut.hir_id); let module = self.tcx.hir.get_module_parent(scrut.id); if inlined_arms.is_empty() { - let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { + let scrutinee_is_uninhabited = if self.tcx.features().never_type { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { self.conservative_is_uninhabited(pat_ty) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 8e4ec93c14baebae44f7ca13e58ff099ca474883..2a571fa82643b2d97777158abcead4396f283349 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -398,7 +398,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, }).collect::, _>>()?)))) } hir::ExprIndex(ref arr, ref idx) => { - if !tcx.sess.features.borrow().const_indexing { + if !tcx.features().const_indexing { signal!(e, IndexOpFeatureGated); } let arr = cx.eval(arr)?; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 15afea19213865a727e30d48fb568f16b172cd55..571cc46bc6413e2eb4f8a9ac9366db05b30b71f2 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -650,7 +650,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test); // these need to be set "early" so that expansion sees `quote` if enabled. - *sess.features.borrow_mut() = features; + sess.init_features(features); *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); @@ -699,7 +699,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, let mut registry = registry.unwrap_or(Registry::new(sess, krate.span)); time(time_passes, "plugin registration", || { - if sess.features.borrow().rustc_diagnostic_macros { + if sess.features_untracked().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", diagnostics::plugin::expand_diagnostic_used); registry.register_macro("__register_diagnostic", @@ -749,7 +749,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, crate_loader, &resolver_arenas); resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; - syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote); + syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); krate = time(time_passes, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their @@ -780,7 +780,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, .filter(|p| env::join_paths(iter::once(p)).is_ok())) .unwrap()); } - let features = sess.features.borrow(); + let features = sess.features_untracked(); let cfg = syntax::ext::expand::ExpansionConfig { features: Some(&features), recursion_limit: sess.recursion_limit.get(), @@ -819,7 +819,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, sess.opts.test, krate, sess.diagnostic(), - &sess.features.borrow()) + &sess.features_untracked()) }); // If we're actually rustdoc then there's no need to actually compile @@ -886,7 +886,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, sess.track_errors(|| { syntax::feature_gate::check_crate(&krate, &sess.parse_sess, - &sess.features.borrow(), + &sess.features_untracked(), &attributes, sess.opts.unstable_features); }) diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 5976b80d90f871f0f8e164b249848e855bf0a5be..17a6176b79e954d4cbb72d2968cb65dff82cf12f 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -69,7 +69,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so // skip the walk. - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c3e283535ec8280fd2ba6da371a02a7f2c4e3e23..e114606a631159c142461f4d67a730c942eb1a8d 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -219,7 +219,7 @@ fn from_dirty_labels(labels: Labels) -> Assertion { pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // can't add `#[rustc_dirty]` etc without opting in to this feature - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 66f34a72edf2d4fce674ae9c15ba32a980861595..62ac898337ca9a13f083cdad8d1bf5aa5115a28d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1356,7 +1356,7 @@ fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId, // visibility is token at start of declaration (can be macro // variable rather than literal `pub`) let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' '); - let replacement = if cx.tcx.sess.features.borrow().crate_visibility_modifier { + let replacement = if cx.tcx.features().crate_visibility_modifier { "crate" } else { "pub(crate)" diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 439533fae49d915d8e9bdb546355c82e7f6952a1..6ab3172c4fefaaa1604dfdf0ec72ae75d5521fe9 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -72,7 +72,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let mut fn_warned = false; let mut op_warned = false; - if cx.tcx.sess.features.borrow().fn_must_use { + if cx.tcx.features().fn_must_use { let maybe_def = match expr.node { hir::ExprCall(ref callee, _) => { match callee.node { diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index c0ce32cc970683effe0ae338c303e681dcb40a98..2504f8dc251f9e0d11db9fc81dc750a0646eaf63 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -146,7 +146,7 @@ fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { None => self.tcx.sess.err(msg), } } - if lib.cfg.is_some() && !self.tcx.sess.features.borrow().link_cfg { + if lib.cfg.is_some() && !self.tcx.features().link_cfg { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "link_cfg", span.unwrap(), @@ -154,7 +154,7 @@ fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { "is feature gated"); } if lib.kind == cstore::NativeStaticNobundle && - !self.tcx.sess.features.borrow().static_nobundle { + !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "static_nobundle", span.unwrap(), diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index c6635d59154e277110c79e40383a3992054fcf24..b77e7cf2ec8b5f1e597802e54cb39d3bb6ab613c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -535,7 +535,7 @@ fn report_unscoped_local_value_does_not_live_long_enough( err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); - if !self.tcx.sess.nll() { + if !self.tcx.nll() { self.tcx.note_and_explain_region( scope_tree, &mut err, @@ -572,7 +572,7 @@ fn report_unscoped_temporary_value_does_not_live_long_enough( err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - if !self.tcx.sess.nll() { + if !self.tcx.nll() { self.tcx.note_and_explain_region( scope_tree, &mut err, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c6ed971f767cf15fba9385874c3d511e14e49cbc..1ff0ffaaa68b398e7166b2a6c01b4cc632cfc71d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -72,7 +72,7 @@ fn mir_borrowck<'a, 'tcx>( let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); - if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.use_mir() { + if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir() { return None; } @@ -101,7 +101,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // contain non-lexical lifetimes. It will have a lifetime tied // to the inference context. let mut mir: Mir<'tcx> = input_mir.clone(); - let free_regions = if !tcx.sess.nll() { + let free_regions = if !tcx.nll() { None } else { let mir = &mut mir; @@ -204,7 +204,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( ); (Some(Rc::new(regioncx)), opt_closure_req) } else { - assert!(!tcx.sess.nll()); + assert!(!tcx.nll()); (None, None) }; let flow_inits = flow_inits; // remove mut @@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// allowed to be split into separate Reservation and /// Activation phases. fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool { - self.tcx.sess.two_phase_borrows() && + self.tcx.two_phase_borrows() && (kind.allows_two_phase_borrow() || self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) } @@ -1253,7 +1253,7 @@ fn check_activations( span: Span, flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - if !self.tcx.sess.two_phase_borrows() { + if !self.tcx.two_phase_borrows() { return; } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a06d39d225c45ccc34076495b2534ac9db756cb4..3af10c5c25169e8205c0f72fa1fd1bb8efec5285 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1587,7 +1587,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: & // When NLL is enabled, the borrow checker runs the typeck // itself, so we don't need this MIR pass anymore. - if tcx.sess.nll() { + if tcx.nll() { return; } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 932aad0bb1d84dcf68f12673d221547452081fac..1ed8289d4418469544d5cd7400a6b718584516c6 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -50,7 +50,7 @@ pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self, block: BasicBlock, source_info: SourceInfo, region_scope: region::Scope) { - if tcx.sess.emit_end_regions() { + if tcx.emit_end_regions() { if let region::ScopeData::CallSite(_) = region_scope.data() { // The CallSite scope (aka the root scope) is sort of weird, in that it is // supposed to "separate" the "interior" and "exterior" of a closure. Being diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index b16d7ed236509e9eeaa6a48f2f3b9f6d88cc8b1f..abea55835466f60434e538f0b2189867afb2c356 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -113,7 +113,7 @@ fn simplify_match_pair<'pat>(&mut self, PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { - self.hir.tcx().sess.features.borrow().never_type && + self.hir.tcx().features().never_type && self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) } }); diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs index 7986313aa81346526da86a6205cbd71d5a8cb5e7..6e8985d99d287b83b14b6d32ddd44ea061445145 100644 --- a/src/librustc_mir/transform/clean_end_regions.rs +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -42,7 +42,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, _source: MirSource, mir: &mut Mir<'tcx>) { - if !tcx.sess.emit_end_regions() { return; } + if !tcx.emit_end_regions() { return; } let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 0b0ce1fb4d48b593eadf1ce64ab5cfb5bc3cdf8b..8f5831270d6e5afa94af754ef71f2f7e24914c61 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -936,7 +936,7 @@ fn visit_terminator_kind(&mut self, if self.mode != Mode::Fn && // feature-gate is not enabled, - !self.tcx.sess.features.borrow() + !self.tcx.features() .declared_lib_features .iter() .any(|&(ref sym, _)| sym == feature_name) && diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 4a7ee397aec00b887fd6382f22c52713e93eb22d..89242ca32bcbfa1586ddb2541e3c13b9d8bc5fce 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -514,7 +514,7 @@ fn cancel_if_wrong_origin<'a>(&'a self, o: Origin) -> DiagnosticBuilder<'a> { - if !o.should_emit_errors(self.sess.borrowck_mode()) { + if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); } diag diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index a46b85d93cbb82cc3024e0b533822d26997a7739..bf59165a9c4614f010e9ca359f3c9bc59d7dc079 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -52,7 +52,7 @@ pub fn load_plugins(sess: &Session, // do not report any error now. since crate attributes are // not touched by expansion, every use of plugin without // the feature enabled will result in an error later... - if sess.features.borrow().plugin { + if sess.features_untracked().plugin { for attr in &krate.attrs { if !attr.check_name("plugin") { continue; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b9899f499148dbd39602fb5804af7077bb4c4df2..bf7b81c4d0e420938ad8ca08a906ec9c02330366 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -590,7 +590,7 @@ pub fn get_macro(&mut self, def: Def) -> Lrc { }; let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features, + &self.session.features_untracked(), ¯o_def)); self.macro_map.insert(def_id, ext.clone()); ext diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 317bd9217b59167500f517121cb460dc6d1b9948..fc1ff248184033dc11d7410375bac313a23c488d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1524,7 +1524,7 @@ pub fn new(session: &'a Session, invocations.insert(Mark::root(), arenas.alloc_invocation_data(InvocationData::root(graph_root))); - let features = session.features.borrow(); + let features = session.features_untracked(); let mut macro_defs = FxHashMap(); macro_defs.insert(Mark::root(), root_def_id); @@ -2998,7 +2998,7 @@ fn resolve_qpath(&mut self, let prim = self.primitive_type_table.primitive_types[&path[0].node.name]; match prim { TyUint(UintTy::U128) | TyInt(IntTy::I128) => { - if !self.session.features.borrow().i128_type { + if !self.session.features_untracked().i128_type { emit_feature_err(&self.session.parse_sess, "i128_type", span, GateIssue::Language, "128-bit type is unstable"); @@ -3089,7 +3089,7 @@ fn resolve_path(&mut self, let prev_name = path[0].node.name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && - self.session.features.borrow().extern_absolute_paths { + self.session.features_untracked().extern_absolute_paths { // `::extern_crate::a::b` let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span); let crate_root = diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 81cc5e59bbbf7d319d4855c9fd9015543f7ebe89..95fa0f3b52fef6b181523c81edef431f6c634e26 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -744,7 +744,7 @@ pub fn define_macro(&mut self, let def_id = self.definitions.local_def_id(item.id); let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features, + &self.session.features_untracked(), item)); self.macro_map.insert(def_id, ext); @@ -838,7 +838,7 @@ pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) { } fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { - if !self.session.features.borrow().custom_derive { + if !self.session.features_untracked().custom_derive { let sess = &self.session.parse_sess; let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE; emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 438ab3a3513fcc2f24bf39bd7de31b22753ce867..01c1ded94578ecc1fa45da7521930f70595598e7 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -609,7 +609,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() || module_path[0].node.name == keywords::Extern.name()) { let is_extern = module_path[0].node.name == keywords::Extern.name() || - self.session.features.borrow().extern_absolute_paths; + self.session.features_untracked().extern_absolute_paths; match directive.subclass { GlobImport { .. } if is_extern => { return Some((directive.span, diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs index 5d7d4f3055bad6f47a6520561ce861f0eece9751..267c8d2bd03c861bcfac1d495c359c6fdfe1b8fd 100644 --- a/src/librustc_trans_utils/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -28,7 +28,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so // skip the walk. - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6a6c49c904838bf85acddaab99305fa12107722e..0df1225cf26247d157d47284abac2f52f0816ddc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -415,7 +415,7 @@ fn create_substs_for_ast_trait_ref(&self, let trait_def = self.tcx().trait_def(trait_def_id); - if !self.tcx().sess.features.borrow().unboxed_closures && + if !self.tcx().features().unboxed_closures && trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index da66a2e52e81f78eab943e69936e635f74953753..a261c12bcdd946dcc88cca1beeb2a5ce29f86d7c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -114,7 +114,7 @@ pub fn check_pat_walk( } }; if pat_adjustments.len() > 0 { - if tcx.sess.features.borrow().match_default_bindings { + if tcx.features().match_default_bindings { debug!("default binding mode is now {:?}", def_bm); self.inh.tables.borrow_mut() .pat_adjustments_mut() diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e2d6817697e8fd87de5180e03b262d5d6648e87c..abb0acd699cba0b148296bf1580684805d3dff22 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -586,7 +586,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc } } - if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion { + if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "unsized_tuple_coercion", self.cause.span, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c95ead285594b8bf3d5eeee0e5e27f4bc7414d88..841559013a093352731791934b3b872c74450c60 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -324,7 +324,7 @@ fn create_steps(&self, // possible that there will be multiple applicable methods. if !is_suggestion.0 { if reached_raw_pointer - && !self.tcx.sess.features.borrow().arbitrary_self_types { + && !self.tcx.features().arbitrary_self_types { // this case used to be allowed by the compiler, // so we do a future-compat lint here for the 2015 epoch // (see https://github.com/rust-lang/rust/issues/46906) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index db5a458bb8ce49c42882c53526bfc25f67849acb..0f59973eab251245ddfc004b9b97e6a2d6e4c167 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1105,7 +1105,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } fcx.demand_suptype(span, ret_ty, actual_return_ty); - if fcx.tcx.sess.features.borrow().termination_trait { + if fcx.tcx.features().termination_trait { // If the termination trait language item is activated, check that the main return type // implements the termination trait. if let Some(term_id) = fcx.tcx.lang_items().termination() { @@ -1616,7 +1616,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let repr_type_ty = def.repr.discr_type().to_ty(tcx); if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { - if !tcx.sess.features.borrow().repr128 { + if !tcx.features().repr128 { emit_feature_err(&tcx.sess.parse_sess, "repr128", sp, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 39e757c52ff2974ed709d62b6e0d3dbb56d8b781..d10ee358e072846e77be1591c47c141b1f55d4b1 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -536,7 +536,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self, let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - if !fcx.tcx.sess.features.borrow().arbitrary_self_types { + if !fcx.tcx.features().arbitrary_self_types { match self_kind { ExplicitSelf::ByValue | ExplicitSelf::ByReference(_, _) | diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index f65d627781f0fb802b848fcc40f5ad5c145d0b3f..d3de31d630a97469b8fad938a3b3912d7cd21a3b 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -74,7 +74,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d return; } - if tcx.sess.features.borrow().unboxed_closures { + if tcx.features().unboxed_closures { // the feature gate allows all Fn traits return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1c8d22e4666a6dd4b9884e2bbfe4878f9028838d..f7158593f0b6e37cd64d51e121afc009e2033392 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -711,7 +711,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); - if paren_sugar && !tcx.sess.features.borrow().unboxed_closures { + if paren_sugar && !tcx.features().unboxed_closures { let mut err = tcx.sess.struct_span_err( item.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ @@ -953,7 +953,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } if !allow_defaults && p.default.is_some() { - if !tcx.sess.features.borrow().default_type_parameter_fallback { + if !tcx.features().default_type_parameter_fallback { tcx.lint_node( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, p.id, @@ -1692,7 +1692,7 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic - && !tcx.sess.features.borrow().simd_ffi { + && !tcx.features().simd_ffi { let check = |ast_ty: &hir::Ty, ty: Ty| { if ty.is_simd() { tcx.sess.struct_span_err(ast_ty.span, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index af32738d9d04b37c6a33b3c0616ebc22b18524f9..d9bd96b0d769fea0fb7ae6c686eb57f17b5470ef 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -207,7 +207,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let actual = tcx.fn_sig(main_def_id); let expected_return_type = if tcx.lang_items().termination().is_some() - && tcx.sess.features.borrow().termination_trait { + && tcx.features().termination_trait { // we take the return type of the given main function, the real check is done // in `check_fn` actual.output().skip_binder() diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f4c9d556c8abf3ea9830d97c9915d8fc0dd2cbfe..e4477bee5c0e9e39e8b0dddd5b9b67959760fc05 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -629,7 +629,7 @@ fn visit_testable(&mut self, nested: F) { let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs); if let Some(ref cfg) = attrs.cfg { - if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features.borrow())) { + if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) { return; } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 728b3e4076d1ba93b7b3b3aba652fe81b51485eb..9162a582599fc6dc79f1b1b9ed6161c47fd6479b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -26,7 +26,6 @@ use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; -use std::cell::RefCell; use std::collections::HashMap; use std::collections::hash_map::Entry; @@ -184,7 +183,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, // Holy self-referential! /// Converts a `macro_rules!` invocation into a syntax extension. -pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) -> SyntaxExtension { +pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> SyntaxExtension { let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs")); let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs")); @@ -296,7 +295,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) } fn check_lhs_nt_follows(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], lhs: "ed::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the @@ -353,7 +352,7 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { } fn check_matcher(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], matcher: &[quoted::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); @@ -601,7 +600,7 @@ fn add_all(&mut self, other: &Self) { // Requires that `first_sets` is pre-computed for `matcher`; // see `FirstSets::new`. fn check_matcher_core(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], first_sets: &FirstSets, matcher: &[quoted::TokenTree], @@ -869,7 +868,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result, + features: &Features, attrs: &[ast::Attribute], tok: "ed::TokenTree) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); @@ -884,7 +883,7 @@ fn has_legal_fragment_specifier(sess: &ParseSess, } fn is_legal_fragment_specifier(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], frag_name: &str, frag_span: Span) -> bool { @@ -892,7 +891,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess, "item" | "block" | "stmt" | "expr" | "pat" | "path" | "ty" | "ident" | "meta" | "tt" | "" => true, "lifetime" => { - if !features.borrow().macro_lifetime_matcher && + if !features.macro_lifetime_matcher && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_LIFETIME_MATCHER; emit_feature_err(sess, @@ -904,7 +903,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess, true }, "vis" => { - if !features.borrow().macro_vis_matcher && + if !features.macro_vis_matcher && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_VIS_MATCHER; emit_feature_err(sess, diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index c9d7f78c2e303142016552176c26098c7da2738f..122bb9ba024a40c321e54a945da2ba0c9020a349 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -17,7 +17,6 @@ use syntax_pos::{BytePos, Span, DUMMY_SP}; use tokenstream; -use std::cell::RefCell; use std::iter::Peekable; use rustc_data_structures::sync::Lrc; @@ -183,7 +182,7 @@ pub fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> Vec { // Will contain the final collection of `self::TokenTree` @@ -251,7 +250,7 @@ fn parse_tree( trees: &mut Peekable, expect_matchers: bool, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> TokenTree where @@ -382,7 +381,7 @@ fn parse_sep_and_kleene_op( input: &mut Peekable, span: Span, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> (Option, KleeneOp) where @@ -415,7 +414,7 @@ fn parse_sep_and_kleene_op( match parse_kleene_op(input, span) { // #2 is a KleeneOp (this is the only valid option) :) Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -438,7 +437,7 @@ fn parse_sep_and_kleene_op( Err(span) => span, } } else { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -460,7 +459,7 @@ fn parse_sep_and_kleene_op( Ok(Err((tok, span))) => match parse_kleene_op(input, span) { // #2 is a KleeneOp :D Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -487,7 +486,7 @@ fn parse_sep_and_kleene_op( Err(span) => span, }; - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { sess.span_diagnostic diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 058df1d516909f9f8e48e6db56ca78c1d7bd629e..45d82bc7af38e824e40ca2d9d27d0c787ae690ca 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -62,6 +62,7 @@ fn f(features: &mut Features, _: Span) { &[$((stringify!($feature), $ver, $issue, set!($feature))),+]; /// A set of features to be used by later passes. + #[derive(Clone)] pub struct Features { /// `#![feature]` attrs for stable language features, for error reporting pub declared_stable_lang_features: Vec<(Symbol, Span)>, @@ -78,6 +79,12 @@ pub fn new() -> Features { $($feature: false),+ } } + + pub fn walk_feature_fields(&self, mut f: F) + where F: FnMut(&str, bool) + { + $(f(stringify!($feature), self.$feature);)+ + } } };