Skip to content

Commit

Permalink
auto merge of #16286 : pcwalton/rust/associated-items-groundwork, r=n…
Browse files Browse the repository at this point in the history
…ikomatsakis

methods.

This paves the way to associated items by introducing an extra level of
abstraction ("impl-or-trait item") between traits/implementations and
methods. This new abstraction is encoded in the metadata and used
throughout the compiler where appropriate.

There are no functional changes; this is purely a refactoring.

r? @nick29581
  • Loading branch information
bors committed Aug 14, 2014
2 parents 404978e + 9907fa4 commit a8c8e3f
Show file tree
Hide file tree
Showing 49 changed files with 1,926 additions and 1,120 deletions.
26 changes: 16 additions & 10 deletions src/librustc/front/config.rs
Expand Up @@ -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()
Expand Down Expand Up @@ -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()),
}
}

Expand Down
28 changes: 20 additions & 8 deletions src/librustc/lint/builtin.rs
Expand Up @@ -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
}
}
}
}
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/lint/context.rs
Expand Up @@ -563,9 +563,9 @@ impl<'a> Visitor<()> for Context<'a> {
visit::walk_generics(self, g, ());
}

fn visit_trait_method(&mut self, m: &ast::TraitMethod, _: ()) {
fn visit_trait_item(&mut self, m: &ast::TraitItem, _: ()) {
run_lints!(self, check_trait_method, m);
visit::walk_trait_method(self, m, ());
visit::walk_trait_item(self, m, ());
}

fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option<ast::Lifetime>, _: ()) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lint/mod.rs
Expand Up @@ -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,
Expand Down
16 changes: 9 additions & 7 deletions src/librustc/metadata/common.rs
Expand Up @@ -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;
Expand All @@ -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;


Expand Down Expand Up @@ -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;

Expand Down
44 changes: 24 additions & 20 deletions src/librustc/metadata/csearch.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -121,30 +122,33 @@ pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
}

/// Returns information about the given implementation.
pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
-> Vec<ast::DefId> {
pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
-> Vec<ty::ImplOrTraitItemId> {
let cdata = cstore.get_crate_data(impl_def_id.krate);
decoder::get_impl_methods(&*cdata, impl_def_id.node)
decoder::get_impl_items(&*cdata, impl_def_id.node)
}

pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
pub fn get_impl_or_trait_item(tcx: &ty::ctxt, def: ast::DefId)
-> ty::ImplOrTraitItem {
let cdata = tcx.sess.cstore.get_crate_data(def.krate);
decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
&*cdata,
def.node,
tcx)
}

pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
def: ast::DefId)
-> (ast::Ident,
ty::ExplicitSelfCategory)
{
pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
-> (ast::Ident, resolve::TraitItemKind) {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
&*cdata,
def.node)
}

pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
def: ast::DefId) -> Vec<ast::DefId> {
pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
-> Vec<ty::ImplOrTraitItemId> {
let cdata = cstore.get_crate_data(def.krate);
decoder::get_trait_method_def_ids(&*cdata, def.node)
decoder::get_trait_item_def_ids(&*cdata, def.node)
}

pub fn get_item_variances(cstore: &cstore::CStore,
Expand Down Expand Up @@ -286,15 +290,15 @@ pub fn each_implementation_for_trait(cstore: &cstore::CStore,
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
}

/// If the given def ID describes a method belonging to a trait (either a
/// If the given def ID describes an item belonging to a trait (either a
/// default method or an implementation of a trait method), returns the ID of
/// the trait that the method belongs to. Otherwise, returns `None`.
pub fn get_trait_of_method(cstore: &cstore::CStore,
def_id: ast::DefId,
tcx: &ty::ctxt)
-> Option<ast::DefId> {
pub fn get_trait_of_item(cstore: &cstore::CStore,
def_id: ast::DefId,
tcx: &ty::ctxt)
-> Option<ast::DefId> {
let cdata = cstore.get_crate_data(def_id.krate);
decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
decoder::get_trait_of_item(&*cdata, def_id.node, tcx)
}

pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
Expand Down

0 comments on commit a8c8e3f

Please sign in to comment.