Skip to content

Commit

Permalink
Auto merge of #48208 - michaelwoerister:track-features, r=petrochenkov
Browse files Browse the repository at this point in the history
Turn feature-gate table into a query so it is covered by dependency tracking.

Turn access to feature gates into a query so we handle them correctly during incremental compilation.

Features are still available via `Session` through `features_untracked()`. I wish we had a better way of hiding untracked information. It would be great if we could remove the `sess` field from `TyCtxt`.

Fixes #47003.
  • Loading branch information
bors committed Mar 5, 2018
2 parents e2746d8 + 93625f1 commit c933440
Show file tree
Hide file tree
Showing 51 changed files with 231 additions and 141 deletions.
10 changes: 6 additions & 4 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,9 @@ impl DepKind {
}

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
Expand Down Expand Up @@ -605,8 +608,8 @@ define_dep_nodes!( <'tcx>
[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
Expand All @@ -630,8 +633,6 @@ define_dep_nodes!( <'tcx>
[] 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>) },

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

[] GetSymbolExportLevel(DefId),

[input] Features,
);

trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ impl<'a> LoweringContext<'a> {
{
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());

Expand Down Expand Up @@ -964,7 +964,7 @@ impl<'a> LoweringContext<'a> {
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,
Expand All @@ -988,7 +988,7 @@ impl<'a> LoweringContext<'a> {
}, 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,
Expand Down Expand Up @@ -3713,7 +3713,7 @@ impl<'a> LoweringContext<'a> {
}

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",
Expand Down
19 changes: 19 additions & 0 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::hash as std_hash;
use std::mem;

use syntax::ast;
use syntax::feature_gate;
use syntax::parse::token;
use syntax::symbol::InternedString;
use syntax::tokenstream;
Expand Down Expand Up @@ -460,3 +461,21 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,

(pos.0 - filemap_start.0, width as u32)
}



impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
// 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);
});
}
}
4 changes: 2 additions & 2 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
) {
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;
}

Expand Down
14 changes: 6 additions & 8 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
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) {
Expand Down Expand Up @@ -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 {
Expand All @@ -408,7 +408,7 @@ impl<'a, '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();
Expand Down Expand Up @@ -677,7 +677,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {

// 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);
Expand Down Expand Up @@ -721,8 +721,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// 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] {
Expand All @@ -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<Symbol, Span>
= 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,
Expand Down
66 changes: 19 additions & 47 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics;
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};
Expand Down Expand Up @@ -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<Option<CrateDisambiguator>>,
pub features: RefCell<feature_gate::Features>,

features: RefCell<Option<feature_gate::Features>>,

/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
Expand Down Expand Up @@ -194,6 +195,7 @@ impl Session {
None => bug!("accessing disambiguator before initialization"),
}
}

pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
Expand Down Expand Up @@ -456,16 +458,22 @@ impl Session {
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 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<feature_gate::Features> {
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
Expand All @@ -475,42 +483,6 @@ impl Session {
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
Expand Down Expand Up @@ -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)),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit c933440

Please sign in to comment.