Skip to content

Commit

Permalink
librustc: Stop assuming that implementations and traits only contain
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pcwalton committed Aug 14, 2014
1 parent 404978e commit 9907fa4
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

5 comments on commit 9907fa4

@bors
Copy link
Contributor

@bors bors commented on 9907fa4 Aug 14, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at pcwalton@9907fa4

@bors
Copy link
Contributor

@bors bors commented on 9907fa4 Aug 14, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging pcwalton/rust/associated-items-groundwork = 9907fa4 into auto

@bors
Copy link
Contributor

@bors bors commented on 9907fa4 Aug 14, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pcwalton/rust/associated-items-groundwork = 9907fa4 merged ok, testing candidate = a8c8e3f

@bors
Copy link
Contributor

@bors bors commented on 9907fa4 Aug 14, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = a8c8e3f

Please sign in to comment.