Compute a ty::method for methods that appear in impls as well
This commit is contained in:
parent
007abe9352
commit
569596573a
4 changed files with 89 additions and 79 deletions
|
@ -714,18 +714,19 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
|||
tcx: ty::ctxt) -> ty::method
|
||||
{
|
||||
let method_doc = lookup_item(id, cdata.data);
|
||||
let def_id = item_def_id(method_doc, cdata);
|
||||
let name = item_name(intr, method_doc);
|
||||
let bounds = item_ty_param_bounds(method_doc, tcx, cdata,
|
||||
tag_item_method_tps);
|
||||
let name = item_name(intr, method_doc);
|
||||
let def_id = item_def_id(method_doc, cdata);
|
||||
let fty = doc_method_fty(method_doc, tcx, cdata);
|
||||
let vis = item_visibility(method_doc);
|
||||
let self_ty = get_self_ty(method_doc);
|
||||
ty::method {
|
||||
ident: name,
|
||||
tps: bounds,
|
||||
fty: fty,
|
||||
self_ty: self_ty,
|
||||
vis: ast::public,
|
||||
vis: vis,
|
||||
def_id: def_id
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,13 +562,25 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext,
|
|||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_method_ty_fields(ecx: @EncodeContext,
|
||||
ebml_w: writer::Encoder,
|
||||
method_ty: &ty::method)
|
||||
{
|
||||
encode_def_id(ebml_w, method_ty.def_id);
|
||||
encode_name(ecx, ebml_w, method_ty.ident);
|
||||
encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
|
||||
tag_item_method_tps);
|
||||
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
||||
encode_visibility(ebml_w, method_ty.vis);
|
||||
encode_self_type(ebml_w, method_ty.self_ty);
|
||||
}
|
||||
|
||||
fn encode_info_for_method(ecx: @EncodeContext,
|
||||
ebml_w: writer::Encoder,
|
||||
impl_path: &[ast_map::path_elt],
|
||||
should_inline: bool,
|
||||
parent_id: node_id,
|
||||
m: @method,
|
||||
parent_visibility: ast::visibility,
|
||||
owner_generics: &ast::Generics,
|
||||
method_generics: &ast::Generics) {
|
||||
debug!("encode_info_for_method: %d %s %u %u", m.id,
|
||||
|
@ -576,7 +588,10 @@ fn encode_info_for_method(ecx: @EncodeContext,
|
|||
owner_generics.ty_params.len(),
|
||||
method_generics.ty_params.len());
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id(ebml_w, local_def(m.id));
|
||||
|
||||
let method_def_id = local_def(m.id);
|
||||
let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
|
||||
encode_method_ty_fields(ecx, ebml_w, method_ty);
|
||||
|
||||
match m.self_ty.node {
|
||||
ast::sty_static => {
|
||||
|
@ -592,16 +607,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
|
|||
encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
|
||||
|
||||
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
|
||||
encode_name(ecx, ebml_w, m.ident);
|
||||
encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
|
||||
encode_self_type(ebml_w, m.self_ty.node);
|
||||
|
||||
// Combine parent visibility and this visibility.
|
||||
let visibility = match m.vis {
|
||||
ast::inherited => parent_visibility,
|
||||
vis => vis,
|
||||
};
|
||||
encode_visibility(ebml_w, visibility);
|
||||
|
||||
if len > 0u || should_inline {
|
||||
(ecx.encode_inlined_item)(
|
||||
|
@ -610,6 +616,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
|
|||
} else {
|
||||
encode_symbol(ecx, ebml_w, m.id);
|
||||
}
|
||||
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
|
@ -863,17 +870,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
|
|||
let mut impl_path = vec::append(~[], path);
|
||||
impl_path += ~[ast_map::path_name(item.ident)];
|
||||
|
||||
// If there is a trait reference, treat the methods as always public.
|
||||
// This is to work around some incorrect behavior in privacy checking:
|
||||
// when the method belongs to a trait, it should acquire the privacy
|
||||
// from the trait, not the impl. Forcing the visibility to be public
|
||||
// makes things sorta work.
|
||||
let parent_visibility = if opt_trait.is_some() {
|
||||
ast::public
|
||||
} else {
|
||||
item.vis
|
||||
};
|
||||
|
||||
for methods.each |m| {
|
||||
index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
|
||||
encode_info_for_method(ecx,
|
||||
|
@ -882,7 +878,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
|
|||
should_inline(m.attrs),
|
||||
item.id,
|
||||
*m,
|
||||
parent_visibility,
|
||||
generics,
|
||||
&m.generics);
|
||||
}
|
||||
|
@ -909,11 +904,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
|
|||
ebml_w.end_tag();
|
||||
|
||||
// Now output the method info for each method.
|
||||
//
|
||||
// Note: for the moment, the data structures here are *slightly*
|
||||
// different from those expected by `encode_info_for_method()`,
|
||||
// but I do plan to refactor this later in this patch to avoid the
|
||||
// duplication.
|
||||
for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
|
||||
assert!(method_def_id.crate == ast::local_crate);
|
||||
|
||||
|
@ -923,9 +913,13 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
|
|||
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
|
||||
encode_def_id(ebml_w, method_def_id);
|
||||
encode_method_ty_fields(ecx, ebml_w, method_ty);
|
||||
|
||||
encode_parent_item(ebml_w, local_def(item.id));
|
||||
encode_name(ecx, ebml_w, method_ty.ident);
|
||||
|
||||
let mut trait_path = vec::append(~[], path);
|
||||
trait_path.push(ast_map::path_name(item.ident));
|
||||
encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
|
||||
|
||||
match method_ty.self_ty {
|
||||
sty_static => {
|
||||
|
@ -946,15 +940,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
|
|||
}
|
||||
}
|
||||
|
||||
encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
|
||||
tag_item_method_tps);
|
||||
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
||||
encode_visibility(ebml_w, method_ty.vis);
|
||||
encode_self_type(ebml_w, method_ty.self_ty);
|
||||
let mut trait_path = vec::append(~[], path);
|
||||
trait_path.push(ast_map::path_name(item.ident));
|
||||
encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
|
||||
|
||||
match ms[i] {
|
||||
required(_) => {
|
||||
encode_method_sort(ebml_w, 'r');
|
||||
|
|
|
@ -315,7 +315,6 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
|||
ty: ty});
|
||||
}
|
||||
|
||||
|
||||
fn ty_method_of_trait_method(self: &CrateCtxt,
|
||||
trait_rp: Option<ty::region_variance>,
|
||||
trait_generics: &ast::Generics,
|
||||
|
@ -336,8 +335,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
|||
AbiSet::Rust(),
|
||||
&m_generics.lifetimes,
|
||||
m_decl),
|
||||
// assume public, because this is only invoked on trait methods
|
||||
self_ty: m_self_ty.node,
|
||||
// assume public, because this is only invoked on trait methods
|
||||
vis: ast::public,
|
||||
def_id: local_def(*m_id)
|
||||
}
|
||||
|
@ -599,7 +598,7 @@ pub fn convert_field(ccx: &CrateCtxt,
|
|||
}
|
||||
|
||||
pub struct ConvertedMethod {
|
||||
mty: ty::method,
|
||||
mty: @ty::method,
|
||||
id: ast::node_id,
|
||||
span: span,
|
||||
body_id: ast::node_id
|
||||
|
@ -609,13 +608,15 @@ pub fn convert_methods(ccx: &CrateCtxt,
|
|||
ms: &[@ast::method],
|
||||
rp: Option<ty::region_variance>,
|
||||
rcvr_bounds: @~[ty::param_bounds],
|
||||
rcvr_generics: &ast::Generics)
|
||||
-> ~[ConvertedMethod] {
|
||||
|
||||
rcvr_generics: &ast::Generics,
|
||||
rcvr_visibility: ast::visibility)
|
||||
-> ~[ConvertedMethod]
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
do vec::map(ms) |m| {
|
||||
return vec::map(ms, |m| {
|
||||
let bounds = ty_param_bounds(ccx, &m.generics);
|
||||
let mty = ty_of_method(ccx, *m, rp, rcvr_generics, &m.generics);
|
||||
let mty = @ty_of_method(ccx, *m, rp, rcvr_generics,
|
||||
rcvr_visibility, &m.generics);
|
||||
let fty = ty::mk_bare_fn(tcx, copy mty.fty);
|
||||
tcx.tcache.insert(
|
||||
local_def(m.id),
|
||||
|
@ -628,8 +629,34 @@ pub fn convert_methods(ccx: &CrateCtxt,
|
|||
ty: fty
|
||||
});
|
||||
write_ty_to_tcx(tcx, m.id, fty);
|
||||
tcx.methods.insert(mty.def_id, mty);
|
||||
ConvertedMethod {mty: mty, id: m.id,
|
||||
span: m.span, body_id: m.body.node.id}
|
||||
});
|
||||
|
||||
fn ty_of_method(ccx: &CrateCtxt,
|
||||
m: @ast::method,
|
||||
rp: Option<ty::region_variance>,
|
||||
rcvr_generics: &ast::Generics,
|
||||
rcvr_visibility: ast::visibility,
|
||||
method_generics: &ast::Generics) -> ty::method
|
||||
{
|
||||
let rscope = MethodRscope::new(m.self_ty.node,
|
||||
rp,
|
||||
rcvr_generics);
|
||||
ty::method {
|
||||
ident: m.ident,
|
||||
tps: ty_param_bounds(ccx, &m.generics),
|
||||
fty: astconv::ty_of_bare_fn(ccx,
|
||||
&rscope,
|
||||
m.purity,
|
||||
ast::RustAbi,
|
||||
&method_generics.lifetimes,
|
||||
&m.decl),
|
||||
self_ty: m.self_ty.node,
|
||||
vis: m.vis.inherit_from(rcvr_visibility),
|
||||
def_id: local_def(m.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -665,7 +692,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
|
|||
generics,
|
||||
rp);
|
||||
}
|
||||
ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
|
||||
ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => {
|
||||
let i_bounds = ty_param_bounds(ccx, generics);
|
||||
let region_parameterization =
|
||||
RegionParameterization::from_variance_and_generics(rp, generics);
|
||||
|
@ -677,9 +704,20 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
|
|||
region_param: rp,
|
||||
ty: selfty});
|
||||
|
||||
// XXX: Bad copy of `ms` below.
|
||||
let cms = convert_methods(ccx, *ms, rp, i_bounds, generics);
|
||||
for trait_ref.each |t| {
|
||||
// If there is a trait reference, treat the methods as always public.
|
||||
// This is to work around some incorrect behavior in privacy checking:
|
||||
// when the method belongs to a trait, it should acquire the privacy
|
||||
// from the trait, not the impl. Forcing the visibility to be public
|
||||
// makes things sorta work.
|
||||
let parent_visibility = if opt_trait_ref.is_some() {
|
||||
ast::public
|
||||
} else {
|
||||
it.vis
|
||||
};
|
||||
|
||||
let cms = convert_methods(ccx, *ms, rp, i_bounds, generics,
|
||||
parent_visibility);
|
||||
for opt_trait_ref.each |t| {
|
||||
check_methods_against_trait(ccx, generics, rp, selfty, *t, cms);
|
||||
}
|
||||
}
|
||||
|
@ -694,7 +732,8 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
|
|||
let (_, provided_methods) =
|
||||
split_trait_methods(*trait_methods);
|
||||
let (bounds, _) = mk_substs(ccx, generics, rp);
|
||||
let _ = convert_methods(ccx, provided_methods, rp, bounds, generics);
|
||||
let _ = convert_methods(ccx, provided_methods, rp, bounds, generics,
|
||||
it.vis);
|
||||
}
|
||||
ast::item_struct(struct_def, ref generics) => {
|
||||
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
|
||||
|
@ -794,30 +833,6 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
|
|||
ccx.tcx.tcache.insert(local_def(i.id), tpt);
|
||||
}
|
||||
|
||||
pub fn ty_of_method(ccx: &CrateCtxt,
|
||||
m: @ast::method,
|
||||
rp: Option<ty::region_variance>,
|
||||
rcvr_generics: &ast::Generics,
|
||||
method_generics: &ast::Generics)
|
||||
-> ty::method {
|
||||
let rscope = MethodRscope::new(m.self_ty.node,
|
||||
rp,
|
||||
rcvr_generics);
|
||||
ty::method {
|
||||
ident: m.ident,
|
||||
tps: ty_param_bounds(ccx, &m.generics),
|
||||
fty: astconv::ty_of_bare_fn(ccx,
|
||||
&rscope,
|
||||
m.purity,
|
||||
AbiSet::Rust(),
|
||||
&method_generics.lifetimes,
|
||||
&m.decl),
|
||||
self_ty: m.self_ty.node,
|
||||
vis: m.vis,
|
||||
def_id: local_def(m.id)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Instantiates the path for the given trait reference, assuming that
|
||||
it's bound to a valid trait type. Returns the def_id for the defining
|
||||
|
|
|
@ -1186,6 +1186,15 @@ pub struct trait_ref {
|
|||
#[deriving(Eq)]
|
||||
pub enum visibility { public, private, inherited }
|
||||
|
||||
impl visibility {
|
||||
fn inherit_from(&self, parent_visibility: visibility) -> visibility {
|
||||
match self {
|
||||
&inherited => parent_visibility,
|
||||
&public | &private => *self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
|
|
Loading…
Add table
Reference in a new issue