mirror of
https://github.com/rust-lang/rust
synced 2024-09-15 22:50:55 +00:00
Auto merge of #25785 - arielb1:cleanup-201505, r=eddyb
The caching essentially eliminates "stability checking" time (my attempt to clean-up junk got tangled up with stability, so I added the caching while I was at it). r? @eddyb
This commit is contained in:
commit
c654a07d29
|
@ -146,7 +146,7 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
|
|||
tag_table_closure_kinds = 0x65,
|
||||
tag_table_upvar_capture_map = 0x66,
|
||||
tag_table_capture_modes = 0x67,
|
||||
tag_table_object_cast_map = 0x68,
|
||||
// GAP 0x68
|
||||
tag_table_const_qualif = 0x69,
|
||||
tag_table_cast_kinds = 0x6a,
|
||||
}
|
||||
|
|
|
@ -297,15 +297,6 @@ pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
decoder::get_impl_trait(&*cdata, def.node, tcx)
|
||||
}
|
||||
|
||||
// Given a def_id for an impl, return information about its vtables
|
||||
pub fn get_impl_vtables<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def: ast::DefId)
|
||||
-> ty::vtable_res<'tcx> {
|
||||
let cstore = &tcx.sess.cstore;
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_impl_vtables(&*cdata, def.node, tcx)
|
||||
}
|
||||
|
||||
pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
|
||||
-> Vec<(cstore::NativeLibraryKind, String)> {
|
||||
let cdata = cstore.get_crate_data(crate_num);
|
||||
|
@ -389,6 +380,11 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: ast::DefId) -> bool {
|
|||
decoder::is_const_fn(&*cdata, did.node)
|
||||
}
|
||||
|
||||
pub fn is_impl(cstore: &cstore::CStore, did: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(did.krate);
|
||||
decoder::is_impl(&*cdata, did.node)
|
||||
}
|
||||
|
||||
pub fn get_stability(cstore: &cstore::CStore,
|
||||
def: ast::DefId)
|
||||
-> Option<attr::Stability> {
|
||||
|
@ -396,8 +392,8 @@ pub fn get_stability(cstore: &cstore::CStore,
|
|||
decoder::get_stability(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
|
||||
let cdata = cstore.get_crate_data(krate);
|
||||
let attrs = decoder::get_crate_attributes(cdata.data());
|
||||
for attr in &attrs {
|
||||
if &attr.name()[..] == "staged_api" {
|
||||
|
@ -414,11 +410,6 @@ pub fn get_repr_attrs(cstore: &cstore::CStore, def: ast::DefId)
|
|||
decoder::get_repr_attrs(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::is_associated_type(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(trait_def_id.krate);
|
||||
decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
use middle::subst;
|
||||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::astencode::vtable_decoder_helpers;
|
||||
use util::nodemap::FnvHashMap;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
@ -522,18 +521,6 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_impl_vtables<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> ty::vtable_res<'tcx>
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
|
||||
let mut decoder = reader::Decoder::new(vtables_doc);
|
||||
decoder.read_vtable_res(tcx, cdata)
|
||||
}
|
||||
|
||||
|
||||
pub fn get_symbol(data: &[u8], id: ast::NodeId) -> String {
|
||||
return item_symbol(lookup_item(id, data));
|
||||
}
|
||||
|
@ -1546,6 +1533,14 @@ pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
match item_family(item_doc) {
|
||||
Impl => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn doc_generics<'tcx>(base_doc: rbml::Doc,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
cdata: Cmd,
|
||||
|
@ -1623,14 +1618,6 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
|
|||
ty::GenericPredicates { predicates: predicates }
|
||||
}
|
||||
|
||||
pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
|
||||
match maybe_find_item(id, items) {
|
||||
None => false,
|
||||
Some(item) => item_sort(item) == Some('t'),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
|
||||
let trait_doc = lookup_item(trait_id, cdata.data());
|
||||
assert!(item_family(trait_doc) == Family::Trait);
|
||||
|
|
|
@ -999,7 +999,7 @@ fn encode_extension_implementations(ecx: &EncodeContext,
|
|||
});
|
||||
}
|
||||
|
||||
fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
|
||||
fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
|
||||
stab_opt.map(|stab| {
|
||||
rbml_w.start_tag(tag_items_data_item_stability);
|
||||
stab.encode(rbml_w).unwrap();
|
||||
|
@ -1215,11 +1215,11 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
|
|||
encode_name(rbml_w, item.ident.name);
|
||||
encode_unsafety(rbml_w, unsafety);
|
||||
|
||||
let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
|
||||
let trait_ref = ty::impl_trait_ref(tcx, local_def(item.id)).unwrap();
|
||||
encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
|
||||
ast::ItemImpl(unsafety, polarity, _, _, ref ty, ref ast_items) => {
|
||||
// We need to encode information about the default methods we
|
||||
// have inherited, so we drive this based on the impl structure.
|
||||
let impl_items = tcx.impl_items.borrow();
|
||||
|
@ -1269,8 +1269,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
|
|||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
if opt_trait.is_some() {
|
||||
let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
|
||||
if let Some(trait_ref) = ty::impl_trait_ref(tcx, local_def(item.id)) {
|
||||
encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
|
||||
}
|
||||
encode_path(rbml_w, path.clone());
|
||||
|
|
|
@ -696,19 +696,6 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
|
|||
pub trait vtable_decoder_helpers<'tcx> {
|
||||
fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
|
||||
F: FnMut(&mut Self) -> T;
|
||||
fn read_vtable_res_with_key(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
-> (u32, ty::vtable_res<'tcx>);
|
||||
fn read_vtable_res(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_res<'tcx>;
|
||||
fn read_vtable_param_res(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_param_res<'tcx>;
|
||||
fn read_vtable_origin(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_origin<'tcx>;
|
||||
}
|
||||
|
||||
impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
|
@ -720,85 +707,6 @@ fn read_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> wh
|
|||
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
||||
VecPerParamSpace::new(types, selfs, fns)
|
||||
}
|
||||
|
||||
fn read_vtable_res_with_key(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
-> (u32, ty::vtable_res<'tcx>) {
|
||||
self.read_struct("VtableWithKey", 2, |this| {
|
||||
let autoderef = this.read_struct_field("autoderef", 0, |this| {
|
||||
Decodable::decode(this)
|
||||
}).unwrap();
|
||||
Ok((autoderef, this.read_struct_field("vtable_res", 1, |this| {
|
||||
Ok(this.read_vtable_res(tcx, cdata))
|
||||
}).unwrap()))
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
fn read_vtable_res(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_res<'tcx>
|
||||
{
|
||||
self.read_vec_per_param_space(
|
||||
|this| this.read_vtable_param_res(tcx, cdata))
|
||||
}
|
||||
|
||||
fn read_vtable_param_res(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_param_res<'tcx> {
|
||||
self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
|
||||
.unwrap().into_iter().collect()
|
||||
}
|
||||
|
||||
fn read_vtable_origin(&mut self,
|
||||
tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
|
||||
-> ty::vtable_origin<'tcx> {
|
||||
self.read_enum("vtable_origin", |this| {
|
||||
this.read_enum_variant(&["vtable_static",
|
||||
"vtable_param",
|
||||
"vtable_error",
|
||||
"vtable_closure"],
|
||||
|this, i| {
|
||||
Ok(match i {
|
||||
0 => {
|
||||
ty::vtable_static(
|
||||
this.read_enum_variant_arg(0, |this| {
|
||||
Ok(this.read_def_id_nodcx(cdata))
|
||||
}).unwrap(),
|
||||
this.read_enum_variant_arg(1, |this| {
|
||||
Ok(this.read_substs_nodcx(tcx, cdata))
|
||||
}).unwrap(),
|
||||
this.read_enum_variant_arg(2, |this| {
|
||||
Ok(this.read_vtable_res(tcx, cdata))
|
||||
}).unwrap()
|
||||
)
|
||||
}
|
||||
1 => {
|
||||
ty::vtable_param(
|
||||
this.read_enum_variant_arg(0, |this| {
|
||||
Decodable::decode(this)
|
||||
}).unwrap(),
|
||||
this.read_enum_variant_arg(1, |this| {
|
||||
this.read_uint()
|
||||
}).unwrap()
|
||||
)
|
||||
}
|
||||
2 => {
|
||||
ty::vtable_closure(
|
||||
this.read_enum_variant_arg(0, |this| {
|
||||
Ok(this.read_def_id_nodcx(cdata))
|
||||
}).unwrap()
|
||||
)
|
||||
}
|
||||
3 => {
|
||||
ty::vtable_error
|
||||
}
|
||||
_ => panic!("bad enum variant")
|
||||
})
|
||||
})
|
||||
}).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
|
@ -1209,13 +1117,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
|||
})
|
||||
}
|
||||
|
||||
if let Some(trait_ref) = tcx.object_cast_map.borrow().get(&id) {
|
||||
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
|
||||
rbml_w.id(id);
|
||||
rbml_w.emit_trait_ref(ecx, &trait_ref.0);
|
||||
})
|
||||
}
|
||||
|
||||
if let Some(adjustment) = tcx.adjustments.borrow().get(&id) {
|
||||
match *adjustment {
|
||||
ty::AdjustDerefRef(ref adj) => {
|
||||
|
@ -1800,11 +1701,6 @@ fn decode_side_tables(dcx: &DecodeContext,
|
|||
};
|
||||
dcx.tcx.method_map.borrow_mut().insert(method_call, method);
|
||||
}
|
||||
c::tag_table_object_cast_map => {
|
||||
let trait_ref = val_dsr.read_poly_trait_ref(dcx);
|
||||
dcx.tcx.object_cast_map.borrow_mut()
|
||||
.insert(id, trait_ref);
|
||||
}
|
||||
c::tag_table_adjustments => {
|
||||
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
|
||||
dcx.tcx.adjustments.borrow_mut().insert(id, adj);
|
||||
|
|
|
@ -23,46 +23,47 @@
|
|||
use syntax::ast;
|
||||
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
|
||||
use syntax::ast::{Item, Generics, StructField};
|
||||
use syntax::ast_util::is_local;
|
||||
use syntax::ast_util::{is_local, local_def};
|
||||
use syntax::attr::{Stability, AttrMetaMethods};
|
||||
use syntax::visit::{FnKind, Visitor};
|
||||
use syntax::feature_gate::emit_feature_err;
|
||||
use util::nodemap::{NodeMap, DefIdMap, FnvHashSet, FnvHashMap};
|
||||
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use std::mem::replace;
|
||||
|
||||
/// A stability index, giving the stability level for items and methods.
|
||||
pub struct Index {
|
||||
// Indicates whether this crate has #![feature(staged_api)]
|
||||
staged_api: bool,
|
||||
// stability for crate-local items; unmarked stability == no entry
|
||||
local: NodeMap<Stability>,
|
||||
// cache for extern-crate items; unmarked stability == entry with None
|
||||
extern_cache: DefIdMap<Option<Stability>>
|
||||
pub struct Index<'tcx> {
|
||||
/// This is mostly a cache, except the stabilities of local items
|
||||
/// are filled by the annotator.
|
||||
map: DefIdMap<Option<&'tcx Stability>>,
|
||||
|
||||
/// Maps for each crate whether it is part of the staged API.
|
||||
staged_api: FnvHashMap<ast::CrateNum, bool>
|
||||
}
|
||||
|
||||
// A private tree-walker for producing an Index.
|
||||
struct Annotator<'a> {
|
||||
sess: &'a Session,
|
||||
index: &'a mut Index,
|
||||
parent: Option<Stability>,
|
||||
struct Annotator<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
index: &'a mut Index<'tcx>,
|
||||
parent: Option<&'tcx Stability>,
|
||||
export_map: &'a PublicItems,
|
||||
}
|
||||
|
||||
impl<'a> Annotator<'a> {
|
||||
impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||
// Determine the stability for a node based on its attributes and inherited
|
||||
// stability. The stability is recorded in the index and used as the parent.
|
||||
fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
|
||||
attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
|
||||
F: FnOnce(&mut Annotator),
|
||||
{
|
||||
if self.index.staged_api {
|
||||
if self.index.staged_api[&ast::LOCAL_CRATE] {
|
||||
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
|
||||
match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
|
||||
match attr::find_stability(self.tcx.sess.diagnostic(), attrs, item_sp) {
|
||||
Some(stab) => {
|
||||
debug!("annotate: found {:?}", stab);
|
||||
self.index.local.insert(id, stab.clone());
|
||||
let stab = self.tcx.intern_stability(stab);
|
||||
self.index.map.insert(local_def(id), Some(stab));
|
||||
|
||||
// Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
|
||||
if stab.level != attr::Stable {
|
||||
|
@ -77,13 +78,14 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
|
|||
debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
|
||||
use_parent, self.parent);
|
||||
if use_parent {
|
||||
if let Some(stab) = self.parent.clone() {
|
||||
self.index.local.insert(id, stab);
|
||||
} else if self.index.staged_api && required
|
||||
if let Some(stab) = self.parent {
|
||||
self.index.map.insert(local_def(id), Some(stab));
|
||||
} else if self.index.staged_api[&ast::LOCAL_CRATE] && required
|
||||
&& self.export_map.contains(&id)
|
||||
&& !self.sess.opts.test {
|
||||
self.sess.span_err(item_sp,
|
||||
"This node does not have a stability attribute");
|
||||
&& !self.tcx.sess.opts.test {
|
||||
self.tcx.sess.span_err(item_sp,
|
||||
"This node does not \
|
||||
have a stability attribute");
|
||||
}
|
||||
}
|
||||
f(self);
|
||||
|
@ -95,7 +97,7 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
|
|||
let tag = attr.name();
|
||||
if tag == "unstable" || tag == "stable" || tag == "deprecated" {
|
||||
attr::mark_used(attr);
|
||||
self.sess.span_err(attr.span(),
|
||||
self.tcx.sess.span_err(attr.span(),
|
||||
"stability attributes may not be used outside \
|
||||
of the standard library");
|
||||
}
|
||||
|
@ -105,7 +107,7 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'v> Visitor<'v> for Annotator<'a> {
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
|
||||
fn visit_item(&mut self, i: &Item) {
|
||||
// FIXME (#18969): the following is a hack around the fact
|
||||
// that we cannot currently annotate the stability of
|
||||
|
@ -168,11 +170,11 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index {
|
||||
impl<'tcx> Index<'tcx> {
|
||||
/// Construct the stability index for a crate being compiled.
|
||||
pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems) {
|
||||
pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, export_map: &PublicItems) {
|
||||
let mut annotator = Annotator {
|
||||
sess: sess,
|
||||
tcx: tcx,
|
||||
index: self,
|
||||
parent: None,
|
||||
export_map: export_map,
|
||||
|
@ -182,22 +184,23 @@ pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems)
|
|||
}
|
||||
|
||||
pub fn new(krate: &Crate) -> Index {
|
||||
let mut staged_api = false;
|
||||
let mut is_staged_api = false;
|
||||
for attr in &krate.attrs {
|
||||
if &attr.name()[..] == "staged_api" {
|
||||
match attr.node.value.node {
|
||||
ast::MetaWord(_) => {
|
||||
attr::mark_used(attr);
|
||||
staged_api = true;
|
||||
is_staged_api = true;
|
||||
}
|
||||
_ => (/*pass*/)
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut staged_api = FnvHashMap();
|
||||
staged_api.insert(ast::LOCAL_CRATE, is_staged_api);
|
||||
Index {
|
||||
staged_api: staged_api,
|
||||
local: NodeMap(),
|
||||
extern_cache: DefIdMap()
|
||||
map: DefIdMap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,13 +235,13 @@ struct Checker<'a, 'tcx: 'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||
fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<Stability>) {
|
||||
fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<&Stability>) {
|
||||
// Only the cross-crate scenario matters when checking unstable APIs
|
||||
let cross_crate = !is_local(id);
|
||||
if !cross_crate { return }
|
||||
|
||||
match *stab {
|
||||
Some(Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
|
||||
Some(&Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
|
||||
self.used_features.insert(feature.clone(), attr::Unstable);
|
||||
|
||||
if !self.active_features.contains(feature) {
|
||||
|
@ -252,7 +255,7 @@ fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<Stability>) {
|
|||
&feature, span, &msg);
|
||||
}
|
||||
}
|
||||
Some(Stability { level, ref feature, .. }) => {
|
||||
Some(&Stability { level, ref feature, .. }) => {
|
||||
self.used_features.insert(feature.clone(), level);
|
||||
|
||||
// Stable APIs are always ok to call and deprecated APIs are
|
||||
|
@ -312,7 +315,7 @@ fn visit_pat(&mut self, pat: &ast::Pat) {
|
|||
|
||||
/// Helper for discovering nodes to check for stability
|
||||
pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
|
||||
match item.node {
|
||||
ast::ItemExternCrate(_) => {
|
||||
// compiler-generated `extern crate` items have a dummy span.
|
||||
|
@ -349,7 +352,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
|
|||
|
||||
/// Helper for discovering nodes to check for stability
|
||||
pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
|
||||
let span;
|
||||
let id = match e.node {
|
||||
ast::ExprMethodCall(i, _, _) => {
|
||||
|
@ -458,7 +461,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
|
|||
}
|
||||
|
||||
pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
|
||||
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
|
||||
Some(def::DefPrimTy(..)) => {}
|
||||
Some(def) => {
|
||||
|
@ -470,7 +473,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
|
|||
}
|
||||
|
||||
pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
|
||||
debug!("check_pat(pat = {:?})", pat);
|
||||
if is_internal(tcx, pat.span) { return; }
|
||||
|
||||
|
@ -511,7 +514,7 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
|
|||
}
|
||||
|
||||
fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
|
||||
cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
|
||||
if !is_staged_api(tcx, id) { return }
|
||||
if is_internal(tcx, span) { return }
|
||||
let ref stability = lookup(tcx, id);
|
||||
|
@ -528,20 +531,27 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
|
|||
if trait_method_id != id => {
|
||||
is_staged_api(tcx, trait_method_id)
|
||||
}
|
||||
_ if is_local(id) => {
|
||||
tcx.stability.borrow().staged_api
|
||||
}
|
||||
_ => {
|
||||
csearch::is_staged_api(&tcx.sess.cstore, id)
|
||||
*tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
|
||||
|| csearch::is_staged_api(&tcx.sess.cstore, id.krate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lookup the stability for a node, loading external crate
|
||||
/// metadata as necessary.
|
||||
pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
|
||||
debug!("lookup(id={})",
|
||||
id.repr(tcx));
|
||||
pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||
if let Some(st) = tcx.stability.borrow().map.get(&id) {
|
||||
return *st;
|
||||
}
|
||||
|
||||
let st = lookup_uncached(tcx, id);
|
||||
tcx.stability.borrow_mut().map.insert(id, st);
|
||||
st
|
||||
}
|
||||
|
||||
fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||
debug!("lookup(id={})", id.repr(tcx));
|
||||
|
||||
// is this definition the implementation of a trait method?
|
||||
match ty::trait_item_of_item(tcx, id) {
|
||||
|
@ -553,25 +563,23 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
|
|||
}
|
||||
|
||||
let item_stab = if is_local(id) {
|
||||
tcx.stability.borrow().local.get(&id.node).cloned()
|
||||
None // The stability cache is filled partially lazily
|
||||
} else {
|
||||
let stab = csearch::get_stability(&tcx.sess.cstore, id);
|
||||
let mut index = tcx.stability.borrow_mut();
|
||||
(*index).extern_cache.insert(id, stab.clone());
|
||||
stab
|
||||
csearch::get_stability(&tcx.sess.cstore, id).map(|st| tcx.intern_stability(st))
|
||||
};
|
||||
|
||||
item_stab.or_else(|| {
|
||||
if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
|
||||
// FIXME (#18969): for the time being, simply use the
|
||||
// stability of the trait to determine the stability of any
|
||||
// unmarked impls for it. See FIXME above for more details.
|
||||
if ty::is_impl(tcx, id) {
|
||||
if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
|
||||
// FIXME (#18969): for the time being, simply use the
|
||||
// stability of the trait to determine the stability of any
|
||||
// unmarked impls for it. See FIXME above for more details.
|
||||
|
||||
debug!("lookup: trait_id={:?}", trait_id);
|
||||
lookup(tcx, trait_id)
|
||||
} else {
|
||||
None
|
||||
debug!("lookup: trait_id={:?}", trait_id);
|
||||
return lookup(tcx, trait_id);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
pub use self::BoundRegion::*;
|
||||
pub use self::sty::*;
|
||||
pub use self::IntVarValue::*;
|
||||
pub use self::vtable_origin::*;
|
||||
pub use self::MethodOrigin::*;
|
||||
pub use self::CopyImplementationError::*;
|
||||
|
||||
|
@ -402,12 +401,6 @@ pub enum CustomCoerceUnsized {
|
|||
Struct(usize)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Debug)]
|
||||
pub struct param_index {
|
||||
pub space: subst::ParamSpace,
|
||||
pub index: usize
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MethodOrigin<'tcx> {
|
||||
// fully statically resolved method
|
||||
|
@ -510,50 +503,6 @@ pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall {
|
|||
// of the method to be invoked
|
||||
pub type MethodMap<'tcx> = RefCell<FnvHashMap<MethodCall, MethodCallee<'tcx>>>;
|
||||
|
||||
pub type vtable_param_res<'tcx> = Vec<vtable_origin<'tcx>>;
|
||||
|
||||
// Resolutions for bounds of all parameters, left to right, for a given path.
|
||||
pub type vtable_res<'tcx> = VecPerParamSpace<vtable_param_res<'tcx>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum vtable_origin<'tcx> {
|
||||
/*
|
||||
Statically known vtable. def_id gives the impl item
|
||||
from whence comes the vtable, and tys are the type substs.
|
||||
vtable_res is the vtable itself.
|
||||
*/
|
||||
vtable_static(ast::DefId, subst::Substs<'tcx>, vtable_res<'tcx>),
|
||||
|
||||
/*
|
||||
Dynamic vtable, comes from a parameter that has a bound on it:
|
||||
fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
|
||||
vtable_param origin
|
||||
|
||||
The first argument is the param index (identifying T in the example),
|
||||
and the second is the bound number (identifying baz)
|
||||
*/
|
||||
vtable_param(param_index, usize),
|
||||
|
||||
/*
|
||||
Vtable automatically generated for a closure. The def ID is the
|
||||
ID of the closure expression.
|
||||
*/
|
||||
vtable_closure(ast::DefId),
|
||||
|
||||
/*
|
||||
Asked to determine the vtable for ty_err. This is the value used
|
||||
for the vtables of `Self` in a virtual call like `foo.bar()`
|
||||
where `foo` is of object type. The same value is also used when
|
||||
type errors occur.
|
||||
*/
|
||||
vtable_error,
|
||||
}
|
||||
|
||||
|
||||
// For every explicit cast into an object type, maps from the cast
|
||||
// expr to the associated trait ref.
|
||||
pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;
|
||||
|
||||
// Contains information needed to resolve types and (in the future) look up
|
||||
// the types of AST nodes.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -601,9 +550,10 @@ pub struct CtxtArenas<'tcx> {
|
|||
substs: TypedArena<Substs<'tcx>>,
|
||||
bare_fn: TypedArena<BareFnTy<'tcx>>,
|
||||
region: TypedArena<Region>,
|
||||
stability: TypedArena<attr::Stability>,
|
||||
|
||||
// references
|
||||
trait_defs: TypedArena<TraitDef<'tcx>>
|
||||
trait_defs: TypedArena<TraitDef<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtArenas<'tcx> {
|
||||
|
@ -613,6 +563,7 @@ pub fn new() -> CtxtArenas<'tcx> {
|
|||
substs: TypedArena::new(),
|
||||
bare_fn: TypedArena::new(),
|
||||
region: TypedArena::new(),
|
||||
stability: TypedArena::new(),
|
||||
|
||||
trait_defs: TypedArena::new()
|
||||
}
|
||||
|
@ -654,6 +605,7 @@ pub struct ctxt<'tcx> {
|
|||
substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
|
||||
bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
|
||||
region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
|
||||
stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
|
||||
|
||||
/// Common types, pre-interned for your convenience.
|
||||
pub types: CommonTypes<'tcx>,
|
||||
|
@ -692,9 +644,7 @@ pub struct ctxt<'tcx> {
|
|||
/// A cache for the trait_items() routine
|
||||
pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
|
||||
|
||||
pub impl_trait_cache: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
|
||||
|
||||
pub impl_trait_refs: RefCell<NodeMap<TraitRef<'tcx>>>,
|
||||
pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
|
||||
pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>,
|
||||
|
||||
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
|
||||
|
@ -709,15 +659,10 @@ pub struct ctxt<'tcx> {
|
|||
/// additional acyclicity requirements).
|
||||
pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
|
||||
|
||||
/// Maps from node-id of a trait object cast (like `foo as
|
||||
/// Box<Trait>`) to the trait reference.
|
||||
pub object_cast_map: ObjectCastMap<'tcx>,
|
||||
|
||||
pub map: ast_map::Map<'tcx>,
|
||||
pub freevars: RefCell<FreevarMap>,
|
||||
pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
|
||||
pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
|
||||
pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
|
||||
pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
|
||||
pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
|
||||
pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
|
||||
|
@ -801,10 +746,7 @@ pub struct ctxt<'tcx> {
|
|||
pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>,
|
||||
|
||||
/// Maps any item's def-id to its stability index.
|
||||
pub stability: RefCell<stability::Index>,
|
||||
|
||||
/// Maps def IDs to true if and only if they're associated types.
|
||||
pub associated_types: RefCell<DefIdMap<bool>>,
|
||||
pub stability: RefCell<stability::Index<'tcx>>,
|
||||
|
||||
/// Caches the results of trait selection. This cache is used
|
||||
/// for things that do not have to do with the parameters in scope.
|
||||
|
@ -847,6 +789,16 @@ pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> {
|
|||
interned
|
||||
}
|
||||
|
||||
pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
|
||||
if let Some(st) = self.stability_interner.borrow().get(&stab) {
|
||||
return st;
|
||||
}
|
||||
|
||||
let interned = self.arenas.stability.alloc(stab);
|
||||
self.stability_interner.borrow_mut().insert(interned, interned);
|
||||
interned
|
||||
}
|
||||
|
||||
pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
|
||||
self.free_region_maps.borrow_mut()
|
||||
.insert(id, map);
|
||||
|
@ -948,6 +900,7 @@ pub fn print_debug_stats(&self) {
|
|||
println!("Substs interner: #{}", self.substs_interner.borrow().len());
|
||||
println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
|
||||
println!("Region interner: #{}", self.region_interner.borrow().len());
|
||||
println!("Stability interner: #{}", self.stability_interner.borrow().len());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2753,7 +2706,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||
freevars: RefCell<FreevarMap>,
|
||||
region_maps: RegionMaps,
|
||||
lang_items: middle::lang_items::LanguageItems,
|
||||
stability: stability::Index) -> ctxt<'tcx>
|
||||
stability: stability::Index<'tcx>) -> ctxt<'tcx>
|
||||
{
|
||||
let mut interner = FnvHashMap();
|
||||
let common_types = CommonTypes::new(&arenas.type_, &mut interner);
|
||||
|
@ -2764,6 +2717,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||
substs_interner: RefCell::new(FnvHashMap()),
|
||||
bare_fn_interner: RefCell::new(FnvHashMap()),
|
||||
region_interner: RefCell::new(FnvHashMap()),
|
||||
stability_interner: RefCell::new(FnvHashMap()),
|
||||
types: common_types,
|
||||
named_region_map: named_region_map,
|
||||
region_maps: region_maps,
|
||||
|
@ -2774,23 +2728,20 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||
def_map: def_map,
|
||||
node_types: RefCell::new(FnvHashMap()),
|
||||
item_substs: RefCell::new(NodeMap()),
|
||||
impl_trait_refs: RefCell::new(NodeMap()),
|
||||
impl_trait_refs: RefCell::new(DefIdMap()),
|
||||
trait_defs: RefCell::new(DefIdMap()),
|
||||
predicates: RefCell::new(DefIdMap()),
|
||||
super_predicates: RefCell::new(DefIdMap()),
|
||||
object_cast_map: RefCell::new(NodeMap()),
|
||||
map: map,
|
||||
freevars: freevars,
|
||||
tcache: RefCell::new(DefIdMap()),
|
||||
rcache: RefCell::new(FnvHashMap()),
|
||||
short_names_cache: RefCell::new(FnvHashMap()),
|
||||
tc_cache: RefCell::new(FnvHashMap()),
|
||||
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
|
||||
enum_var_cache: RefCell::new(DefIdMap()),
|
||||
impl_or_trait_items: RefCell::new(DefIdMap()),
|
||||
trait_item_def_ids: RefCell::new(DefIdMap()),
|
||||
trait_items_cache: RefCell::new(DefIdMap()),
|
||||
impl_trait_cache: RefCell::new(DefIdMap()),
|
||||
ty_param_defs: RefCell::new(NodeMap()),
|
||||
adjustments: RefCell::new(NodeMap()),
|
||||
normalized_cache: RefCell::new(FnvHashMap()),
|
||||
|
@ -2816,7 +2767,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
|||
node_lint_levels: RefCell::new(FnvHashMap()),
|
||||
transmute_restrictions: RefCell::new(Vec::new()),
|
||||
stability: RefCell::new(stability),
|
||||
associated_types: RefCell::new(DefIdMap()),
|
||||
selection_cache: traits::SelectionCache::new(),
|
||||
repr_hint_cache: RefCell::new(DefIdMap()),
|
||||
type_impls_copy_cache: RefCell::new(HashMap::new()),
|
||||
|
@ -4305,17 +4255,9 @@ fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
|
|||
}
|
||||
|
||||
pub fn type_is_trait(ty: Ty) -> bool {
|
||||
type_trait_info(ty).is_some()
|
||||
}
|
||||
|
||||
pub fn type_trait_info<'tcx>(ty: Ty<'tcx>) -> Option<&'tcx TyTrait<'tcx>> {
|
||||
match ty.sty {
|
||||
ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match ty.sty {
|
||||
ty_trait(ref t) => Some(&**t),
|
||||
_ => None
|
||||
},
|
||||
ty_trait(ref t) => Some(&**t),
|
||||
_ => None
|
||||
ty_trait(..) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4506,16 +4448,6 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
|
||||
-> ty::TraitRef<'tcx> {
|
||||
match cx.impl_trait_refs.borrow().get(&id) {
|
||||
Some(ty) => *ty,
|
||||
None => cx.sess.bug(
|
||||
&format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
|
||||
cx.map.node_to_string(id)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
|
||||
match node_id_to_type_opt(cx, id) {
|
||||
Some(ty) => ty,
|
||||
|
@ -5310,12 +5242,12 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
|||
/// the future).
|
||||
fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
|
||||
def_id: ast::DefId,
|
||||
map: &mut DefIdMap<V>,
|
||||
map: &RefCell<DefIdMap<V>>,
|
||||
load_external: F) -> V where
|
||||
V: Clone,
|
||||
F: FnOnce() -> V,
|
||||
{
|
||||
match map.get(&def_id).cloned() {
|
||||
match map.borrow().get(&def_id).cloned() {
|
||||
Some(v) => { return v; }
|
||||
None => { }
|
||||
}
|
||||
|
@ -5324,7 +5256,7 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
|
|||
panic!("No def'n found for {:?} in tcx.{}", def_id, descr);
|
||||
}
|
||||
let v = load_external();
|
||||
map.insert(def_id, v.clone());
|
||||
map.borrow_mut().insert(def_id, v.clone());
|
||||
v
|
||||
}
|
||||
|
||||
|
@ -5390,33 +5322,9 @@ pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
|
|||
|
||||
pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||
-> ImplOrTraitItem<'tcx> {
|
||||
lookup_locally_or_in_crate_store("impl_or_trait_items",
|
||||
id,
|
||||
&mut *cx.impl_or_trait_items
|
||||
.borrow_mut(),
|
||||
|| {
|
||||
csearch::get_impl_or_trait_item(cx, id)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if the given ID refers to an associated type and false if it
|
||||
/// refers to anything else.
|
||||
pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
|
||||
memoized(&cx.associated_types, id, |id: ast::DefId| {
|
||||
if id.krate == ast::LOCAL_CRATE {
|
||||
match cx.impl_or_trait_items.borrow().get(&id) {
|
||||
Some(ref item) => {
|
||||
match **item {
|
||||
TypeTraitItem(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
} else {
|
||||
csearch::is_associated_type(&cx.sess.cstore, id)
|
||||
}
|
||||
})
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_or_trait_items", id, &cx.impl_or_trait_items,
|
||||
|| csearch::get_impl_or_trait_item(cx, id))
|
||||
}
|
||||
|
||||
/// Returns the parameter index that the given associated type corresponds to.
|
||||
|
@ -5434,34 +5342,33 @@ pub fn associated_type_parameter_index(cx: &ctxt,
|
|||
|
||||
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
||||
-> Rc<Vec<ImplOrTraitItemId>> {
|
||||
lookup_locally_or_in_crate_store("trait_item_def_ids",
|
||||
id,
|
||||
&mut *cx.trait_item_def_ids.borrow_mut(),
|
||||
|| {
|
||||
Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
|
||||
})
|
||||
lookup_locally_or_in_crate_store(
|
||||
"trait_item_def_ids", id, &cx.trait_item_def_ids,
|
||||
|| Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id)))
|
||||
}
|
||||
|
||||
/// Returns the trait-ref corresponding to a given impl, or None if it is
|
||||
/// an inherent impl.
|
||||
pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||
-> Option<TraitRef<'tcx>> {
|
||||
memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
|
||||
if id.krate == ast::LOCAL_CRATE {
|
||||
debug!("(impl_trait_ref) searching for trait impl {:?}", id);
|
||||
if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
|
||||
match item.node {
|
||||
ast::ItemImpl(_, _, _, Some(_), _, _) |
|
||||
ast::ItemDefaultImpl(..) => {
|
||||
Some(ty::impl_id_to_trait_ref(cx, id.node))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
-> Option<TraitRef<'tcx>>
|
||||
{
|
||||
lookup_locally_or_in_crate_store(
|
||||
"impl_trait_refs", id, &cx.impl_trait_refs,
|
||||
|| csearch::get_impl_trait(cx, id))
|
||||
}
|
||||
|
||||
/// Returns whether this DefId refers to an impl
|
||||
pub fn is_impl<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> bool {
|
||||
if id.krate == ast::LOCAL_CRATE {
|
||||
if let Some(ast_map::NodeItem(
|
||||
&ast::Item { node: ast::ItemImpl(..), .. })) = cx.map.find(id.node) {
|
||||
true
|
||||
} else {
|
||||
csearch::get_impl_trait(cx, id)
|
||||
false
|
||||
}
|
||||
})
|
||||
} else {
|
||||
csearch::is_impl(&cx.sess.cstore, id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
|
||||
|
@ -5944,37 +5851,35 @@ pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
|
|||
did: ast::DefId)
|
||||
-> TypeScheme<'tcx> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"tcache", did, &mut *cx.tcache.borrow_mut(),
|
||||
"tcache", did, &cx.tcache,
|
||||
|| csearch::get_type(cx, did))
|
||||
}
|
||||
|
||||
/// Given the did of a trait, returns its canonical trait ref.
|
||||
pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
|
||||
-> &'tcx TraitDef<'tcx> {
|
||||
memoized(&cx.trait_defs, did, |did: DefId| {
|
||||
assert!(did.krate != ast::LOCAL_CRATE);
|
||||
cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
|
||||
})
|
||||
lookup_locally_or_in_crate_store(
|
||||
"trait_defs", did, &cx.trait_defs,
|
||||
|| cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
|
||||
)
|
||||
}
|
||||
|
||||
/// Given the did of an item, returns its full set of predicates.
|
||||
pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
|
||||
-> GenericPredicates<'tcx>
|
||||
{
|
||||
memoized(&cx.predicates, did, |did: DefId| {
|
||||
assert!(did.krate != ast::LOCAL_CRATE);
|
||||
csearch::get_predicates(cx, did)
|
||||
})
|
||||
lookup_locally_or_in_crate_store(
|
||||
"predicates", did, &cx.predicates,
|
||||
|| csearch::get_predicates(cx, did))
|
||||
}
|
||||
|
||||
/// Given the did of a trait, returns its superpredicates.
|
||||
pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
|
||||
-> GenericPredicates<'tcx>
|
||||
{
|
||||
memoized(&cx.super_predicates, did, |did: DefId| {
|
||||
assert!(did.krate != ast::LOCAL_CRATE);
|
||||
csearch::get_super_predicates(cx, did)
|
||||
})
|
||||
lookup_locally_or_in_crate_store(
|
||||
"super_predicates", did, &cx.super_predicates,
|
||||
|| csearch::get_super_predicates(cx, did))
|
||||
}
|
||||
|
||||
pub fn predicates<'tcx>(
|
||||
|
@ -6344,7 +6249,7 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
|
|||
|
||||
pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
|
||||
lookup_locally_or_in_crate_store(
|
||||
"item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
|
||||
"item_variance_map", item_id, &tcx.item_variance_map,
|
||||
|| Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
|
||||
}
|
||||
|
||||
|
@ -7223,32 +7128,6 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for vtable_origin<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
match *self {
|
||||
vtable_static(def_id, ref tys, ref vtable_res) => {
|
||||
format!("vtable_static({:?}:{}, {}, {})",
|
||||
def_id,
|
||||
ty::item_path_str(tcx, def_id),
|
||||
tys.repr(tcx),
|
||||
vtable_res.repr(tcx))
|
||||
}
|
||||
|
||||
vtable_param(x, y) => {
|
||||
format!("vtable_param({:?}, {})", x, y)
|
||||
}
|
||||
|
||||
vtable_closure(def_id) => {
|
||||
format!("vtable_closure({:?})", def_id)
|
||||
}
|
||||
|
||||
vtable_error => {
|
||||
format!("vtable_error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
trait_ref: &ty::TraitRef<'tcx>,
|
||||
method: &ty::Method<'tcx>)
|
||||
|
|
|
@ -336,27 +336,6 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::MethodOrigin<'tc
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::vtable_origin<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::vtable_origin<'tcx> {
|
||||
match *self {
|
||||
ty::vtable_static(def_id, ref substs, ref origins) => {
|
||||
let r_substs = substs.fold_with(folder);
|
||||
let r_origins = origins.fold_with(folder);
|
||||
ty::vtable_static(def_id, r_substs, r_origins)
|
||||
}
|
||||
ty::vtable_param(n, b) => {
|
||||
ty::vtable_param(n, b)
|
||||
}
|
||||
ty::vtable_closure(def_id) => {
|
||||
ty::vtable_closure(def_id)
|
||||
}
|
||||
ty::vtable_error => {
|
||||
ty::vtable_error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
|
||||
*self
|
||||
|
|
|
@ -653,7 +653,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
|||
|
||||
// Do not move this check past lint
|
||||
time(time_passes, "stability index", (), |_|
|
||||
ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items));
|
||||
ty_cx.stability.borrow_mut().build(&ty_cx, krate, &public_items));
|
||||
|
||||
time(time_passes, "intrinsic checking", (), |_|
|
||||
middle::intrinsicck::check_crate(&ty_cx));
|
||||
|
|
|
@ -1798,20 +1798,21 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
|
|||
pub struct Stability;
|
||||
|
||||
impl Stability {
|
||||
fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
|
||||
fn lint(&self, cx: &Context, _id: ast::DefId,
|
||||
span: Span, stability: &Option<&attr::Stability>) {
|
||||
// Deprecated attributes apply in-crate and cross-crate.
|
||||
let (lint, label) = match *stability {
|
||||
Some(attr::Stability { deprecated_since: Some(_), .. }) =>
|
||||
Some(&attr::Stability { deprecated_since: Some(_), .. }) =>
|
||||
(DEPRECATED, "deprecated"),
|
||||
_ => return
|
||||
};
|
||||
|
||||
output(cx, span, stability, lint, label);
|
||||
|
||||
fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
|
||||
fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>,
|
||||
lint: &'static Lint, label: &'static str) {
|
||||
let msg = match *stability {
|
||||
Some(attr::Stability { reason: Some(ref s), .. }) => {
|
||||
Some(&attr::Stability { reason: Some(ref s), .. }) => {
|
||||
format!("use of {} item: {}", label, *s)
|
||||
}
|
||||
_ => format!("use of {} item", label)
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
||||
use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use middle::ty::liberate_late_bound_regions;
|
||||
use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
|
||||
use middle::ty::{MethodCall, MethodCallee, MethodMap};
|
||||
use middle::ty_fold::{TypeFolder, TypeFoldable};
|
||||
use rscope::RegionScope;
|
||||
use session::Session;
|
||||
|
@ -164,7 +164,6 @@ pub struct Inherited<'a, 'tcx: 'a> {
|
|||
upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
|
||||
closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
|
||||
closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
|
||||
object_cast_map: ObjectCastMap<'tcx>,
|
||||
|
||||
// A mapping from each fn's id to its signature, with all bound
|
||||
// regions replaced with free ones. Unlike the other tables, this
|
||||
|
@ -383,7 +382,6 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
|
|||
item_substs: RefCell::new(NodeMap()),
|
||||
adjustments: RefCell::new(NodeMap()),
|
||||
method_map: RefCell::new(FnvHashMap()),
|
||||
object_cast_map: RefCell::new(NodeMap()),
|
||||
upvar_capture_map: RefCell::new(FnvHashMap()),
|
||||
closure_tys: RefCell::new(DefIdMap()),
|
||||
closure_kinds: RefCell::new(DefIdMap()),
|
||||
|
|
|
@ -81,7 +81,8 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
|
|||
self.check_impl(item);
|
||||
}
|
||||
ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
|
||||
let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
|
||||
let trait_ref = ty::impl_trait_ref(ccx.tcx,
|
||||
local_def(item.id)).unwrap();
|
||||
ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
|
||||
match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
|
||||
Some(ty::BoundSend) | Some(ty::BoundSync) => {}
|
||||
|
|
|
@ -41,7 +41,6 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
|
|||
wbcx.visit_expr(e);
|
||||
wbcx.visit_upvar_borrow_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_object_cast_map();
|
||||
}
|
||||
|
||||
pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
|
||||
|
@ -62,7 +61,6 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
|
|||
}
|
||||
wbcx.visit_upvar_borrow_map();
|
||||
wbcx.visit_closures();
|
||||
wbcx.visit_object_cast_map();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -239,27 +237,6 @@ fn visit_closures(&self) {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_object_cast_map(&self) {
|
||||
if self.fcx.writeback_errors.get() {
|
||||
return
|
||||
}
|
||||
|
||||
for (&node_id, trait_ref) in self.fcx
|
||||
.inh
|
||||
.object_cast_map
|
||||
.borrow()
|
||||
.iter()
|
||||
{
|
||||
let span = ty::expr_span(self.tcx(), node_id);
|
||||
let reason = ResolvingExpr(span);
|
||||
let closure_ty = self.resolve(trait_ref, reason);
|
||||
self.tcx()
|
||||
.object_cast_map
|
||||
.borrow_mut()
|
||||
.insert(node_id, closure_ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
|
||||
// Resolve any borrowings for the node with id `id`
|
||||
self.visit_adjustments(reason, id);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
use std::rc::Rc;
|
||||
use syntax::ast::{Crate, DefId};
|
||||
use syntax::ast::{Item, ItemImpl};
|
||||
use syntax::ast::{LOCAL_CRATE, TraitRef};
|
||||
use syntax::ast::{LOCAL_CRATE};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map::NodeItem;
|
||||
use syntax::ast_map;
|
||||
|
@ -100,11 +100,8 @@ struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &Item) {
|
||||
|
||||
//debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
|
||||
|
||||
if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
|
||||
self.cc.check_implementation(item, opt_trait.as_ref())
|
||||
if let ItemImpl(..) = item.node {
|
||||
self.cc.check_implementation(item)
|
||||
}
|
||||
|
||||
visit::walk_item(self, item);
|
||||
|
@ -141,7 +138,7 @@ fn check(&self, krate: &Crate) {
|
|||
self.check_implementations_of_coerce_unsized();
|
||||
}
|
||||
|
||||
fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
|
||||
fn check_implementation(&self, item: &Item) {
|
||||
let tcx = self.crate_context.tcx;
|
||||
let impl_did = local_def(item.id);
|
||||
let self_type = ty::lookup_item_type(tcx, impl_did);
|
||||
|
@ -151,8 +148,8 @@ fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
|
|||
|
||||
let impl_items = self.create_impl_from_item(item);
|
||||
|
||||
if opt_trait.is_some() {
|
||||
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
|
||||
if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
|
||||
impl_did) {
|
||||
debug!("(checking implementation) adding impl for trait '{}', item '{}'",
|
||||
trait_ref.repr(self.crate_context.tcx),
|
||||
token::get_ident(item.ident));
|
||||
|
@ -161,22 +158,13 @@ fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
|
|||
item.span,
|
||||
trait_ref.def_id);
|
||||
self.add_trait_impl(trait_ref, impl_did);
|
||||
}
|
||||
|
||||
// Add the implementation to the mapping from implementation to base
|
||||
// type def ID, if there is a base type for this implementation and
|
||||
// the implementation does not have any associated traits.
|
||||
match get_base_type_def_id(&self.inference_context,
|
||||
item.span,
|
||||
self_type.ty) {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
Some(base_type_def_id) => {
|
||||
// FIXME: Gather up default methods?
|
||||
if opt_trait.is_none() {
|
||||
self.add_inherent_impl(base_type_def_id, impl_did);
|
||||
}
|
||||
} else {
|
||||
// Add the implementation to the mapping from implementation to base
|
||||
// type def ID, if there is a base type for this implementation and
|
||||
// the implementation does not have any associated traits.
|
||||
if let Some(base_type_def_id) = get_base_type_def_id(
|
||||
&self.inference_context, item.span, self_type.ty) {
|
||||
self.add_inherent_impl(base_type_def_id, impl_did);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +255,7 @@ fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId)
|
|||
// Converts an implementation in the AST to a vector of items.
|
||||
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
||||
match item.node {
|
||||
ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
|
||||
ItemImpl(_, _, _, _, _, ref impl_items) => {
|
||||
let mut items: Vec<ImplOrTraitItemId> =
|
||||
impl_items.iter().map(|impl_item| {
|
||||
match impl_item.node {
|
||||
|
@ -287,10 +275,8 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
|||
}
|
||||
}).collect();
|
||||
|
||||
if opt_trait.is_some() {
|
||||
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
|
||||
item.id);
|
||||
|
||||
if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
|
||||
local_def(item.id)) {
|
||||
self.instantiate_default_methods(local_def(item.id),
|
||||
&trait_ref,
|
||||
&mut items);
|
||||
|
@ -300,7 +286,8 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
|
|||
}
|
||||
_ => {
|
||||
self.crate_context.tcx.sess.span_bug(item.span,
|
||||
"can't convert a non-impl to an impl");
|
||||
"can't convert a non-impl \
|
||||
to an impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,8 +440,8 @@ fn check_implementations_of_coerce_unsized(&self) {
|
|||
}
|
||||
|
||||
let source = ty::lookup_item_type(tcx, impl_did).ty;
|
||||
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
|
||||
impl_did.node);
|
||||
let trait_ref = ty::impl_trait_ref(self.crate_context.tcx,
|
||||
impl_did).unwrap();
|
||||
let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
|
||||
debug!("check_implementations_of_coerce_unsized: {} -> {} (bound)",
|
||||
source.repr(tcx), target.repr(tcx));
|
||||
|
|
|
@ -820,7 +820,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
|
|||
|
||||
ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
|
||||
|
||||
tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
|
||||
tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
|
||||
}
|
||||
ast::ItemImpl(_, _,
|
||||
ref generics,
|
||||
|
@ -828,7 +828,6 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
|
|||
ref selfty,
|
||||
ref impl_items) => {
|
||||
// Create generics from the generics specified in the impl head.
|
||||
|
||||
debug!("convert: ast_generics={:?}", generics);
|
||||
let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
|
||||
let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
|
||||
|
@ -926,14 +925,16 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(ref ast_trait_ref) = *opt_trait_ref {
|
||||
let trait_ref =
|
||||
astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
|
||||
&ExplicitRscope,
|
||||
ast_trait_ref,
|
||||
Some(selfty));
|
||||
|
||||
tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
|
||||
if let &Some(ref ast_trait_ref) = opt_trait_ref {
|
||||
tcx.impl_trait_refs.borrow_mut().insert(
|
||||
local_def(it.id),
|
||||
Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
|
||||
&ExplicitRscope,
|
||||
ast_trait_ref,
|
||||
Some(selfty)))
|
||||
);
|
||||
} else {
|
||||
tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None);
|
||||
}
|
||||
|
||||
enforce_impl_params_are_constrained(tcx,
|
||||
|
|
|
@ -2695,6 +2695,21 @@ fn clean(&self, _: &DocContext) -> Stability {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Clean<Stability> for &'a attr::Stability {
|
||||
fn clean(&self, _: &DocContext) -> Stability {
|
||||
Stability {
|
||||
level: self.level,
|
||||
feature: self.feature.to_string(),
|
||||
since: self.since.as_ref().map_or("".to_string(),
|
||||
|interned| interned.to_string()),
|
||||
deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
|
||||
|istr| istr.to_string()),
|
||||
reason: self.reason.as_ref().map_or("".to_string(),
|
||||
|interned| interned.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
|
|
|
@ -61,7 +61,8 @@ pub fn new(cx: &'a core::DocContext<'tcx>,
|
|||
}
|
||||
|
||||
fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
|
||||
self.cx.tcx_opt().and_then(|tcx| stability::lookup(tcx, ast_util::local_def(id)))
|
||||
self.cx.tcx_opt().and_then(
|
||||
|tcx| stability::lookup(tcx, ast_util::local_def(id)).map(|x| x.clone()))
|
||||
}
|
||||
|
||||
pub fn visit(&mut self, krate: &ast::Crate) {
|
||||
|
|
|
@ -366,7 +366,7 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me
|
|||
}
|
||||
|
||||
/// Represents the #[deprecated] and friends attributes.
|
||||
#[derive(RustcEncodable,RustcDecodable,Clone,Debug)]
|
||||
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Stability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: InternedString,
|
||||
|
@ -378,7 +378,7 @@ pub struct Stability {
|
|||
}
|
||||
|
||||
/// The available stability levels.
|
||||
#[derive(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Debug,Copy)]
|
||||
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
|
||||
pub enum StabilityLevel {
|
||||
Unstable,
|
||||
Stable,
|
||||
|
|
Loading…
Reference in a new issue