librustc: Implement basic lazy implementation loading.

This is only for implementations defined in the same crate as the trait they
implement.
This commit is contained in:
Patrick Walton 2013-08-23 14:34:00 -07:00
parent ff7b8d6d88
commit 6c37e3b7f8
12 changed files with 384 additions and 79 deletions

View File

@ -185,6 +185,9 @@ pub static tag_item_impl_vtables: uint = 0x82;
pub static tag_impls: uint = 0x83;
pub static tag_impls_impl: uint = 0x84;
pub static tag_items_data_item_inherent_impl: uint = 0x85;
pub static tag_items_data_item_extension_impl: uint = 0x86;
pub struct LinkMeta {
name: @str,
vers: @str,

View File

@ -272,3 +272,28 @@ pub fn each_impl(cstore: @mut cstore::CStore,
decoder::each_impl(cdata, callback)
}
pub fn each_implementation_for_type(cstore: @mut cstore::CStore,
def_id: ast::def_id,
callback: &fn(ast::def_id)) {
let cdata = cstore::get_crate_data(cstore, def_id.crate);
decoder::each_implementation_for_type(cdata, def_id.node, callback)
}
pub fn each_implementation_for_trait(cstore: @mut cstore::CStore,
def_id: ast::def_id,
callback: &fn(ast::def_id)) {
let cdata = cstore::get_crate_data(cstore, def_id.crate);
decoder::each_implementation_for_trait(cdata, def_id.node, callback)
}
/// If the given def ID describes a method 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: @mut cstore::CStore,
def_id: ast::def_id,
tcx: ty::ctxt)
-> Option<ast::def_id> {
let cdata = cstore::get_crate_data(cstore, def_id.crate);
decoder::get_trait_of_method(cdata, def_id.node, tcx)
}

View File

@ -20,6 +20,7 @@ use metadata::decoder;
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::ty::{ImplContainer, TraitContainer};
use middle::ty;
use middle::typeck;
use middle::astencode::vtable_decoder_helpers;
@ -958,8 +959,15 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
{
let method_doc = lookup_item(id, cdata.data);
let def_id = item_def_id(method_doc, cdata);
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
method_doc);
let container_doc = lookup_item(container_id.node, cdata.data);
let container = match item_family(container_doc) {
Trait => TraitContainer(container_id),
_ => ImplContainer(container_id),
};
let name = item_name(intr, method_doc);
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
tag_item_method_tps);
@ -980,7 +988,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
explicit_self,
vis,
def_id,
container_id,
container,
provided_source
)
}
@ -1391,4 +1399,56 @@ pub fn each_impl(cdata: cmd, callback: &fn(ast::def_id)) {
};
}
pub fn each_implementation_for_type(cdata: cmd,
id: ast::NodeId,
callback: &fn(ast::def_id)) {
let item_doc = lookup_item(id, cdata.data);
/*println(fmt!(">>> reading inherent impls from %s",
token::ident_to_str(&item_name(token::get_ident_interner(),
item_doc))));*/
do reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl)
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
/*println(fmt!(">>>>> read inherent impl: %d:%d",
implementation_def_id.crate,
implementation_def_id.node));*/
callback(implementation_def_id);
true
};
}
pub fn each_implementation_for_trait(cdata: cmd,
id: ast::NodeId,
callback: &fn(ast::def_id)) {
let item_doc = lookup_item(id, cdata.data);
let _ = do reader::tagged_docs(item_doc,
tag_items_data_item_extension_impl)
|impl_doc| {
let implementation_def_id = item_def_id(impl_doc, cdata);
callback(implementation_def_id);
true
};
}
pub fn get_trait_of_method(cdata: cmd, id: ast::NodeId, tcx: ty::ctxt)
-> Option<ast::def_id> {
let item_doc = lookup_item(id, cdata.data);
let parent_item_id = match item_parent_item(item_doc) {
None => return None,
Some(item_id) => item_id,
};
let parent_item_id = translate_def_id(cdata, parent_item_id);
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data);
match item_family(parent_item_doc) {
Trait => Some(item_def_id(parent_item_doc, cdata)),
Impl => {
do reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref).map
|_| {
item_trait_ref(parent_item_doc, tcx, cdata).def_id
}
}
_ => None
}
}

