From 9907fa4acc2af5b2b07d1362b3ceb29171954c58 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 4 Aug 2014 13:56:56 -0700 Subject: [PATCH] librustc: Stop assuming that implementations and traits only contain 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. --- src/librustc/front/config.rs | 26 +- src/librustc/lint/builtin.rs | 28 +- src/librustc/lint/context.rs | 4 +- src/librustc/lint/mod.rs | 2 +- src/librustc/metadata/common.rs | 16 +- src/librustc/metadata/csearch.rs | 44 +-- src/librustc/metadata/decoder.rs | 181 +++++++----- src/librustc/metadata/encoder.rs | 265 +++++++++++------- src/librustc/middle/astencode.rs | 59 +++- src/librustc/middle/dead.rs | 50 ++-- src/librustc/middle/expr_use_visitor.rs | 6 +- src/librustc/middle/privacy.rs | 136 ++++++--- src/librustc/middle/reachable.rs | 61 ++-- src/librustc/middle/resolve.rs | 213 +++++++------- src/librustc/middle/save/mod.rs | 153 +++++++--- src/librustc/middle/stability.rs | 17 +- src/librustc/middle/trans/base.rs | 62 ++-- src/librustc/middle/trans/callee.rs | 72 ++--- src/librustc/middle/trans/debuginfo.rs | 22 +- src/librustc/middle/trans/inline.rs | 51 ++-- src/librustc/middle/trans/meth.rs | 143 ++++++---- src/librustc/middle/trans/monomorphize.rs | 24 +- src/librustc/middle/trans/reflect.rs | 18 +- src/librustc/middle/ty.rs | 248 +++++++++++----- src/librustc/middle/typeck/check/method.rs | 98 +++++-- src/librustc/middle/typeck/check/mod.rs | 141 ++++++---- src/librustc/middle/typeck/coherence.rs | 82 ++++-- src/librustc/middle/typeck/collect.rs | 146 +++++----- .../middle/typeck/infer/error_reporting.rs | 29 +- src/librustc/middle/typeck/variance.rs | 16 +- src/librustc/util/ppaux.rs | 4 +- src/librustc_back/svh.rs | 4 +- src/librustdoc/clean/inline.rs | 60 ++-- src/librustdoc/clean/mod.rs | 57 ++-- src/librustdoc/doctree.rs | 4 +- src/librustdoc/fold.rs | 20 +- src/librustdoc/html/render.rs | 45 ++- src/librustdoc/passes.rs | 2 +- src/librustdoc/stability_summary.rs | 25 +- src/librustdoc/visit_ast.rs | 8 +- src/libsyntax/ast.rs | 23 +- src/libsyntax/ast_map/blocks.rs | 18 +- src/libsyntax/ast_map/mod.rs | 152 ++++++---- src/libsyntax/ast_util.rs | 75 ++--- src/libsyntax/ext/deriving/generic/mod.rs | 9 +- src/libsyntax/fold.rs | 25 +- src/libsyntax/parse/parser.rs | 40 +-- src/libsyntax/print/pprust.rs | 29 +- src/libsyntax/visit.rs | 33 ++- 49 files changed, 1926 insertions(+), 1120 deletions(-) diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index ab363a88db2d9..93320caf5f281 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -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()), } } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index f929860c6864b..d08e2ce527f1f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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 diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 59a6b08638e91..cf018927f70b4 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -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, _: ()) { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 1bf77b42bec04..dbdda96dcb84f 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -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, diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 7d0a21b2f8e42..6a1c7c6c951c9 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -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; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 252d19bbb237b..ac161ef8bdefe 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -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 { +pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId) + -> Vec { 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 { +pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId) + -> Vec { 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 { +pub fn get_trait_of_item(cstore: &cstore::CStore, + def_id: ast::DefId, + tcx: &ty::ctxt) + -> Option { 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, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index c9807a18383e8..74810261d4a75 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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, 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, 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 { - 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 { + 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, - 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, + 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, cdata: Cmd, id: ast::NodeId, - tcx: &ty::ctxt) -> ty::Method -{ +pub fn get_impl_or_trait_item(intr: Rc, + 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, 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 - ) -} - -pub fn get_trait_method_def_ids(cdata: Cmd, - id: ast::NodeId) -> Vec { + + 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_item_def_ids(cdata: Cmd, id: ast::NodeId) + -> Vec { 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, cdata: Cmd, - id: ast::NodeId, tcx: &ty::ctxt) +pub fn get_provided_trait_methods(intr: Rc, + cdata: Cmd, + id: ast::NodeId, + tcx: &ty::ctxt) -> Vec> { 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, 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 { +pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) + -> Option { let item_doc = lookup_item(id, cdata.data()); let parent_item_id = match item_parent_item(item_doc) { None => return None, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 1b47227fea403..1d426aaaf5c91 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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 stab = stability::lookup(tcx, method_def_id); - encode_stability(rbml_w, stab); - - let elem = ast_map::PathName(method_ty.ident.name); - encode_path(rbml_w, path.clone().chain(Some(elem).move_iter())); - - match method_ty.explicit_self { - ty::StaticExplicitSelfCategory => { - encode_family(rbml_w, - fn_style_static_method_family( - method_ty.fty.fn_style)); - - 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) { - &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); - } + 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(); + + encode_method_ty_fields(ecx, rbml_w, &*method_ty); + encode_parent_item(rbml_w, def_id); + + let stab = stability::lookup(tcx, method_def_id); + encode_stability(rbml_w, stab); + + let elem = ast_map::PathName(method_ty.ident.name); + encode_path(rbml_w, + path.clone().chain(Some(elem).move_iter())); + + match method_ty.explicit_self { + ty::StaticExplicitSelfCategory => { + encode_family(rbml_w, + fn_style_static_method_family( + method_ty.fty.fn_style)); + + 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)); + } + } - &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); + 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()); } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index b1ce2ece4afe8..26cb2f25129aa 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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)) } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 86fe6dc0ddc6c..9a7bfb0e6dca2 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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(_) => () } } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7c805b1ac4bcd..b76b85e024c44 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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(_) => { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 62b5299f8fbc8..61e6debb08647 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -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 { ... }. 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 { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7ed1209bdf750..5dfc43daa646f 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -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 diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 13a29842fcbb3..9edf9fcbdbad6 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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>, + trait_item_map: RefCell>, structs: FnvHashMap>, @@ -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, self_type: &Ty, - methods: &[Gc]) { + 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); - - // We also need a new scope for the method-specific type parameters. - this.resolve_method(MethodRibKind(id, Provided(method.id)), - &**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, + 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)); } diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs index 4a58a8bba99c8..11b16f1853379 100644 --- a/src/librustc/middle/save/mod.rs +++ b/src/librustc/middle/save/mod.rs @@ -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, typ: ast::P, - methods: &Vec>) { + impl_items: &Vec) { 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, - methods: &Vec) { + methods: &Vec) { 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 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 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 for DxrVisitor<'l> { method_type.id, e); } - ast::Provided(method) => self.process_method(&*method, e), + ast::ProvidedMethod(method) => self.process_method(&*method, e), } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index a3fa5a5f85ba4..e73d81d9bf597 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -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> for Annotator { visit::walk_fn(self, fk, fd, b, s, stab) } - fn visit_trait_method(&mut self, t: &TraitMethod, parent: Option) { + fn visit_trait_item(&mut self, t: &TraitItem, parent: Option) { 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) { @@ -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 { +pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option { // 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) => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 16ba3ddbd7076..9aa4355632cfb 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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) => { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 379b53eebbb4f..56c1c66533133 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -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"); - - // 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); - - 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); - - debug!("trans_fn_with_vtables - default method: \ - param_vtables = {}", - param_vtables.repr(tcx)); - - (true, source_id, new_substs, param_vtables) + 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); + + // 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)); + + 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)); + + (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) => { diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 96b8acbfb404a..9b78cedd4ac7f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -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(), diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index bf39f3a6aa385..4b1f37fcdc22a 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -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); - - // 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); } + ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1); + } + } - 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(); + 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(); - 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) + } + } } }; } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 3ae4c552b84e8..31f2a3df66202 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -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], + 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"); - - ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did); - *meth_did + 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.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() } diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 6d705c7d914e3..e19ee035a781e 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -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, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 9caa9f681aadf..2aff12c2b68c5 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -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], + 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 diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index f03c982bb083f..40c4d9682c4a3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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), +} + +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 @@ -102,7 +155,7 @@ impl Method { explicit_self: ExplicitSelfCategory, vis: ast::Visibility, def_id: ast::DefId, - container: MethodContainer, + container: ImplOrTraitItemContainer, provided_source: Option) -> Method { Method { @@ -274,14 +327,14 @@ pub struct ctxt { /// other items. pub item_substs: RefCell>, - /// Maps from a method to the method "descriptor" - pub methods: RefCell>>, + /// Maps from a trait item to the trait item "descriptor" + pub impl_or_trait_items: RefCell>, - /// Maps from a trait def-id to a list of the def-ids of its methods - pub trait_method_def_ids: RefCell>>>, + /// Maps from a trait def-id to a list of the def-ids of its trait items + pub trait_item_def_ids: RefCell>>>, - /// A cache for the trait_methods() routine - pub trait_methods_cache: RefCell>>>>, + /// A cache for the trait_items() routine + pub trait_items_cache: RefCell>>>, pub impl_trait_cache: RefCell>>>, @@ -332,11 +385,11 @@ pub struct ctxt { /// Methods in these implementations don't need to be exported. pub inherent_impls: RefCell>>>>, - /// 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>>, + pub impl_items: RefCell>>, /// 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::>()).as_slice()); } -pub fn method_idx(id: ast::Ident, meths: &[Rc]) -> Option { - meths.iter().position(|m| m.ident == id) +pub fn impl_or_trait_item_idx(id: ast::Ident, trait_items: &[ImplOrTraitItem]) + -> Option { + 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> { 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( /*! * 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 } -pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc { - 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>> { - 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> { + 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>> = 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> = + 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 { - 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> { - lookup_locally_or_in_crate_store("trait_method_def_ids", +pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId) + -> Rc> { + 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 { 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 { +pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option { 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 { - let method = match tcx.methods.borrow().find(&def_id) { +pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId) + -> Option { + 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 } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index dfcde8ca9b9bc..1e3ea095704bf 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -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(); - - match mk_cand(bound_trait_ref, method, pos, this_bound_idx) { + let method = match *trait_items.get(pos) { + ty::MethodTraitItem(ref method) => (*method).clone(), + }; + + 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::>() - .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, + impl_items.iter() + .map(|&did| { + ty::impl_or_trait_item(self.tcx(), + did.def_id()).ident() + }) + .collect::>() + .repr(self.tcx())); + + 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 diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index aa5a358515885..3403a51610cff 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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]) { +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); - - // 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()); + 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_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 diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 76af54ba4d15c..3dee787b6c906 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -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) { + fn instantiate_default_methods( + &self, + impl_id: DefId, + trait_ref: &ty::TraitRef, + all_impl_items: &mut Vec) { 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 { + // Converts an implementation in the AST to a vector of items. + fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { - ItemImpl(_, ref trait_refs, _, ref ast_methods) => { - let mut methods: Vec = ast_methods.iter().map(|ast_method| { - local_def(ast_method.id) - }).collect(); + ItemImpl(_, ref trait_refs, _, ref ast_items) => { + let mut items: Vec = + 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, 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. diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a81c6344cc9c6..284330c51c86a 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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) - } - &ast::Provided(ref method) => { - local_def(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)) + } } - } - }).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], 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, diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index e191fb343b53a..a4e7f28b45063 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -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 diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 54b9ce035348d..e0fab95a04529 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -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!(), } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 4e193f0f1d952..301143e504550 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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!( diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index d45ebb3858e9f..29668795ed7ba 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -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) { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3c942d0791e77..0e87be1c241b9 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a1f486b3b31b8..c5d3c73c9bcf7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -907,7 +907,7 @@ impl Clean for ast::RetStyle { #[deriving(Clone, Encodable, Decodable)] pub struct Trait { - pub methods: Vec, + pub items: Vec, pub generics: Generics, pub parents: Vec, } @@ -922,7 +922,7 @@ impl Clean 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 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 for ast::TraitMethod { - fn clean(&self) -> TraitMethod { +impl Clean 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 for ast::ImplItem { + fn clean(&self) -> ImplItem { + match self { + &ast::MethodImplItem(ref t) => MethodImplItem(t.clean()), } } } @@ -1019,6 +1032,14 @@ impl Clean for ty::Method { } } +impl Clean 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, pub for_: Type, - pub methods: Vec, + pub items: Vec, pub derived: bool, } @@ -1735,7 +1756,11 @@ impl Clean 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()), }), } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 313f1c81c79e8..a5ead46384a00 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -154,7 +154,7 @@ pub struct Static { pub struct Trait { pub name: Ident, - pub methods: Vec, //should be TraitMethod + pub items: Vec, //should be TraitItem pub generics: ast::Generics, pub parents: Vec, pub attrs: Vec, @@ -168,7 +168,7 @@ pub struct Impl { pub generics: ast::Generics, pub trait_: Option, pub for_: ast::P, - pub methods: Vec>, + pub items: Vec, pub attrs: Vec, pub where: Span, pub vis: ast::Visibility, diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 60853f450ab32..f0082f8900e6a 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -40,29 +40,31 @@ pub trait DocFolder { EnumItem(i) }, TraitItem(mut i) => { - fn vtrm(this: &mut T, trm: TraitMethod) -> Option { + fn vtrm(this: &mut T, trm: TraitItem) + -> Option { 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) => { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4f511e390ff98..bb68c6536a00d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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::>(); - let provided = t.methods.iter().filter(|m| !m.is_req()).collect::>(); - - if t.methods.len() == 0 { + let required = t.items.iter() + .filter(|m| { + match **m { + clean::RequiredMethod(_) => true, + _ => false, + } + }) + .collect::>(); + let provided = t.items.iter() + .filter(|m| { + match **m { + clean::ProvidedMethod(_) => true, + _ => false, + } + }) + .collect::>(); + + 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, "

{}", shortty(m.item()), *m.item().name.get_ref(), @@ -1669,7 +1684,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for m in required.iter() { - try!(meth(w, *m)); + try!(trait_item(w, *m)); } try!(write!(w, "
")); } @@ -1679,7 +1694,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for m in provided.iter() { - try!(meth(w, *m)); + try!(trait_item(w, *m)); } try!(write!(w, "
")); } @@ -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, "

{}", *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, "
")); - 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(()) } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index cc5bc5cb7c170..eeccc3303ebfe 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -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) diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 60db4fda05190..bbcf38f495571 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -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) { 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) { .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, .. }) => { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5b2a542ca9664..f7ccad79fdacc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -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, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7d9a23e91bae9..1ff8ca10fffbd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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), +pub enum TraitItem { + RequiredMethod(TypeMethod), + ProvidedMethod(Gc), +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum ImplItem { + MethodImplItem(Gc), } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] @@ -1273,11 +1278,11 @@ pub enum Item_ { Option, // (optional) default bound not required for Self. // Currently, only Sized makes sense here. Vec , - Vec), + Vec), ItemImpl(Generics, Option, // (optional) trait this impl implements P, // self - Vec>), + Vec), /// 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), - IIMethod(DefId /* impl id */, bool /* is provided */, Gc), + IITraitItem(DefId /* impl id */, InlinedTraitItem), IIForeign(Gc), } +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum InlinedTraitItem { + ProvidedInlinedTraitItem(Gc), + RequiredInlinedTraitItem(Gc), +} + #[cfg(test)] mod test { use serialize::json; diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 83af390c4edc3..b00c6ce14b5b8 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -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)), diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 881ee4fd8d13e..78afa8441c5f3 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -99,8 +99,8 @@ pub fn path_to_string>(mut path: PI) -> String { pub enum Node { NodeItem(Gc), NodeForeignItem(Gc), - NodeTraitMethod(Gc), - NodeMethod(Gc), + NodeTraitItem(Gc), + NodeImplItem(Gc), NodeVariant(P), NodeExpr(Gc), NodeStmt(Gc), @@ -125,8 +125,8 @@ enum MapEntry { /// All the node types, with a parent ID. EntryItem(NodeId, Gc), EntryForeignItem(NodeId, Gc), - EntryTraitMethod(NodeId, Gc), - EntryMethod(NodeId, Gc), + EntryTraitItem(NodeId, Gc), + EntryImplItem(NodeId, Gc), EntryVariant(NodeId, P), EntryExpr(NodeId, Gc), EntryStmt(NodeId, Gc), @@ -144,7 +144,7 @@ enum MapEntry { struct InlinedParent { path: Vec , - /// 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 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 Named for Spanned { 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 { + RequiredMethod(ref tm) => tm.ident.name, + ProvidedMethod(m) => m.name(), + } + } +} +impl Named for ImplItem { fn name(&self) -> Name { match *self { - Required(ref tm) => tm.ident.name, - Provided(m) => m.name(), + 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(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) diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index cf2b5bc406373..7689646d373c4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -241,51 +241,52 @@ pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { token::gensym_ident(pretty.as_slice()) } -/// extract a TypeMethod from a TraitMethod. if the TraitMethod is +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") + } +} + +/// 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_method_to_ty_method(method: &TraitMethod) -> TypeMethod { +pub fn trait_item_to_ty_method(method: &TraitItem) -> 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") - } - - } + RequiredMethod(ref m) => (*m).clone(), + ProvidedMethod(ref m) => trait_method_to_ty_method(&**m), } } -pub fn split_trait_methods(trait_methods: &[TraitMethod]) +pub fn split_trait_methods(trait_methods: &[TraitItem]) -> (Vec , Vec> ) { 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, ()); } } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 5842ca4a0d54d..7a8ee6d141683 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -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, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index cebe186252825..4ed2a3ed4c2b0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -834,26 +834,37 @@ pub fn noop_fold_item_underscore(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 = + let methods : SmallVector = folder.fold_method(method).move_iter() - .map(|m| Provided(m)).collect(); + .map(|m| ProvidedMethod(m)).collect(); methods.move_iter() } }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f6db577a00453..f272f7e188723 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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 { + pub fn parse_trait_methods(&mut self) -> Vec { 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, Vec) { + 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 Foo { ... } /// impl 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 diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4ee73406f0340..c573cc0c0adec 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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), } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 79a870422a68b..18cbf797d03c4 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -99,7 +99,7 @@ pub trait Visitor { 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>(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>(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>(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>(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>(visitor: &mut V, } } -pub fn walk_trait_method>(visitor: &mut V, - trait_method: &TraitMethod, +pub fn walk_trait_item>(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), } }