提交 b80b0688 编写于 作者: P Patrick Walton

rustc: Add a new method_self method call origin. Part of default methods.

上级 02c33f8d
......@@ -493,6 +493,9 @@ fn tr(xcx: extended_decode_ctxt) -> method_origin {
typeck::method_trait(did, m, vstore) => {
typeck::method_trait(did.tr(xcx), m, vstore)
}
typeck::method_self(did, m) => {
typeck::method_self(did.tr(xcx), m)
}
}
}
}
......
......@@ -8,8 +8,8 @@
use syntax::ast::{provided, required};
use syntax::ast_map::{node_item, node_method};
use ty::ty_class;
use typeck::{method_map, method_origin, method_param, method_static};
use typeck::{method_trait};
use typeck::{method_map, method_origin, method_param, method_self};
use typeck::{method_static, method_trait};
use core::util::ignore;
use dvec::DVec;
......@@ -81,7 +81,8 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
}
}
method_param({trait_id: trait_id, method_num: method_num, _}) |
method_trait(trait_id, method_num, _) => {
method_trait(trait_id, method_num, _) |
method_self(trait_id, method_num) => {
if trait_id.crate == local_crate {
match tcx.items.find(trait_id.node) {
Some(node_item(item, _)) => {
......
......@@ -1847,7 +1847,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast::item_impl(tps, trait_refs, _, ms) => {
ast::item_impl(tps, trait_refs, self_ast_ty, ms) => {
meth::trans_impl(ccx, *path, item.ident, ms, tps, None);
// Translate any methods that have provided implementations.
......@@ -1860,13 +1860,22 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
loop;
}
// Get the self type.
let self_ty;
match ccx.tcx.ast_ty_to_ty_cache.get(self_ast_ty) {
ty::atttce_resolved(self_type) => self_ty = self_type,
ty::atttce_unresolved => {
ccx.tcx.sess.impossible_case(item.span,
~"didn't cache self ast ty");
}
}
match ccx.tcx.items.get(trait_id.node) {
ast_map::node_item(trait_item, _) => {
match trait_item.node {
ast::item_trait(tps, _, trait_methods) => {
// XXX: ty_self is wrong here. Get the real type.
trans_trait(ccx, tps, trait_methods, path,
item.ident, ty::mk_self(ccx.tcx));
item.ident, self_ty);
}
_ => {
ccx.tcx.sess.impossible_case(item.span,
......
......@@ -154,6 +154,9 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
typeck::method_trait(_, off, vstore) => {
trans_trait_callee(bcx, callee_id, off, self, vstore)
}
typeck::method_self(_, off) => {
bcx.tcx().sess.span_bug(self.span, ~"self method call");
}
}
}
......
......@@ -247,7 +247,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
typeck::method_param({param_num: param, _}) => {
cx.uses[param] |= use_tydesc;
}
typeck::method_trait(*) => (),
typeck::method_trait(*) | typeck::method_self(*) => (),
}
}
}
......
......@@ -2826,7 +2826,8 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
}
typeck::method_param({trait_id:trt_id,
method_num:n_mth, _}) |
typeck::method_trait(trt_id, n_mth, _) => {
typeck::method_trait(trt_id, n_mth, _) |
typeck::method_self(trt_id, n_mth) => {
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
......
......@@ -73,7 +73,7 @@
export vtable_map;
export vtable_res;
export vtable_origin;
export method_static, method_param, method_trait;
export method_static, method_param, method_trait, method_self;
export vtable_static, vtable_param, vtable_trait;
export provided_methods_map;
......@@ -87,6 +87,9 @@ enum method_origin {
// method invoked on a trait instance
method_trait(ast::def_id, uint, ty::vstore),
// method invoked on "self" inside a default method
method_self(ast::def_id, uint),
}
// details for a method invoked with a receiver whose type is a type parameter
......
......@@ -232,9 +232,8 @@ fn push_inherent_candidates(&self, self_ty: ty::t) {
let self_did = self.fcx.self_impl_def_id.expect(
~"unexpected `none` for self_impl_def_id");
let substs = {self_r: None, self_ty: None, tps: ~[]};
self.push_inherent_candidates_from_trait(
self_ty, self_did, &substs,
ty::vstore_slice(ty::re_static)); // XXX: Wrong!
self.push_inherent_candidates_from_self(
self_ty, self_did, &substs);
}
ty_enum(did, _) | ty_class(did, _) => {
self.push_inherent_impl_candidates_for_type(did);
......@@ -397,6 +396,33 @@ fn push_inherent_candidates_from_trait(&self,
});
}
fn push_inherent_candidates_from_self(&self,
self_ty: ty::t,
did: def_id,
substs: &ty::substs) {
let tcx = self.tcx();
let methods = ty::trait_methods(tcx, did); // XXX: Inherited methods.
let index;
match vec::position(*methods, |m| m.ident == self.m_name) {
Some(i) => index = i,
None => return
}
let method = &methods[index];
let rcvr_substs = { self_ty: Some(self_ty), ..*substs };
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
method.self_ty, self_ty, move rcvr_substs);
self.inherent_candidates.push(Candidate {
rcvr_ty: rcvr_ty,
rcvr_substs: move rcvr_substs,
num_method_tps: method.tps.len(),
self_mode: get_mode_from_self_type(method.self_ty),
origin: method_self(did, index)
});
}
fn push_inherent_impl_candidates_for_type(did: def_id)
{
let opt_impl_infos =
......@@ -737,7 +763,7 @@ fn enforce_trait_instance_limitations(&self,
* vtable and hence cannot be monomorphized. */
match candidate.origin {
method_static(*) | method_param(*) => {
method_static(*) | method_param(*) | method_self(*) => {
return; // not a call to a trait instance
}
method_trait(*) => {}
......@@ -772,7 +798,7 @@ fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
method_param(ref mp) => {
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
}
method_trait(did, idx, _) => {
method_trait(did, idx, _) | method_self(did, idx) => {
type_of_trait_method(self.tcx(), did, idx)
}
};
......@@ -793,7 +819,7 @@ fn report_candidate(&self, idx: uint, origin: &method_origin) {
method_param(mp) => {
self.report_param_candidate(idx, mp.trait_id)
}
method_trait(trait_did, _, _) => {
method_trait(trait_did, _, _) | method_self(trait_did, _) => {
self.report_param_candidate(idx, trait_did)
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册