View File

@ -799,6 +799,38 @@ fn should_inline(attrs: &[Attribute]) -> bool {
}
}
// Encodes the inherent implementations of a structure, enumeration, or trait.
fn encode_inherent_implementations(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
def_id: def_id) {
match ecx.tcx.inherent_impls.find(&def_id) {
None => {}
Some(&implementations) => {
for implementation in implementations.iter() {
ebml_w.start_tag(tag_items_data_item_inherent_impl);
encode_def_id(ebml_w, implementation.did);
ebml_w.end_tag();
}
}
}
}
// Encodes the implementations of a trait defined in this crate.
fn encode_extension_implementations(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
trait_def_id: def_id) {
match ecx.tcx.trait_impls.find(&trait_def_id) {
None => {}
Some(&implementations) => {
for implementation in implementations.iter() {
ebml_w.start_tag(tag_items_data_item_extension_impl);
encode_def_id(ebml_w, implementation.did);
ebml_w.end_tag();
}
}
}
}
fn encode_info_for_item(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
item: @item,
@ -902,6 +934,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ecx, ebml_w, item);
// Encode inherent implementations for this enumeration.
encode_inherent_implementations(ecx, ebml_w, def_id);
ebml_w.end_tag();
encode_enum_variant_info(ecx,
@ -954,6 +990,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
}
// Encode inherent implementations for this structure.
encode_inherent_implementations(ecx, ebml_w, def_id);
/* Each class has its own index -- encode it */
let bkts = create_index(idx);
encode_index(ebml_w, bkts, write_i64);
@ -1069,6 +1108,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
}
// Encode the implementations of this trait.
encode_extension_implementations(ecx, ebml_w, def_id);
ebml_w.end_tag();
// Now output the method info for each method.
@ -1130,6 +1173,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
ebml_w.end_tag();
}
// Encode inherent implementations for this trait.
encode_inherent_implementations(ecx, ebml_w, def_id);
}
item_mac(*) => fail!("item macros unimplemented")
}
@ -1523,10 +1569,19 @@ struct ImplVisitor<'self> {
impl<'self> Visitor<()> for ImplVisitor<'self> {
fn visit_item(&mut self, item: @item, _: ()) {
match item.node {
item_impl(*) => {
self.ebml_w.start_tag(tag_impls_impl);
encode_def_id(self.ebml_w, local_def(item.id));
self.ebml_w.end_tag();
item_impl(_, Some(ref trait_ref), _, _) => {
let def_map = self.ecx.tcx.def_map;
let trait_def = def_map.get_copy(&trait_ref.ref_id);
let def_id = ast_util::def_id_of_def(trait_def);
// Load eagerly if this is an implementation of the Drop trait
// or if the trait is not defined in this crate.
if def_id == self.ecx.tcx.lang_items.drop_trait().unwrap() ||
def_id.crate != LOCAL_CRATE {
self.ebml_w.start_tag(tag_impls_impl);
encode_def_id(self.ebml_w, local_def(item.id));
self.ebml_w.end_tag();
}
}
_ => {}
}
@ -1534,6 +1589,16 @@ impl<'self> Visitor<()> for ImplVisitor<'self> {
}
}
/// Encodes implementations that are eagerly loaded.
///
/// None of this is necessary in theory; we can load all implementations
/// lazily. However, in two cases the optimizations to lazily load
/// implementations are not yet implemented. These two cases, which require us
/// to load implementations eagerly, are:
///
/// * Destructors (implementations of the Drop trait).
///
/// * Implementations of traits not defined in this crate.
fn encode_impls(ecx: &EncodeContext,
crate: &Crate,
ebml_w: &mut writer::Encoder) {

View File

@ -225,7 +225,7 @@ impl PrivacyVisitor {
if method_id.crate == LOCAL_CRATE {
let is_private = self.method_is_private(span, method_id.node);
let container_id = ty::method(self.tcx, method_id).container_id;
let container_id = ty::method(self.tcx, method_id).container_id();
if is_private &&
(container_id.crate != LOCAL_CRATE ||
!self.privileged_items.iter().any(|x| x == &(container_id.node))) {

View File

@ -283,6 +283,14 @@ pub fn trans_fn_ref_with_vtables(
self_ty: None,
tps: /*bad*/ type_params.to_owned() };
// Load the info for the appropriate trait if necessary.
match ty::trait_of_method(tcx, def_id) {
None => {}
Some(trait_id) => {
ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
}
}
// We need to do a bunch of special handling for default methods.
// We need to modify the def_id and our substs in order to monomorphize
// the function.
@ -303,7 +311,7 @@ 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 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 \

View File

@ -176,6 +176,10 @@ pub fn trans_method_callee(bcx: @mut Block,
}) => {
match bcx.fcx.param_substs {
Some(substs) => {
ty::populate_implementations_for_trait_if_necessary(
bcx.tcx(),
trait_id);
let vtbl = find_vtable(bcx.tcx(), substs,
p, b);
trans_monomorphized_callee(bcx, callee_id, this, mentry,
@ -210,6 +214,8 @@ pub fn trans_static_method_callee(bcx: @mut Block,
callee_id);
let _indenter = indenter();
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
// When we translate a static fn defined in a trait like:
//
// trait<T1...Tn> Trait {
@ -575,6 +581,8 @@ fn emit_vtable_methods(bcx: @mut Block,
make a vtable for a type impl!")
};
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
do trait_method_def_ids.map |method_def_id| {
let ident = ty::method(tcx, *method_def_id).ident;

View File

@ -60,6 +60,12 @@ pub struct field {
mt: mt
}
#[deriving(Clone)]
pub enum MethodContainer {
TraitContainer(ast::def_id),
ImplContainer(ast::def_id),
}
#[deriving(Clone)]
pub struct Method {
ident: ast::ident,
@ -69,7 +75,7 @@ pub struct Method {
explicit_self: ast::explicit_self_,
vis: ast::visibility,
def_id: ast::def_id,
container_id: ast::def_id,
container: MethodContainer,
// If this method is provided, we need to know where it came from
provided_source: Option<ast::def_id>
@ -83,7 +89,7 @@ impl Method {
explicit_self: ast::explicit_self_,
vis: ast::visibility,
def_id: ast::def_id,
container_id: ast::def_id,
container: MethodContainer,
provided_source: Option<ast::def_id>)
-> Method {
// Check the invariants.
@ -101,10 +107,17 @@ impl Method {
explicit_self: explicit_self,
vis: vis,
def_id: def_id,
container_id: container_id,
container: container,
provided_source: provided_source
}
}
pub fn container_id(&self) -> ast::def_id {
match self.container {
TraitContainer(id) => id,
ImplContainer(id) => id,
}
}
}
pub struct Impl {
@ -324,7 +337,15 @@ struct ctxt_ {
used_mut_nodes: @mut HashSet<ast::NodeId>,
// vtable resolution information for impl declarations
impl_vtables: typeck::impl_vtable_map
impl_vtables: typeck::impl_vtable_map,
// The set of external nominal types whose implementations have been read.
// This is used for lazy resolution of methods.
populated_external_types: @mut HashSet<ast::def_id>,
// The set of external traits whose implementations have been read. This
// is used for lazy resolution of traits.
populated_external_traits: @mut HashSet<ast::def_id>,
}
pub enum tbox_flag {
@ -938,6 +959,8 @@ pub fn mk_ctxt(s: session::Session,
used_unsafe: @mut HashSet::new(),
used_mut_nodes: @mut HashSet::new(),
impl_vtables: @mut HashMap::new(),
populated_external_types: @mut HashSet::new(),
populated_external_traits: @mut HashSet::new(),
}
}
@ -3612,8 +3635,7 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
}
}
pub fn provided_source(cx: ctxt, id: ast::def_id)
-> Option<ast::def_id> {
pub fn provided_source(cx: ctxt, id: ast::def_id) -> Option<ast::def_id> {
cx.provided_method_sources.find(&id).map_move(|x| *x)
}
@ -4553,3 +4575,135 @@ pub fn visitor_object_ty(tcx: ctxt,
ast::m_imm,
EmptyBuiltinBounds())))
}
/// Records a trait-to-implementation mapping.
fn record_trait_implementation(tcx: ctxt,
trait_def_id: def_id,
implementation: @Impl) {
let implementation_list;
match tcx.trait_impls.find(&trait_def_id) {
None => {
implementation_list = @mut ~[];
tcx.trait_impls.insert(trait_def_id, implementation_list);
}
Some(&existing_implementation_list) => {
implementation_list = existing_implementation_list
}
}
implementation_list.push(implementation);
}
/// Populates the type context with all the implementations for the given type
/// if necessary.
pub fn populate_implementations_for_type_if_necessary(tcx: ctxt,
type_id: ast::def_id) {
if type_id.crate == LOCAL_CRATE {
return
}
if tcx.populated_external_types.contains(&type_id) {
return
}
do csearch::each_implementation_for_type(tcx.sess.cstore, type_id)
|implementation_def_id| {
let implementation = @csearch::get_impl(tcx, implementation_def_id);
// Record the trait->implementation mappings, if applicable.
let associated_traits = csearch::get_impl_trait(tcx,
implementation.did);
for trait_ref in associated_traits.iter() {
record_trait_implementation(tcx,
trait_ref.def_id,
implementation);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for method in implementation.methods.iter() {
for source in method.provided_source.iter() {
tcx.provided_method_sources.insert(method.def_id, *source);
}
}
// If this is an inherent implementation, record it.
if associated_traits.is_none() {
let implementation_list;
match tcx.inherent_impls.find(&type_id) {
None => {
implementation_list = @mut ~[];
tcx.inherent_impls.insert(type_id, implementation_list);
}
Some(&existing_implementation_list) => {
implementation_list = existing_implementation_list;
}
}
implementation_list.push(implementation);
}
// Store the implementation info.
tcx.impls.insert(implementation_def_id, implementation);
}
tcx.populated_external_types.insert(type_id);
}
/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(
tcx: ctxt,
trait_id: ast::def_id) {
if trait_id.crate == LOCAL_CRATE {
return
}
if tcx.populated_external_traits.contains(&trait_id) {
return
}
do csearch::each_implementation_for_trait(tcx.sess.cstore, trait_id)
|implementation_def_id| {
let implementation = @csearch::get_impl(tcx, implementation_def_id);
// Record the trait->implementation mapping.
record_trait_implementation(tcx, trait_id, implementation);
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
for method in implementation.methods.iter() {
for source in method.provided_source.iter() {
tcx.provided_method_sources.insert(method.def_id, *source);
}
}
// Store the implementation info.
tcx.impls.insert(implementation_def_id, implementation);
}
tcx.populated_external_traits.insert(trait_id);
}
/// If the given def ID describes a trait method, returns the ID of the trait
/// that the method belongs to. Otherwise, returns `None`.
pub fn trait_of_method(tcx: ctxt, def_id: ast::def_id)
-> Option<ast::def_id> {
match tcx.methods.find(&def_id) {
Some(method_descriptor) => {
match method_descriptor.container {
TraitContainer(id) => return Some(id),
_ => {}
}
}
None => {}
}
// If the method was in the local crate, then if we got here we know the
// answer is negative.
if def_id.crate == LOCAL_CRATE {
return None
}
let result = csearch::get_trait_of_method(tcx.cstore, def_id, tcx);
result
}

View File

@ -350,6 +350,10 @@ impl<'self> LookupContext<'self> {
let opt_applicable_traits = trait_map.find(&self.expr.id);
for applicable_traits in opt_applicable_traits.iter() {
for trait_did in applicable_traits.iter() {
ty::populate_implementations_for_trait_if_necessary(
self.tcx(),
*trait_did);
// Look for explicit implementations.
let opt_impl_infos = self.tcx().trait_impls.find(trait_did);
for impl_infos in opt_impl_infos.iter() {
@ -534,6 +538,10 @@ impl<'self> LookupContext<'self> {
fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
// Read the inherent implementation candidates for this type from the
// metadata if necessary.
ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
let opt_impl_infos = self.tcx().inherent_impls.find(&did);
for impl_infos in opt_impl_infos.iter() {
for impl_info in impl_infos.iter() {

View File

@ -136,6 +136,9 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
// ...and here trait_ref is each bound that was declared on A,
// expressed in terms of the type parameters.
ty::populate_implementations_for_trait_if_necessary(tcx,
trait_ref.def_id);
// Substitute the values of the type parameters that may
// appear in the bound.
let trait_ref = substs.map_default(trait_ref, |substs| {
@ -321,6 +324,10 @@ fn search_for_vtable(vcx: &VtableContext,
let mut found = ~[];
let mut impls_seen = HashSet::new();
// Load the implementations from external metadata if necessary.
ty::populate_implementations_for_trait_if_necessary(tcx,
trait_ref.def_id);
// XXX: this is a bad way to do this, since we do
// pointless allocations.
let impls = tcx.trait_impls.find(&trait_ref.def_id)

View File

@ -19,7 +19,7 @@ use metadata::csearch::{each_impl, get_impl_trait};
use metadata::csearch;
use metadata::cstore::iter_crate_data;
use middle::ty::get;
use middle::ty::{lookup_item_type, subst};
use middle::ty::{ImplContainer, lookup_item_type, subst};
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
@ -42,13 +42,12 @@ use syntax::ast;
use syntax::ast_map::node_item;
use syntax::ast_map;
use syntax::ast_util::{def_id_of_def, local_def};
use syntax::codemap::{span, dummy_sp};
use syntax::codemap::span;
use syntax::opt_vec;
use syntax::visit;
use syntax::parse;
use util::ppaux::ty_to_str;
use std::hashmap::{HashMap, HashSet};
use std::hashmap::HashSet;
use std::result::Ok;
use std::vec;
@ -149,19 +148,12 @@ pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker {
CoherenceChecker {
crate_context: crate_context,
inference_context: new_infer_ctxt(crate_context.tcx),
base_type_def_ids: @mut HashMap::new(),
}
}
pub struct CoherenceChecker {
crate_context: @mut CrateCtxt,
inference_context: @mut InferCtxt,
// A mapping from implementations to the corresponding base type
// definition ID.
base_type_def_ids: @mut HashMap<def_id,def_id>,
}
struct CoherenceCheckVisitor { cc: CoherenceChecker }
@ -320,9 +312,6 @@ impl CoherenceChecker {
if associated_traits.len() == 0 {
self.add_inherent_impl(base_type_def_id, implementation);
}
self.base_type_def_ids.insert(local_def(item.id),
base_type_def_id);
}
}
@ -686,25 +675,11 @@ impl CoherenceChecker {
}
// Good. Continue.
let self_type = lookup_item_type(tcx, implementation.did);
let associated_traits = get_impl_trait(tcx,
implementation.did);
let _ = lookup_item_type(tcx, implementation.did);
let associated_traits = get_impl_trait(tcx, implementation.did);
// Do a sanity check to make sure that inherent methods have base
// types.
if associated_traits.is_none() {
match get_base_type_def_id(self.inference_context,
dummy_sp(),
self_type.ty) {
None => {
tcx.sess.bug(fmt!("no base type for external impl with no \
trait: %s (type %s)!",
tcx.sess.str_of(implementation.ident),
ty_to_str(tcx, self_type.ty)));
}
Some(_) => {} // Nothing to do.
}
}
// Do a sanity check.
assert!(associated_traits.is_some());
// Record all the trait methods.
for trait_ref in associated_traits.iter() {
@ -719,25 +694,6 @@ impl CoherenceChecker {
}
}
// Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation.
match get_base_type_def_id(self.inference_context,
dummy_sp(),
self_type.ty) {
None => {} // Nothing to do.
Some(base_type_def_id) => {
// inherent methods apply to `impl Type` but not
// `impl Trait for Type`:
if associated_traits.is_none() {
self.add_inherent_impl(base_type_def_id,
implementation);
}
self.base_type_def_ids.insert(implementation.did,
base_type_def_id);
}
}
tcx.impls.insert(implementation.did, implementation);
}
@ -883,7 +839,7 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
method.explicit_self,
method.vis,
new_def_id,
impl_id,
ImplContainer(impl_id),
provided_source
)
}

View File

@ -32,7 +32,8 @@ are represented as `ty_param()` instances.
use metadata::csearch;
use middle::ty::{substs, ty_param_bounds_and_ty};
use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
use middle::ty::{ty_param_bounds_and_ty};
use middle::ty;
use middle::subst::Subst;
use middle::typeck::astconv::{AstConv, ty_of_arg};
@ -388,7 +389,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
// assume public, because this is only invoked on trait methods
ast::public,
local_def(*m_id),
local_def(trait_id),
TraitContainer(local_def(trait_id)),
None
)
}
@ -744,7 +745,7 @@ pub struct ConvertedMethod {
}
pub fn convert_methods(ccx: &CrateCtxt,
container_id: ast::NodeId,
container: MethodContainer,
ms: &[@ast::method],
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
@ -758,11 +759,14 @@ pub fn convert_methods(ccx: &CrateCtxt,
let m_ty_generics =
ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
num_rcvr_ty_params);
let mty =
@ty_of_method(ccx, container_id, *m, rcvr_ty_generics.region_param,
untransformed_rcvr_ty,
rcvr_ast_generics, rcvr_visibility,
&m.generics);
let mty = @ty_of_method(ccx,
container,
*m,
rcvr_ty_generics.region_param,
untransformed_rcvr_ty,
rcvr_ast_generics,
rcvr_visibility,
&m.generics);
let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
tcx.tcache.insert(
local_def(m.id),
@ -785,7 +789,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
}).collect();
fn ty_of_method(ccx: &CrateCtxt,
container_id: ast::NodeId,
container: MethodContainer,
m: &ast::method,
rp: Option<ty::region_variance>,
untransformed_rcvr_ty: ty::t,
@ -817,7 +821,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
m.explicit_self.node,
method_vis,
local_def(m.id),
local_def(container_id),
container,
None
)
}
@ -877,8 +881,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
it.vis
};
let cms = convert_methods(ccx, it.id, *ms, selfty,
&i_ty_generics, generics,
let cms = convert_methods(ccx,
ImplContainer(local_def(it.id)),
*ms,
selfty,
&i_ty_generics,
generics,
parent_visibility);
for t in opt_trait_ref.iter() {
// Prevent the builtin kind traits from being manually implemented.
@ -901,9 +909,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
let (ty_generics, _) = mk_item_substs(ccx, generics, rp,
Some(untransformed_rcvr_ty));
let _ = convert_methods(ccx, it.id, provided_methods,
let _ = convert_methods(ccx,
TraitContainer(local_def(it.id)),
provided_methods,
untransformed_rcvr_ty,
&ty_generics, generics,
&ty_generics,
generics,
it.vis);
// We need to do this *after* converting methods, since