auto merge of #16286 : pcwalton/rust/associated-items-groundwork, r=nikomatsakis
methods. This paves the way to associated items by introducing an extra level of abstraction ("impl-or-trait item") between traits/implementations and methods. This new abstraction is encoded in the metadata and used throughout the compiler where appropriate. There are no functional changes; this is purely a refactoring. r? @nick29581
This commit is contained in:
commit
a8c8e3f80f
@ -109,10 +109,14 @@ fn fold_foreign_mod(cx: &mut Context, nm: &ast::ForeignMod) -> ast::ForeignMod {
|
||||
|
||||
fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
|
||||
let item = match *item {
|
||||
ast::ItemImpl(ref a, ref b, c, ref methods) => {
|
||||
let methods = methods.iter().filter(|m| method_in_cfg(cx, &***m))
|
||||
.map(|x| *x).collect();
|
||||
ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
|
||||
ast::ItemImpl(ref a, ref b, c, ref impl_items) => {
|
||||
let impl_items = impl_items.iter()
|
||||
.filter(|ii| {
|
||||
impl_item_in_cfg(cx, &**ii)
|
||||
})
|
||||
.map(|x| *x)
|
||||
.collect();
|
||||
ast::ItemImpl((*a).clone(), (*b).clone(), c, impl_items)
|
||||
}
|
||||
ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
|
||||
let methods = methods.iter()
|
||||
@ -230,14 +234,16 @@ fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
|
||||
return (cx.in_cfg)(item.attrs.as_slice());
|
||||
}
|
||||
|
||||
fn method_in_cfg(cx: &mut Context, meth: &ast::Method) -> bool {
|
||||
return (cx.in_cfg)(meth.attrs.as_slice());
|
||||
fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
|
||||
match *meth {
|
||||
ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
ast::ProvidedMethod(meth) => (cx.in_cfg)(meth.attrs.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitMethod) -> bool {
|
||||
match *meth {
|
||||
ast::Required(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
ast::Provided(meth) => (cx.in_cfg)(meth.attrs.as_slice())
|
||||
fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(meth) => (cx.in_cfg)(meth.attrs.as_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,15 +801,19 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
|
||||
node: m.id
|
||||
};
|
||||
|
||||
match cx.tcx.methods.borrow().find_copy(&did) {
|
||||
match cx.tcx.impl_or_trait_items.borrow().find_copy(&did) {
|
||||
None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
|
||||
Some(md) => {
|
||||
match md.container {
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
match md {
|
||||
ty::MethodTraitItem(md) => {
|
||||
match md.container {
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1470,7 +1474,15 @@ impl LintPass for Stability {
|
||||
trait_id: trait_id,
|
||||
method_num: index,
|
||||
..
|
||||
}) => ty::trait_method(cx.tcx, trait_id, index).def_id
|
||||
}) => {
|
||||
match ty::trait_item(cx.tcx,
|
||||
trait_id,
|
||||
index) {
|
||||
ty::MethodTraitItem(method) => {
|
||||
method.def_id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => return
|
||||
|
@ -563,9 +563,9 @@ impl<'a> Visitor<()> for Context<'a> {
|
||||
visit::walk_generics(self, g, ());
|
||||
}
|
||||
|
||||
fn visit_trait_method(&mut self, m: &ast::TraitMethod, _: ()) {
|
||||
fn visit_trait_item(&mut self, m: &ast::TraitItem, _: ()) {
|
||||
run_lints!(self, check_trait_method, m);
|
||||
visit::walk_trait_method(self, m, ());
|
||||
visit::walk_trait_item(self, m, ());
|
||||
}
|
||||
|
||||
fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option<ast::Lifetime>, _: ()) {
|
||||
|
@ -141,7 +141,7 @@ pub trait LintPass {
|
||||
fn check_fn(&mut self, _: &Context,
|
||||
_: &FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
|
||||
fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { }
|
||||
fn check_trait_method(&mut self, _: &Context, _: &ast::TraitMethod) { }
|
||||
fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { }
|
||||
fn check_struct_def(&mut self, _: &Context,
|
||||
_: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
|
||||
fn check_struct_def_post(&mut self, _: &Context,
|
||||
|
@ -77,7 +77,7 @@ pub static tag_crate_dep_hash: uint = 0x1e;
|
||||
|
||||
pub static tag_mod_impl: uint = 0x1f;
|
||||
|
||||
pub static tag_item_trait_method: uint = 0x20;
|
||||
pub static tag_item_trait_item: uint = 0x20;
|
||||
|
||||
pub static tag_item_trait_ref: uint = 0x21;
|
||||
pub static tag_item_super_trait_ref: uint = 0x22;
|
||||
@ -95,14 +95,14 @@ pub static tag_item_field_origin: uint = 0x29;
|
||||
|
||||
pub static tag_item_variances: uint = 0x2a;
|
||||
/*
|
||||
trait items contain tag_item_trait_method elements,
|
||||
impl items contain tag_item_impl_method elements, and classes
|
||||
trait items contain tag_item_trait_item elements,
|
||||
impl items contain tag_item_impl_item elements, and classes
|
||||
have both. That's because some code treats classes like traits,
|
||||
and other code treats them like impls. Because classes can contain
|
||||
both, tag_item_trait_method and tag_item_impl_method have to be two
|
||||
both, tag_item_trait_item and tag_item_impl_item have to be two
|
||||
different tags.
|
||||
*/
|
||||
pub static tag_item_impl_method: uint = 0x30;
|
||||
pub static tag_item_impl_item: uint = 0x30;
|
||||
pub static tag_item_trait_method_explicit_self: uint = 0x31;
|
||||
|
||||
|
||||
@ -154,9 +154,11 @@ impl astencode_tag {
|
||||
}
|
||||
}
|
||||
|
||||
pub static tag_item_trait_method_sort: uint = 0x60;
|
||||
pub static tag_item_trait_item_sort: uint = 0x60;
|
||||
|
||||
pub static tag_item_impl_type_basename: uint = 0x61;
|
||||
pub static tag_item_trait_parent_sort: uint = 0x61;
|
||||
|
||||
pub static tag_item_impl_type_basename: uint = 0x62;
|
||||
|
||||
pub static tag_crate_triple: uint = 0x66;
|
||||
|
||||
|
@ -16,6 +16,7 @@ use metadata::common::*;
|
||||
use metadata::cstore;
|
||||
use metadata::decoder;
|
||||
use middle::lang_items;
|
||||
use middle::resolve;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use middle::subst::VecPerParamSpace;
|
||||
@ -121,30 +122,33 @@ pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
|
||||
}
|
||||
|
||||
/// Returns information about the given implementation.
|
||||
pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
|
||||
-> Vec<ast::DefId> {
|
||||
pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
let cdata = cstore.get_crate_data(impl_def_id.krate);
|
||||
decoder::get_impl_methods(&*cdata, impl_def_id.node)
|
||||
decoder::get_impl_items(&*cdata, impl_def_id.node)
|
||||
}
|
||||
|
||||
pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
|
||||
pub fn get_impl_or_trait_item(tcx: &ty::ctxt, def: ast::DefId)
|
||||
-> ty::ImplOrTraitItem {
|
||||
let cdata = tcx.sess.cstore.get_crate_data(def.krate);
|
||||
decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
|
||||
decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
|
||||
&*cdata,
|
||||
def.node,
|
||||
tcx)
|
||||
}
|
||||
|
||||
pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
|
||||
def: ast::DefId)
|
||||
-> (ast::Ident,
|
||||
ty::ExplicitSelfCategory)
|
||||
{
|
||||
pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
|
||||
-> (ast::Ident, resolve::TraitItemKind) {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
|
||||
decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
|
||||
&*cdata,
|
||||
def.node)
|
||||
}
|
||||
|
||||
pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
|
||||
def: ast::DefId) -> Vec<ast::DefId> {
|
||||
pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_trait_method_def_ids(&*cdata, def.node)
|
||||
decoder::get_trait_item_def_ids(&*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn get_item_variances(cstore: &cstore::CStore,
|
||||
@ -286,15 +290,15 @@ pub fn each_implementation_for_trait(cstore: &cstore::CStore,
|
||||
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
|
||||
}
|
||||
|
||||
/// If the given def ID describes a method belonging to a trait (either a
|
||||
/// If the given def ID describes an item belonging to a trait (either a
|
||||
/// default method or an implementation of a trait method), returns the ID of
|
||||
/// the trait that the method belongs to. Otherwise, returns `None`.
|
||||
pub fn get_trait_of_method(cstore: &cstore::CStore,
|
||||
def_id: ast::DefId,
|
||||
tcx: &ty::ctxt)
|
||||
-> Option<ast::DefId> {
|
||||
pub fn get_trait_of_item(cstore: &cstore::CStore,
|
||||
def_id: ast::DefId,
|
||||
tcx: &ty::ctxt)
|
||||
-> Option<ast::DefId> {
|
||||
let cdata = cstore.get_crate_data(def_id.krate);
|
||||
decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
|
||||
decoder::get_trait_of_item(&*cdata, def_id.node, tcx)
|
||||
}
|
||||
|
||||
pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
|
||||
|
@ -18,11 +18,12 @@ use metadata::common::*;
|
||||
use metadata::csearch::StaticMethodInfo;
|
||||
use metadata::csearch;
|
||||
use metadata::cstore;
|
||||
use metadata::tydecode::{parse_ty_data, parse_def_id,
|
||||
parse_type_param_def_data,
|
||||
parse_bare_fn_ty_data, parse_trait_ref_data};
|
||||
use middle::lang_items;
|
||||
use metadata::tydecode::{parse_ty_data, parse_def_id};
|
||||
use metadata::tydecode::{parse_type_param_def_data, parse_bare_fn_ty_data};
|
||||
use metadata::tydecode::{parse_trait_ref_data};
|
||||
use middle::def;
|
||||
use middle::lang_items;
|
||||
use middle::resolve::TraitItemKind;
|
||||
use middle::subst;
|
||||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty;
|
||||
@ -165,9 +166,9 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
|
||||
}
|
||||
}
|
||||
|
||||
fn item_method_sort(item: rbml::Doc) -> char {
|
||||
fn item_sort(item: rbml::Doc) -> char {
|
||||
let mut ret = 'r';
|
||||
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
|
||||
reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
|
||||
ret = doc.as_str_slice().as_bytes()[0] as char;
|
||||
false
|
||||
});
|
||||
@ -338,15 +339,18 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
|
||||
UnsafeFn => DlDef(def::DefFn(did, ast::UnsafeFn)),
|
||||
Fn => DlDef(def::DefFn(did, ast::NormalFn)),
|
||||
StaticMethod | UnsafeStaticMethod => {
|
||||
let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
|
||||
{ ast::NormalFn };
|
||||
let fn_style = if fam == UnsafeStaticMethod {
|
||||
ast::UnsafeFn
|
||||
} else {
|
||||
ast::NormalFn
|
||||
};
|
||||
// def_static_method carries an optional field of its enclosing
|
||||
// trait or enclosing impl (if this is an inherent static method).
|
||||
// So we need to detect whether this is in a trait or not, which
|
||||
// we do through the mildly hacky way of checking whether there is
|
||||
// a trait_method_sort.
|
||||
// a trait_parent_sort.
|
||||
let provenance = if reader::maybe_get_doc(
|
||||
item, tag_item_trait_method_sort).is_some() {
|
||||
item, tag_item_trait_parent_sort).is_some() {
|
||||
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
|
||||
item))
|
||||
} else {
|
||||
@ -536,14 +540,11 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
|
||||
None => {}
|
||||
Some(inherent_impl_doc) => {
|
||||
let _ = reader::tagged_docs(inherent_impl_doc,
|
||||
tag_item_impl_method,
|
||||
|impl_method_def_id_doc| {
|
||||
let impl_method_def_id =
|
||||
reader::with_doc_data(impl_method_def_id_doc,
|
||||
parse_def_id);
|
||||
let impl_method_def_id =
|
||||
translate_def_id(cdata, impl_method_def_id);
|
||||
match maybe_find_item(impl_method_def_id.node, items) {
|
||||
tag_item_impl_item,
|
||||
|impl_item_def_id_doc| {
|
||||
let impl_item_def_id = item_def_id(impl_item_def_id_doc,
|
||||
cdata);
|
||||
match maybe_find_item(impl_item_def_id.node, items) {
|
||||
None => {}
|
||||
Some(impl_method_doc) => {
|
||||
match item_family(impl_method_doc) {
|
||||
@ -554,7 +555,7 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
|
||||
item_name(&*intr, impl_method_doc);
|
||||
let static_method_def_like =
|
||||
item_to_def_like(impl_method_doc,
|
||||
impl_method_def_id,
|
||||
impl_item_def_id,
|
||||
cdata.cnum);
|
||||
callback(static_method_def_like,
|
||||
static_method_name,
|
||||
@ -752,33 +753,46 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns information about the given implementation.
|
||||
pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
|
||||
let mut methods = Vec::new();
|
||||
/// Returns the def IDs of all the items in the given implementation.
|
||||
pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
let mut impl_items = Vec::new();
|
||||
reader::tagged_docs(lookup_item(impl_id, cdata.data()),
|
||||
tag_item_impl_method, |doc| {
|
||||
let m_did = reader::with_doc_data(doc, parse_def_id);
|
||||
methods.push(translate_def_id(cdata, m_did));
|
||||
tag_item_impl_item, |doc| {
|
||||
let def_id = item_def_id(doc, cdata);
|
||||
match item_sort(doc) {
|
||||
'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
|
||||
_ => fail!("unknown impl item sort"),
|
||||
}
|
||||
true
|
||||
});
|
||||
|
||||
methods
|
||||
impl_items
|
||||
}
|
||||
|
||||
pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> (ast::Ident,
|
||||
ty::ExplicitSelfCategory) {
|
||||
let method_doc = lookup_item(id, cdata.data());
|
||||
let name = item_name(&*intr, method_doc);
|
||||
let explicit_self = get_explicit_self(method_doc);
|
||||
(name, explicit_self)
|
||||
pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> (ast::Ident, TraitItemKind) {
|
||||
let doc = lookup_item(id, cdata.data());
|
||||
let name = item_name(&*intr, doc);
|
||||
match item_sort(doc) {
|
||||
'r' | 'p' => {
|
||||
let explicit_self = get_explicit_self(doc);
|
||||
(name, TraitItemKind::from_explicit_self_category(explicit_self))
|
||||
}
|
||||
c => {
|
||||
fail!("get_trait_item_name_and_kind(): unknown trait item kind \
|
||||
in metadata: `{}`", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
|
||||
tcx: &ty::ctxt) -> ty::Method
|
||||
{
|
||||
pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt)
|
||||
-> ty::ImplOrTraitItem {
|
||||
let method_doc = lookup_item(id, cdata.data());
|
||||
let def_id = item_def_id(method_doc, cdata);
|
||||
|
||||
@ -791,36 +805,45 @@ pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
|
||||
};
|
||||
|
||||
let name = item_name(&*intr, method_doc);
|
||||
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
|
||||
tag_item_method_tps);
|
||||
let rp_defs = item_region_param_defs(method_doc, cdata);
|
||||
let fty = doc_method_fty(method_doc, tcx, cdata);
|
||||
let vis = item_visibility(method_doc);
|
||||
let explicit_self = get_explicit_self(method_doc);
|
||||
let provided_source = get_provided_source(method_doc, cdata);
|
||||
|
||||
ty::Method::new(
|
||||
name,
|
||||
ty::Generics {
|
||||
types: type_param_defs,
|
||||
regions: rp_defs,
|
||||
},
|
||||
fty,
|
||||
explicit_self,
|
||||
vis,
|
||||
def_id,
|
||||
container,
|
||||
provided_source
|
||||
)
|
||||
match item_sort(method_doc) {
|
||||
'r' | 'p' => {
|
||||
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
|
||||
tag_item_method_tps);
|
||||
let rp_defs = item_region_param_defs(method_doc, cdata);
|
||||
let fty = doc_method_fty(method_doc, tcx, cdata);
|
||||
let vis = item_visibility(method_doc);
|
||||
let explicit_self = get_explicit_self(method_doc);
|
||||
let provided_source = get_provided_source(method_doc, cdata);
|
||||
|
||||
let generics = ty::Generics {
|
||||
types: type_param_defs,
|
||||
regions: rp_defs,
|
||||
};
|
||||
ty::MethodTraitItem(Rc::new(ty::Method::new(name,
|
||||
generics,
|
||||
fty,
|
||||
explicit_self,
|
||||
vis,
|
||||
def_id,
|
||||
container,
|
||||
provided_source)))
|
||||
}
|
||||
_ => fail!("unknown impl/trait item sort"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trait_method_def_ids(cdata: Cmd,
|
||||
id: ast::NodeId) -> Vec<ast::DefId> {
|
||||
pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let mut result = Vec::new();
|
||||
reader::tagged_docs(item, tag_item_trait_method, |mth| {
|
||||
result.push(item_def_id(mth, cdata));
|
||||
reader::tagged_docs(item, tag_item_trait_item, |mth| {
|
||||
let def_id = item_def_id(mth, cdata);
|
||||
match item_sort(mth) {
|
||||
'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
|
||||
_ => fail!("unknown trait item sort"),
|
||||
}
|
||||
true
|
||||
});
|
||||
result
|
||||
@ -834,19 +857,29 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
|
||||
id: ast::NodeId, tcx: &ty::ctxt)
|
||||
pub fn get_provided_trait_methods(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt)
|
||||
-> Vec<Rc<ty::Method>> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let mut result = Vec::new();
|
||||
|
||||
reader::tagged_docs(item, tag_item_trait_method, |mth_id| {
|
||||
reader::tagged_docs(item, tag_item_trait_item, |mth_id| {
|
||||
let did = item_def_id(mth_id, cdata);
|
||||
let mth = lookup_item(did.node, data);
|
||||
|
||||
if item_method_sort(mth) == 'p' {
|
||||
result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
|
||||
if item_sort(mth) == 'p' {
|
||||
let trait_item = get_impl_or_trait_item(intr.clone(),
|
||||
cdata,
|
||||
did.node,
|
||||
tcx);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(ref method) => {
|
||||
result.push((*method).clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
@ -905,8 +938,8 @@ pub fn get_static_methods_if_impl(intr: Rc<IdentInterner>,
|
||||
if !ret { return None }
|
||||
|
||||
let mut impl_method_ids = Vec::new();
|
||||
reader::tagged_docs(item, tag_item_impl_method, |impl_method_doc| {
|
||||
impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id));
|
||||
reader::tagged_docs(item, tag_item_impl_item, |impl_method_doc| {
|
||||
impl_method_ids.push(item_def_id(impl_method_doc, cdata));
|
||||
true
|
||||
});
|
||||
|
||||
@ -1230,8 +1263,8 @@ pub fn each_implementation_for_trait(cdata: Cmd,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
|
||||
-> Option<ast::DefId> {
|
||||
pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
|
||||
-> Option<ast::DefId> {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let parent_item_id = match item_parent_item(item_doc) {
|
||||
None => return None,
|
||||
|
@ -54,13 +54,19 @@ use syntax;
|
||||
use rbml::writer;
|
||||
use rbml::io::SeekableMemWriter;
|
||||
|
||||
/// A borrowed version of ast::InlinedItem.
|
||||
/// A borrowed version of `ast::InlinedItem`.
|
||||
pub enum InlinedItemRef<'a> {
|
||||
IIItemRef(&'a ast::Item),
|
||||
IIMethodRef(ast::DefId, bool, &'a ast::Method),
|
||||
IITraitItemRef(ast::DefId, InlinedTraitItemRef<'a>),
|
||||
IIForeignRef(&'a ast::ForeignItem)
|
||||
}
|
||||
|
||||
/// A borrowed version of `ast::InlinedTraitItem`.
|
||||
pub enum InlinedTraitItemRef<'a> {
|
||||
ProvidedInlinedTraitItemRef(&'a Method),
|
||||
RequiredInlinedTraitItemRef(&'a Method),
|
||||
}
|
||||
|
||||
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
|
||||
|
||||
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
|
||||
@ -403,14 +409,24 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
exp: &middle::resolve::Export2)
|
||||
-> bool {
|
||||
let impl_methods = ecx.tcx.impl_methods.borrow();
|
||||
let impl_items = ecx.tcx.impl_items.borrow();
|
||||
match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
|
||||
Some(implementations) => {
|
||||
for base_impl_did in implementations.borrow().iter() {
|
||||
for &method_did in impl_methods.get(base_impl_did).iter() {
|
||||
let m = ty::method(ecx.tcx, method_did);
|
||||
if m.explicit_self == ty::StaticExplicitSelfCategory {
|
||||
encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
|
||||
for &method_did in impl_items.get(base_impl_did).iter() {
|
||||
let impl_item = ty::impl_or_trait_item(
|
||||
ecx.tcx,
|
||||
method_did.def_id());
|
||||
match impl_item {
|
||||
ty::MethodTraitItem(ref m) => {
|
||||
if m.explicit_self ==
|
||||
ty::StaticExplicitSelfCategory {
|
||||
encode_reexported_static_method(rbml_w,
|
||||
exp,
|
||||
m.def_id,
|
||||
m.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -425,11 +441,18 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
exp: &middle::resolve::Export2)
|
||||
-> bool {
|
||||
match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
|
||||
Some(methods) => {
|
||||
for m in methods.iter() {
|
||||
if m.explicit_self == ty::StaticExplicitSelfCategory {
|
||||
encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
|
||||
match ecx.tcx.trait_items_cache.borrow().find(&exp.def_id) {
|
||||
Some(trait_items) => {
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(ref m) if m.explicit_self ==
|
||||
ty::StaticExplicitSelfCategory => {
|
||||
encode_reexported_static_method(rbml_w,
|
||||
exp,
|
||||
m.def_id,
|
||||
m.ident);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,8 +698,14 @@ fn encode_explicit_self(rbml_w: &mut Encoder,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_method_sort(rbml_w: &mut Encoder, sort: char) {
|
||||
rbml_w.start_tag(tag_item_trait_method_sort);
|
||||
fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
|
||||
rbml_w.start_tag(tag_item_trait_item_sort);
|
||||
rbml_w.writer.write(&[ sort as u8 ]);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
|
||||
rbml_w.start_tag(tag_item_trait_parent_sort);
|
||||
rbml_w.writer.write(&[ sort as u8 ]);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
@ -799,6 +828,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
|
||||
|
||||
encode_method_ty_fields(ecx, rbml_w, m);
|
||||
encode_parent_item(rbml_w, local_def(parent_id));
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
|
||||
let stab = stability::lookup(ecx.tcx, m.def_id);
|
||||
encode_stability(rbml_w, stab);
|
||||
@ -819,9 +849,11 @@ fn encode_info_for_method(ecx: &EncodeContext,
|
||||
for &ast_method in ast_method_opt.iter() {
|
||||
let any_types = !pty.generics.types.is_empty();
|
||||
if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
|
||||
encode_inlined_item(ecx, rbml_w,
|
||||
IIMethodRef(local_def(parent_id), false,
|
||||
&*ast_method));
|
||||
encode_inlined_item(ecx,
|
||||
rbml_w,
|
||||
IITraitItemRef(local_def(parent_id),
|
||||
RequiredInlinedTraitItemRef(
|
||||
&*ast_method)));
|
||||
} else {
|
||||
encode_symbol(ecx, rbml_w, m.def_id.node);
|
||||
}
|
||||
@ -1106,11 +1138,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
|
||||
ItemImpl(_, ref opt_trait, 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_methods = tcx.impl_methods.borrow();
|
||||
let methods = impl_methods.get(&def_id);
|
||||
let impl_items = tcx.impl_items.borrow();
|
||||
let items = impl_items.get(&def_id);
|
||||
|
||||
add_to_index(item, rbml_w, index);
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
@ -1128,10 +1160,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
for &method_def_id in methods.iter() {
|
||||
rbml_w.start_tag(tag_item_impl_method);
|
||||
let s = def_to_string(method_def_id);
|
||||
rbml_w.writer.write(s.as_bytes());
|
||||
for &item_def_id in items.iter() {
|
||||
rbml_w.start_tag(tag_item_impl_item);
|
||||
match item_def_id {
|
||||
ty::MethodTraitItemId(item_def_id) => {
|
||||
encode_def_id(rbml_w, item_def_id);
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
}
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
for ast_trait_ref in opt_trait.iter() {
|
||||
@ -1145,27 +1181,46 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
encode_stability(rbml_w, stab);
|
||||
rbml_w.end_tag();
|
||||
|
||||
// Iterate down the methods, emitting them. We rely on the
|
||||
// assumption that all of the actually implemented methods
|
||||
// Iterate down the trait items, emitting them. We rely on the
|
||||
// assumption that all of the actually implemented trait items
|
||||
// appear first in the impl structure, in the same order they do
|
||||
// in the ast. This is a little sketchy.
|
||||
let num_implemented_methods = ast_methods.len();
|
||||
for (i, &method_def_id) in methods.iter().enumerate() {
|
||||
let ast_method = if i < num_implemented_methods {
|
||||
Some(*ast_methods.get(i))
|
||||
} else { None };
|
||||
let num_implemented_methods = ast_items.len();
|
||||
for (i, &trait_item_def_id) in items.iter().enumerate() {
|
||||
let ast_item = if i < num_implemented_methods {
|
||||
Some(*ast_items.get(i))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
index.push(entry {
|
||||
val: method_def_id.node as i64,
|
||||
val: trait_item_def_id.def_id().node as i64,
|
||||
pos: rbml_w.writer.tell().unwrap(),
|
||||
});
|
||||
encode_info_for_method(ecx,
|
||||
rbml_w,
|
||||
&*ty::method(tcx, method_def_id),
|
||||
path.clone(),
|
||||
false,
|
||||
item.id,
|
||||
ast_method)
|
||||
|
||||
let trait_item_type =
|
||||
ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
|
||||
match (trait_item_type, ast_item) {
|
||||
(ty::MethodTraitItem(method_type),
|
||||
Some(ast::MethodImplItem(ast_method))) => {
|
||||
encode_info_for_method(ecx,
|
||||
rbml_w,
|
||||
&*method_type,
|
||||
path.clone(),
|
||||
false,
|
||||
item.id,
|
||||
Some(ast_method))
|
||||
}
|
||||
(ty::MethodTraitItem(method_type), None) => {
|
||||
encode_info_for_method(ecx,
|
||||
rbml_w,
|
||||
&*method_type,
|
||||
path.clone(),
|
||||
false,
|
||||
item.id,
|
||||
None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemTrait(_, _, ref super_traits, ref ms) => {
|
||||
@ -1184,13 +1239,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
encode_attributes(rbml_w, item.attrs.as_slice());
|
||||
encode_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
|
||||
rbml_w.start_tag(tag_item_trait_method);
|
||||
encode_def_id(rbml_w, method_def_id);
|
||||
for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
|
||||
rbml_w.start_tag(tag_item_trait_item);
|
||||
match method_def_id {
|
||||
ty::MethodTraitItemId(method_def_id) => {
|
||||
encode_def_id(rbml_w, method_def_id);
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
}
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
|
||||
rbml_w.start_tag(tag_mod_child);
|
||||
rbml_w.wr_str(def_to_string(method_def_id).as_slice());
|
||||
rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice());
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
encode_path(rbml_w, path.clone());
|
||||
@ -1207,66 +1267,83 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
|
||||
rbml_w.end_tag();
|
||||
|
||||
// Now output the method info for each method.
|
||||
let r = ty::trait_method_def_ids(tcx, def_id);
|
||||
for (i, &method_def_id) in r.iter().enumerate() {
|
||||
assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
|
||||
|
||||
let method_ty = ty::method(tcx, method_def_id);
|
||||
// Now output the trait item info for each trait item.
|
||||
let r = ty::trait_item_def_ids(tcx, def_id);
|
||||
for (i, &item_def_id) in r.iter().enumerate() {
|
||||
assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
|
||||
|
||||
index.push(entry {
|
||||
val: method_def_id.node as i64,
|
||||
val: item_def_id.def_id().node as i64,
|
||||
pos: rbml_w.writer.tell().unwrap(),
|
||||
});
|
||||
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
|
||||
encode_method_ty_fields(ecx, rbml_w, &*method_ty);
|
||||
encode_parent_item(rbml_w, def_id);
|
||||
let trait_item_type =
|
||||
ty::impl_or_trait_item(tcx, item_def_id.def_id());
|
||||
match trait_item_type {
|
||||
ty::MethodTraitItem(method_ty) => {
|
||||
let method_def_id = item_def_id.def_id();
|
||||
|
||||
let stab = stability::lookup(tcx, method_def_id);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_method_ty_fields(ecx, rbml_w, &*method_ty);
|
||||
encode_parent_item(rbml_w, def_id);
|
||||
|
||||
let elem = ast_map::PathName(method_ty.ident.name);
|
||||
encode_path(rbml_w, path.clone().chain(Some(elem).move_iter()));
|
||||
let stab = stability::lookup(tcx, method_def_id);
|
||||
encode_stability(rbml_w, stab);
|
||||
|
||||
match method_ty.explicit_self {
|
||||
ty::StaticExplicitSelfCategory => {
|
||||
encode_family(rbml_w,
|
||||
fn_style_static_method_family(
|
||||
method_ty.fty.fn_style));
|
||||
let elem = ast_map::PathName(method_ty.ident.name);
|
||||
encode_path(rbml_w,
|
||||
path.clone().chain(Some(elem).move_iter()));
|
||||
|
||||
let pty = ty::lookup_item_type(tcx, method_def_id);
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
}
|
||||
match method_ty.explicit_self {
|
||||
ty::StaticExplicitSelfCategory => {
|
||||
encode_family(rbml_w,
|
||||
fn_style_static_method_family(
|
||||
method_ty.fty.fn_style));
|
||||
|
||||
_ => {
|
||||
encode_family(rbml_w,
|
||||
style_fn_family(
|
||||
method_ty.fty.fn_style));
|
||||
}
|
||||
}
|
||||
let pty = ty::lookup_item_type(tcx,
|
||||
method_def_id);
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
}
|
||||
|
||||
match ms.get(i) {
|
||||
&Required(ref tm) => {
|
||||
encode_attributes(rbml_w, tm.attrs.as_slice());
|
||||
encode_method_sort(rbml_w, 'r');
|
||||
encode_method_argument_names(rbml_w, &*tm.decl);
|
||||
}
|
||||
|
||||
&Provided(m) => {
|
||||
encode_attributes(rbml_w, m.attrs.as_slice());
|
||||
// If this is a static method, we've already encoded
|
||||
// this.
|
||||
if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
|
||||
// FIXME: I feel like there is something funny going on.
|
||||
let pty = ty::lookup_item_type(tcx, method_def_id);
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
_ => {
|
||||
encode_family(rbml_w,
|
||||
style_fn_family(
|
||||
method_ty.fty.fn_style));
|
||||
}
|
||||
}
|
||||
|
||||
match ms.get(i) {
|
||||
&RequiredMethod(ref tm) => {
|
||||
encode_attributes(rbml_w, tm.attrs.as_slice());
|
||||
encode_item_sort(rbml_w, 'r');
|
||||
encode_parent_sort(rbml_w, 't');
|
||||
encode_method_argument_names(rbml_w, &*tm.decl);
|
||||
}
|
||||
|
||||
&ProvidedMethod(m) => {
|
||||
encode_attributes(rbml_w, m.attrs.as_slice());
|
||||
// If this is a static method, we've already
|
||||
// encoded this.
|
||||
if method_ty.explicit_self !=
|
||||
ty::StaticExplicitSelfCategory {
|
||||
// FIXME: I feel like there is something funny
|
||||
// going on.
|
||||
let pty = ty::lookup_item_type(tcx, method_def_id);
|
||||
encode_bounds_and_type(rbml_w, ecx, &pty);
|
||||
}
|
||||
encode_item_sort(rbml_w, 'p');
|
||||
encode_parent_sort(rbml_w, 't');
|
||||
encode_inlined_item(
|
||||
ecx,
|
||||
rbml_w,
|
||||
IITraitItemRef(
|
||||
def_id,
|
||||
ProvidedInlinedTraitItemRef(&*m)));
|
||||
encode_method_argument_names(rbml_w,
|
||||
&*m.pe_fn_decl());
|
||||
}
|
||||
}
|
||||
encode_method_sort(rbml_w, 'p');
|
||||
encode_inlined_item(ecx, rbml_w,
|
||||
IIMethodRef(def_id, true, &*m));
|
||||
encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,8 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
|
||||
let id = match ii {
|
||||
e::IIItemRef(i) => i.id,
|
||||
e::IIForeignRef(i) => i.id,
|
||||
e::IIMethodRef(_, _, m) => m.id,
|
||||
e::IITraitItemRef(_, e::ProvidedInlinedTraitItemRef(m)) => m.id,
|
||||
e::IITraitItemRef(_, e::RequiredInlinedTraitItemRef(m)) => m.id,
|
||||
};
|
||||
debug!("> Encoding inlined item: {} ({})",
|
||||
ecx.tcx.map.path_to_string(id),
|
||||
@ -137,7 +138,12 @@ pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
|
||||
let ident = match ii {
|
||||
ast::IIItem(i) => i.ident,
|
||||
ast::IIForeign(i) => i.ident,
|
||||
ast::IIMethod(_, _, m) => m.pe_ident(),
|
||||
ast::IITraitItem(_, iti) => {
|
||||
match iti {
|
||||
ast::ProvidedInlinedTraitItem(m) => m.pe_ident(),
|
||||
ast::RequiredInlinedTraitItem(m) => m.pe_ident(),
|
||||
}
|
||||
}
|
||||
};
|
||||
debug!("Fn named: {}", token::get_ident(ident));
|
||||
debug!("< Decoded inlined fn: {}::{}",
|
||||
@ -344,12 +350,29 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
|
||||
|
||||
match ii {
|
||||
// HACK we're not dropping items.
|
||||
e::IIItemRef(i) => ast::IIItem(fold::noop_fold_item(i, &mut fld)
|
||||
.expect_one("expected one item")),
|
||||
e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)
|
||||
.expect_one(
|
||||
"noop_fold_method must produce exactly one method")),
|
||||
e::IIForeignRef(i) => ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
|
||||
e::IIItemRef(i) => {
|
||||
ast::IIItem(fold::noop_fold_item(i, &mut fld)
|
||||
.expect_one("expected one item"))
|
||||
}
|
||||
e::IITraitItemRef(d, iti) => {
|
||||
ast::IITraitItem(d, match iti {
|
||||
e::ProvidedInlinedTraitItemRef(m) => {
|
||||
ast::ProvidedInlinedTraitItem(
|
||||
fold::noop_fold_method(m, &mut fld)
|
||||
.expect_one("noop_fold_method must produce \
|
||||
exactly one method"))
|
||||
}
|
||||
e::RequiredInlinedTraitItemRef(m) => {
|
||||
ast::RequiredInlinedTraitItem(
|
||||
fold::noop_fold_method(m, &mut fld)
|
||||
.expect_one("noop_fold_method must produce \
|
||||
exactly one method"))
|
||||
}
|
||||
})
|
||||
}
|
||||
e::IIForeignRef(i) => {
|
||||
ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,9 +412,23 @@ fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
|
||||
ast::IIItem(i) => {
|
||||
ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
|
||||
}
|
||||
ast::IIMethod(d, is_provided, m) => {
|
||||
ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m)
|
||||
.expect_one("expected one method"))
|
||||
ast::IITraitItem(d, iti) => {
|
||||
match iti {
|
||||
ast::ProvidedInlinedTraitItem(m) => {
|
||||
ast::IITraitItem(
|
||||
xcx.tr_def_id(d),
|
||||
ast::ProvidedInlinedTraitItem(
|
||||
fld.fold_method(m)
|
||||
.expect_one("expected one method")))
|
||||
}
|
||||
ast::RequiredInlinedTraitItem(m) => {
|
||||
ast::IITraitItem(
|
||||
xcx.tr_def_id(d),
|
||||
ast::RequiredInlinedTraitItem(
|
||||
fld.fold_method(m)
|
||||
.expect_one("expected one method")))
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
|
||||
|
||||
match tcx.map.find(def_id.node) {
|
||||
Some(ast_map::NodeItem(..))
|
||||
| Some(ast_map::NodeMethod(..))
|
||||
| Some(ast_map::NodeImplItem(..))
|
||||
| Some(ast_map::NodeForeignItem(..))
|
||||
| Some(ast_map::NodeTraitMethod(..)) => true,
|
||||
| Some(ast_map::NodeTraitItem(..)) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
@ -114,9 +114,14 @@ impl<'a> MarkSymbolVisitor<'a> {
|
||||
method_num: index,
|
||||
..
|
||||
}) => {
|
||||
let def_id = ty::trait_method(self.tcx,
|
||||
trait_id, index).def_id;
|
||||
self.check_def_id(def_id);
|
||||
let trait_item = ty::trait_item(self.tcx,
|
||||
trait_id,
|
||||
index);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
self.check_def_id(method.def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,11 +213,15 @@ impl<'a> MarkSymbolVisitor<'a> {
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(trait_method) => {
|
||||
visit::walk_trait_method(self, &*trait_method, ctxt);
|
||||
ast_map::NodeTraitItem(trait_method) => {
|
||||
visit::walk_trait_item(self, &*trait_method, ctxt);
|
||||
}
|
||||
ast_map::NodeMethod(method) => {
|
||||
visit::walk_block(self, &*method.pe_body(), ctxt);
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
visit::walk_block(self, &*method.pe_body(), ctxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeForeignItem(foreign_item) => {
|
||||
visit::walk_foreign_item(self, &*foreign_item, ctxt);
|
||||
@ -316,9 +325,13 @@ impl Visitor<()> for LifeSeeder {
|
||||
self.worklist.push(item.id);
|
||||
}
|
||||
match item.node {
|
||||
ast::ItemImpl(_, Some(ref _trait_ref), _, ref methods) => {
|
||||
for method in methods.iter() {
|
||||
self.worklist.push(method.id);
|
||||
ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
self.worklist.push(method.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
@ -443,13 +456,14 @@ impl<'a> DeadVisitor<'a> {
|
||||
// This is done to handle the case where, for example, the static
|
||||
// method of a private type is used, but the type itself is never
|
||||
// called directly.
|
||||
let impl_methods = self.tcx.impl_methods.borrow();
|
||||
let impl_items = self.tcx.impl_items.borrow();
|
||||
match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
|
||||
None => (),
|
||||
Some(impl_list) => {
|
||||
for impl_did in impl_list.borrow().iter() {
|
||||
for method_did in impl_methods.get(impl_did).iter() {
|
||||
if self.live_symbols.contains(&method_did.node) {
|
||||
for item_did in impl_items.get(impl_did).iter() {
|
||||
if self.live_symbols.contains(&item_did.def_id()
|
||||
.node) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -516,12 +530,12 @@ impl<'a> Visitor<()> for DeadVisitor<'a> {
|
||||
}
|
||||
|
||||
// Overwrite so that we don't warn the trait method itself.
|
||||
fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
|
||||
fn visit_trait_item(&mut self, trait_method: &ast::TraitItem, _: ()) {
|
||||
match *trait_method {
|
||||
ast::Provided(ref method) => {
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
visit::walk_block(self, &*method.pe_body(), ())
|
||||
}
|
||||
ast::Required(_) => ()
|
||||
ast::RequiredMethod(_) => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,12 +131,14 @@ impl OverloadedCallType {
|
||||
fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
|
||||
-> OverloadedCallType {
|
||||
let method_descriptor =
|
||||
match tcx.methods.borrow_mut().find(&method_id) {
|
||||
match tcx.impl_or_trait_items.borrow_mut().find(&method_id) {
|
||||
Some(&ty::MethodTraitItem(ref method_descriptor)) => {
|
||||
(*method_descriptor).clone()
|
||||
}
|
||||
None => {
|
||||
tcx.sess.bug("overloaded call method wasn't in method \
|
||||
map")
|
||||
}
|
||||
Some(ref method_descriptor) => (*method_descriptor).clone(),
|
||||
};
|
||||
let impl_id = match method_descriptor.container {
|
||||
ty::TraitContainer(_) => {
|
||||
|
@ -83,8 +83,8 @@ impl Visitor<()> for ParentVisitor {
|
||||
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
|
||||
for m in methods.iter() {
|
||||
match *m {
|
||||
ast::Provided(ref m) => self.parents.insert(m.id, item.id),
|
||||
ast::Required(ref m) => self.parents.insert(m.id, item.id),
|
||||
ast::ProvidedMethod(ref m) => self.parents.insert(m.id, item.id),
|
||||
ast::RequiredMethod(ref m) => self.parents.insert(m.id, item.id),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -240,7 +240,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||
// undefined symbols at linkage time if this case is not handled.
|
||||
//
|
||||
// * Private trait impls for private types can be completely ignored
|
||||
ast::ItemImpl(_, _, ref ty, ref methods) => {
|
||||
ast::ItemImpl(_, _, ref ty, ref impl_items) => {
|
||||
let public_ty = match ty.node {
|
||||
ast::TyPath(_, _, id) => {
|
||||
match self.tcx.def_map.borrow().get_copy(&id) {
|
||||
@ -261,13 +261,18 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||
});
|
||||
|
||||
if public_ty || public_trait {
|
||||
for method in methods.iter() {
|
||||
let meth_public = match method.pe_explicit_self().node {
|
||||
ast::SelfStatic => public_ty,
|
||||
_ => true,
|
||||
} && method.pe_vis() == ast::Public;
|
||||
if meth_public || tr.is_some() {
|
||||
self.exported_items.insert(method.id);
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
let meth_public =
|
||||
match method.pe_explicit_self().node {
|
||||
ast::SelfStatic => public_ty,
|
||||
_ => true,
|
||||
} && method.pe_vis() == ast::Public;
|
||||
if meth_public || tr.is_some() {
|
||||
self.exported_items.insert(method.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,11 +283,11 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||
ast::ItemTrait(_, _, _, ref methods) if public_first => {
|
||||
for method in methods.iter() {
|
||||
match *method {
|
||||
ast::Provided(ref m) => {
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
debug!("provided {}", m.id);
|
||||
self.exported_items.insert(m.id);
|
||||
}
|
||||
ast::Required(ref m) => {
|
||||
ast::RequiredMethod(ref m) => {
|
||||
debug!("required {}", m.id);
|
||||
self.exported_items.insert(m.id);
|
||||
}
|
||||
@ -387,9 +392,10 @@ impl<'a> PrivacyVisitor<'a> {
|
||||
}
|
||||
debug!("privacy - is {:?} a public method", did);
|
||||
|
||||
return match self.tcx.methods.borrow().find(&did) {
|
||||
Some(meth) => {
|
||||
debug!("privacy - well at least it's a method: {:?}", meth);
|
||||
return match self.tcx.impl_or_trait_items.borrow().find(&did) {
|
||||
Some(&ty::MethodTraitItem(ref meth)) => {
|
||||
debug!("privacy - well at least it's a method: {:?}",
|
||||
*meth);
|
||||
match meth.container {
|
||||
ty::TraitContainer(id) => {
|
||||
debug!("privacy - recursing on trait {:?}", id);
|
||||
@ -451,15 +457,23 @@ impl<'a> PrivacyVisitor<'a> {
|
||||
// invocation.
|
||||
// FIXME(#10573) is this the right behavior? Why not consider
|
||||
// where the method was defined?
|
||||
Some(ast_map::NodeMethod(ref m)) => {
|
||||
let imp = self.tcx.map.get_parent_did(closest_private_id);
|
||||
match ty::impl_trait_ref(self.tcx, imp) {
|
||||
Some(..) => return Allowable,
|
||||
_ if m.pe_vis() == ast::Public => return Allowable,
|
||||
_ => m.pe_vis()
|
||||
Some(ast_map::NodeImplItem(ref ii)) => {
|
||||
match **ii {
|
||||
ast::MethodImplItem(m) => {
|
||||
let imp = self.tcx
|
||||
.map
|
||||
.get_parent_did(closest_private_id);
|
||||
match ty::impl_trait_ref(self.tcx, imp) {
|
||||
Some(..) => return Allowable,
|
||||
_ if m.pe_vis() == ast::Public => {
|
||||
return Allowable
|
||||
}
|
||||
_ => m.pe_vis()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitMethod(_)) => {
|
||||
Some(ast_map::NodeTraitItem(_)) => {
|
||||
return Allowable;
|
||||
}
|
||||
|
||||
@ -648,12 +662,17 @@ impl<'a> PrivacyVisitor<'a> {
|
||||
}
|
||||
|
||||
// Given the ID of a method, checks to ensure it's in scope.
|
||||
fn check_static_method(&mut self, span: Span, method_id: ast::DefId,
|
||||
fn check_static_method(&mut self,
|
||||
span: Span,
|
||||
method_id: ast::DefId,
|
||||
name: ast::Ident) {
|
||||
// If the method is a default method, we need to use the def_id of
|
||||
// the default implementation.
|
||||
let method_id = ty::method(self.tcx, method_id).provided_source
|
||||
.unwrap_or(method_id);
|
||||
let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
|
||||
ty::MethodTraitItem(method_type) => {
|
||||
method_type.provided_source.unwrap_or(method_id)
|
||||
}
|
||||
};
|
||||
|
||||
let string = token::get_ident(name);
|
||||
self.report_error(self.ensure_public(span,
|
||||
@ -1075,12 +1094,16 @@ impl<'a> SanePrivacyVisitor<'a> {
|
||||
match item.node {
|
||||
// implementations of traits don't need visibility qualifiers because
|
||||
// that's controlled by having the trait in scope.
|
||||
ast::ItemImpl(_, Some(..), _, ref methods) => {
|
||||
ast::ItemImpl(_, Some(..), _, ref impl_items) => {
|
||||
check_inherited(item.span, item.vis,
|
||||
"visibility qualifiers have no effect on trait \
|
||||
impls");
|
||||
for m in methods.iter() {
|
||||
check_inherited(m.span, m.pe_vis(), "");
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(m) => {
|
||||
check_inherited(m.span, m.pe_vis(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1111,11 +1134,11 @@ impl<'a> SanePrivacyVisitor<'a> {
|
||||
ast::ItemTrait(_, _, _, ref methods) => {
|
||||
for m in methods.iter() {
|
||||
match *m {
|
||||
ast::Provided(ref m) => {
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
check_inherited(m.span, m.pe_vis(),
|
||||
"unnecessary visibility");
|
||||
}
|
||||
ast::Required(ref m) => {
|
||||
ast::RequiredMethod(ref m) => {
|
||||
check_inherited(m.span, m.vis,
|
||||
"unnecessary visibility");
|
||||
}
|
||||
@ -1148,9 +1171,13 @@ impl<'a> SanePrivacyVisitor<'a> {
|
||||
};
|
||||
check_inherited(tcx, item.span, item.vis);
|
||||
match item.node {
|
||||
ast::ItemImpl(_, _, _, ref methods) => {
|
||||
for m in methods.iter() {
|
||||
check_inherited(tcx, m.span, m.pe_vis());
|
||||
ast::ItemImpl(_, _, _, ref impl_items) => {
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(m) => {
|
||||
check_inherited(tcx, m.span, m.pe_vis());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ItemForeignMod(ref fm) => {
|
||||
@ -1174,8 +1201,8 @@ impl<'a> SanePrivacyVisitor<'a> {
|
||||
ast::ItemTrait(_, _, _, ref methods) => {
|
||||
for m in methods.iter() {
|
||||
match *m {
|
||||
ast::Required(..) => {}
|
||||
ast::Provided(ref m) => check_inherited(tcx, m.span,
|
||||
ast::RequiredMethod(..) => {}
|
||||
ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
|
||||
m.pe_vis()),
|
||||
}
|
||||
}
|
||||
@ -1270,7 +1297,7 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
|
||||
// (i.e. we could just return here to not check them at
|
||||
// all, or some worse estimation of whether an impl is
|
||||
// publicly visible.
|
||||
ast::ItemImpl(ref g, ref trait_ref, self_, ref methods) => {
|
||||
ast::ItemImpl(ref g, ref trait_ref, self_, ref impl_items) => {
|
||||
// `impl [... for] Private` is never visible.
|
||||
let self_contains_private;
|
||||
// impl [... for] Public<...>, but not `impl [... for]
|
||||
@ -1311,7 +1338,14 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
|
||||
// are private (because `T` won't be visible externally).
|
||||
let trait_or_some_public_method =
|
||||
trait_ref.is_some() ||
|
||||
methods.iter().any(|m| self.exported_items.contains(&m.id));
|
||||
impl_items.iter()
|
||||
.any(|impl_item| {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(m) => {
|
||||
self.exported_items.contains(&m.id)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if !self_contains_private &&
|
||||
not_private_trait &&
|
||||
@ -1321,8 +1355,14 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
|
||||
|
||||
match *trait_ref {
|
||||
None => {
|
||||
for method in methods.iter() {
|
||||
visit::walk_method_helper(self, &**method, ())
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
visit::walk_method_helper(self,
|
||||
&*method,
|
||||
())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ref tr) => {
|
||||
@ -1345,11 +1385,19 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
|
||||
// impl Public<Private> { ... }. Any public static
|
||||
// methods will be visible as `Public::foo`.
|
||||
let mut found_pub_static = false;
|
||||
for method in methods.iter() {
|
||||
if method.pe_explicit_self().node == ast::SelfStatic &&
|
||||
self.exported_items.contains(&method.id) {
|
||||
found_pub_static = true;
|
||||
visit::walk_method_helper(self, &**method, ());
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
if method.pe_explicit_self().node ==
|
||||
ast::SelfStatic &&
|
||||
self.exported_items
|
||||
.contains(&method.id) {
|
||||
found_pub_static = true;
|
||||
visit::walk_method_helper(self,
|
||||
&*method,
|
||||
());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if found_pub_static {
|
||||
|
@ -193,26 +193,37 @@ impl<'a> ReachableContext<'a> {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitMethod(trait_method)) => {
|
||||
Some(ast_map::NodeTraitItem(trait_method)) => {
|
||||
match *trait_method {
|
||||
ast::Required(_) => false,
|
||||
ast::Provided(_) => true,
|
||||
ast::RequiredMethod(_) => false,
|
||||
ast::ProvidedMethod(_) => true,
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeMethod(method)) => {
|
||||
if generics_require_inlining(method.pe_generics()) ||
|
||||
attributes_specify_inlining(method.attrs.as_slice()) {
|
||||
true
|
||||
} else {
|
||||
let impl_did = self.tcx.map.get_parent_did(node_id);
|
||||
// Check the impl. If the generics on the self type of the
|
||||
// impl require inlining, this method does too.
|
||||
assert!(impl_did.krate == ast::LOCAL_CRATE);
|
||||
match self.tcx.map.expect_item(impl_did.node).node {
|
||||
ast::ItemImpl(ref generics, _, _, _) => {
|
||||
generics_require_inlining(generics)
|
||||
Some(ast_map::NodeImplItem(impl_item)) => {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
if generics_require_inlining(method.pe_generics()) ||
|
||||
attributes_specify_inlining(
|
||||
method.attrs.as_slice()) {
|
||||
true
|
||||
} else {
|
||||
let impl_did = self.tcx
|
||||
.map
|
||||
.get_parent_did(node_id);
|
||||
// Check the impl. If the generics on the self
|
||||
// type of the impl require inlining, this method
|
||||
// does too.
|
||||
assert!(impl_did.krate == ast::LOCAL_CRATE);
|
||||
match self.tcx
|
||||
.map
|
||||
.expect_item(impl_did.node)
|
||||
.node {
|
||||
ast::ItemImpl(ref generics, _, _, _) => {
|
||||
generics_require_inlining(generics)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,20 +321,24 @@ impl<'a> ReachableContext<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(trait_method) => {
|
||||
ast_map::NodeTraitItem(trait_method) => {
|
||||
match *trait_method {
|
||||
ast::Required(..) => {
|
||||
ast::RequiredMethod(..) => {
|
||||
// Keep going, nothing to get exported
|
||||
}
|
||||
ast::Provided(ref method) => {
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
visit::walk_block(self, &*method.pe_body(), ())
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeMethod(method) => {
|
||||
let did = self.tcx.map.get_parent_did(search_item);
|
||||
if method_might_be_inlined(self.tcx, &*method, did) {
|
||||
visit::walk_block(self, &*method.pe_body(), ())
|
||||
ast_map::NodeImplItem(impl_item) => {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
let did = self.tcx.map.get_parent_did(search_item);
|
||||
if method_might_be_inlined(self.tcx, &*method, did) {
|
||||
visit::walk_block(self, &*method.pe_body(), ())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Nothing to recurse on for these
|
||||
|
@ -24,7 +24,7 @@ use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
|
||||
use syntax::ast::*;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::{local_def, PostExpansionMethod};
|
||||
use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
|
||||
use syntax::ast_util::{walk_pat, trait_item_to_ty_method};
|
||||
use syntax::ext::mtwt;
|
||||
use syntax::parse::token::special_names;
|
||||
use syntax::parse::token::special_idents;
|
||||
@ -36,7 +36,7 @@ use syntax::visit::Visitor;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::gc::{Gc, GC};
|
||||
use std::gc::GC;
|
||||
use std::mem::replace;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::uint;
|
||||
@ -225,7 +225,7 @@ enum FallbackSuggestion {
|
||||
NoSuggestion,
|
||||
Field,
|
||||
Method,
|
||||
TraitMethod,
|
||||
TraitItem,
|
||||
StaticMethod(String),
|
||||
StaticTraitMethod(String),
|
||||
}
|
||||
@ -272,10 +272,10 @@ enum RibKind {
|
||||
ConstantItemRibKind
|
||||
}
|
||||
|
||||
// Methods can be required or provided. Required methods only occur in traits.
|
||||
// Methods can be required or provided. RequiredMethod methods only occur in traits.
|
||||
enum MethodSort {
|
||||
Required,
|
||||
Provided(NodeId)
|
||||
RequiredMethod,
|
||||
ProvidedMethod(NodeId)
|
||||
}
|
||||
|
||||
enum UseLexicalScopeFlag {
|
||||
@ -289,19 +289,19 @@ enum ModulePrefixResult {
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, PartialEq)]
|
||||
enum MethodIsStaticFlag {
|
||||
MethodIsNotStatic,
|
||||
MethodIsStatic,
|
||||
pub enum TraitItemKind {
|
||||
NonstaticMethodTraitItemKind,
|
||||
StaticMethodTraitItemKind,
|
||||
}
|
||||
|
||||
impl MethodIsStaticFlag {
|
||||
fn from_explicit_self_category(explicit_self_category:
|
||||
ExplicitSelfCategory)
|
||||
-> MethodIsStaticFlag {
|
||||
impl TraitItemKind {
|
||||
pub fn from_explicit_self_category(explicit_self_category:
|
||||
ExplicitSelfCategory)
|
||||
-> TraitItemKind {
|
||||
if explicit_self_category == StaticExplicitSelfCategory {
|
||||
MethodIsStatic
|
||||
StaticMethodTraitItemKind
|
||||
} else {
|
||||
MethodIsNotStatic
|
||||
NonstaticMethodTraitItemKind
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -824,7 +824,7 @@ struct Resolver<'a> {
|
||||
|
||||
graph_root: NameBindings,
|
||||
|
||||
method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
|
||||
trait_item_map: RefCell<FnvHashMap<(Name, DefId), TraitItemKind>>,
|
||||
|
||||
structs: FnvHashMap<DefId, Vec<Name>>,
|
||||
|
||||
@ -934,7 +934,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
graph_root: graph_root,
|
||||
|
||||
method_map: RefCell::new(FnvHashMap::new()),
|
||||
trait_item_map: RefCell::new(FnvHashMap::new()),
|
||||
structs: FnvHashMap::new(),
|
||||
|
||||
unresolved_imports: 0,
|
||||
@ -1263,7 +1263,7 @@ impl<'a> Resolver<'a> {
|
||||
parent
|
||||
}
|
||||
|
||||
ItemImpl(_, None, ty, ref methods) => {
|
||||
ItemImpl(_, None, ty, ref impl_items) => {
|
||||
// If this implements an anonymous trait, then add all the
|
||||
// methods within to a new module, if the type was defined
|
||||
// within this module.
|
||||
@ -1315,35 +1315,43 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
// For each method...
|
||||
for method in methods.iter() {
|
||||
// Add the method to the module.
|
||||
let ident = method.pe_ident();
|
||||
let method_name_bindings =
|
||||
self.add_child(ident,
|
||||
new_parent.clone(),
|
||||
ForbidDuplicateValues,
|
||||
method.span);
|
||||
let def = match method.pe_explicit_self().node {
|
||||
SelfStatic => {
|
||||
// Static methods become
|
||||
// `def_static_method`s.
|
||||
DefStaticMethod(local_def(method.id),
|
||||
FromImpl(local_def(
|
||||
item.id)),
|
||||
method.pe_fn_style())
|
||||
}
|
||||
_ => {
|
||||
// Non-static methods become
|
||||
// `def_method`s.
|
||||
DefMethod(local_def(method.id), None)
|
||||
}
|
||||
};
|
||||
// For each implementation item...
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
MethodImplItem(method) => {
|
||||
// Add the method to the module.
|
||||
let ident = method.pe_ident();
|
||||
let method_name_bindings =
|
||||
self.add_child(ident,
|
||||
new_parent.clone(),
|
||||
ForbidDuplicateValues,
|
||||
method.span);
|
||||
let def = match method.pe_explicit_self()
|
||||
.node {
|
||||
SelfStatic => {
|
||||
// Static methods become
|
||||
// `def_static_method`s.
|
||||
DefStaticMethod(
|
||||
local_def(method.id),
|
||||
FromImpl(local_def(item.id)),
|
||||
method.pe_fn_style())
|
||||
}
|
||||
_ => {
|
||||
// Non-static methods become
|
||||
// `def_method`s.
|
||||
DefMethod(local_def(method.id),
|
||||
None)
|
||||
}
|
||||
};
|
||||
|
||||
let is_public = method.pe_vis() == ast::Public;
|
||||
method_name_bindings.define_value(def,
|
||||
method.span,
|
||||
is_public);
|
||||
let is_public =
|
||||
method.pe_vis() == ast::Public;
|
||||
method_name_bindings.define_value(
|
||||
def,
|
||||
method.span,
|
||||
is_public);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -1376,7 +1384,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// Add the names of all the methods to the trait info.
|
||||
for method in methods.iter() {
|
||||
let ty_m = trait_method_to_ty_method(method);
|
||||
let ty_m = trait_item_to_ty_method(method);
|
||||
|
||||
let ident = ty_m.ident;
|
||||
|
||||
@ -1387,13 +1395,13 @@ impl<'a> Resolver<'a> {
|
||||
(DefStaticMethod(local_def(ty_m.id),
|
||||
FromTrait(local_def(item.id)),
|
||||
ty_m.fn_style),
|
||||
MethodIsStatic)
|
||||
StaticMethodTraitItemKind)
|
||||
}
|
||||
_ => {
|
||||
// Non-static methods become `def_method`s.
|
||||
(DefMethod(local_def(ty_m.id),
|
||||
Some(local_def(item.id))),
|
||||
MethodIsNotStatic)
|
||||
NonstaticMethodTraitItemKind)
|
||||
}
|
||||
};
|
||||
|
||||
@ -1404,7 +1412,7 @@ impl<'a> Resolver<'a> {
|
||||
ty_m.span);
|
||||
method_name_bindings.define_value(def, ty_m.span, true);
|
||||
|
||||
self.method_map
|
||||
self.trait_item_map
|
||||
.borrow_mut()
|
||||
.insert((ident.name, def_id), static_flag);
|
||||
}
|
||||
@ -1714,29 +1722,29 @@ impl<'a> Resolver<'a> {
|
||||
debug!("(building reduced graph for external \
|
||||
crate) building type {}", final_ident);
|
||||
|
||||
// If this is a trait, add all the method names
|
||||
// to the trait info.
|
||||
// If this is a trait, add all the trait item names to the trait
|
||||
// info.
|
||||
|
||||
let method_def_ids =
|
||||
csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
|
||||
for &method_def_id in method_def_ids.iter() {
|
||||
let (method_name, explicit_self) =
|
||||
csearch::get_method_name_and_explicit_self(&self.session.cstore,
|
||||
method_def_id);
|
||||
let trait_item_def_ids =
|
||||
csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
|
||||
for trait_item_def_id in trait_item_def_ids.iter() {
|
||||
let (trait_item_name, trait_item_kind) =
|
||||
csearch::get_trait_item_name_and_kind(
|
||||
&self.session.cstore,
|
||||
trait_item_def_id.def_id());
|
||||
|
||||
debug!("(building reduced graph for \
|
||||
external crate) ... adding \
|
||||
trait method '{}'",
|
||||
token::get_ident(method_name));
|
||||
debug!("(building reduced graph for external crate) ... \
|
||||
adding trait item '{}'",
|
||||
token::get_ident(trait_item_name));
|
||||
|
||||
self.method_map
|
||||
self.trait_item_map
|
||||
.borrow_mut()
|
||||
.insert((method_name.name, def_id),
|
||||
MethodIsStaticFlag::from_explicit_self_category(
|
||||
explicit_self));
|
||||
.insert((trait_item_name.name, def_id),
|
||||
trait_item_kind);
|
||||
|
||||
if is_exported {
|
||||
self.external_exports.insert(method_def_id);
|
||||
self.external_exports
|
||||
.insert(trait_item_def_id.def_id());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3680,12 +3688,12 @@ impl<'a> Resolver<'a> {
|
||||
ItemImpl(ref generics,
|
||||
ref implemented_traits,
|
||||
ref self_type,
|
||||
ref methods) => {
|
||||
ref impl_items) => {
|
||||
self.resolve_implementation(item.id,
|
||||
generics,
|
||||
implemented_traits,
|
||||
&**self_type,
|
||||
methods.as_slice());
|
||||
impl_items.as_slice());
|
||||
}
|
||||
|
||||
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
|
||||
@ -3724,12 +3732,12 @@ impl<'a> Resolver<'a> {
|
||||
// FIXME #4951: Do we need a node ID here?
|
||||
|
||||
match *method {
|
||||
ast::Required(ref ty_m) => {
|
||||
ast::RequiredMethod(ref ty_m) => {
|
||||
this.with_type_parameter_rib
|
||||
(HasTypeParameters(&ty_m.generics,
|
||||
FnSpace,
|
||||
item.id,
|
||||
MethodRibKind(item.id, Required)),
|
||||
MethodRibKind(item.id, RequiredMethod)),
|
||||
|this| {
|
||||
|
||||
// Resolve the method-specific type
|
||||
@ -3751,9 +3759,9 @@ impl<'a> Resolver<'a> {
|
||||
this.resolve_type(&*ty_m.decl.output);
|
||||
});
|
||||
}
|
||||
ast::Provided(ref m) => {
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
this.resolve_method(MethodRibKind(item.id,
|
||||
Provided(m.id)),
|
||||
ProvidedMethod(m.id)),
|
||||
&**m)
|
||||
}
|
||||
}
|
||||
@ -4129,7 +4137,7 @@ impl<'a> Resolver<'a> {
|
||||
generics: &Generics,
|
||||
opt_trait_reference: &Option<TraitRef>,
|
||||
self_type: &Ty,
|
||||
methods: &[Gc<Method>]) {
|
||||
impl_items: &[ImplItem]) {
|
||||
// If applicable, create a rib for the type parameters.
|
||||
self.with_type_parameter_rib(HasTypeParameters(generics,
|
||||
TypeSpace,
|
||||
@ -4145,27 +4153,36 @@ impl<'a> Resolver<'a> {
|
||||
this.resolve_type(self_type);
|
||||
|
||||
this.with_current_self_type(self_type, |this| {
|
||||
for method in methods.iter() {
|
||||
// If this is a trait impl, ensure the method exists in trait
|
||||
this.check_trait_method(&**method);
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
MethodImplItem(method) => {
|
||||
// If this is a trait impl, ensure the method
|
||||
// exists in trait
|
||||
this.check_trait_item(method.pe_ident(),
|
||||
method.span);
|
||||
|
||||
// We also need a new scope for the method-specific type parameters.
|
||||
this.resolve_method(MethodRibKind(id, Provided(method.id)),
|
||||
&**method);
|
||||
// We also need a new scope for the method-
|
||||
// specific type parameters.
|
||||
this.resolve_method(
|
||||
MethodRibKind(id,
|
||||
ProvidedMethod(method.id)),
|
||||
&*method);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn check_trait_method(&self, method: &Method) {
|
||||
fn check_trait_item(&self, ident: Ident, span: Span) {
|
||||
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
|
||||
for &(did, ref trait_ref) in self.current_trait_ref.iter() {
|
||||
let method_name = method.pe_ident().name;
|
||||
let method_name = ident.name;
|
||||
|
||||
if self.method_map.borrow().find(&(method_name, did)).is_none() {
|
||||
if self.trait_item_map.borrow().find(&(method_name, did)).is_none() {
|
||||
let path_str = self.path_idents_to_string(&trait_ref.path);
|
||||
self.resolve_error(method.span,
|
||||
self.resolve_error(span,
|
||||
format!("method `{}` is not a member of trait `{}`",
|
||||
token::get_name(method_name),
|
||||
path_str).as_slice());
|
||||
@ -4845,8 +4862,8 @@ impl<'a> Resolver<'a> {
|
||||
TraitModuleKind | ImplModuleKind => {
|
||||
match containing_module.def_id.get() {
|
||||
Some(def_id) => {
|
||||
match self.method_map.borrow().find(&(ident.name, def_id)) {
|
||||
Some(&MethodIsStatic) => (),
|
||||
match self.trait_item_map.borrow().find(&(ident.name, def_id)) {
|
||||
Some(&StaticMethodTraitItemKind) => (),
|
||||
None => (),
|
||||
_ => {
|
||||
debug!("containing module was a trait or impl \
|
||||
@ -5102,7 +5119,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
Some(DefMethod(_, None)) if allowed == Everything => return Method,
|
||||
Some(DefMethod(_, Some(_))) => return TraitMethod,
|
||||
Some(DefMethod(_, Some(_))) => return TraitItem,
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
@ -5112,14 +5129,14 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
// Look for a method in the current trait.
|
||||
let method_map = self.method_map.borrow();
|
||||
let trait_item_map = self.trait_item_map.borrow();
|
||||
match self.current_trait_ref {
|
||||
Some((did, ref trait_ref)) => {
|
||||
let path_str = self.path_idents_to_string(&trait_ref.path);
|
||||
|
||||
match method_map.find(&(name, did)) {
|
||||
Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
|
||||
Some(_) => return TraitMethod,
|
||||
match trait_item_map.find(&(name, did)) {
|
||||
Some(&StaticMethodTraitItemKind) => return StaticTraitMethod(path_str),
|
||||
Some(_) => return TraitItem,
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
@ -5262,7 +5279,7 @@ impl<'a> Resolver<'a> {
|
||||
Field =>
|
||||
format!("`self.{}`", wrong_name),
|
||||
Method
|
||||
| TraitMethod =>
|
||||
| TraitItem =>
|
||||
format!("to call `self.{}`", wrong_name),
|
||||
StaticTraitMethod(path_str)
|
||||
| StaticMethod(path_str) =>
|
||||
@ -5437,9 +5454,9 @@ impl<'a> Resolver<'a> {
|
||||
// Look for the current trait.
|
||||
match self.current_trait_ref {
|
||||
Some((trait_def_id, _)) => {
|
||||
let method_map = self.method_map.borrow();
|
||||
let trait_item_map = self.trait_item_map.borrow();
|
||||
|
||||
if method_map.contains_key(&(name, trait_def_id)) {
|
||||
if trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
add_trait_info(&mut found_traits, trait_def_id, name);
|
||||
}
|
||||
}
|
||||
@ -5450,7 +5467,7 @@ impl<'a> Resolver<'a> {
|
||||
self.populate_module_if_necessary(&search_module);
|
||||
|
||||
{
|
||||
let method_map = self.method_map.borrow();
|
||||
let trait_item_map = self.trait_item_map.borrow();
|
||||
for (_, child_names) in search_module.children.borrow().iter() {
|
||||
let def = match child_names.def_for_namespace(TypeNS) {
|
||||
Some(def) => def,
|
||||
@ -5460,7 +5477,7 @@ impl<'a> Resolver<'a> {
|
||||
DefTrait(trait_def_id) => trait_def_id,
|
||||
_ => continue,
|
||||
};
|
||||
if method_map.contains_key(&(name, trait_def_id)) {
|
||||
if trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
add_trait_info(&mut found_traits, trait_def_id, name);
|
||||
}
|
||||
}
|
||||
@ -5476,7 +5493,7 @@ impl<'a> Resolver<'a> {
|
||||
Some(DefTrait(trait_def_id)) => trait_def_id,
|
||||
Some(..) | None => continue,
|
||||
};
|
||||
if self.method_map.borrow().contains_key(&(name, did)) {
|
||||
if self.trait_item_map.borrow().contains_key(&(name, did)) {
|
||||
add_trait_info(&mut found_traits, did, name);
|
||||
self.used_imports.insert((import.type_id, TypeNS));
|
||||
}
|
||||
|
@ -283,8 +283,8 @@ impl <'l> DxrVisitor<'l> {
|
||||
let mut result = String::from_str("<");
|
||||
result.push_str(ty_to_string(&*ty).as_slice());
|
||||
|
||||
match ty::trait_of_method(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id)) {
|
||||
match ty::trait_of_item(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id)) {
|
||||
Some(def_id) => {
|
||||
result.push_str(" as ");
|
||||
result.push_str(
|
||||
@ -310,8 +310,8 @@ impl <'l> DxrVisitor<'l> {
|
||||
).as_slice());
|
||||
},
|
||||
},
|
||||
None => match ty::trait_of_method(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id)) {
|
||||
None => match ty::trait_of_item(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id)) {
|
||||
Some(def_id) => {
|
||||
scope_id = def_id.node;
|
||||
match self.analysis.ty_cx.map.get(def_id.node) {
|
||||
@ -338,9 +338,19 @@ impl <'l> DxrVisitor<'l> {
|
||||
let qualname = qualname.as_slice();
|
||||
|
||||
// record the decl for this def (if it has one)
|
||||
let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id))
|
||||
.filtered(|def_id| method.id != 0 && def_id.node == 0);
|
||||
let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method.id))
|
||||
.filtered(|def_id| {
|
||||
match *def_id {
|
||||
ty::MethodTraitItemId(def_id) => {
|
||||
method.id != 0 && def_id.node == 0
|
||||
}
|
||||
}
|
||||
});
|
||||
let decl_id = match decl_id {
|
||||
None => None,
|
||||
Some(ty::MethodTraitItemId(def_id)) => Some(def_id),
|
||||
};
|
||||
|
||||
let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn);
|
||||
self.fmt.method_str(method.span,
|
||||
@ -601,7 +611,7 @@ impl <'l> DxrVisitor<'l> {
|
||||
type_parameters: &ast::Generics,
|
||||
trait_ref: &Option<ast::TraitRef>,
|
||||
typ: ast::P<ast::Ty>,
|
||||
methods: &Vec<Gc<ast::Method>>) {
|
||||
impl_items: &Vec<ast::ImplItem>) {
|
||||
match typ.node {
|
||||
ast::TyPath(ref path, _, id) => {
|
||||
match self.lookup_type_ref(id) {
|
||||
@ -630,8 +640,12 @@ impl <'l> DxrVisitor<'l> {
|
||||
}
|
||||
|
||||
self.process_generic_params(type_parameters, item.span, "", item.id, e);
|
||||
for method in methods.iter() {
|
||||
visit::walk_method_helper(self, &**method, e)
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
visit::walk_method_helper(self, &*method, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,7 +654,7 @@ impl <'l> DxrVisitor<'l> {
|
||||
e: DxrVisitorEnv,
|
||||
generics: &ast::Generics,
|
||||
trait_refs: &Vec<ast::TraitRef>,
|
||||
methods: &Vec<ast::TraitMethod>) {
|
||||
methods: &Vec<ast::TraitItem>) {
|
||||
let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
|
||||
|
||||
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
|
||||
@ -672,7 +686,7 @@ impl <'l> DxrVisitor<'l> {
|
||||
// walk generics and methods
|
||||
self.process_generic_params(generics, item.span, qualname.as_slice(), item.id, e);
|
||||
for method in methods.iter() {
|
||||
self.visit_trait_method(method, e)
|
||||
self.visit_trait_item(method, e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,18 +749,44 @@ impl <'l> DxrVisitor<'l> {
|
||||
def::DefStaticMethod(declid, provenence, _) => {
|
||||
let sub_span = self.span.sub_span_for_meth_name(ex.span);
|
||||
let defid = if declid.krate == ast::LOCAL_CRATE {
|
||||
let m = ty::method(&self.analysis.ty_cx, declid);
|
||||
let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
|
||||
declid);
|
||||
match provenence {
|
||||
def::FromTrait(def_id) =>
|
||||
Some(ty::trait_methods(&self.analysis.ty_cx, def_id)
|
||||
.iter().find(|mr| mr.ident.name == m.ident.name).unwrap().def_id),
|
||||
def::FromTrait(def_id) => {
|
||||
Some(ty::trait_items(&self.analysis.ty_cx,
|
||||
def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
match **mr {
|
||||
ty::MethodTraitItem(ref mr) => {
|
||||
mr.ident.name == ti.ident()
|
||||
.name
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
.def_id())
|
||||
}
|
||||
def::FromImpl(def_id) => {
|
||||
let impl_methods = self.analysis.ty_cx.impl_methods.borrow();
|
||||
Some(*impl_methods.get(&def_id)
|
||||
.iter().find(|mr|
|
||||
ty::method(
|
||||
&self.analysis.ty_cx, **mr).ident.name == m.ident.name)
|
||||
.unwrap())
|
||||
let impl_items = self.analysis
|
||||
.ty_cx
|
||||
.impl_items
|
||||
.borrow();
|
||||
Some(impl_items.get(&def_id)
|
||||
.iter()
|
||||
.find(|mr| {
|
||||
match **mr {
|
||||
ty::MethodTraitItemId(mr) => {
|
||||
ty::impl_or_trait_item(
|
||||
&self.analysis
|
||||
.ty_cx,
|
||||
mr).ident()
|
||||
.name ==
|
||||
ti.ident().name
|
||||
}
|
||||
}
|
||||
}).unwrap()
|
||||
.def_id())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -845,27 +885,45 @@ impl <'l> DxrVisitor<'l> {
|
||||
typeck::MethodStatic(def_id) |
|
||||
typeck::MethodStaticUnboxedClosure(def_id) => {
|
||||
// method invoked on an object with a concrete type (not a static method)
|
||||
let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
|
||||
let decl_id =
|
||||
match ty::trait_item_of_item(&self.analysis.ty_cx,
|
||||
def_id) {
|
||||
None => None,
|
||||
Some(ty::MethodTraitItemId(decl_id)) => Some(decl_id),
|
||||
};
|
||||
|
||||
// This incantation is required if the method referenced is a trait's
|
||||
// default implementation.
|
||||
let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
|
||||
.unwrap_or(def_id);
|
||||
// This incantation is required if the method referenced is a
|
||||
// trait's default implementation.
|
||||
let def_id = match ty::impl_or_trait_item(&self.analysis
|
||||
.ty_cx,
|
||||
def_id) {
|
||||
ty::MethodTraitItem(method) => {
|
||||
method.provided_source.unwrap_or(def_id)
|
||||
}
|
||||
};
|
||||
(Some(def_id), decl_id)
|
||||
}
|
||||
typeck::MethodParam(mp) => {
|
||||
// method invoked on a type parameter
|
||||
let method = ty::trait_method(&self.analysis.ty_cx,
|
||||
mp.trait_id,
|
||||
mp.method_num);
|
||||
(None, Some(method.def_id))
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mp.trait_id,
|
||||
mp.method_num);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
(None, Some(method.def_id))
|
||||
}
|
||||
}
|
||||
},
|
||||
typeck::MethodObject(mo) => {
|
||||
// method invoked on a trait instance
|
||||
let method = ty::trait_method(&self.analysis.ty_cx,
|
||||
mo.trait_id,
|
||||
mo.method_num);
|
||||
(None, Some(method.def_id))
|
||||
let trait_item = ty::trait_item(&self.analysis.ty_cx,
|
||||
mo.trait_id,
|
||||
mo.method_num);
|
||||
match trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
(None, Some(method.def_id))
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
let sub_span = self.span.sub_span_for_meth_name(ex.span);
|
||||
@ -968,8 +1026,17 @@ impl<'l> Visitor<DxrVisitorEnv> for DxrVisitor<'l> {
|
||||
self.process_static(item, e, typ, mt, &*expr),
|
||||
ast::ItemStruct(def, ref ty_params) => self.process_struct(item, e, &*def, ty_params),
|
||||
ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, e, def, ty_params),
|
||||
ast::ItemImpl(ref ty_params, ref trait_ref, typ, ref methods) =>
|
||||
self.process_impl(item, e, ty_params, trait_ref, typ, methods),
|
||||
ast::ItemImpl(ref ty_params,
|
||||
ref trait_ref,
|
||||
typ,
|
||||
ref impl_items) => {
|
||||
self.process_impl(item,
|
||||
e,
|
||||
ty_params,
|
||||
trait_ref,
|
||||
typ,
|
||||
impl_items)
|
||||
}
|
||||
ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) =>
|
||||
self.process_trait(item, e, generics, trait_refs, methods),
|
||||
ast::ItemMod(ref m) => self.process_mod(item, e, m),
|
||||
@ -1027,16 +1094,16 @@ impl<'l> Visitor<DxrVisitorEnv> for DxrVisitor<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_method(&mut self, tm: &ast::TraitMethod, e: DxrVisitorEnv) {
|
||||
fn visit_trait_item(&mut self, tm: &ast::TraitItem, e: DxrVisitorEnv) {
|
||||
match *tm {
|
||||
ast::Required(ref method_type) => {
|
||||
ast::RequiredMethod(ref method_type) => {
|
||||
if generated_code(method_type.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut scope_id ;
|
||||
let mut qualname = match ty::trait_of_method(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method_type.id)) {
|
||||
let mut scope_id;
|
||||
let mut qualname = match ty::trait_of_item(&self.analysis.ty_cx,
|
||||
ast_util::local_def(method_type.id)) {
|
||||
Some(def_id) => {
|
||||
scope_id = def_id.node;
|
||||
ty::item_path_str(&self.analysis.ty_cx, def_id).append("::")
|
||||
@ -1070,7 +1137,7 @@ impl<'l> Visitor<DxrVisitorEnv> for DxrVisitor<'l> {
|
||||
method_type.id,
|
||||
e);
|
||||
}
|
||||
ast::Provided(method) => self.process_method(&*method, e),
|
||||
ast::ProvidedMethod(method) => self.process_method(&*method, e),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ use syntax::codemap::Span;
|
||||
use syntax::{attr, visit};
|
||||
use syntax::ast;
|
||||
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
|
||||
use syntax::ast::{Item, Required, Provided, TraitMethod, TypeMethod, Method};
|
||||
use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem, TypeMethod, Method};
|
||||
use syntax::ast::{Generics, StructDef, StructField, Ident};
|
||||
use syntax::ast_util::is_local;
|
||||
use syntax::attr::Stability;
|
||||
@ -68,18 +68,18 @@ impl Visitor<Option<Stability>> for Annotator {
|
||||
visit::walk_fn(self, fk, fd, b, s, stab)
|
||||
}
|
||||
|
||||
fn visit_trait_method(&mut self, t: &TraitMethod, parent: Option<Stability>) {
|
||||
fn visit_trait_item(&mut self, t: &TraitItem, parent: Option<Stability>) {
|
||||
let stab = match *t {
|
||||
Required(TypeMethod {attrs: ref attrs, id: id, ..}) =>
|
||||
RequiredMethod(TypeMethod {attrs: ref attrs, id: id, ..}) =>
|
||||
self.annotate(id, attrs.as_slice(), parent),
|
||||
|
||||
// work around lack of pattern matching for @ types
|
||||
Provided(method) => match *method {
|
||||
ProvidedMethod(method) => match *method {
|
||||
Method {attrs: ref attrs, id: id, ..} =>
|
||||
self.annotate(id, attrs.as_slice(), parent)
|
||||
}
|
||||
};
|
||||
visit::walk_trait_method(self, t, stab)
|
||||
visit::walk_trait_item(self, t, stab)
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &Variant, g: &Generics, parent: Option<Stability>) {
|
||||
@ -116,10 +116,11 @@ impl Index {
|
||||
|
||||
/// Lookup the stability for a node, loading external crate
|
||||
/// metadata as necessary.
|
||||
pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
|
||||
pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
|
||||
// is this definition the implementation of a trait method?
|
||||
match ty::trait_method_of_method(tcx, id) {
|
||||
Some(trait_method_id) if trait_method_id != id => {
|
||||
match ty::trait_item_of_item(tcx, id) {
|
||||
Some(ty::MethodTraitItemId(trait_method_id))
|
||||
if trait_method_id != id => {
|
||||
lookup(tcx, trait_method_id)
|
||||
}
|
||||
_ if is_local(id) => {
|
||||
|
@ -1299,9 +1299,9 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
|
||||
_ => tcx.sess.bug("unexpected item variant in has_nested_returns")
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeTraitMethod(trait_method)) => {
|
||||
Some(ast_map::NodeTraitItem(trait_method)) => {
|
||||
match *trait_method {
|
||||
ast::Provided(m) => {
|
||||
ast::ProvidedMethod(m) => {
|
||||
match m.node {
|
||||
ast::MethDecl(_, _, _, _, _, _, blk, _) => {
|
||||
let mut explicit = CheckForNestedReturnsVisitor { found: false };
|
||||
@ -1313,20 +1313,34 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
|
||||
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
|
||||
}
|
||||
}
|
||||
ast::Required(_) => tcx.sess.bug("unexpected variant: required trait method in \
|
||||
has_nested_returns")
|
||||
ast::RequiredMethod(_) => {
|
||||
tcx.sess.bug("unexpected variant: required trait method \
|
||||
in has_nested_returns")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeMethod(m)) => {
|
||||
match m.node {
|
||||
ast::MethDecl(_, _, _, _, _, _, blk, _) => {
|
||||
let mut explicit = CheckForNestedReturnsVisitor { found: false };
|
||||
let mut implicit = CheckForNestedReturnsVisitor { found: false };
|
||||
visit::walk_method_helper(&mut explicit, &*m, false);
|
||||
visit::walk_expr_opt(&mut implicit, blk.expr, true);
|
||||
explicit.found || implicit.found
|
||||
Some(ast_map::NodeImplItem(ref ii)) => {
|
||||
match **ii {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
match m.node {
|
||||
ast::MethDecl(_, _, _, _, _, _, blk, _) => {
|
||||
let mut explicit = CheckForNestedReturnsVisitor {
|
||||
found: false,
|
||||
};
|
||||
let mut implicit = CheckForNestedReturnsVisitor {
|
||||
found: false,
|
||||
};
|
||||
visit::walk_method_helper(&mut explicit,
|
||||
&**m,
|
||||
false);
|
||||
visit::walk_expr_opt(&mut implicit,
|
||||
blk.expr,
|
||||
true);
|
||||
explicit.found || implicit.found
|
||||
}
|
||||
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
|
||||
}
|
||||
}
|
||||
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
|
||||
}
|
||||
}
|
||||
Some(ast_map::NodeExpr(e)) => {
|
||||
@ -2107,8 +2121,12 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
v.visit_block(&**body, ());
|
||||
}
|
||||
ast::ItemImpl(ref generics, _, _, ref ms) => {
|
||||
meth::trans_impl(ccx, item.ident, ms.as_slice(), generics, item.id);
|
||||
ast::ItemImpl(ref generics, _, _, ref impl_items) => {
|
||||
meth::trans_impl(ccx,
|
||||
item.ident,
|
||||
impl_items.as_slice(),
|
||||
generics,
|
||||
item.id);
|
||||
}
|
||||
ast::ItemMod(ref m) => {
|
||||
trans_mod(ccx, m);
|
||||
@ -2615,21 +2633,23 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
v
|
||||
}
|
||||
|
||||
ast_map::NodeTraitMethod(trait_method) => {
|
||||
debug!("get_item_val(): processing a NodeTraitMethod");
|
||||
ast_map::NodeTraitItem(trait_method) => {
|
||||
debug!("get_item_val(): processing a NodeTraitItem");
|
||||
match *trait_method {
|
||||
ast::Required(_) => {
|
||||
ast::RequiredMethod(_) => {
|
||||
ccx.sess().bug("unexpected variant: required trait method in \
|
||||
get_item_val()");
|
||||
}
|
||||
ast::Provided(m) => {
|
||||
ast::ProvidedMethod(m) => {
|
||||
register_method(ccx, id, &*m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_map::NodeMethod(m) => {
|
||||
register_method(ccx, id, &*m)
|
||||
ast_map::NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
ast::MethodImplItem(m) => register_method(ccx, id, &*m),
|
||||
}
|
||||
}
|
||||
|
||||
ast_map::NodeForeignItem(ni) => {
|
||||
|
@ -77,7 +77,7 @@ pub enum CalleeData {
|
||||
|
||||
Intrinsic(ast::NodeId, subst::Substs),
|
||||
|
||||
TraitMethod(MethodData)
|
||||
TraitItem(MethodData)
|
||||
}
|
||||
|
||||
pub struct Callee<'a> {
|
||||
@ -449,7 +449,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
|
||||
|
||||
// Load the info for the appropriate trait if necessary.
|
||||
match ty::trait_of_method(tcx, def_id) {
|
||||
match ty::trait_of_item(tcx, def_id) {
|
||||
None => {}
|
||||
Some(trait_id) => {
|
||||
ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
|
||||
@ -476,35 +476,43 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// So, what we need to do is find this substitution and
|
||||
// compose it with the one we already have.
|
||||
|
||||
let impl_id = ty::method(tcx, def_id).container_id();
|
||||
let method = ty::method(tcx, source_id);
|
||||
let trait_ref = ty::impl_trait_ref(tcx, impl_id)
|
||||
.expect("could not find trait_ref for impl with \
|
||||
default methods");
|
||||
let impl_id = ty::impl_or_trait_item(tcx, def_id).container()
|
||||
.id();
|
||||
let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
|
||||
match impl_or_trait_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
let trait_ref = ty::impl_trait_ref(tcx, impl_id)
|
||||
.expect("could not find trait_ref for impl with \
|
||||
default methods");
|
||||
|
||||
// Compute the first substitution
|
||||
let first_subst = make_substs_for_receiver_types(
|
||||
tcx, &*trait_ref, &*method);
|
||||
// Compute the first substitution
|
||||
let first_subst = make_substs_for_receiver_types(
|
||||
tcx, &*trait_ref, &*method);
|
||||
|
||||
// And compose them
|
||||
let new_substs = first_subst.subst(tcx, &substs);
|
||||
// And compose them
|
||||
let new_substs = first_subst.subst(tcx, &substs);
|
||||
|
||||
debug!("trans_fn_with_vtables - default method: \
|
||||
substs = {}, trait_subst = {}, \
|
||||
first_subst = {}, new_subst = {}, \
|
||||
vtables = {}",
|
||||
substs.repr(tcx), trait_ref.substs.repr(tcx),
|
||||
first_subst.repr(tcx), new_substs.repr(tcx),
|
||||
vtables.repr(tcx));
|
||||
debug!("trans_fn_with_vtables - default method: \
|
||||
substs = {}, trait_subst = {}, \
|
||||
first_subst = {}, new_subst = {}, \
|
||||
vtables = {}",
|
||||
substs.repr(tcx), trait_ref.substs.repr(tcx),
|
||||
first_subst.repr(tcx), new_substs.repr(tcx),
|
||||
vtables.repr(tcx));
|
||||
|
||||
let param_vtables =
|
||||
resolve_default_method_vtables(bcx, impl_id, &substs, vtables);
|
||||
let param_vtables =
|
||||
resolve_default_method_vtables(bcx,
|
||||
impl_id,
|
||||
&substs,
|
||||
vtables);
|
||||
|
||||
debug!("trans_fn_with_vtables - default method: \
|
||||
param_vtables = {}",
|
||||
param_vtables.repr(tcx));
|
||||
debug!("trans_fn_with_vtables - default method: \
|
||||
param_vtables = {}",
|
||||
param_vtables.repr(tcx));
|
||||
|
||||
(true, source_id, new_substs, param_vtables)
|
||||
(true, source_id, new_substs, param_vtables)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -742,7 +750,7 @@ pub fn trans_call_inner<'a>(
|
||||
Fn(llfn) => {
|
||||
(llfn, None, None)
|
||||
}
|
||||
TraitMethod(d) => {
|
||||
TraitItem(d) => {
|
||||
(d.llfn, None, Some(d.llself))
|
||||
}
|
||||
Closure(d) => {
|
||||
|
@ -1140,13 +1140,17 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeMethod(ref method) => {
|
||||
(method.pe_ident(),
|
||||
method.pe_fn_decl(),
|
||||
method.pe_generics(),
|
||||
method.pe_body(),
|
||||
method.span,
|
||||
true)
|
||||
ast_map::NodeImplItem(ref item) => {
|
||||
match **item {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
(method.pe_ident(),
|
||||
method.pe_fn_decl(),
|
||||
method.pe_generics(),
|
||||
method.pe_body(),
|
||||
method.span,
|
||||
true)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeExpr(ref expr) => {
|
||||
match expr.node {
|
||||
@ -1168,9 +1172,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
"create_function_debug_context: expected an expr_fn_block here")
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(ref trait_method) => {
|
||||
ast_map::NodeTraitItem(ref trait_method) => {
|
||||
match **trait_method {
|
||||
ast::Provided(ref method) => {
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
(method.pe_ident(),
|
||||
method.pe_fn_decl(),
|
||||
method.pe_generics(),
|
||||
|
@ -115,27 +115,42 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
|
||||
ccx.sess().bug("maybe_get_item_ast returned a found_parent \
|
||||
with a non-item parent");
|
||||
}
|
||||
csearch::found(ast::IIMethod(impl_did, is_provided, mth)) => {
|
||||
ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
|
||||
ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
|
||||
csearch::found(ast::IITraitItem(impl_did, impl_item)) => {
|
||||
match impl_item {
|
||||
ast::ProvidedInlinedTraitItem(mth) |
|
||||
ast::RequiredInlinedTraitItem(mth) => {
|
||||
ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
|
||||
ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
|
||||
|
||||
ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
|
||||
ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a default method, we can't look up the
|
||||
// impl type. But we aren't going to translate anyways, so don't.
|
||||
if is_provided { return local_def(mth.id); }
|
||||
match impl_item {
|
||||
ast::ProvidedInlinedTraitItem(mth) => {
|
||||
// If this is a default method, we can't look up the
|
||||
// impl type. But we aren't going to translate anyways, so
|
||||
// don't.
|
||||
local_def(mth.id)
|
||||
}
|
||||
ast::RequiredInlinedTraitItem(mth) => {
|
||||
let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
|
||||
let unparameterized = impl_tpt.generics.types.is_empty() &&
|
||||
mth.pe_generics().ty_params.is_empty();
|
||||
|
||||
let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
|
||||
let unparameterized =
|
||||
impl_tpt.generics.types.is_empty() &&
|
||||
mth.pe_generics().ty_params.is_empty();
|
||||
|
||||
if unparameterized {
|
||||
let llfn = get_item_val(ccx, mth.id);
|
||||
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), llfn,
|
||||
¶m_substs::empty(), mth.id, []);
|
||||
}
|
||||
local_def(mth.id)
|
||||
if unparameterized {
|
||||
let llfn = get_item_val(ccx, mth.id);
|
||||
trans_fn(ccx,
|
||||
&*mth.pe_fn_decl(),
|
||||
&*mth.pe_body(),
|
||||
llfn,
|
||||
¶m_substs::empty(),
|
||||
mth.id,
|
||||
[]);
|
||||
}
|
||||
local_def(mth.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ use util::common::indenter;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::gc::Gc;
|
||||
use syntax::abi::{Rust, RustCall};
|
||||
use syntax::parse::token;
|
||||
use syntax::{ast, ast_map, visit};
|
||||
@ -49,7 +48,7 @@ see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
|
||||
*/
|
||||
pub fn trans_impl(ccx: &CrateContext,
|
||||
name: ast::Ident,
|
||||
methods: &[Gc<ast::Method>],
|
||||
impl_items: &[ast::ImplItem],
|
||||
generics: &ast::Generics,
|
||||
id: ast::NodeId) {
|
||||
let _icx = push_ctxt("meth::trans_impl");
|
||||
@ -61,24 +60,34 @@ pub fn trans_impl(ccx: &CrateContext,
|
||||
// items that we need to translate.
|
||||
if !generics.ty_params.is_empty() {
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
for method in methods.iter() {
|
||||
visit::walk_method_helper(&mut v, &**method, ());
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
visit::walk_method_helper(&mut v, &*method, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for method in methods.iter() {
|
||||
if method.pe_generics().ty_params.len() == 0u {
|
||||
let llfn = get_item_val(ccx, method.id);
|
||||
trans_fn(ccx,
|
||||
&*method.pe_fn_decl(),
|
||||
&*method.pe_body(),
|
||||
llfn,
|
||||
¶m_substs::empty(),
|
||||
method.id,
|
||||
[]);
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(method) => {
|
||||
if method.pe_generics().ty_params.len() == 0u {
|
||||
let llfn = get_item_val(ccx, method.id);
|
||||
trans_fn(ccx,
|
||||
&*method.pe_fn_decl(),
|
||||
&*method.pe_body(),
|
||||
llfn,
|
||||
¶m_substs::empty(),
|
||||
method.id,
|
||||
[]);
|
||||
}
|
||||
let mut v = TransItemVisitor {
|
||||
ccx: ccx,
|
||||
};
|
||||
visit::walk_method_helper(&mut v, &*method, ());
|
||||
}
|
||||
}
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
visit::walk_method_helper(&mut v, &**method, ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,10 +174,10 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
|
||||
let mname = if method_id.krate == ast::LOCAL_CRATE {
|
||||
match bcx.tcx().map.get(method_id.node) {
|
||||
ast_map::NodeTraitMethod(method) => {
|
||||
ast_map::NodeTraitItem(method) => {
|
||||
let ident = match *method {
|
||||
ast::Required(ref m) => m.ident,
|
||||
ast::Provided(ref m) => m.pe_ident()
|
||||
ast::RequiredMethod(ref m) => m.ident,
|
||||
ast::ProvidedMethod(ref m) => m.pe_ident()
|
||||
};
|
||||
ident.name
|
||||
}
|
||||
@ -213,22 +222,33 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
}
|
||||
}
|
||||
|
||||
fn method_with_name(ccx: &CrateContext,
|
||||
impl_id: ast::DefId,
|
||||
name: ast::Name) -> ast::DefId {
|
||||
fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
|
||||
-> ast::DefId {
|
||||
match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
|
||||
Some(m) => return m,
|
||||
None => {}
|
||||
}
|
||||
|
||||
let methods = ccx.tcx.impl_methods.borrow();
|
||||
let methods = methods.find(&impl_id)
|
||||
.expect("could not find impl while translating");
|
||||
let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
|
||||
.expect("could not find method while translating");
|
||||
let impl_items = ccx.tcx.impl_items.borrow();
|
||||
let impl_items =
|
||||
impl_items.find(&impl_id)
|
||||
.expect("could not find impl while translating");
|
||||
let meth_did = impl_items.iter()
|
||||
.find(|&did| {
|
||||
match *did {
|
||||
ty::MethodTraitItemId(did) => {
|
||||
ty::impl_or_trait_item(&ccx.tcx,
|
||||
did).ident()
|
||||
.name ==
|
||||
name
|
||||
}
|
||||
}
|
||||
}).expect("could not find method while \
|
||||
translating");
|
||||
|
||||
ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
|
||||
*meth_did
|
||||
ccx.impl_method_cache.borrow_mut().insert((impl_id, name),
|
||||
meth_did.def_id());
|
||||
meth_did.def_id()
|
||||
}
|
||||
|
||||
fn trans_monomorphized_callee<'a>(
|
||||
@ -242,7 +262,9 @@ fn trans_monomorphized_callee<'a>(
|
||||
match vtbl {
|
||||
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
|
||||
let ccx = bcx.ccx();
|
||||
let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
|
||||
let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
|
||||
ty::MethodTraitItem(method) => method.ident,
|
||||
};
|
||||
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
|
||||
|
||||
// create a concatenated set of substitutions which includes
|
||||
@ -433,7 +455,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
|
||||
|
||||
return Callee {
|
||||
bcx: bcx,
|
||||
data: TraitMethod(MethodData {
|
||||
data: TraitItem(MethodData {
|
||||
llfn: mptr,
|
||||
llself: llself,
|
||||
})
|
||||
@ -552,35 +574,42 @@ fn emit_vtable_methods(bcx: &Block,
|
||||
|
||||
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
|
||||
|
||||
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
||||
trait_method_def_ids.iter().map(|method_def_id| {
|
||||
let ident = ty::method(tcx, *method_def_id).ident;
|
||||
let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
|
||||
trait_item_def_ids.iter().map(|method_def_id| {
|
||||
let method_def_id = method_def_id.def_id();
|
||||
let ident = ty::impl_or_trait_item(tcx, method_def_id).ident();
|
||||
// The substitutions we have are on the impl, so we grab
|
||||
// the method type from the impl to substitute into.
|
||||
let m_id = method_with_name(ccx, impl_id, ident.name);
|
||||
let m = ty::method(tcx, m_id);
|
||||
debug!("(making impl vtable) emitting method {} at subst {}",
|
||||
m.repr(tcx),
|
||||
substs.repr(tcx));
|
||||
if m.generics.has_type_params(subst::FnSpace) ||
|
||||
ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
|
||||
debug!("(making impl vtable) method has self or type params: {}",
|
||||
token::get_ident(ident));
|
||||
C_null(Type::nil(ccx).ptr_to())
|
||||
} else {
|
||||
let mut fn_ref = trans_fn_ref_with_vtables(bcx,
|
||||
m_id,
|
||||
ExprId(0),
|
||||
substs.clone(),
|
||||
vtables.clone());
|
||||
if m.explicit_self == ty::ByValueExplicitSelfCategory {
|
||||
fn_ref = trans_unboxing_shim(bcx,
|
||||
fn_ref,
|
||||
&*m,
|
||||
m_id,
|
||||
substs.clone());
|
||||
let ti = ty::impl_or_trait_item(tcx, m_id);
|
||||
match ti {
|
||||
ty::MethodTraitItem(m) => {
|
||||
debug!("(making impl vtable) emitting method {} at subst {}",
|
||||
m.repr(tcx),
|
||||
substs.repr(tcx));
|
||||
if m.generics.has_type_params(subst::FnSpace) ||
|
||||
ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
|
||||
debug!("(making impl vtable) method has self or type \
|
||||
params: {}",
|
||||
token::get_ident(ident));
|
||||
C_null(Type::nil(ccx).ptr_to())
|
||||
} else {
|
||||
let mut fn_ref = trans_fn_ref_with_vtables(
|
||||
bcx,
|
||||
m_id,
|
||||
ExprId(0),
|
||||
substs.clone(),
|
||||
vtables.clone());
|
||||
if m.explicit_self == ty::ByValueExplicitSelfCategory {
|
||||
fn_ref = trans_unboxing_shim(bcx,
|
||||
fn_ref,
|
||||
&*m,
|
||||
m_id,
|
||||
substs.clone());
|
||||
}
|
||||
fn_ref
|
||||
}
|
||||
}
|
||||
fn_ref
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
@ -197,15 +197,25 @@ pub fn monomorphic_fn(ccx: &CrateContext,
|
||||
}
|
||||
d
|
||||
}
|
||||
ast_map::NodeMethod(mth) => {
|
||||
let d = mk_lldecl(abi::Rust);
|
||||
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
|
||||
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, []);
|
||||
d
|
||||
ast_map::NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
ast::MethodImplItem(mth) => {
|
||||
let d = mk_lldecl(abi::Rust);
|
||||
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
|
||||
trans_fn(ccx,
|
||||
&*mth.pe_fn_decl(),
|
||||
&*mth.pe_body(),
|
||||
d,
|
||||
&psubsts,
|
||||
mth.id,
|
||||
[]);
|
||||
d
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(method) => {
|
||||
ast_map::NodeTraitItem(method) => {
|
||||
match *method {
|
||||
ast::Provided(mth) => {
|
||||
ast::ProvidedMethod(mth) => {
|
||||
let d = mk_lldecl(abi::Rust);
|
||||
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
|
||||
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
|
||||
|
@ -25,7 +25,6 @@ use middle::trans::type_of::*;
|
||||
use middle::ty;
|
||||
use util::ppaux::ty_to_string;
|
||||
|
||||
use std::rc::Rc;
|
||||
use arena::TypedArena;
|
||||
use libc::c_uint;
|
||||
use syntax::ast::DefId;
|
||||
@ -36,7 +35,7 @@ use syntax::parse::token;
|
||||
|
||||
pub struct Reflector<'a, 'b> {
|
||||
visitor_val: ValueRef,
|
||||
visitor_methods: &'a [Rc<ty::Method>],
|
||||
visitor_items: &'a [ty::ImplOrTraitItem],
|
||||
final_bcx: &'b Block<'b>,
|
||||
tydesc_ty: Type,
|
||||
bcx: &'b Block<'b>
|
||||
@ -87,13 +86,14 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||
pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
|
||||
let fcx = self.bcx.fcx;
|
||||
let tcx = self.bcx.tcx();
|
||||
let mth_idx = ty::method_idx(token::str_to_ident(format!(
|
||||
let mth_idx = ty::impl_or_trait_item_idx(token::str_to_ident(format!(
|
||||
"visit_{}", ty_name).as_slice()),
|
||||
self.visitor_methods.as_slice()).expect(
|
||||
self.visitor_items.as_slice()).expect(
|
||||
format!("couldn't find visit method for {}", ty_name).as_slice());
|
||||
let mth_ty =
|
||||
ty::mk_bare_fn(tcx,
|
||||
self.visitor_methods[mth_idx].fty.clone());
|
||||
let method = match self.visitor_items[mth_idx] {
|
||||
ty::MethodTraitItem(ref method) => (*method).clone(),
|
||||
};
|
||||
let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
|
||||
let v = self.visitor_val;
|
||||
debug!("passing {} args:", args.len());
|
||||
let mut bcx = self.bcx;
|
||||
@ -397,10 +397,10 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
|
||||
let final = fcx.new_temp_block("final");
|
||||
let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
|
||||
let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
|
||||
let visitor_methods = ty::trait_methods(bcx.tcx(), visitor_trait_id);
|
||||
let visitor_items = ty::trait_items(bcx.tcx(), visitor_trait_id);
|
||||
let mut r = Reflector {
|
||||
visitor_val: visitor_val,
|
||||
visitor_methods: visitor_methods.as_slice(),
|
||||
visitor_items: visitor_items.as_slice(),
|
||||
final_bcx: final,
|
||||
tydesc_ty: tydesc_ty,
|
||||
bcx: bcx
|
||||
|
@ -76,11 +76,64 @@ pub struct field {
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum MethodContainer {
|
||||
pub enum ImplOrTraitItemContainer {
|
||||
TraitContainer(ast::DefId),
|
||||
ImplContainer(ast::DefId),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItemContainer {
|
||||
pub fn id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
TraitContainer(id) => id,
|
||||
ImplContainer(id) => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum ImplOrTraitItem {
|
||||
MethodTraitItem(Rc<Method>),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItem {
|
||||
fn id(&self) -> ImplOrTraitItemId {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.def_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ident(&self) -> ast::Ident {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.ident,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container(&self) -> ImplOrTraitItemContainer {
|
||||
match *self {
|
||||
MethodTraitItem(ref method) => method.container,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum ImplOrTraitItemId {
|
||||
MethodTraitItemId(ast::DefId),
|
||||
}
|
||||
|
||||
impl ImplOrTraitItemId {
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
MethodTraitItemId(def_id) => def_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct Method {
|
||||
pub ident: ast::Ident,
|
||||
@ -89,7 +142,7 @@ pub struct Method {
|
||||
pub explicit_self: ExplicitSelfCategory,
|
||||
pub vis: ast::Visibility,
|
||||
pub def_id: ast::DefId,
|
||||
pub container: MethodContainer,
|
||||
pub container: ImplOrTraitItemContainer,
|
||||
|
||||
// If this method is provided, we need to know where it came from
|
||||
pub provided_source: Option<ast::DefId>
|
||||
@ -102,7 +155,7 @@ impl Method {
|
||||
explicit_self: ExplicitSelfCategory,
|
||||
vis: ast::Visibility,
|
||||
def_id: ast::DefId,
|
||||
container: MethodContainer,
|
||||
container: ImplOrTraitItemContainer,
|
||||
provided_source: Option<ast::DefId>)
|
||||
-> Method {
|
||||
Method {
|
||||
@ -274,14 +327,14 @@ pub struct ctxt {
|
||||
/// other items.
|
||||
pub item_substs: RefCell<NodeMap<ItemSubsts>>,
|
||||
|
||||
/// Maps from a method to the method "descriptor"
|
||||
pub methods: RefCell<DefIdMap<Rc<Method>>>,
|
||||
/// Maps from a trait item to the trait item "descriptor"
|
||||
pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem>>,
|
||||
|
||||
/// Maps from a trait def-id to a list of the def-ids of its methods
|
||||
pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
|
||||
/// Maps from a trait def-id to a list of the def-ids of its trait items
|
||||
pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
|
||||
|
||||
/// A cache for the trait_methods() routine
|
||||
pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
|
||||
/// A cache for the trait_items() routine
|
||||
pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem>>>>,
|
||||
|
||||
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
|
||||
|
||||
@ -332,11 +385,11 @@ pub struct ctxt {
|
||||
/// Methods in these implementations don't need to be exported.
|
||||
pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
|
||||
|
||||
/// Maps a DefId of an impl to a list of its methods.
|
||||
/// Maps a DefId of an impl to a list of its items.
|
||||
/// Note that this contains all of the impls that we know about,
|
||||
/// including ones in other crates. It's not clear that this is the best
|
||||
/// way to do it.
|
||||
pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
|
||||
pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
|
||||
|
||||
/// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
|
||||
/// present in this set can be warned about.
|
||||
@ -1104,9 +1157,9 @@ pub fn mk_ctxt(s: Session,
|
||||
tc_cache: RefCell::new(HashMap::new()),
|
||||
ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
|
||||
enum_var_cache: RefCell::new(DefIdMap::new()),
|
||||
methods: RefCell::new(DefIdMap::new()),
|
||||
trait_method_def_ids: RefCell::new(DefIdMap::new()),
|
||||
trait_methods_cache: RefCell::new(DefIdMap::new()),
|
||||
impl_or_trait_items: RefCell::new(DefIdMap::new()),
|
||||
trait_item_def_ids: RefCell::new(DefIdMap::new()),
|
||||
trait_items_cache: RefCell::new(DefIdMap::new()),
|
||||
impl_trait_cache: RefCell::new(DefIdMap::new()),
|
||||
ty_param_defs: RefCell::new(NodeMap::new()),
|
||||
adjustments: RefCell::new(NodeMap::new()),
|
||||
@ -1120,7 +1173,7 @@ pub fn mk_ctxt(s: Session,
|
||||
destructors: RefCell::new(DefIdSet::new()),
|
||||
trait_impls: RefCell::new(DefIdMap::new()),
|
||||
inherent_impls: RefCell::new(DefIdMap::new()),
|
||||
impl_methods: RefCell::new(DefIdMap::new()),
|
||||
impl_items: RefCell::new(DefIdMap::new()),
|
||||
used_unsafe: RefCell::new(NodeSet::new()),
|
||||
used_mut_nodes: RefCell::new(NodeSet::new()),
|
||||
impl_vtables: RefCell::new(DefIdMap::new()),
|
||||
@ -3075,11 +3128,19 @@ pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
|
||||
Err(s) => tcx.sess.fatal(s.as_slice()),
|
||||
}
|
||||
}
|
||||
typeck::MethodParam(typeck::MethodParam{trait_id: trt_id,
|
||||
method_num: n_mth, ..}) |
|
||||
typeck::MethodObject(typeck::MethodObject{trait_id: trt_id,
|
||||
method_num: n_mth, ..}) => {
|
||||
ty::trait_method(tcx, trt_id, n_mth).generics.types.clone()
|
||||
typeck::MethodParam(typeck::MethodParam{
|
||||
trait_id: trt_id,
|
||||
method_num: n_mth,
|
||||
..
|
||||
}) |
|
||||
typeck::MethodObject(typeck::MethodObject{
|
||||
trait_id: trt_id,
|
||||
method_num: n_mth,
|
||||
..
|
||||
}) => {
|
||||
match ty::trait_item(tcx, trt_id, n_mth) {
|
||||
ty::MethodTraitItem(method) => method.generics.types.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3297,8 +3358,9 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
|
||||
.collect::<Vec<String>>()).as_slice());
|
||||
}
|
||||
|
||||
pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
|
||||
meths.iter().position(|m| m.ident == id)
|
||||
pub fn impl_or_trait_item_idx(id: ast::Ident, trait_items: &[ImplOrTraitItem])
|
||||
-> Option<uint> {
|
||||
trait_items.iter().position(|m| m.ident() == id)
|
||||
}
|
||||
|
||||
/// Returns a vector containing the indices of all type parameters that appear
|
||||
@ -3540,7 +3602,15 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
|
||||
match item.node {
|
||||
ItemTrait(_, _, _, ref ms) => {
|
||||
let (_, p) = ast_util::split_trait_methods(ms.as_slice());
|
||||
p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
|
||||
p.iter()
|
||||
.map(|m| {
|
||||
match impl_or_trait_item(
|
||||
cx,
|
||||
ast_util::local_def(m.id)) {
|
||||
MethodTraitItem(m) => m,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => {
|
||||
cx.sess.bug(format!("provided_trait_methods: `{}` is \
|
||||
@ -3592,7 +3662,7 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
|
||||
/*!
|
||||
* Helper for looking things up in the various maps
|
||||
* that are populated during typeck::collect (e.g.,
|
||||
* `cx.methods`, `cx.tcache`, etc). All of these share
|
||||
* `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share
|
||||
* the pattern that if the id is local, it should have
|
||||
* been loaded into the map by the `typeck::collect` phase.
|
||||
* If the def-id is external, then we have to go consult
|
||||
@ -3612,40 +3682,47 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
|
||||
v
|
||||
}
|
||||
|
||||
pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
|
||||
let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
|
||||
ty::method(cx, method_def_id)
|
||||
pub fn trait_item(cx: &ctxt, trait_did: ast::DefId, idx: uint)
|
||||
-> ImplOrTraitItem {
|
||||
let method_def_id = ty::trait_item_def_ids(cx, trait_did).get(idx)
|
||||
.def_id();
|
||||
impl_or_trait_item(cx, method_def_id)
|
||||
}
|
||||
|
||||
|
||||
pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
|
||||
let mut trait_methods = cx.trait_methods_cache.borrow_mut();
|
||||
match trait_methods.find_copy(&trait_did) {
|
||||
Some(methods) => methods,
|
||||
pub fn trait_items(cx: &ctxt, trait_did: ast::DefId)
|
||||
-> Rc<Vec<ImplOrTraitItem>> {
|
||||
let mut trait_items = cx.trait_items_cache.borrow_mut();
|
||||
match trait_items.find_copy(&trait_did) {
|
||||
Some(trait_items) => trait_items,
|
||||
None => {
|
||||
let def_ids = ty::trait_method_def_ids(cx, trait_did);
|
||||
let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
|
||||
ty::method(cx, *d)
|
||||
}).collect());
|
||||
trait_methods.insert(trait_did, methods.clone());
|
||||
methods
|
||||
let def_ids = ty::trait_item_def_ids(cx, trait_did);
|
||||
let items: Rc<Vec<ImplOrTraitItem>> =
|
||||
Rc::new(def_ids.iter()
|
||||
.map(|d| impl_or_trait_item(cx, d.def_id()))
|
||||
.collect());
|
||||
trait_items.insert(trait_did, items.clone());
|
||||
items
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
|
||||
lookup_locally_or_in_crate_store("methods", id,
|
||||
&mut *cx.methods.borrow_mut(), || {
|
||||
Rc::new(csearch::get_method(cx, id))
|
||||
pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
|
||||
lookup_locally_or_in_crate_store("trait_method_def_ids",
|
||||
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_method_def_ids.borrow_mut(),
|
||||
&mut *cx.trait_item_def_ids.borrow_mut(),
|
||||
|| {
|
||||
Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
|
||||
Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
|
||||
})
|
||||
}
|
||||
|
||||
@ -4459,7 +4536,8 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
|
||||
|
||||
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|
||||
|impl_def_id| {
|
||||
let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
|
||||
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
|
||||
impl_def_id);
|
||||
|
||||
// Record the trait->implementation mappings, if applicable.
|
||||
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
|
||||
@ -4469,14 +4547,21 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for &method_def_id in methods.iter() {
|
||||
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
|
||||
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
|
||||
for impl_item_def_id in impl_items.iter() {
|
||||
let method_def_id = impl_item_def_id.def_id();
|
||||
match impl_or_trait_item(tcx, method_def_id) {
|
||||
MethodTraitItem(method) => {
|
||||
for &source in method.provided_source.iter() {
|
||||
tcx.provided_method_sources
|
||||
.borrow_mut()
|
||||
.insert(method_def_id, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
|
||||
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
|
||||
|
||||
// If this is an inherent implementation, record it.
|
||||
if associated_traits.is_none() {
|
||||
@ -4509,21 +4594,28 @@ pub fn populate_implementations_for_trait_if_necessary(
|
||||
|
||||
csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
|
||||
|implementation_def_id| {
|
||||
let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
|
||||
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
|
||||
|
||||
// Record the trait->implementation mapping.
|
||||
record_trait_implementation(tcx, trait_id, implementation_def_id);
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for &method_def_id in methods.iter() {
|
||||
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
|
||||
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
|
||||
for impl_item_def_id in impl_items.iter() {
|
||||
let method_def_id = impl_item_def_id.def_id();
|
||||
match impl_or_trait_item(tcx, method_def_id) {
|
||||
MethodTraitItem(method) => {
|
||||
for &source in method.provided_source.iter() {
|
||||
tcx.provided_method_sources
|
||||
.borrow_mut()
|
||||
.insert(method_def_id, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
|
||||
tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
|
||||
});
|
||||
|
||||
tcx.populated_external_traits.borrow_mut().insert(trait_id);
|
||||
@ -4555,14 +4647,15 @@ pub fn trait_id_of_impl(tcx: &ctxt,
|
||||
pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
|
||||
-> Option<ast::DefId> {
|
||||
if def_id.krate != LOCAL_CRATE {
|
||||
return match csearch::get_method(tcx, def_id).container {
|
||||
return match csearch::get_impl_or_trait_item(tcx,
|
||||
def_id).container() {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
};
|
||||
}
|
||||
match tcx.methods.borrow().find_copy(&def_id) {
|
||||
Some(method) => {
|
||||
match method.container {
|
||||
match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
|
||||
Some(trait_item) => {
|
||||
match trait_item.container() {
|
||||
TraitContainer(_) => None,
|
||||
ImplContainer(def_id) => Some(def_id),
|
||||
}
|
||||
@ -4571,17 +4664,16 @@ pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
|
||||
}
|
||||
}
|
||||
|
||||
/// If the given def ID describes a method belonging to a trait (either a
|
||||
/// If the given def ID describes an item belonging to a trait (either a
|
||||
/// default method or an implementation of a trait method), return the ID of
|
||||
/// the trait that the method belongs to. Otherwise, return `None`.
|
||||
pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
|
||||
-> Option<ast::DefId> {
|
||||
pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
|
||||
if def_id.krate != LOCAL_CRATE {
|
||||
return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
|
||||
return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
|
||||
}
|
||||
match tcx.methods.borrow().find_copy(&def_id) {
|
||||
Some(method) => {
|
||||
match method.container {
|
||||
match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
|
||||
Some(impl_or_trait_item) => {
|
||||
match impl_or_trait_item.container() {
|
||||
TraitContainer(def_id) => Some(def_id),
|
||||
ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
|
||||
}
|
||||
@ -4590,25 +4682,27 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
|
||||
}
|
||||
}
|
||||
|
||||
/// If the given def ID describes a method belonging to a trait, (either a
|
||||
/// If the given def ID describes an item belonging to a trait, (either a
|
||||
/// default method or an implementation of a trait method), return the ID of
|
||||
/// the method inside trait definition (this means that if the given def ID
|
||||
/// is already that of the original trait method, then the return value is
|
||||
/// the same).
|
||||
/// Otherwise, return `None`.
|
||||
pub fn trait_method_of_method(tcx: &ctxt,
|
||||
def_id: ast::DefId) -> Option<ast::DefId> {
|
||||
let method = match tcx.methods.borrow().find(&def_id) {
|
||||
pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
|
||||
-> Option<ImplOrTraitItemId> {
|
||||
let impl_item = match tcx.impl_or_trait_items.borrow().find(&def_id) {
|
||||
Some(m) => m.clone(),
|
||||
None => return None,
|
||||
};
|
||||
let name = method.ident.name;
|
||||
match trait_of_method(tcx, def_id) {
|
||||
let name = match impl_item {
|
||||
MethodTraitItem(method) => method.ident.name,
|
||||
};
|
||||
match trait_of_item(tcx, def_id) {
|
||||
Some(trait_did) => {
|
||||
let trait_methods = ty::trait_methods(tcx, trait_did);
|
||||
trait_methods.iter()
|
||||
.position(|m| m.ident.name == name)
|
||||
.map(|idx| ty::trait_method(tcx, trait_did, idx).def_id)
|
||||
let trait_items = ty::trait_items(tcx, trait_did);
|
||||
trait_items.iter()
|
||||
.position(|m| m.ident().name == name)
|
||||
.map(|idx| ty::trait_item(tcx, trait_did, idx).id())
|
||||
}
|
||||
None => None
|
||||
}
|
||||
|
@ -220,9 +220,15 @@ fn get_method_index(tcx: &ty::ctxt,
|
||||
// methods from them.
|
||||
let mut method_count = 0;
|
||||
ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
|
||||
if bound_ref.def_id == trait_ref.def_id { false }
|
||||
else {
|
||||
method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
|
||||
if bound_ref.def_id == trait_ref.def_id {
|
||||
false
|
||||
} else {
|
||||
let trait_items = ty::trait_items(tcx, bound_ref.def_id);
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => method_count += 1,
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
});
|
||||
@ -488,11 +494,13 @@ impl<'a> LookupContext<'a> {
|
||||
ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
|
||||
|
||||
// Look for explicit implementations.
|
||||
let impl_methods = self.tcx().impl_methods.borrow();
|
||||
let impl_items = self.tcx().impl_items.borrow();
|
||||
for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
|
||||
for impl_did in impl_infos.borrow().iter() {
|
||||
let methods = impl_methods.get(impl_did);
|
||||
self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
|
||||
let items = impl_items.get(impl_did);
|
||||
self.push_candidates_from_impl(*impl_did,
|
||||
items.as_slice(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -520,8 +528,11 @@ impl<'a> LookupContext<'a> {
|
||||
trait_did: DefId,
|
||||
closure_did: DefId,
|
||||
closure_function_type: &ClosureTy) {
|
||||
let method =
|
||||
ty::trait_methods(self.tcx(), trait_did).get(0).clone();
|
||||
let trait_item = ty::trait_items(self.tcx(), trait_did).get(0)
|
||||
.clone();
|
||||
let method = match trait_item {
|
||||
ty::MethodTraitItem(method) => method,
|
||||
};
|
||||
|
||||
let vcx = self.fcx.vtable_context();
|
||||
let region_params =
|
||||
@ -701,14 +712,24 @@ impl<'a> LookupContext<'a> {
|
||||
let this_bound_idx = next_bound_idx;
|
||||
next_bound_idx += 1;
|
||||
|
||||
let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
|
||||
match trait_methods.iter().position(|m| {
|
||||
m.explicit_self != ty::StaticExplicitSelfCategory &&
|
||||
m.ident.name == self.m_name }) {
|
||||
let trait_items = ty::trait_items(tcx, bound_trait_ref.def_id);
|
||||
match trait_items.iter().position(|ti| {
|
||||
match *ti {
|
||||
ty::MethodTraitItem(ref m) => {
|
||||
m.explicit_self != ty::StaticExplicitSelfCategory &&
|
||||
m.ident.name == self.m_name
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Some(pos) => {
|
||||
let method = trait_methods.get(pos).clone();
|
||||
let method = match *trait_items.get(pos) {
|
||||
ty::MethodTraitItem(ref method) => (*method).clone(),
|
||||
};
|
||||
|
||||
match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
|
||||
match mk_cand(bound_trait_ref,
|
||||
method,
|
||||
pos,
|
||||
this_bound_idx) {
|
||||
Some(cand) => {
|
||||
debug!("pushing inherent candidate for param: {}",
|
||||
cand.repr(self.tcx()));
|
||||
@ -733,18 +754,20 @@ impl<'a> LookupContext<'a> {
|
||||
// metadata if necessary.
|
||||
ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
|
||||
|
||||
let impl_methods = self.tcx().impl_methods.borrow();
|
||||
let impl_items = self.tcx().impl_items.borrow();
|
||||
for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
|
||||
for impl_did in impl_infos.borrow().iter() {
|
||||
let methods = impl_methods.get(impl_did);
|
||||
self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
|
||||
let items = impl_items.get(impl_did);
|
||||
self.push_candidates_from_impl(*impl_did,
|
||||
items.as_slice(),
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_candidates_from_impl(&mut self,
|
||||
impl_did: DefId,
|
||||
impl_methods: &[DefId],
|
||||
impl_items: &[ImplOrTraitItemId],
|
||||
is_extension: bool) {
|
||||
let did = if self.report_statics == ReportStaticMethods {
|
||||
// we only want to report each base trait once
|
||||
@ -762,13 +785,23 @@ impl<'a> LookupContext<'a> {
|
||||
|
||||
debug!("push_candidates_from_impl: {} {}",
|
||||
token::get_name(self.m_name),
|
||||
impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
|
||||
.collect::<Vec<ast::Ident>>()
|
||||
.repr(self.tcx()));
|
||||
impl_items.iter()
|
||||
.map(|&did| {
|
||||
ty::impl_or_trait_item(self.tcx(),
|
||||
did.def_id()).ident()
|
||||
})
|
||||
.collect::<Vec<ast::Ident>>()
|
||||
.repr(self.tcx()));
|
||||
|
||||
let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
|
||||
.find(|m| m.ident.name == self.m_name) {
|
||||
Some(method) => method,
|
||||
let method = match impl_items.iter()
|
||||
.map(|&did| {
|
||||
ty::impl_or_trait_item(self.tcx(),
|
||||
did.def_id())
|
||||
})
|
||||
.find(|m| {
|
||||
m.ident().name == self.m_name
|
||||
}) {
|
||||
Some(ty::MethodTraitItem(method)) => method,
|
||||
None => { return; } // No method with the right name.
|
||||
};
|
||||
|
||||
@ -1486,9 +1519,16 @@ impl<'a> LookupContext<'a> {
|
||||
let did = if self.report_statics == ReportStaticMethods {
|
||||
// If we're reporting statics, we want to report the trait
|
||||
// definition if possible, rather than an impl
|
||||
match ty::trait_method_of_method(self.tcx(), impl_did) {
|
||||
None => {debug!("(report candidate) No trait method found"); impl_did},
|
||||
Some(trait_did) => {debug!("(report candidate) Found trait ref"); trait_did}
|
||||
match ty::trait_item_of_item(self.tcx(), impl_did) {
|
||||
None => {
|
||||
debug!("(report candidate) No trait method \
|
||||
found");
|
||||
impl_did
|
||||
}
|
||||
Some(MethodTraitItemId(trait_did)) => {
|
||||
debug!("(report candidate) Found trait ref");
|
||||
trait_did
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it is an instantiated default method, use the original
|
||||
|
@ -123,7 +123,7 @@ use std::mem::replace;
|
||||
use std::rc::Rc;
|
||||
use std::gc::Gc;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{Provided, Required};
|
||||
use syntax::ast::{ProvidedMethod, RequiredMethod};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util::{local_def, PostExpansionMethod};
|
||||
@ -680,23 +680,27 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
|
||||
check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
|
||||
}
|
||||
ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
|
||||
ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
|
||||
debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
|
||||
|
||||
let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
|
||||
for m in ms.iter() {
|
||||
check_method_body(ccx, &impl_pty.generics, &**m);
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(m) => {
|
||||
check_method_body(ccx, &impl_pty.generics, &*m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match *opt_trait_ref {
|
||||
Some(ref ast_trait_ref) => {
|
||||
let impl_trait_ref =
|
||||
ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
|
||||
check_impl_methods_against_trait(ccx,
|
||||
it.span,
|
||||
ast_trait_ref,
|
||||
&*impl_trait_ref,
|
||||
ms.as_slice());
|
||||
check_impl_items_against_trait(ccx,
|
||||
it.span,
|
||||
ast_trait_ref,
|
||||
&*impl_trait_ref,
|
||||
impl_items.as_slice());
|
||||
vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
|
||||
}
|
||||
None => { }
|
||||
@ -707,11 +711,11 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
|
||||
for trait_method in (*trait_methods).iter() {
|
||||
match *trait_method {
|
||||
Required(..) => {
|
||||
RequiredMethod(..) => {
|
||||
// Nothing to do, since required methods don't have
|
||||
// bodies to check.
|
||||
}
|
||||
Provided(m) => {
|
||||
ProvidedMethod(m) => {
|
||||
check_method_body(ccx, &trait_def.generics, &*m);
|
||||
}
|
||||
}
|
||||
@ -770,7 +774,9 @@ fn check_method_body(ccx: &CrateCtxt,
|
||||
item_generics.repr(ccx.tcx),
|
||||
method.id);
|
||||
let method_def_id = local_def(method.id);
|
||||
let method_ty = ty::method(ccx.tcx, method_def_id);
|
||||
let method_ty = match ty::impl_or_trait_item(ccx.tcx, method_def_id) {
|
||||
ty::MethodTraitItem(ref method_ty) => (*method_ty).clone(),
|
||||
};
|
||||
let method_generics = &method_ty.generics;
|
||||
|
||||
let param_env = ty::construct_parameter_environment(ccx.tcx,
|
||||
@ -787,43 +793,58 @@ fn check_method_body(ccx: &CrateCtxt,
|
||||
param_env);
|
||||
}
|
||||
|
||||
fn check_impl_methods_against_trait(ccx: &CrateCtxt,
|
||||
impl_span: Span,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
impl_trait_ref: &ty::TraitRef,
|
||||
impl_methods: &[Gc<ast::Method>]) {
|
||||
fn check_impl_items_against_trait(ccx: &CrateCtxt,
|
||||
impl_span: Span,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
impl_trait_ref: &ty::TraitRef,
|
||||
impl_items: &[ast::ImplItem]) {
|
||||
// Locate trait methods
|
||||
let tcx = ccx.tcx;
|
||||
let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
|
||||
let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
|
||||
|
||||
// Check existing impl methods to see if they are both present in trait
|
||||
// and compatible with trait signature
|
||||
for impl_method in impl_methods.iter() {
|
||||
let impl_method_def_id = local_def(impl_method.id);
|
||||
let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(impl_method) => {
|
||||
let impl_method_def_id = local_def(impl_method.id);
|
||||
let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
|
||||
impl_method_def_id);
|
||||
|
||||
// If this is an impl of a trait method, find the corresponding
|
||||
// method definition in the trait.
|
||||
let opt_trait_method_ty =
|
||||
trait_methods.iter().
|
||||
find(|tm| tm.ident.name == impl_method_ty.ident.name);
|
||||
match opt_trait_method_ty {
|
||||
Some(trait_method_ty) => {
|
||||
compare_impl_method(ccx.tcx,
|
||||
&*impl_method_ty,
|
||||
impl_method.span,
|
||||
impl_method.pe_body().id,
|
||||
&**trait_method_ty,
|
||||
&impl_trait_ref.substs);
|
||||
}
|
||||
None => {
|
||||
// This is span_bug as it should have already been caught in resolve.
|
||||
tcx.sess.span_bug(
|
||||
impl_method.span,
|
||||
format!(
|
||||
"method `{}` is not a member of trait `{}`",
|
||||
token::get_ident(impl_method_ty.ident),
|
||||
pprust::path_to_string(&ast_trait_ref.path)).as_slice());
|
||||
// If this is an impl of a trait method, find the
|
||||
// corresponding method definition in the trait.
|
||||
let opt_trait_method_ty =
|
||||
trait_items.iter()
|
||||
.find(|ti| {
|
||||
ti.ident().name == impl_item_ty.ident()
|
||||
.name
|
||||
});
|
||||
match opt_trait_method_ty {
|
||||
Some(trait_method_ty) => {
|
||||
match (trait_method_ty, &impl_item_ty) {
|
||||
(&ty::MethodTraitItem(ref trait_method_ty),
|
||||
&ty::MethodTraitItem(ref impl_method_ty)) => {
|
||||
compare_impl_method(ccx.tcx,
|
||||
&**impl_method_ty,
|
||||
impl_method.span,
|
||||
impl_method.pe_body().id,
|
||||
&**trait_method_ty,
|
||||
&impl_trait_ref.substs);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// This is span_bug as it should have already been
|
||||
// caught in resolve.
|
||||
tcx.sess.span_bug(
|
||||
impl_method.span,
|
||||
format!(
|
||||
"method `{}` is not a member of trait `{}`",
|
||||
token::get_ident(impl_item_ty.ident()),
|
||||
pprust::path_to_string(
|
||||
&ast_trait_ref.path)).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -832,16 +853,26 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
|
||||
let provided_methods = ty::provided_trait_methods(tcx,
|
||||
impl_trait_ref.def_id);
|
||||
let mut missing_methods = Vec::new();
|
||||
for trait_method in trait_methods.iter() {
|
||||
let is_implemented =
|
||||
impl_methods.iter().any(
|
||||
|m| m.pe_ident().name == trait_method.ident.name);
|
||||
let is_provided =
|
||||
provided_methods.iter().any(
|
||||
|m| m.ident.name == trait_method.ident.name);
|
||||
if !is_implemented && !is_provided {
|
||||
missing_methods.push(
|
||||
format!("`{}`", token::get_ident(trait_method.ident)));
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(ref trait_method) => {
|
||||
let is_implemented =
|
||||
impl_items.iter().any(|ii| {
|
||||
match *ii {
|
||||
ast::MethodImplItem(m) => {
|
||||
m.pe_ident().name == trait_method.ident.name
|
||||
}
|
||||
}
|
||||
});
|
||||
let is_provided =
|
||||
provided_methods.iter().any(
|
||||
|m| m.ident.name == trait_method.ident.name);
|
||||
if !is_implemented && !is_provided {
|
||||
missing_methods.push(
|
||||
format!("`{}`",
|
||||
token::get_ident(trait_method.ident)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,7 +884,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a method from an impl/class conforms to the signature of
|
||||
* Checks that a method from an impl conforms to the signature of
|
||||
* the same method as declared in the trait.
|
||||
*
|
||||
* # Parameters
|
||||
|
@ -20,7 +20,8 @@ use metadata::csearch;
|
||||
use middle::subst;
|
||||
use middle::subst::{Substs};
|
||||
use middle::ty::get;
|
||||
use middle::ty::{ImplContainer, lookup_item_type};
|
||||
use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
|
||||
use middle::ty::{lookup_item_type};
|
||||
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_param, Polytype, ty_ptr};
|
||||
@ -308,7 +309,7 @@ impl<'a> CoherenceChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let impl_methods = self.create_impl_from_item(item);
|
||||
let impl_items = self.create_impl_from_item(item);
|
||||
|
||||
for associated_trait in associated_traits.iter() {
|
||||
let trait_ref = ty::node_id_to_trait_ref(
|
||||
@ -337,16 +338,17 @@ impl<'a> CoherenceChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
|
||||
tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
|
||||
}
|
||||
|
||||
// Creates default method IDs and performs type substitutions for an impl
|
||||
// and trait pair. Then, for each provided method in the trait, inserts a
|
||||
// `ProvidedMethodInfo` instance into the `provided_method_sources` map.
|
||||
fn instantiate_default_methods(&self,
|
||||
impl_id: DefId,
|
||||
trait_ref: &ty::TraitRef,
|
||||
all_methods: &mut Vec<DefId>) {
|
||||
fn instantiate_default_methods(
|
||||
&self,
|
||||
impl_id: DefId,
|
||||
trait_ref: &ty::TraitRef,
|
||||
all_impl_items: &mut Vec<ImplOrTraitItemId>) {
|
||||
let tcx = self.crate_context.tcx;
|
||||
debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
|
||||
impl_id, trait_ref.repr(tcx));
|
||||
@ -373,7 +375,7 @@ impl<'a> CoherenceChecker<'a> {
|
||||
Some(trait_method.def_id)));
|
||||
|
||||
debug!("new_method_ty={}", new_method_ty.repr(tcx));
|
||||
all_methods.push(new_did);
|
||||
all_impl_items.push(MethodTraitItemId(new_did));
|
||||
|
||||
// construct the polytype for the method based on the
|
||||
// method_ty. it will have all the generics from the
|
||||
@ -385,7 +387,9 @@ impl<'a> CoherenceChecker<'a> {
|
||||
debug!("new_polytype={}", new_polytype.repr(tcx));
|
||||
|
||||
tcx.tcache.borrow_mut().insert(new_did, new_polytype);
|
||||
tcx.methods.borrow_mut().insert(new_did, new_method_ty);
|
||||
tcx.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(new_did, ty::MethodTraitItem(new_method_ty));
|
||||
|
||||
// Pair the new synthesized ID up with the
|
||||
// ID of the method.
|
||||
@ -576,13 +580,20 @@ impl<'a> CoherenceChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Converts an implementation in the AST to a vector of methods.
|
||||
fn create_impl_from_item(&self, item: &Item) -> Vec<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 trait_refs, _, ref ast_methods) => {
|
||||
let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
|
||||
local_def(ast_method.id)
|
||||
}).collect();
|
||||
ItemImpl(_, ref trait_refs, _, ref ast_items) => {
|
||||
let mut items: Vec<ImplOrTraitItemId> =
|
||||
ast_items.iter()
|
||||
.map(|ast_item| {
|
||||
match *ast_item {
|
||||
ast::MethodImplItem(ast_method) => {
|
||||
MethodTraitItemId(
|
||||
local_def(ast_method.id))
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
for trait_ref in trait_refs.iter() {
|
||||
let ty_trait_ref = ty::node_id_to_trait_ref(
|
||||
@ -591,10 +602,10 @@ impl<'a> CoherenceChecker<'a> {
|
||||
|
||||
self.instantiate_default_methods(local_def(item.id),
|
||||
&*ty_trait_ref,
|
||||
&mut methods);
|
||||
&mut items);
|
||||
}
|
||||
|
||||
methods
|
||||
items
|
||||
}
|
||||
_ => {
|
||||
self.crate_context.tcx.sess.span_bug(item.span,
|
||||
@ -614,7 +625,8 @@ impl<'a> CoherenceChecker<'a> {
|
||||
impls_seen: &mut HashSet<DefId>,
|
||||
impl_def_id: DefId) {
|
||||
let tcx = self.crate_context.tcx;
|
||||
let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
|
||||
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
|
||||
impl_def_id);
|
||||
|
||||
// Make sure we don't visit the same implementation multiple times.
|
||||
if !impls_seen.insert(impl_def_id) {
|
||||
@ -629,20 +641,27 @@ impl<'a> CoherenceChecker<'a> {
|
||||
// Do a sanity check.
|
||||
assert!(associated_traits.is_some());
|
||||
|
||||
// Record all the trait methods.
|
||||
// Record all the trait items.
|
||||
for trait_ref in associated_traits.iter() {
|
||||
self.add_trait_impl(trait_ref.def_id, impl_def_id);
|
||||
}
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for &method_def_id in methods.iter() {
|
||||
for &source in ty::method(tcx, method_def_id).provided_source.iter() {
|
||||
tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
|
||||
for item_def_id in impl_items.iter() {
|
||||
let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id());
|
||||
match impl_item {
|
||||
ty::MethodTraitItem(ref method) => {
|
||||
for &source in method.provided_source.iter() {
|
||||
tcx.provided_method_sources
|
||||
.borrow_mut()
|
||||
.insert(item_def_id.def_id(), source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
|
||||
tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
|
||||
}
|
||||
|
||||
// Adds implementations and traits from external crates to the coherence
|
||||
@ -669,28 +688,31 @@ impl<'a> CoherenceChecker<'a> {
|
||||
Some(id) => id, None => { return }
|
||||
};
|
||||
|
||||
let impl_methods = tcx.impl_methods.borrow();
|
||||
let impl_items = tcx.impl_items.borrow();
|
||||
let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
|
||||
None => return, // No types with (new-style) dtors present.
|
||||
Some(found_impls) => found_impls
|
||||
};
|
||||
|
||||
for &impl_did in trait_impls.borrow().iter() {
|
||||
let methods = impl_methods.get(&impl_did);
|
||||
if methods.len() < 1 {
|
||||
let items = impl_items.get(&impl_did);
|
||||
if items.len() < 1 {
|
||||
// We'll error out later. For now, just don't ICE.
|
||||
continue;
|
||||
}
|
||||
let method_def_id = *methods.get(0);
|
||||
let method_def_id = *items.get(0);
|
||||
|
||||
let self_type = self.get_self_type_for_implementation(impl_did);
|
||||
match ty::get(self_type.ty).sty {
|
||||
ty::ty_enum(type_def_id, _) |
|
||||
ty::ty_struct(type_def_id, _) |
|
||||
ty::ty_unboxed_closure(type_def_id, _) => {
|
||||
tcx.destructor_for_type.borrow_mut().insert(type_def_id,
|
||||
method_def_id);
|
||||
tcx.destructors.borrow_mut().insert(method_def_id);
|
||||
tcx.destructor_for_type
|
||||
.borrow_mut()
|
||||
.insert(type_def_id, method_def_id.def_id());
|
||||
tcx.destructors
|
||||
.borrow_mut()
|
||||
.insert(method_def_id.def_id());
|
||||
}
|
||||
_ => {
|
||||
// Destructors only work on nominal types.
|
||||
|
@ -37,7 +37,7 @@ use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::subst;
|
||||
use middle::subst::{Substs};
|
||||
use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
|
||||
use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use middle::ty::{Polytype};
|
||||
use middle::ty;
|
||||
use middle::ty_fold::TypeFolder;
|
||||
@ -200,64 +200,74 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
||||
match tcx.map.get(trait_id) {
|
||||
ast_map::NodeItem(item) => {
|
||||
match item.node {
|
||||
ast::ItemTrait(_, _, _, ref ms) => {
|
||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
||||
// For each method, construct a suitable ty::Method and
|
||||
// store it into the `tcx.methods` table:
|
||||
for m in ms.iter() {
|
||||
let ty_method = Rc::new(match m {
|
||||
&ast::Required(ref m) => {
|
||||
ty_method_of_trait_method(
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
&m.id,
|
||||
&m.ident,
|
||||
&m.explicit_self,
|
||||
m.abi,
|
||||
&m.generics,
|
||||
&m.fn_style,
|
||||
&*m.decl)
|
||||
}
|
||||
// store it into the `tcx.impl_or_trait_items` table:
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ast::RequiredMethod(_) |
|
||||
ast::ProvidedMethod(_) => {
|
||||
let ty_method = Rc::new(match *trait_item {
|
||||
ast::RequiredMethod(ref m) => {
|
||||
ty_method_of_trait_method(
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
&m.id,
|
||||
&m.ident,
|
||||
&m.explicit_self,
|
||||
m.abi,
|
||||
&m.generics,
|
||||
&m.fn_style,
|
||||
&*m.decl)
|
||||
}
|
||||
ast::ProvidedMethod(ref m) => {
|
||||
ty_method_of_trait_method(
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
&m.id,
|
||||
&m.pe_ident(),
|
||||
m.pe_explicit_self(),
|
||||
m.pe_abi(),
|
||||
m.pe_generics(),
|
||||
&m.pe_fn_style(),
|
||||
&*m.pe_fn_decl())
|
||||
}
|
||||
});
|
||||
|
||||
&ast::Provided(ref m) => {
|
||||
ty_method_of_trait_method(
|
||||
ccx,
|
||||
trait_id,
|
||||
&trait_def.generics,
|
||||
&m.id,
|
||||
&m.pe_ident(),
|
||||
m.pe_explicit_self(),
|
||||
m.pe_abi(),
|
||||
m.pe_generics(),
|
||||
&m.pe_fn_style(),
|
||||
&*m.pe_fn_decl())
|
||||
}
|
||||
});
|
||||
if ty_method.explicit_self ==
|
||||
ty::StaticExplicitSelfCategory {
|
||||
make_static_method_ty(ccx, &*ty_method);
|
||||
}
|
||||
|
||||
if ty_method.explicit_self ==
|
||||
ty::StaticExplicitSelfCategory {
|
||||
make_static_method_ty(ccx, &*ty_method);
|
||||
tcx.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(ty_method.def_id,
|
||||
ty::MethodTraitItem(ty_method));
|
||||
}
|
||||
}
|
||||
|
||||
tcx.methods.borrow_mut().insert(ty_method.def_id,
|
||||
ty_method);
|
||||
}
|
||||
|
||||
// Add an entry mapping
|
||||
let method_def_ids = Rc::new(ms.iter().map(|m| {
|
||||
match m {
|
||||
&ast::Required(ref ty_method) => {
|
||||
local_def(ty_method.id)
|
||||
let trait_item_def_ids =
|
||||
Rc::new(trait_items.iter()
|
||||
.map(|ti| {
|
||||
match *ti {
|
||||
ast::RequiredMethod(ref ty_method) => {
|
||||
ty::MethodTraitItemId(local_def(
|
||||
ty_method.id))
|
||||
}
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
ty::MethodTraitItemId(local_def(
|
||||
method.id))
|
||||
}
|
||||
}
|
||||
&ast::Provided(ref method) => {
|
||||
local_def(method.id)
|
||||
}
|
||||
}
|
||||
}).collect());
|
||||
}).collect());
|
||||
|
||||
let trait_def_id = local_def(trait_id);
|
||||
tcx.trait_method_def_ids.borrow_mut()
|
||||
.insert(trait_def_id, method_def_ids);
|
||||
tcx.trait_item_def_ids.borrow_mut()
|
||||
.insert(trait_def_id, trait_item_def_ids);
|
||||
}
|
||||
_ => {} // Ignore things that aren't traits.
|
||||
}
|
||||
@ -346,12 +356,11 @@ pub fn convert_field(ccx: &CrateCtxt,
|
||||
}
|
||||
|
||||
fn convert_methods(ccx: &CrateCtxt,
|
||||
container: MethodContainer,
|
||||
container: ImplOrTraitItemContainer,
|
||||
ms: &[Gc<ast::Method>],
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
rcvr_ty_generics: &ty::Generics,
|
||||
rcvr_visibility: ast::Visibility)
|
||||
{
|
||||
rcvr_visibility: ast::Visibility) {
|
||||
let tcx = ccx.tcx;
|
||||
let mut seen_methods = HashSet::new();
|
||||
for m in ms.iter() {
|
||||
@ -379,11 +388,13 @@ fn convert_methods(ccx: &CrateCtxt,
|
||||
|
||||
write_ty_to_tcx(tcx, m.id, fty);
|
||||
|
||||
tcx.methods.borrow_mut().insert(mty.def_id, mty);
|
||||
tcx.impl_or_trait_items
|
||||
.borrow_mut()
|
||||
.insert(mty.def_id, ty::MethodTraitItem(mty));
|
||||
}
|
||||
|
||||
fn ty_of_method(ccx: &CrateCtxt,
|
||||
container: MethodContainer,
|
||||
container: ImplOrTraitItemContainer,
|
||||
m: &ast::Method,
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
rcvr_ty_generics: &ty::Generics,
|
||||
@ -459,7 +470,10 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
enum_definition.variants.as_slice(),
|
||||
generics);
|
||||
},
|
||||
ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
|
||||
ast::ItemImpl(ref generics,
|
||||
ref opt_trait_ref,
|
||||
selfty,
|
||||
ref impl_items) => {
|
||||
let ty_generics = ty_generics_for_type(ccx, generics);
|
||||
let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
|
||||
write_ty_to_tcx(tcx, it.id, selfty);
|
||||
@ -480,16 +494,22 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
it.vis
|
||||
};
|
||||
|
||||
for method in ms.iter() {
|
||||
check_method_self_type(ccx,
|
||||
&BindingRscope::new(method.id),
|
||||
selfty,
|
||||
method.pe_explicit_self())
|
||||
let mut methods = Vec::new();
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(ref method) => {
|
||||
check_method_self_type(ccx,
|
||||
&BindingRscope::new(method.id),
|
||||
selfty,
|
||||
method.pe_explicit_self());
|
||||
methods.push(*method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert_methods(ccx,
|
||||
ImplContainer(local_def(it.id)),
|
||||
ms.as_slice(),
|
||||
methods.as_slice(),
|
||||
selfty,
|
||||
&ty_generics,
|
||||
parent_visibility);
|
||||
@ -507,14 +527,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
0,
|
||||
local_def(it.id));
|
||||
match *trait_method {
|
||||
ast::Required(ref type_method) => {
|
||||
ast::RequiredMethod(ref type_method) => {
|
||||
let rscope = BindingRscope::new(type_method.id);
|
||||
check_method_self_type(ccx,
|
||||
&rscope,
|
||||
self_type,
|
||||
&type_method.explicit_self)
|
||||
}
|
||||
ast::Provided(ref method) => {
|
||||
ast::ProvidedMethod(ref method) => {
|
||||
check_method_self_type(ccx,
|
||||
&BindingRscope::new(method.id),
|
||||
self_type,
|
||||
|
@ -305,7 +305,8 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
ast_map::NodeMethod(..) => {
|
||||
ast_map::NodeImplItem(..) |
|
||||
ast_map::NodeTraitItem(..) => {
|
||||
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
|
||||
},
|
||||
_ => None
|
||||
@ -699,9 +700,17 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
ast_map::NodeMethod(ref m) => {
|
||||
Some((m.pe_fn_decl(), m.pe_generics(), m.pe_fn_style(),
|
||||
m.pe_ident(), Some(m.pe_explicit_self().node), m.span))
|
||||
ast_map::NodeImplItem(ref item) => {
|
||||
match **item {
|
||||
ast::MethodImplItem(ref m) => {
|
||||
Some((m.pe_fn_decl(),
|
||||
m.pe_generics(),
|
||||
m.pe_fn_style(),
|
||||
m.pe_ident(),
|
||||
Some(m.pe_explicit_self().node),
|
||||
m.span))
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
@ -1454,10 +1463,14 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
ast_map::NodeMethod(m) => {
|
||||
taken.push_all(m.pe_generics().lifetimes.as_slice());
|
||||
Some(m.id)
|
||||
},
|
||||
ast_map::NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
ast::MethodImplItem(m) => {
|
||||
taken.push_all(m.pe_generics().lifetimes.as_slice());
|
||||
Some(m.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
},
|
||||
None => None
|
||||
|
@ -515,10 +515,14 @@ impl<'a> Visitor<()> for ConstraintContext<'a> {
|
||||
}
|
||||
|
||||
ast::ItemTrait(..) => {
|
||||
let methods = ty::trait_methods(tcx, did);
|
||||
for method in methods.iter() {
|
||||
self.add_constraints_from_sig(
|
||||
&method.fty.sig, self.covariant);
|
||||
let trait_items = ty::trait_items(tcx, did);
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(ref method) => {
|
||||
self.add_constraints_from_sig(&method.fty.sig,
|
||||
self.covariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,8 +613,8 @@ impl<'a> ConstraintContext<'a> {
|
||||
_ => cannot_happen!(),
|
||||
}
|
||||
}
|
||||
ast_map::NodeTraitMethod(..) => is_inferred = false,
|
||||
ast_map::NodeMethod(_) => is_inferred = false,
|
||||
ast_map::NodeTraitItem(..) => is_inferred = false,
|
||||
ast_map::NodeImplItem(..) => is_inferred = false,
|
||||
_ => cannot_happen!(),
|
||||
}
|
||||
|
||||
|
@ -762,8 +762,8 @@ impl Repr for ast::DefId {
|
||||
match tcx.map.find(self.node) {
|
||||
Some(ast_map::NodeItem(..)) |
|
||||
Some(ast_map::NodeForeignItem(..)) |
|
||||
Some(ast_map::NodeMethod(..)) |
|
||||
Some(ast_map::NodeTraitMethod(..)) |
|
||||
Some(ast_map::NodeImplItem(..)) |
|
||||
Some(ast_map::NodeTraitItem(..)) |
|
||||
Some(ast_map::NodeVariant(..)) |
|
||||
Some(ast_map::NodeStructCtor(..)) => {
|
||||
return format!(
|
||||
|
@ -480,8 +480,8 @@ mod svh_visitor {
|
||||
SawTyMethod.hash(self.st); visit::walk_ty_method(self, t, e)
|
||||
}
|
||||
|
||||
fn visit_trait_method(&mut self, t: &TraitMethod, e: E) {
|
||||
SawTraitMethod.hash(self.st); visit::walk_trait_method(self, t, e)
|
||||
fn visit_trait_item(&mut self, t: &TraitItem, e: E) {
|
||||
SawTraitMethod.hash(self.st); visit::walk_trait_item(self, t, e)
|
||||
}
|
||||
|
||||
fn visit_struct_field(&mut self, s: &StructField, e: E) {
|
||||
|
@ -157,13 +157,13 @@ pub fn record_extern_fqn(cx: &core::DocContext,
|
||||
|
||||
pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
|
||||
let def = ty::lookup_trait_def(tcx, did);
|
||||
let methods = ty::trait_methods(tcx, did).clean();
|
||||
let trait_items = ty::trait_items(tcx, did).clean();
|
||||
let provided = ty::provided_trait_methods(tcx, did);
|
||||
let mut methods = methods.move_iter().map(|meth| {
|
||||
if provided.iter().any(|a| a.def_id == meth.def_id) {
|
||||
clean::Provided(meth)
|
||||
let mut items = trait_items.move_iter().map(|trait_item| {
|
||||
if provided.iter().any(|a| a.def_id == trait_item.def_id) {
|
||||
clean::ProvidedMethod(trait_item)
|
||||
} else {
|
||||
clean::Required(meth)
|
||||
clean::RequiredMethod(trait_item)
|
||||
}
|
||||
});
|
||||
let supertraits = ty::trait_supertraits(tcx, did);
|
||||
@ -176,7 +176,7 @@ pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
|
||||
|
||||
clean::Trait {
|
||||
generics: (&def.generics, subst::TypeSpace).clean(),
|
||||
methods: methods.collect(),
|
||||
items: items.collect(),
|
||||
parents: parents.collect()
|
||||
}
|
||||
}
|
||||
@ -303,27 +303,33 @@ fn build_impl(cx: &core::DocContext,
|
||||
|
||||
let attrs = load_attrs(tcx, did);
|
||||
let ty = ty::lookup_item_type(tcx, did);
|
||||
let methods = csearch::get_impl_methods(&tcx.sess.cstore,
|
||||
did).iter().filter_map(|did| {
|
||||
let method = ty::method(tcx, *did);
|
||||
if method.vis != ast::Public && associated_trait.is_none() {
|
||||
return None
|
||||
}
|
||||
let mut item = ty::method(tcx, *did).clean();
|
||||
item.inner = match item.inner.clone() {
|
||||
clean::TyMethodItem(clean::TyMethod {
|
||||
fn_style, decl, self_, generics
|
||||
}) => {
|
||||
clean::MethodItem(clean::Method {
|
||||
fn_style: fn_style,
|
||||
decl: decl,
|
||||
self_: self_,
|
||||
generics: generics,
|
||||
})
|
||||
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
|
||||
.iter()
|
||||
.filter_map(|did| {
|
||||
let did = did.def_id();
|
||||
let impl_item = ty::impl_or_trait_item(tcx, did);
|
||||
match impl_item {
|
||||
ty::MethodTraitItem(method) => {
|
||||
if method.vis != ast::Public && associated_trait.is_none() {
|
||||
return None
|
||||
}
|
||||
let mut item = method.clean();
|
||||
item.inner = match item.inner.clone() {
|
||||
clean::TyMethodItem(clean::TyMethod {
|
||||
fn_style, decl, self_, generics
|
||||
}) => {
|
||||
clean::MethodItem(clean::Method {
|
||||
fn_style: fn_style,
|
||||
decl: decl,
|
||||
self_: self_,
|
||||
generics: generics,
|
||||
})
|
||||
}
|
||||
_ => fail!("not a tymethod"),
|
||||
};
|
||||
Some(item)
|
||||
}
|
||||
_ => fail!("not a tymethod"),
|
||||
};
|
||||
Some(item)
|
||||
}
|
||||
}).collect();
|
||||
return Some(clean::Item {
|
||||
inner: clean::ImplItem(clean::Impl {
|
||||
@ -336,7 +342,7 @@ fn build_impl(cx: &core::DocContext,
|
||||
}),
|
||||
for_: ty.ty.clean(),
|
||||
generics: (&ty.generics, subst::TypeSpace).clean(),
|
||||
methods: methods,
|
||||
items: trait_items,
|
||||
}),
|
||||
source: clean::Span::empty(),
|
||||
name: None,
|
||||
|
@ -907,7 +907,7 @@ impl Clean<RetStyle> for ast::RetStyle {
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub struct Trait {
|
||||
pub methods: Vec<TraitMethod>,
|
||||
pub items: Vec<TraitItem>,
|
||||
pub generics: Generics,
|
||||
pub parents: Vec<Type>,
|
||||
}
|
||||
@ -922,7 +922,7 @@ impl Clean<Item> for doctree::Trait {
|
||||
visibility: self.vis.clean(),
|
||||
stability: self.stab.clean(),
|
||||
inner: TraitItem(Trait {
|
||||
methods: self.methods.clean(),
|
||||
items: self.items.clean(),
|
||||
generics: self.generics.clean(),
|
||||
parents: self.parents.clean(),
|
||||
}),
|
||||
@ -937,37 +937,50 @@ impl Clean<Type> for ast::TraitRef {
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub enum TraitMethod {
|
||||
Required(Item),
|
||||
Provided(Item),
|
||||
pub enum TraitItem {
|
||||
RequiredMethod(Item),
|
||||
ProvidedMethod(Item),
|
||||
}
|
||||
|
||||
impl TraitMethod {
|
||||
impl TraitItem {
|
||||
pub fn is_req(&self) -> bool {
|
||||
match self {
|
||||
&Required(..) => true,
|
||||
&RequiredMethod(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_def(&self) -> bool {
|
||||
match self {
|
||||
&Provided(..) => true,
|
||||
&ProvidedMethod(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn item<'a>(&'a self) -> &'a Item {
|
||||
match *self {
|
||||
Required(ref item) => item,
|
||||
Provided(ref item) => item,
|
||||
RequiredMethod(ref item) => item,
|
||||
ProvidedMethod(ref item) => item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<TraitMethod> for ast::TraitMethod {
|
||||
fn clean(&self) -> TraitMethod {
|
||||
impl Clean<TraitItem> for ast::TraitItem {
|
||||
fn clean(&self) -> TraitItem {
|
||||
match self {
|
||||
&ast::Required(ref t) => Required(t.clean()),
|
||||
&ast::Provided(ref t) => Provided(t.clean()),
|
||||
&ast::RequiredMethod(ref t) => RequiredMethod(t.clean()),
|
||||
&ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Encodable, Decodable)]
|
||||
pub enum ImplItem {
|
||||
MethodImplItem(Item),
|
||||
}
|
||||
|
||||
impl Clean<ImplItem> for ast::ImplItem {
|
||||
fn clean(&self) -> ImplItem {
|
||||
match self {
|
||||
&ast::MethodImplItem(ref t) => MethodImplItem(t.clean()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1019,6 +1032,14 @@ impl Clean<Item> for ty::Method {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for ty::ImplOrTraitItem {
|
||||
fn clean(&self) -> Item {
|
||||
match *self {
|
||||
ty::MethodTraitItem(ref mti) => mti.clean(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
|
||||
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
|
||||
/// it does not preserve mutability or boxes.
|
||||
@ -1714,7 +1735,7 @@ pub struct Impl {
|
||||
pub generics: Generics,
|
||||
pub trait_: Option<Type>,
|
||||
pub for_: Type,
|
||||
pub methods: Vec<Item>,
|
||||
pub items: Vec<Item>,
|
||||
pub derived: bool,
|
||||
}
|
||||
|
||||
@ -1735,7 +1756,11 @@ impl Clean<Item> for doctree::Impl {
|
||||
generics: self.generics.clean(),
|
||||
trait_: self.trait_.clean(),
|
||||
for_: self.for_.clean(),
|
||||
methods: self.methods.clean(),
|
||||
items: self.items.clean().move_iter().map(|ti| {
|
||||
match ti {
|
||||
MethodImplItem(i) => i,
|
||||
}
|
||||
}).collect(),
|
||||
derived: detect_derived(self.attrs.as_slice()),
|
||||
}),
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ pub struct Static {
|
||||
|
||||
pub struct Trait {
|
||||
pub name: Ident,
|
||||
pub methods: Vec<ast::TraitMethod>, //should be TraitMethod
|
||||
pub items: Vec<ast::TraitItem>, //should be TraitItem
|
||||
pub generics: ast::Generics,
|
||||
pub parents: Vec<ast::TraitRef>,
|
||||
pub attrs: Vec<ast::Attribute>,
|
||||
@ -168,7 +168,7 @@ pub struct Impl {
|
||||
pub generics: ast::Generics,
|
||||
pub trait_: Option<ast::TraitRef>,
|
||||
pub for_: ast::P<ast::Ty>,
|
||||
pub methods: Vec<Gc<ast::Method>>,
|
||||
pub items: Vec<ast::ImplItem>,
|
||||
pub attrs: Vec<ast::Attribute>,
|
||||
pub where: Span,
|
||||
pub vis: ast::Visibility,
|
||||
|
@ -40,29 +40,31 @@ pub trait DocFolder {
|
||||
EnumItem(i)
|
||||
},
|
||||
TraitItem(mut i) => {
|
||||
fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
|
||||
fn vtrm<T: DocFolder>(this: &mut T, trm: TraitItem)
|
||||
-> Option<TraitItem> {
|
||||
match trm {
|
||||
Required(it) => {
|
||||
RequiredMethod(it) => {
|
||||
match this.fold_item(it) {
|
||||
Some(x) => return Some(Required(x)),
|
||||
Some(x) => return Some(RequiredMethod(x)),
|
||||
None => return None,
|
||||
}
|
||||
},
|
||||
Provided(it) => {
|
||||
ProvidedMethod(it) => {
|
||||
match this.fold_item(it) {
|
||||
Some(x) => return Some(Provided(x)),
|
||||
Some(x) => return Some(ProvidedMethod(x)),
|
||||
None => return None,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
|
||||
i.methods.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
|
||||
let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
|
||||
i.items.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
|
||||
TraitItem(i)
|
||||
},
|
||||
ImplItem(mut i) => {
|
||||
let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
|
||||
i.methods.extend(foo.move_iter().filter_map(|x| self.fold_item(x)));
|
||||
let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
|
||||
i.items.extend(foo.move_iter()
|
||||
.filter_map(|x| self.fold_item(x)));
|
||||
ImplItem(i)
|
||||
},
|
||||
VariantItem(i) => {
|
||||
|
@ -1624,10 +1624,24 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
it.name.get_ref().as_slice(),
|
||||
t.generics,
|
||||
parents));
|
||||
let required = t.methods.iter().filter(|m| m.is_req()).collect::<Vec<&clean::TraitMethod>>();
|
||||
let provided = t.methods.iter().filter(|m| !m.is_req()).collect::<Vec<&clean::TraitMethod>>();
|
||||
let required = t.items.iter()
|
||||
.filter(|m| {
|
||||
match **m {
|
||||
clean::RequiredMethod(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<&clean::TraitItem>>();
|
||||
let provided = t.items.iter()
|
||||
.filter(|m| {
|
||||
match **m {
|
||||
clean::ProvidedMethod(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<&clean::TraitItem>>();
|
||||
|
||||
if t.methods.len() == 0 {
|
||||
if t.items.len() == 0 {
|
||||
try!(write!(w, "{{ }}"));
|
||||
} else {
|
||||
try!(write!(w, "{{\n"));
|
||||
@ -1651,7 +1665,8 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
// Trait documentation
|
||||
try!(document(w, it));
|
||||
|
||||
fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
|
||||
fn trait_item(w: &mut fmt::Formatter, m: &clean::TraitItem)
|
||||
-> fmt::Result {
|
||||
try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
|
||||
shortty(m.item()),
|
||||
*m.item().name.get_ref(),
|
||||
@ -1669,7 +1684,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
<div class='methods'>
|
||||
"));
|
||||
for m in required.iter() {
|
||||
try!(meth(w, *m));
|
||||
try!(trait_item(w, *m));
|
||||
}
|
||||
try!(write!(w, "</div>"));
|
||||
}
|
||||
@ -1679,7 +1694,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
<div class='methods'>
|
||||
"));
|
||||
for m in provided.iter() {
|
||||
try!(meth(w, *m));
|
||||
try!(trait_item(w, *m));
|
||||
}
|
||||
try!(write!(w, "</div>"));
|
||||
}
|
||||
@ -1991,8 +2006,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
|
||||
None => {}
|
||||
}
|
||||
|
||||
fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
|
||||
dox: bool) -> fmt::Result {
|
||||
fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
|
||||
-> fmt::Result {
|
||||
try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
|
||||
*item.name.get_ref(),
|
||||
ConciseStability(&item.stability)));
|
||||
@ -2008,21 +2023,21 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
|
||||
}
|
||||
|
||||
try!(write!(w, "<div class='impl-methods'>"));
|
||||
for meth in i.impl_.methods.iter() {
|
||||
try!(docmeth(w, meth, true));
|
||||
for trait_item in i.impl_.items.iter() {
|
||||
try!(doctraititem(w, trait_item, true));
|
||||
}
|
||||
|
||||
fn render_default_methods(w: &mut fmt::Formatter,
|
||||
t: &clean::Trait,
|
||||
i: &clean::Impl) -> fmt::Result {
|
||||
for method in t.methods.iter() {
|
||||
let n = method.item().name.clone();
|
||||
match i.methods.iter().find(|m| { m.name == n }) {
|
||||
for trait_item in t.items.iter() {
|
||||
let n = trait_item.item().name.clone();
|
||||
match i.items.iter().find(|m| { m.name == n }) {
|
||||
Some(..) => continue,
|
||||
None => {}
|
||||
}
|
||||
|
||||
try!(docmeth(w, method.item(), false));
|
||||
try!(doctraititem(w, trait_item.item(), false));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
||||
clean::ModuleItem(ref m)
|
||||
if m.items.len() == 0 &&
|
||||
i.doc_value().is_none() => None,
|
||||
clean::ImplItem(ref i) if i.methods.len() == 0 => None,
|
||||
clean::ImplItem(ref i) if i.items.len() == 0 => None,
|
||||
_ => {
|
||||
self.retained.insert(i.def_id.node);
|
||||
Some(i)
|
||||
|
@ -21,7 +21,7 @@ use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
|
||||
use syntax::ast::Public;
|
||||
|
||||
use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
|
||||
use clean::{ImplItem, Impl, TraitItem, Trait, TraitMethod, Provided, Required};
|
||||
use clean::{ImplItem, Impl, Trait, TraitItem, ProvidedMethod, RequiredMethod};
|
||||
use clean::{ViewItemItem, PrimitiveItem};
|
||||
|
||||
#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
|
||||
@ -110,7 +110,7 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
|
||||
match item.inner {
|
||||
// Require explicit `pub` to be visible
|
||||
StructItem(Struct { fields: ref subitems, .. }) |
|
||||
ImplItem(Impl { methods: ref subitems, trait_: None, .. }) => {
|
||||
ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
|
||||
let subcounts = subitems.iter().filter(|i| visible(*i))
|
||||
.map(summarize_item)
|
||||
.map(|s| s.val0())
|
||||
@ -124,16 +124,21 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
|
||||
.sum();
|
||||
(item_counts + subcounts, None)
|
||||
}
|
||||
TraitItem(Trait { methods: ref methods, .. }) => {
|
||||
fn extract_item<'a>(meth: &'a TraitMethod) -> &'a Item {
|
||||
match *meth {
|
||||
Provided(ref item) | Required(ref item) => item
|
||||
TraitItem(Trait {
|
||||
items: ref trait_items,
|
||||
..
|
||||
}) => {
|
||||
fn extract_item<'a>(trait_item: &'a TraitItem) -> &'a Item {
|
||||
match *trait_item {
|
||||
ProvidedMethod(ref item) |
|
||||
RequiredMethod(ref item) => item
|
||||
}
|
||||
}
|
||||
let subcounts = methods.iter().map(extract_item)
|
||||
.map(summarize_item)
|
||||
.map(|s| s.val0())
|
||||
.sum();
|
||||
let subcounts = trait_items.iter()
|
||||
.map(extract_item)
|
||||
.map(summarize_item)
|
||||
.map(|s| s.val0())
|
||||
.sum();
|
||||
(item_counts + subcounts, None)
|
||||
}
|
||||
ModuleItem(Module { items: ref items, .. }) => {
|
||||
|
@ -317,10 +317,10 @@ impl<'a> RustdocVisitor<'a> {
|
||||
};
|
||||
om.statics.push(s);
|
||||
},
|
||||
ast::ItemTrait(ref gen, _, ref tr, ref met) => {
|
||||
ast::ItemTrait(ref gen, _, ref tr, ref items) => {
|
||||
let t = Trait {
|
||||
name: item.ident,
|
||||
methods: met.iter().map(|x| (*x).clone()).collect(),
|
||||
items: items.iter().map(|x| (*x).clone()).collect(),
|
||||
generics: gen.clone(),
|
||||
parents: tr.iter().map(|x| (*x).clone()).collect(),
|
||||
id: item.id,
|
||||
@ -331,12 +331,12 @@ impl<'a> RustdocVisitor<'a> {
|
||||
};
|
||||
om.traits.push(t);
|
||||
},
|
||||
ast::ItemImpl(ref gen, ref tr, ty, ref meths) => {
|
||||
ast::ItemImpl(ref gen, ref tr, ty, ref items) => {
|
||||
let i = Impl {
|
||||
generics: gen.clone(),
|
||||
trait_: tr.clone(),
|
||||
for_: ty,
|
||||
methods: meths.iter().map(|x| *x).collect(),
|
||||
items: items.iter().map(|x| *x).collect(),
|
||||
attrs: item.attrs.iter().map(|x| *x).collect(),
|
||||
id: item.id,
|
||||
where: item.span,
|
||||
|
@ -767,9 +767,14 @@ pub struct TypeMethod {
|
||||
/// doesn't have an implementation, just a signature) or provided (meaning it
|
||||
/// has a default implementation).
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum TraitMethod {
|
||||
Required(TypeMethod),
|
||||
Provided(Gc<Method>),
|
||||
pub enum TraitItem {
|
||||
RequiredMethod(TypeMethod),
|
||||
ProvidedMethod(Gc<Method>),
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum ImplItem {
|
||||
MethodImplItem(Gc<Method>),
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
|
||||
@ -1273,11 +1278,11 @@ pub enum Item_ {
|
||||
Option<TyParamBound>, // (optional) default bound not required for Self.
|
||||
// Currently, only Sized makes sense here.
|
||||
Vec<TraitRef> ,
|
||||
Vec<TraitMethod>),
|
||||
Vec<TraitItem>),
|
||||
ItemImpl(Generics,
|
||||
Option<TraitRef>, // (optional) trait this impl implements
|
||||
P<Ty>, // self
|
||||
Vec<Gc<Method>>),
|
||||
Vec<ImplItem>),
|
||||
/// A macro invocation (which includes macro definition)
|
||||
ItemMac(Mac),
|
||||
}
|
||||
@ -1311,10 +1316,16 @@ pub enum UnboxedClosureKind {
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum InlinedItem {
|
||||
IIItem(Gc<Item>),
|
||||
IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
|
||||
IITraitItem(DefId /* impl id */, InlinedTraitItem),
|
||||
IIForeign(Gc<ForeignItem>),
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum InlinedTraitItem {
|
||||
ProvidedInlinedTraitItem(Gc<Method>),
|
||||
RequiredInlinedTraitItem(Gc<Method>),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use serialize::json;
|
||||
|
@ -60,9 +60,9 @@ impl MaybeFnLike for ast::Item {
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeFnLike for ast::TraitMethod {
|
||||
impl MaybeFnLike for ast::TraitItem {
|
||||
fn is_fn_like(&self) -> bool {
|
||||
match *self { ast::Provided(_) => true, _ => false, }
|
||||
match *self { ast::ProvidedMethod(_) => true, _ => false, }
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,9 +97,9 @@ impl Code {
|
||||
match node {
|
||||
ast_map::NodeItem(item) if item.is_fn_like() =>
|
||||
Some(FnLikeCode(new(node))),
|
||||
ast_map::NodeTraitMethod(tm) if tm.is_fn_like() =>
|
||||
ast_map::NodeTraitItem(tm) if tm.is_fn_like() =>
|
||||
Some(FnLikeCode(new(node))),
|
||||
ast_map::NodeMethod(_) =>
|
||||
ast_map::NodeImplItem(_) =>
|
||||
Some(FnLikeCode(new(node))),
|
||||
ast_map::NodeExpr(e) if e.is_fn_like() =>
|
||||
Some(FnLikeCode(new(node))),
|
||||
@ -200,11 +200,15 @@ impl FnLikeNode {
|
||||
}),
|
||||
_ => fail!("item FnLikeNode that is not fn-like"),
|
||||
},
|
||||
ast_map::NodeTraitMethod(ref t) => match **t {
|
||||
ast::Provided(ref m) => method(&**m),
|
||||
ast_map::NodeTraitItem(ref t) => match **t {
|
||||
ast::ProvidedMethod(ref m) => method(&**m),
|
||||
_ => fail!("trait method FnLikeNode that is not fn-like"),
|
||||
},
|
||||
ast_map::NodeMethod(ref m) => method(&**m),
|
||||
ast_map::NodeImplItem(ref ii) => {
|
||||
match **ii {
|
||||
ast::MethodImplItem(ref m) => method(&**m),
|
||||
}
|
||||
}
|
||||
ast_map::NodeExpr(ref e) => match e.node {
|
||||
ast::ExprFnBlock(_, ref decl, ref block) =>
|
||||
closure(ClosureParts::new(*decl, *block, e.id, e.span)),
|
||||
|
@ -99,8 +99,8 @@ pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String {
|
||||
pub enum Node {
|
||||
NodeItem(Gc<Item>),
|
||||
NodeForeignItem(Gc<ForeignItem>),
|
||||
NodeTraitMethod(Gc<TraitMethod>),
|
||||
NodeMethod(Gc<Method>),
|
||||
NodeTraitItem(Gc<TraitItem>),
|
||||
NodeImplItem(Gc<ImplItem>),
|
||||
NodeVariant(P<Variant>),
|
||||
NodeExpr(Gc<Expr>),
|
||||
NodeStmt(Gc<Stmt>),
|
||||
@ -125,8 +125,8 @@ enum MapEntry {
|
||||
/// All the node types, with a parent ID.
|
||||
EntryItem(NodeId, Gc<Item>),
|
||||
EntryForeignItem(NodeId, Gc<ForeignItem>),
|
||||
EntryTraitMethod(NodeId, Gc<TraitMethod>),
|
||||
EntryMethod(NodeId, Gc<Method>),
|
||||
EntryTraitItem(NodeId, Gc<TraitItem>),
|
||||
EntryImplItem(NodeId, Gc<ImplItem>),
|
||||
EntryVariant(NodeId, P<Variant>),
|
||||
EntryExpr(NodeId, Gc<Expr>),
|
||||
EntryStmt(NodeId, Gc<Stmt>),
|
||||
@ -144,7 +144,7 @@ enum MapEntry {
|
||||
|
||||
struct InlinedParent {
|
||||
path: Vec<PathElem> ,
|
||||
/// Required by NodeTraitMethod and NodeMethod.
|
||||
/// RequiredMethod by NodeTraitItem and NodeImplItem.
|
||||
def_id: DefId
|
||||
}
|
||||
|
||||
@ -153,8 +153,8 @@ impl MapEntry {
|
||||
Some(match *self {
|
||||
EntryItem(id, _) => id,
|
||||
EntryForeignItem(id, _) => id,
|
||||
EntryTraitMethod(id, _) => id,
|
||||
EntryMethod(id, _) => id,
|
||||
EntryTraitItem(id, _) => id,
|
||||
EntryImplItem(id, _) => id,
|
||||
EntryVariant(id, _) => id,
|
||||
EntryExpr(id, _) => id,
|
||||
EntryStmt(id, _) => id,
|
||||
@ -172,8 +172,8 @@ impl MapEntry {
|
||||
Some(match *self {
|
||||
EntryItem(_, p) => NodeItem(p),
|
||||
EntryForeignItem(_, p) => NodeForeignItem(p),
|
||||
EntryTraitMethod(_, p) => NodeTraitMethod(p),
|
||||
EntryMethod(_, p) => NodeMethod(p),
|
||||
EntryTraitItem(_, p) => NodeTraitItem(p),
|
||||
EntryImplItem(_, p) => NodeImplItem(p),
|
||||
EntryVariant(_, p) => NodeVariant(p),
|
||||
EntryExpr(_, p) => NodeExpr(p),
|
||||
EntryStmt(_, p) => NodeStmt(p),
|
||||
@ -324,13 +324,23 @@ impl Map {
|
||||
}
|
||||
}
|
||||
NodeForeignItem(i) => PathName(i.ident.name),
|
||||
NodeMethod(m) => match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) => PathName(ident.name),
|
||||
MethMac(_) => fail!("no path elem for {:?}", node)
|
||||
NodeImplItem(ii) => {
|
||||
match *ii {
|
||||
MethodImplItem(ref m) => {
|
||||
match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) => {
|
||||
PathName(ident.name)
|
||||
}
|
||||
MethMac(_) => {
|
||||
fail!("no path elem for {:?}", node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
NodeTraitMethod(tm) => match *tm {
|
||||
Required(ref m) => PathName(m.ident.name),
|
||||
Provided(m) => match m.node {
|
||||
NodeTraitItem(tm) => match *tm {
|
||||
RequiredMethod(ref m) => PathName(m.ident.name),
|
||||
ProvidedMethod(m) => match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) => {
|
||||
PathName(ident.name)
|
||||
}
|
||||
@ -393,11 +403,15 @@ impl Map {
|
||||
let attrs = match node {
|
||||
NodeItem(ref i) => Some(i.attrs.as_slice()),
|
||||
NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
|
||||
NodeTraitMethod(ref tm) => match **tm {
|
||||
Required(ref type_m) => Some(type_m.attrs.as_slice()),
|
||||
Provided(ref m) => Some(m.attrs.as_slice())
|
||||
NodeTraitItem(ref tm) => match **tm {
|
||||
RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()),
|
||||
ProvidedMethod(ref m) => Some(m.attrs.as_slice())
|
||||
},
|
||||
NodeMethod(ref m) => Some(m.attrs.as_slice()),
|
||||
NodeImplItem(ref ii) => {
|
||||
match **ii {
|
||||
MethodImplItem(ref m) => Some(m.attrs.as_slice()),
|
||||
}
|
||||
}
|
||||
NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
|
||||
// unit/tuple structs take the attributes straight from
|
||||
// the struct definition.
|
||||
@ -428,13 +442,17 @@ impl Map {
|
||||
let sp = match self.find(id) {
|
||||
Some(NodeItem(item)) => item.span,
|
||||
Some(NodeForeignItem(foreign_item)) => foreign_item.span,
|
||||
Some(NodeTraitMethod(trait_method)) => {
|
||||
Some(NodeTraitItem(trait_method)) => {
|
||||
match *trait_method {
|
||||
Required(ref type_method) => type_method.span,
|
||||
Provided(ref method) => method.span,
|
||||
RequiredMethod(ref type_method) => type_method.span,
|
||||
ProvidedMethod(ref method) => method.span,
|
||||
}
|
||||
}
|
||||
Some(NodeImplItem(ref impl_item)) => {
|
||||
match **impl_item {
|
||||
MethodImplItem(ref method) => method.span,
|
||||
}
|
||||
}
|
||||
Some(NodeMethod(method)) => method.span,
|
||||
Some(NodeVariant(variant)) => variant.span,
|
||||
Some(NodeExpr(expr)) => expr.span,
|
||||
Some(NodeStmt(stmt)) => stmt.span,
|
||||
@ -532,8 +550,8 @@ impl<'a,S:Str> Iterator<NodeId> for NodesMatchingSuffix<'a,S> {
|
||||
let (p, name) = match self.map.find_entry(idx) {
|
||||
Some(EntryItem(p, n)) => (p, n.name()),
|
||||
Some(EntryForeignItem(p, n)) => (p, n.name()),
|
||||
Some(EntryTraitMethod(p, n)) => (p, n.name()),
|
||||
Some(EntryMethod(p, n)) => (p, n.name()),
|
||||
Some(EntryTraitItem(p, n)) => (p, n.name()),
|
||||
Some(EntryImplItem(p, n)) => (p, n.name()),
|
||||
Some(EntryVariant(p, n)) => (p, n.name()),
|
||||
_ => continue,
|
||||
};
|
||||
@ -553,11 +571,18 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
|
||||
impl Named for Item { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
|
||||
impl Named for Variant_ { fn name(&self) -> Name { self.name.name } }
|
||||
impl Named for TraitMethod {
|
||||
impl Named for TraitItem {
|
||||
fn name(&self) -> Name {
|
||||
match *self {
|
||||
Required(ref tm) => tm.ident.name,
|
||||
Provided(m) => m.name(),
|
||||
RequiredMethod(ref tm) => tm.ident.name,
|
||||
ProvidedMethod(m) => m.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Named for ImplItem {
|
||||
fn name(&self) -> Name {
|
||||
match *self {
|
||||
MethodImplItem(ref m) => m.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,9 +641,15 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
|
||||
assert_eq!(self.parent, i.id);
|
||||
|
||||
match i.node {
|
||||
ItemImpl(_, _, _, ref ms) => {
|
||||
for &m in ms.iter() {
|
||||
self.insert(m.id, EntryMethod(self.parent, m));
|
||||
ItemImpl(_, _, _, ref impl_items) => {
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
MethodImplItem(m) => {
|
||||
self.insert(m.id,
|
||||
EntryImplItem(self.parent,
|
||||
box(GC) *impl_item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemEnum(ref enum_definition, _) => {
|
||||
@ -649,13 +680,13 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
|
||||
|
||||
for tm in methods.iter() {
|
||||
match *tm {
|
||||
Required(ref m) => {
|
||||
self.insert(m.id, EntryTraitMethod(self.parent,
|
||||
RequiredMethod(ref m) => {
|
||||
self.insert(m.id, EntryTraitItem(self.parent,
|
||||
box(GC) (*tm).clone()));
|
||||
}
|
||||
Provided(m) => {
|
||||
self.insert(m.id, EntryTraitMethod(self.parent,
|
||||
box(GC) Provided(m)));
|
||||
ProvidedMethod(m) => {
|
||||
self.insert(m.id, EntryTraitItem(self.parent,
|
||||
box(GC) ProvidedMethod(m)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -798,13 +829,18 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
|
||||
let ii = fold(&mut cx);
|
||||
match ii {
|
||||
IIItem(_) => {}
|
||||
IIMethod(impl_did, is_provided, m) => {
|
||||
let entry = if is_provided {
|
||||
EntryTraitMethod(cx.parent, box(GC) Provided(m))
|
||||
} else {
|
||||
EntryMethod(cx.parent, m)
|
||||
IITraitItem(impl_did, inlined_trait_item) => {
|
||||
let (trait_item_id, entry) = match inlined_trait_item {
|
||||
ProvidedInlinedTraitItem(m) => {
|
||||
(m.id,
|
||||
EntryTraitItem(cx.parent, box(GC) ProvidedMethod(m)))
|
||||
}
|
||||
RequiredInlinedTraitItem(m) => {
|
||||
(m.id,
|
||||
EntryImplItem(cx.parent, box(GC) MethodImplItem(m)))
|
||||
}
|
||||
};
|
||||
cx.insert(m.id, entry);
|
||||
cx.insert(trait_item_id, entry);
|
||||
def_id = impl_did;
|
||||
}
|
||||
IIForeign(i) => {
|
||||
@ -829,8 +865,8 @@ impl<'a> NodePrinter for pprust::State<'a> {
|
||||
match *node {
|
||||
NodeItem(a) => self.print_item(&*a),
|
||||
NodeForeignItem(a) => self.print_foreign_item(&*a),
|
||||
NodeTraitMethod(a) => self.print_trait_method(&*a),
|
||||
NodeMethod(a) => self.print_method(&*a),
|
||||
NodeTraitItem(a) => self.print_trait_method(&*a),
|
||||
NodeImplItem(a) => self.print_impl_item(&*a),
|
||||
NodeVariant(a) => self.print_variant(&*a),
|
||||
NodeExpr(a) => self.print_expr(&*a),
|
||||
NodeStmt(a) => self.print_stmt(&*a),
|
||||
@ -870,17 +906,23 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
|
||||
let path_str = map.path_to_str_with_ident(id, item.ident);
|
||||
format!("foreign item {} (id={})", path_str, id)
|
||||
}
|
||||
Some(NodeMethod(m)) => match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) =>
|
||||
format!("method {} in {} (id={})",
|
||||
token::get_ident(ident),
|
||||
map.path_to_string(id), id),
|
||||
MethMac(ref mac) =>
|
||||
format!("method macro {} (id={})",
|
||||
pprust::mac_to_string(mac), id)
|
||||
},
|
||||
Some(NodeTraitMethod(ref tm)) => {
|
||||
let m = ast_util::trait_method_to_ty_method(&**tm);
|
||||
Some(NodeImplItem(ref ii)) => {
|
||||
match **ii {
|
||||
MethodImplItem(ref m) => {
|
||||
match m.node {
|
||||
MethDecl(ident, _, _, _, _, _, _, _) =>
|
||||
format!("method {} in {} (id={})",
|
||||
token::get_ident(ident),
|
||||
map.path_to_string(id), id),
|
||||
MethMac(ref mac) =>
|
||||
format!("method macro {} (id={})",
|
||||
pprust::mac_to_string(mac), id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(NodeTraitItem(ref tm)) => {
|
||||
let m = ast_util::trait_item_to_ty_method(&**tm);
|
||||
format!("method {} in {} (id={})",
|
||||
token::get_ident(m.ident),
|
||||
map.path_to_string(id), id)
|
||||
|
@ -241,51 +241,52 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
|
||||
token::gensym_ident(pretty.as_slice())
|
||||
}
|
||||
|
||||
/// extract a TypeMethod from a TraitMethod. if the TraitMethod is
|
||||
/// a default, pull out the useful fields to make a TypeMethod
|
||||
//
|
||||
// NB: to be used only after expansion is complete, and macros are gone.
|
||||
pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
|
||||
match *method {
|
||||
Required(ref m) => (*m).clone(),
|
||||
Provided(m) => {
|
||||
match m.node {
|
||||
MethDecl(ident,
|
||||
ref generics,
|
||||
abi,
|
||||
explicit_self,
|
||||
fn_style,
|
||||
decl,
|
||||
_,
|
||||
vis) => {
|
||||
TypeMethod {
|
||||
ident: ident,
|
||||
attrs: m.attrs.clone(),
|
||||
fn_style: fn_style,
|
||||
decl: decl,
|
||||
generics: generics.clone(),
|
||||
explicit_self: explicit_self,
|
||||
id: m.id,
|
||||
span: m.span,
|
||||
vis: vis,
|
||||
abi: abi,
|
||||
}
|
||||
},
|
||||
MethMac(_) => fail!("expected non-macro method declaration")
|
||||
pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
|
||||
match method.node {
|
||||
MethDecl(ident,
|
||||
ref generics,
|
||||
abi,
|
||||
explicit_self,
|
||||
fn_style,
|
||||
decl,
|
||||
_,
|
||||
vis) => {
|
||||
TypeMethod {
|
||||
ident: ident,
|
||||
attrs: method.attrs.clone(),
|
||||
fn_style: fn_style,
|
||||
decl: decl,
|
||||
generics: generics.clone(),
|
||||
explicit_self: explicit_self,
|
||||
id: method.id,
|
||||
span: method.span,
|
||||
vis: vis,
|
||||
abi: abi,
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
MethMac(_) => fail!("expected non-macro method declaration")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_trait_methods(trait_methods: &[TraitMethod])
|
||||
/// extract a TypeMethod from a TraitItem. if the TraitItem is
|
||||
/// a default, pull out the useful fields to make a TypeMethod
|
||||
//
|
||||
// NB: to be used only after expansion is complete, and macros are gone.
|
||||
pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod {
|
||||
match *method {
|
||||
RequiredMethod(ref m) => (*m).clone(),
|
||||
ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn split_trait_methods(trait_methods: &[TraitItem])
|
||||
-> (Vec<TypeMethod> , Vec<Gc<Method>> ) {
|
||||
let mut reqd = Vec::new();
|
||||
let mut provd = Vec::new();
|
||||
for trt_method in trait_methods.iter() {
|
||||
match *trt_method {
|
||||
Required(ref tm) => reqd.push((*tm).clone()),
|
||||
Provided(m) => provd.push(m)
|
||||
RequiredMethod(ref tm) => reqd.push((*tm).clone()),
|
||||
ProvidedMethod(m) => provd.push(m)
|
||||
}
|
||||
};
|
||||
(reqd, provd)
|
||||
@ -543,12 +544,12 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
|
||||
visit::walk_struct_def(self, struct_def, ());
|
||||
}
|
||||
|
||||
fn visit_trait_method(&mut self, tm: &ast::TraitMethod, _: ()) {
|
||||
fn visit_trait_item(&mut self, tm: &ast::TraitItem, _: ()) {
|
||||
match *tm {
|
||||
ast::Required(ref m) => self.operation.visit_id(m.id),
|
||||
ast::Provided(ref m) => self.operation.visit_id(m.id),
|
||||
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
|
||||
ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
|
||||
}
|
||||
visit::walk_trait_method(self, tm, ());
|
||||
visit::walk_trait_item(self, tm, ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,8 +452,13 @@ impl<'a> TraitDef<'a> {
|
||||
self.span,
|
||||
ident,
|
||||
(vec!(attr)).append(self.attributes.as_slice()),
|
||||
ast::ItemImpl(trait_generics, opt_trait_ref,
|
||||
self_type, methods))
|
||||
ast::ItemImpl(trait_generics,
|
||||
opt_trait_ref,
|
||||
self_type,
|
||||
methods.move_iter()
|
||||
.map(|method| {
|
||||
ast::MethodImplItem(method)
|
||||
}).collect()))
|
||||
}
|
||||
|
||||
fn expand_struct_def(&self,
|
||||
|
@ -834,26 +834,37 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
|
||||
let struct_def = folder.fold_struct_def(*struct_def);
|
||||
ItemStruct(struct_def, folder.fold_generics(generics))
|
||||
}
|
||||
ItemImpl(ref generics, ref ifce, ty, ref methods) => {
|
||||
ItemImpl(ref generics, ref ifce, ty, ref impl_items) => {
|
||||
ItemImpl(folder.fold_generics(generics),
|
||||
ifce.as_ref().map(|p| folder.fold_trait_ref(p)),
|
||||
folder.fold_ty(ty),
|
||||
methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
|
||||
impl_items.iter()
|
||||
.flat_map(|impl_item| {
|
||||
match *impl_item {
|
||||
MethodImplItem(x) => {
|
||||
folder.fold_method(x)
|
||||
.move_iter()
|
||||
.map(|x| MethodImplItem(x))
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
)
|
||||
}
|
||||
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
|
||||
let methods = methods.iter().flat_map(|method| {
|
||||
let r = match *method {
|
||||
Required(ref m) =>
|
||||
SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
|
||||
Provided(method) => {
|
||||
RequiredMethod(ref m) => {
|
||||
SmallVector::one(RequiredMethod(
|
||||
folder.fold_type_method(m))).move_iter()
|
||||
}
|
||||
ProvidedMethod(method) => {
|
||||
// the awkward collect/iter idiom here is because
|
||||
// even though an iter and a map satisfy the same trait bound,
|
||||
// they're not actually the same type, so the method arms
|
||||
// don't unify.
|
||||
let methods : SmallVector<ast::TraitMethod> =
|
||||
let methods : SmallVector<ast::TraitItem> =
|
||||
folder.fold_method(method).move_iter()
|
||||
.map(|m| Provided(m)).collect();
|
||||
.map(|m| ProvidedMethod(m)).collect();
|
||||
methods.move_iter()
|
||||
}
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
use abi;
|
||||
use ast::{BareFnTy, ClosureTy};
|
||||
use ast::{StaticRegionTyParamBound, OtherRegionTyParamBound, TraitTyParamBound};
|
||||
use ast::{Provided, Public, FnStyle};
|
||||
use ast::{ProvidedMethod, Public, FnStyle};
|
||||
use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
|
||||
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
|
||||
use ast::{BlockCheckMode, UnBox};
|
||||
@ -33,23 +33,24 @@ use ast::{ExprVstoreUniq, Once, Many};
|
||||
use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
|
||||
use ast::{FnOnceUnboxedClosureKind};
|
||||
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
|
||||
use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
|
||||
use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
|
||||
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
|
||||
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
|
||||
use ast::{LitBool, LitChar, LitByte, LitBinary};
|
||||
use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
|
||||
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
|
||||
use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
|
||||
use ast::{MethodImplItem};
|
||||
use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum};
|
||||
use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
|
||||
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
|
||||
use ast::{BiRem, Required};
|
||||
use ast::{BiRem, RequiredMethod};
|
||||
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
|
||||
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
|
||||
use ast::{StructVariantKind, BiSub};
|
||||
use ast::StrStyle;
|
||||
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
|
||||
use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
|
||||
use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
|
||||
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
@ -1238,7 +1239,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse the methods in a trait declaration
|
||||
pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
|
||||
pub fn parse_trait_methods(&mut self) -> Vec<TraitItem> {
|
||||
self.parse_unspanned_seq(
|
||||
&token::LBRACE,
|
||||
&token::RBRACE,
|
||||
@ -1276,7 +1277,7 @@ impl<'a> Parser<'a> {
|
||||
token::SEMI => {
|
||||
p.bump();
|
||||
debug!("parse_trait_methods(): parsing required method");
|
||||
Required(TypeMethod {
|
||||
RequiredMethod(TypeMethod {
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
fn_style: style,
|
||||
@ -1294,7 +1295,7 @@ impl<'a> Parser<'a> {
|
||||
let (inner_attrs, body) =
|
||||
p.parse_inner_attrs_and_block();
|
||||
let attrs = attrs.append(inner_attrs.as_slice());
|
||||
Provided(box(GC) ast::Method {
|
||||
ProvidedMethod(box(GC) ast::Method {
|
||||
attrs: attrs,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
@ -4243,6 +4244,18 @@ impl<'a> Parser<'a> {
|
||||
(ident, ItemTrait(tps, sized, traits, meths), None)
|
||||
}
|
||||
|
||||
fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
|
||||
let mut impl_items = Vec::new();
|
||||
self.expect(&token::LBRACE);
|
||||
let (inner_attrs, next) = self.parse_inner_attrs_and_next();
|
||||
let mut method_attrs = Some(next);
|
||||
while !self.eat(&token::RBRACE) {
|
||||
impl_items.push(MethodImplItem(self.parse_method(method_attrs)));
|
||||
method_attrs = None;
|
||||
}
|
||||
(impl_items, inner_attrs)
|
||||
}
|
||||
|
||||
/// Parses two variants (with the region/type params always optional):
|
||||
/// impl<T> Foo { ... }
|
||||
/// impl<T> ToString for ~[T] { ... }
|
||||
@ -4284,18 +4297,13 @@ impl<'a> Parser<'a> {
|
||||
None
|
||||
};
|
||||
|
||||
let mut meths = Vec::new();
|
||||
self.expect(&token::LBRACE);
|
||||
let (inner_attrs, next) = self.parse_inner_attrs_and_next();
|
||||
let mut method_attrs = Some(next);
|
||||
while !self.eat(&token::RBRACE) {
|
||||
meths.push(self.parse_method(method_attrs));
|
||||
method_attrs = None;
|
||||
}
|
||||
let (impl_items, attrs) = self.parse_impl_items();
|
||||
|
||||
let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
|
||||
|
||||
(ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
|
||||
(ident,
|
||||
ItemImpl(generics, opt_trait, ty, impl_items),
|
||||
Some(attrs))
|
||||
}
|
||||
|
||||
/// Parse a::B<String,int>
|
||||
|
@ -10,9 +10,9 @@
|
||||
|
||||
use abi;
|
||||
use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
|
||||
use ast::{FnUnboxedClosureKind, P, OtherRegionTyParamBound};
|
||||
use ast::{FnUnboxedClosureKind, MethodImplItem, P, OtherRegionTyParamBound};
|
||||
use ast::{StaticRegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
|
||||
use ast::{UnboxedFnTyParamBound, Required, Provided};
|
||||
use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
|
||||
use ast;
|
||||
use ast_util;
|
||||
use owned_slice::OwnedSlice;
|
||||
@ -787,7 +787,10 @@ impl<'a> State<'a> {
|
||||
item.span));
|
||||
}
|
||||
|
||||
ast::ItemImpl(ref generics, ref opt_trait, ref ty, ref methods) => {
|
||||
ast::ItemImpl(ref generics,
|
||||
ref opt_trait,
|
||||
ref ty,
|
||||
ref impl_items) => {
|
||||
try!(self.head(visibility_qualified(item.vis,
|
||||
"impl").as_slice()));
|
||||
if generics.is_parameterized() {
|
||||
@ -809,8 +812,12 @@ impl<'a> State<'a> {
|
||||
try!(space(&mut self.s));
|
||||
try!(self.bopen());
|
||||
try!(self.print_inner_attributes(item.attrs.as_slice()));
|
||||
for meth in methods.iter() {
|
||||
try!(self.print_method(&**meth));
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(meth) => {
|
||||
try!(self.print_method(&*meth));
|
||||
}
|
||||
}
|
||||
}
|
||||
try!(self.bclose(item.span));
|
||||
}
|
||||
@ -1061,10 +1068,16 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn print_trait_method(&mut self,
|
||||
m: &ast::TraitMethod) -> IoResult<()> {
|
||||
m: &ast::TraitItem) -> IoResult<()> {
|
||||
match *m {
|
||||
Required(ref ty_m) => self.print_ty_method(ty_m),
|
||||
Provided(ref m) => self.print_method(&**m)
|
||||
RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
|
||||
ProvidedMethod(ref m) => self.print_method(&**m)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> {
|
||||
match *ii {
|
||||
MethodImplItem(ref m) => self.print_method(&**m),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ pub trait Visitor<E: Clone> {
|
||||
walk_fn(self, fk, fd, b, s, e)
|
||||
}
|
||||
fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
|
||||
fn visit_trait_method(&mut self, t: &TraitMethod, e: E) { walk_trait_method(self, t, e) }
|
||||
fn visit_trait_item(&mut self, t: &TraitItem, e: E) { walk_trait_item(self, t, e) }
|
||||
fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics, _: NodeId, e: E) {
|
||||
walk_struct_def(self, s, e)
|
||||
}
|
||||
@ -148,7 +148,16 @@ pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||
match *item {
|
||||
IIItem(i) => visitor.visit_item(&*i, env),
|
||||
IIForeign(i) => visitor.visit_foreign_item(&*i, env),
|
||||
IIMethod(_, _, m) => walk_method_helper(visitor, &*m, env),
|
||||
IITraitItem(_, iti) => {
|
||||
match iti {
|
||||
ProvidedInlinedTraitItem(m) => {
|
||||
walk_method_helper(visitor, &*m, env)
|
||||
}
|
||||
RequiredInlinedTraitItem(m) => {
|
||||
walk_method_helper(visitor, &*m, env)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +278,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
|
||||
ItemImpl(ref type_parameters,
|
||||
ref trait_reference,
|
||||
typ,
|
||||
ref methods) => {
|
||||
ref impl_items) => {
|
||||
visitor.visit_generics(type_parameters, env.clone());
|
||||
match *trait_reference {
|
||||
Some(ref trait_reference) => walk_trait_ref_helper(visitor,
|
||||
@ -277,8 +286,12 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
|
||||
None => ()
|
||||
}
|
||||
visitor.visit_ty(&*typ, env.clone());
|
||||
for method in methods.iter() {
|
||||
walk_method_helper(visitor, &**method, env.clone())
|
||||
for impl_item in impl_items.iter() {
|
||||
match *impl_item {
|
||||
MethodImplItem(method) => {
|
||||
walk_method_helper(visitor, &*method, env.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemStruct(ref struct_definition, ref generics) => {
|
||||
@ -297,7 +310,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
|
||||
env.clone())
|
||||
}
|
||||
for method in methods.iter() {
|
||||
visitor.visit_trait_method(method, env.clone())
|
||||
visitor.visit_trait_item(method, env.clone())
|
||||
}
|
||||
}
|
||||
ItemMac(ref macro) => visitor.visit_mac(macro, env.clone()),
|
||||
@ -626,14 +639,14 @@ pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||
trait_method: &TraitMethod,
|
||||
pub fn walk_trait_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||
trait_method: &TraitItem,
|
||||
env: E) {
|
||||
match *trait_method {
|
||||
Required(ref method_type) => {
|
||||
RequiredMethod(ref method_type) => {
|
||||
visitor.visit_ty_method(method_type, env)
|
||||
}
|
||||
Provided(ref method) => walk_method_helper(visitor, &**method, env),
|
||||
ProvidedMethod(ref method) => walk_method_helper(visitor, &**method, env),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user