fn export_macros(&self, cnum: CrateNum);
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
- fn is_staged_api(&self, cnum: CrateNum) -> bool;
fn is_allocator(&self, cnum: CrateNum) -> bool;
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
{ bug!("lang_items") }
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
{ bug!("missing_lang_items") }
- fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
pub use self::StabilityLevel::*;
-use hir::map as hir_map;
use lint;
use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
use ty::{self, TyCtxt};
use middle::privacy::AccessLevels;
+use session::Session;
use syntax::symbol::Symbol;
use syntax_pos::{Span, DUMMY_SP};
use syntax::ast;
item_sp: Span, kind: AnnotationKind, visit_children: F)
where F: FnOnce(&mut Self)
{
- if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
+ if self.index.staged_api[&LOCAL_CRATE] {
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
parent_depr: None,
in_trait_impl: false,
};
+
+ // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+ // a parent stability annotation which indicates that this is private
+ // with the `rustc_private` feature. This is intended for use when
+ // compiling librustc crates themselves so we can leverage crates.io
+ // while maintaining the invariant that all sysroot crates are unstable
+ // by default and are unable to be used.
+ if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ let reason = "this crate is being loaded from the sysroot, and \
+ unstable location; did you mean to load this crate \
+ from crates.io via `Cargo.toml` instead?";
+ let stability = tcx.intern_stability(Stability {
+ level: attr::StabilityLevel::Unstable {
+ reason: Some(Symbol::intern(reason)),
+ issue: 27812,
+ },
+ feature: Symbol::intern("rustc_private"),
+ rustc_depr: None,
+ });
+ annotator.parent_stab = Some(stability);
+ }
+
annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required,
|v| intravisit::walk_crate(v, krate));
}
- pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
- let krate = hir_map.krate();
-
- let mut is_staged_api = false;
- for attr in &krate.attrs {
- if attr.path == "stable" || attr.path == "unstable" {
- is_staged_api = true;
- break
- }
- }
+ pub fn new(sess: &Session) -> Index<'tcx> {
+ let is_staged_api =
+ sess.opts.debugging_opts.force_unstable_if_unmarked ||
+ sess.features.borrow().staged_api;
let mut staged_api = FxHashMap();
staged_api.insert(LOCAL_CRATE, is_staged_api);
}
}
- let is_staged_api = *self.stability.borrow_mut().staged_api.entry(def_id.krate)
- .or_insert_with(|| self.sess.cstore.is_staged_api(def_id.krate));
+ let is_staged_api = self.lookup_stability(DefId {
+ index: CRATE_DEF_INDEX,
+ ..def_id
+ }).is_some();
if !is_staged_api {
return;
}
match stability {
Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
- if !self.stability.borrow().active_features.contains(feature) {
- let msg = match *reason {
- Some(ref r) => format!("use of unstable library feature '{}': {}",
- feature.as_str(), &r),
- None => format!("use of unstable library feature '{}'", &feature)
- };
- emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
- GateIssue::Library(Some(issue)), &msg);
+ if self.stability.borrow().active_features.contains(feature) {
+ return
}
+
+ // When we're compiling the compiler itself we may pull in
+ // crates from crates.io, but those crates may depend on other
+ // crates also pulled in from crates.io. We want to ideally be
+ // able to compile everything without requiring upstream
+ // modifications, so in the case that this looks like a
+ // rustc_private crate (e.g. a compiler crate) and we also have
+ // the `-Z force-unstable-if-unmarked` flag present (we're
+ // compiling a compiler crate), then let this missing feature
+ // annotation slide.
+ if *feature == "rustc_private" && issue == 27812 {
+ if self.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ return
+ }
+ }
+
+ let msg = match *reason {
+ Some(ref r) => format!("use of unstable library feature '{}': {}",
+ feature.as_str(), &r),
+ None => format!("use of unstable library feature '{}'", &feature)
+ };
+ emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
+ GateIssue::Library(Some(issue)), &msg);
}
Some(_) => {
// Stable APIs are always ok to call and deprecated APIs are
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
- if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
+ if tcx.stability.borrow().staged_api[&LOCAL_CRATE] {
let krate = tcx.hir.krate();
let mut missing = MissingStabilityAnnotations {
tcx: tcx,