Turn features() into a query.
This commit is contained in:
parent
e2746d8700
commit
542bc75dea
@ -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
|
||||
@ -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
|
||||
@ -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>) },
|
||||
|
||||
@ -642,6 +643,7 @@ define_dep_nodes!( <'tcx>
|
||||
|
||||
[] GetSymbolExportLevel(DefId),
|
||||
|
||||
[input] Features,
|
||||
);
|
||||
|
||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
||||
|
@ -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());
|
||||
|
||||
@ -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,
|
||||
@ -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,
|
||||
@ -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",
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
@ -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 @@ 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();
|
||||
@ -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);
|
||||
@ -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] {
|
||||
@ -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,
|
||||
|
@ -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};
|
||||
@ -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.
|
||||
@ -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)
|
||||
@ -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
|
||||
/// 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
|
||||
@ -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
|
||||
@ -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)),
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use dep_graph::DepGraph;
|
||||
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::abi;
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.all_crate_nums(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
pub fn features(self) -> Lrc<feature_gate::Features> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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())
|
||||
};
|
||||
}
|
||||
|
@ -593,6 +593,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::fully_normalize_monormophic_ty<'t
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -52,6 +52,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
||||
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 @@ define_maps! { <'tcx>
|
||||
// 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<feature_gate::Features>,
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// 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 }
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -2335,7 +2335,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// 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)
|
||||
|
@ -276,7 +276,7 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
|
||||
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
|
||||
|
@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
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
|
||||
|
@ -212,7 +212,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
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)
|
||||
|
@ -398,7 +398,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}).collect::<Result<Vec<_>, _>>()?))))
|
||||
}
|
||||
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)?;
|
||||
|
@ -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);
|
||||
})
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ impl 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;
|
||||
}
|
||||
|
||||
|
@ -1356,7 +1356,7 @@ impl UnreachablePub {
|
||||
// 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)"
|
||||
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
||||
|
||||
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 {
|
||||
|
@ -146,7 +146,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
|
||||
"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(),
|
||||
|
@ -535,7 +535,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
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,
|
||||
|
@ -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 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
if !self.tcx.sess.two_phase_borrows() {
|
||||
if !self.tcx.two_phase_borrows() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1587,7 +1587,7 @@ impl MirPass for TypeckMir {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ impl<'tcx> CFG<'tcx> {
|
||||
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
|
||||
|
@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
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)
|
||||
}
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ impl MirPass for CleanEndRegions {
|
||||
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()
|
||||
|
@ -936,7 +936,7 @@ This does not pose a problem by itself because they can't be accessed directly."
|
||||
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) &&
|
||||
|
@ -514,7 +514,7 @@ impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -590,7 +590,7 @@ impl<'a> Resolver<'a> {
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -1524,7 +1524,7 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
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 =
|
||||
|
@ -744,7 +744,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
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 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -609,7 +609,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
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 {
|
||||
|
@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
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()
|
||||
|
@ -586,7 +586,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// 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)
|
||||
|
@ -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,
|
||||
|
@ -536,7 +536,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||
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(_, _) |
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -629,7 +629,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ use parse::token::Token::*;
|
||||
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<Features>, 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<Features>, def: &ast::Item)
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(sess: &ParseSess,
|
||||
features: &RefCell<Features>,
|
||||
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: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
matcher: &[quoted::TokenTree]) -> bool {
|
||||
let first_sets = FirstSets::new(matcher);
|
||||
@ -601,7 +600,7 @@ impl TokenSet {
|
||||
// Requires that `first_sets` is pre-computed for `matcher`;
|
||||
// see `FirstSets::new`.
|
||||
fn check_matcher_core(sess: &ParseSess,
|
||||
features: &RefCell<Features>,
|
||||
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<bool, (String, &'
|
||||
}
|
||||
|
||||
fn has_legal_fragment_specifier(sess: &ParseSess,
|
||||
features: &RefCell<Features>,
|
||||
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: &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,
|
||||
|
@ -17,7 +17,6 @@ use symbol::keywords;
|
||||
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: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
) -> Vec<TokenTree> {
|
||||
// Will contain the final collection of `self::TokenTree`
|
||||
@ -251,7 +250,7 @@ fn parse_tree<I>(
|
||||
trees: &mut Peekable<I>,
|
||||
expect_matchers: bool,
|
||||
sess: &ParseSess,
|
||||
features: &RefCell<Features>,
|
||||
features: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
) -> TokenTree
|
||||
where
|
||||
@ -382,7 +381,7 @@ fn parse_sep_and_kleene_op<I>(
|
||||
input: &mut Peekable<I>,
|
||||
span: Span,
|
||||
sess: &ParseSess,
|
||||
features: &RefCell<Features>,
|
||||
features: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
) -> (Option<token::Token>, KleeneOp)
|
||||
where
|
||||
@ -415,7 +414,7 @@ where
|
||||
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 @@ where
|
||||
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 @@ where
|
||||
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 @@ where
|
||||
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
|
||||
|
@ -62,6 +62,7 @@ macro_rules! declare_features {
|
||||
&[$((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 @@ macro_rules! declare_features {
|
||||
$($feature: false),+
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_feature_fields<F>(&self, mut f: F)
|
||||
where F: FnMut(&str, bool)
|
||||
{
|
||||
$(f(stringify!($feature), self.$feature);)+
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user