Skip to content

Commit f787bdd

Browse files
Turn features() into a query.
1 parent 4d2d3fc commit f787bdd

File tree

47 files changed

+202
-135
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+202
-135
lines changed

src/librustc/dep_graph/dep_node.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ impl DepKind {
436436
}
437437

438438
define_dep_nodes!( <'tcx>
439+
// We use this for most things when incr. comp. is turned off.
440+
[] Null,
441+
439442
// Represents the `Krate` as a whole (the `hir::Krate` value) (as
440443
// distinct from the krate module). This is basically a hash of
441444
// the entire krate, so if you read from `Krate` (e.g., by calling
@@ -605,8 +608,8 @@ define_dep_nodes!( <'tcx>
605608
[input] MissingExternCrateItem(CrateNum),
606609
[input] UsedCrateSource(CrateNum),
607610
[input] PostorderCnums,
608-
[input] HasCloneClosures(CrateNum),
609-
[input] HasCopyClosures(CrateNum),
611+
[] HasCloneClosures(CrateNum),
612+
[] HasCopyClosures(CrateNum),
610613

611614
// This query is not expected to have inputs -- as a result, it's
612615
// not a good candidate for "replay" because it's essentially a
@@ -630,8 +633,6 @@ define_dep_nodes!( <'tcx>
630633
[] CompileCodegenUnit(InternedString),
631634
[input] OutputFilenames,
632635
[anon] NormalizeTy,
633-
// We use this for most things when incr. comp. is turned off.
634-
[] Null,
635636

636637
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
637638

@@ -642,6 +643,7 @@ define_dep_nodes!( <'tcx>
642643

643644
[] GetSymbolExportLevel(DefId),
644645

646+
[input] Features,
645647
);
646648

647649
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {

src/librustc/hir/lowering.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ impl<'a> LoweringContext<'a> {
550550
{
551551
assert!(!self.is_collecting_in_band_lifetimes);
552552
assert!(self.lifetimes_to_define.is_empty());
553-
self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes;
553+
self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes;
554554

555555
assert!(self.in_band_ty_params.is_empty());
556556

@@ -957,7 +957,7 @@ impl<'a> LoweringContext<'a> {
957957
let span = t.span;
958958
match itctx {
959959
ImplTraitContext::Existential => {
960-
let has_feature = self.sess.features.borrow().conservative_impl_trait;
960+
let has_feature = self.sess.features_untracked().conservative_impl_trait;
961961
if !t.span.allows_unstable() && !has_feature {
962962
emit_feature_err(&self.sess.parse_sess, "conservative_impl_trait",
963963
t.span, GateIssue::Language,
@@ -981,7 +981,7 @@ impl<'a> LoweringContext<'a> {
981981
}, lifetimes)
982982
},
983983
ImplTraitContext::Universal(def_id) => {
984-
let has_feature = self.sess.features.borrow().universal_impl_trait;
984+
let has_feature = self.sess.features_untracked().universal_impl_trait;
985985
if !t.span.allows_unstable() && !has_feature {
986986
emit_feature_err(&self.sess.parse_sess, "universal_impl_trait",
987987
t.span, GateIssue::Language,

src/librustc/ich/impls_syntax.rs

+19
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::hash as std_hash;
1717
use std::mem;
1818

1919
use syntax::ast;
20+
use syntax::feature_gate;
2021
use syntax::parse::token;
2122
use syntax::symbol::InternedString;
2223
use syntax::tokenstream;
@@ -460,3 +461,21 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
460461

461462
(pos.0 - filemap_start.0, width as u32)
462463
}
464+
465+
466+
467+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
468+
fn hash_stable<W: StableHasherResult>(&self,
469+
hcx: &mut StableHashingContext<'gcx>,
470+
hasher: &mut StableHasher<W>) {
471+
// Unfortunately we cannot exhaustively list fields here, since the
472+
// struct is macro generated.
473+
self.declared_stable_lang_features.hash_stable(hcx, hasher);
474+
self.declared_lib_features.hash_stable(hcx, hasher);
475+
476+
self.walk_feature_fields(|feature_name, value| {
477+
feature_name.hash_stable(hcx, hasher);
478+
value.hash_stable(hcx, hasher);
479+
});
480+
}
481+
}

src/librustc/infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
262262
will_later_be_reported_by_nll: bool) {
263263
debug!("report_region_errors(): {} errors to start", errors.len());
264264

265-
if will_later_be_reported_by_nll && self.tcx.sess.nll() {
265+
if will_later_be_reported_by_nll && self.tcx.nll() {
266266
// With `#![feature(nll)]`, we want to present a nice user
267267
// experience, so don't even mention the errors from the
268268
// AST checker.
269-
if self.tcx.sess.features.borrow().nll {
269+
if self.tcx.features().nll {
270270
return;
271271
}
272272

src/librustc/middle/stability.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
131131
item_sp: Span, kind: AnnotationKind, visit_children: F)
132132
where F: FnOnce(&mut Self)
133133
{
134-
if self.tcx.sess.features.borrow().staged_api {
134+
if self.tcx.features().staged_api {
135135
// This crate explicitly wants staged API.
136136
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
137137
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
@@ -398,7 +398,7 @@ impl<'a, 'tcx> Index<'tcx> {
398398
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
399399
let is_staged_api =
400400
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked ||
401-
tcx.sess.features.borrow().staged_api;
401+
tcx.features().staged_api;
402402
let mut staged_api = FxHashMap();
403403
staged_api.insert(LOCAL_CRATE, is_staged_api);
404404
let mut index = Index {
@@ -408,7 +408,7 @@ impl<'a, 'tcx> Index<'tcx> {
408408
active_features: FxHashSet(),
409409
};
410410

411-
let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
411+
let ref active_lib_features = tcx.features().declared_lib_features;
412412

413413
// Put the active features into a map for quick lookup
414414
index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
@@ -677,7 +677,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
677677

678678
// There's no good place to insert stability check for non-Copy unions,
679679
// so semi-randomly perform it here in stability.rs
680-
hir::ItemUnion(..) if !self.tcx.sess.features.borrow().untagged_unions => {
680+
hir::ItemUnion(..) if !self.tcx.features().untagged_unions => {
681681
let def_id = self.tcx.hir.local_def_id(item.id);
682682
let adt_def = self.tcx.adt_def(def_id);
683683
let ty = self.tcx.type_of(def_id);
@@ -721,8 +721,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
721721
/// were expected to be library features), and the list of features used from
722722
/// libraries, identify activated features that don't exist and error about them.
723723
pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
724-
let sess = &tcx.sess;
725-
726724
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
727725

728726
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>) {
736734
krate.visit_all_item_likes(&mut missing.as_deep_visitor());
737735
}
738736

739-
let ref declared_lib_features = sess.features.borrow().declared_lib_features;
737+
let ref declared_lib_features = tcx.features().declared_lib_features;
740738
let mut remaining_lib_features: FxHashMap<Symbol, Span>
741739
= declared_lib_features.clone().into_iter().collect();
742740
remaining_lib_features.remove(&Symbol::intern("proc_macro"));
743741

744-
for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features {
742+
for &(ref stable_lang_feature, span) in &tcx.features().declared_stable_lang_features {
745743
let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str())
746744
.expect("unexpectedly couldn't find version feature was stabilized");
747745
tcx.lint_node(lint::builtin::STABLE_FEATURES,

src/librustc/session/mod.rs

+19-47
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use lint;
1919
use middle::allocator::AllocatorKind;
2020
use middle::dependency_format;
2121
use session::search_paths::PathKind;
22-
use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch};
22+
use session::config::{DebugInfoLevel, OutputType, Epoch};
2323
use ty::tls;
2424
use util::nodemap::{FxHashMap, FxHashSet};
2525
use util::common::{duration_to_secs_str, ErrorReported};
@@ -91,7 +91,8 @@ pub struct Session {
9191
/// multiple crates with the same name to coexist. See the
9292
/// trans::back::symbol_names module for more information.
9393
pub crate_disambiguator: RefCell<Option<CrateDisambiguator>>,
94-
pub features: RefCell<feature_gate::Features>,
94+
95+
features: RefCell<Option<feature_gate::Features>>,
9596

9697
/// The maximum recursion limit for potentially infinitely recursive
9798
/// operations such as auto-dereference and monomorphization.
@@ -192,6 +193,7 @@ impl Session {
192193
None => bug!("accessing disambiguator before initialization"),
193194
}
194195
}
196+
195197
pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
196198
sp: S,
197199
msg: &str)
@@ -443,16 +445,22 @@ impl Session {
443445
self.opts.debugging_opts.print_llvm_passes
444446
}
445447

446-
/// If true, we should use NLL-style region checking instead of
447-
/// lexical style.
448-
pub fn nll(&self) -> bool {
449-
self.features.borrow().nll || self.opts.debugging_opts.nll
448+
/// Get the features enabled for the current compilation session. Do not use
449+
/// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
450+
/// dependency tracking. Use tcx.features() instead.
451+
#[inline]
452+
pub fn features_untracked(&self) -> cell::Ref<feature_gate::Features> {
453+
let features = self.features.borrow();
454+
455+
if features.is_none() {
456+
bug!("Access to Session::features before it is initialized");
457+
}
458+
459+
cell::Ref::map(features, |r| r.as_ref().unwrap())
450460
}
451461

452-
/// If true, we should use the MIR-based borrowck (we may *also* use
453-
/// the AST-based borrowck).
454-
pub fn use_mir(&self) -> bool {
455-
self.borrowck_mode().use_mir()
462+
pub fn init_features(&self, features: feature_gate::Features) {
463+
*(self.features.borrow_mut()) = Some(features);
456464
}
457465

458466
/// If true, we should gather causal information during NLL
@@ -462,42 +470,6 @@ impl Session {
462470
self.opts.debugging_opts.nll_dump_cause
463471
}
464472

465-
/// If true, we should enable two-phase borrows checks. This is
466-
/// done with either `-Ztwo-phase-borrows` or with
467-
/// `#![feature(nll)]`.
468-
pub fn two_phase_borrows(&self) -> bool {
469-
self.features.borrow().nll || self.opts.debugging_opts.two_phase_borrows
470-
}
471-
472-
/// What mode(s) of borrowck should we run? AST? MIR? both?
473-
/// (Also considers the `#![feature(nll)]` setting.)
474-
pub fn borrowck_mode(&self) -> BorrowckMode {
475-
match self.opts.borrowck_mode {
476-
mode @ BorrowckMode::Mir |
477-
mode @ BorrowckMode::Compare => mode,
478-
479-
mode @ BorrowckMode::Ast => {
480-
if self.nll() {
481-
BorrowckMode::Mir
482-
} else {
483-
mode
484-
}
485-
}
486-
487-
}
488-
}
489-
490-
/// Should we emit EndRegion MIR statements? These are consumed by
491-
/// MIR borrowck, but not when NLL is used. They are also consumed
492-
/// by the validation stuff.
493-
pub fn emit_end_regions(&self) -> bool {
494-
// FIXME(#46875) -- we should not emit end regions when NLL is enabled,
495-
// but for now we can't stop doing so because it causes false positives
496-
self.opts.debugging_opts.emit_end_regions ||
497-
self.opts.debugging_opts.mir_emit_validate > 0 ||
498-
self.use_mir()
499-
}
500-
501473
/// Calculates the flavor of LTO to use for this compilation.
502474
pub fn lto(&self) -> config::Lto {
503475
// If our target has codegen requirements ignore the command line
@@ -1009,7 +981,7 @@ pub fn build_session_(sopts: config::Options,
1009981
crate_types: RefCell::new(Vec::new()),
1010982
dependency_formats: RefCell::new(FxHashMap()),
1011983
crate_disambiguator: RefCell::new(None),
1012-
features: RefCell::new(feature_gate::Features::new()),
984+
features: RefCell::new(None),
1013985
recursion_limit: Cell::new(64),
1014986
type_length_limit: Cell::new(1048576),
1015987
next_node_id: Cell::new(NodeId::new(1)),

src/librustc/traits/specialize/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
162162

163163
// The feature gate should prevent introducing new specializations, but not
164164
// taking advantage of upstream ones.
165-
if !tcx.sess.features.borrow().specialization &&
165+
if !tcx.features().specialization &&
166166
(impl1_def_id.is_local() || impl2_def_id.is_local()) {
167167
return false;
168168
}

src/librustc/ty/context.rs

+60-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use dep_graph::DepGraph;
1414
use dep_graph::{DepNode, DepConstructor};
1515
use errors::DiagnosticBuilder;
1616
use session::Session;
17-
use session::config::OutputFilenames;
17+
use session::config::{BorrowckMode, OutputFilenames};
1818
use middle;
1919
use hir::{TraitCandidate, HirId, ItemLocalId};
2020
use hir::def::{Def, Export};
@@ -71,6 +71,7 @@ use syntax::abi;
7171
use syntax::ast::{self, Name, NodeId};
7272
use syntax::attr;
7373
use syntax::codemap::MultiSpan;
74+
use syntax::feature_gate;
7475
use syntax::symbol::{Symbol, keywords};
7576
use syntax_pos::Span;
7677

@@ -1251,6 +1252,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12511252
self.stability_index(LOCAL_CRATE)
12521253
}
12531254

1255+
pub fn features(self) -> Rc<feature_gate::Features> {
1256+
self.features_query(LOCAL_CRATE)
1257+
}
1258+
12541259
pub fn crates(self) -> Rc<Vec<CrateNum>> {
12551260
self.all_crate_nums(LOCAL_CRATE)
12561261
}
@@ -1362,6 +1367,53 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
13621367
self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder)
13631368
}
13641369

1370+
/// If true, we should use NLL-style region checking instead of
1371+
/// lexical style.
1372+
pub fn nll(self) -> bool {
1373+
self.features().nll || self.sess.opts.debugging_opts.nll
1374+
}
1375+
1376+
/// If true, we should use the MIR-based borrowck (we may *also* use
1377+
/// the AST-based borrowck).
1378+
pub fn use_mir(self) -> bool {
1379+
self.borrowck_mode().use_mir()
1380+
}
1381+
1382+
/// If true, we should enable two-phase borrows checks. This is
1383+
/// done with either `-Ztwo-phase-borrows` or with
1384+
/// `#![feature(nll)]`.
1385+
pub fn two_phase_borrows(self) -> bool {
1386+
self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows
1387+
}
1388+
1389+
/// What mode(s) of borrowck should we run? AST? MIR? both?
1390+
/// (Also considers the `#![feature(nll)]` setting.)
1391+
pub fn borrowck_mode(&self) -> BorrowckMode {
1392+
match self.sess.opts.borrowck_mode {
1393+
mode @ BorrowckMode::Mir |
1394+
mode @ BorrowckMode::Compare => mode,
1395+
1396+
mode @ BorrowckMode::Ast => {
1397+
if self.nll() {
1398+
BorrowckMode::Mir
1399+
} else {
1400+
mode
1401+
}
1402+
}
1403+
1404+
}
1405+
}
1406+
1407+
/// Should we emit EndRegion MIR statements? These are consumed by
1408+
/// MIR borrowck, but not when NLL is used. They are also consumed
1409+
/// by the validation stuff.
1410+
pub fn emit_end_regions(self) -> bool {
1411+
// FIXME(#46875) -- we should not emit end regions when NLL is enabled,
1412+
// but for now we can't stop doing so because it causes false positives
1413+
self.sess.opts.debugging_opts.emit_end_regions ||
1414+
self.sess.opts.debugging_opts.mir_emit_validate > 0 ||
1415+
self.use_mir()
1416+
}
13651417
}
13661418

13671419
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
@@ -2020,7 +2072,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
20202072
}
20212073

20222074
pub fn mk_diverging_default(self) -> Ty<'tcx> {
2023-
if self.sess.features.borrow().never_type {
2075+
if self.features().never_type {
20242076
self.types.never
20252077
} else {
20262078
self.intern_tup(&[], true)
@@ -2395,13 +2447,17 @@ pub fn provide(providers: &mut ty::maps::Providers) {
23952447
};
23962448
providers.has_copy_closures = |tcx, cnum| {
23972449
assert_eq!(cnum, LOCAL_CRATE);
2398-
tcx.sess.features.borrow().copy_closures
2450+
tcx.features().copy_closures
23992451
};
24002452
providers.has_clone_closures = |tcx, cnum| {
24012453
assert_eq!(cnum, LOCAL_CRATE);
2402-
tcx.sess.features.borrow().clone_closures
2454+
tcx.features().clone_closures
24032455
};
24042456
providers.fully_normalize_monormophic_ty = |tcx, ty| {
24052457
tcx.fully_normalize_associated_types_in(&ty)
24062458
};
2459+
providers.features_query = |tcx, cnum| {
2460+
assert_eq!(cnum, LOCAL_CRATE);
2461+
Rc::new(tcx.sess.features_untracked().clone())
2462+
};
24072463
}

0 commit comments

Comments
 (0)