mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 02:54:00 +00:00
commit
293660d443
@ -586,8 +586,13 @@ impl tr for method_origin {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
typeck::method_trait(did, m) => {
|
typeck::method_object(ref mo) => {
|
||||||
typeck::method_trait(did.tr(xcx), m)
|
typeck::method_object(
|
||||||
|
typeck::method_object {
|
||||||
|
trait_id: mo.trait_id.tr(xcx),
|
||||||
|
.. *mo
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use metadata::csearch;
|
|||||||
use middle::ty::{ty_struct, ty_enum};
|
use middle::ty::{ty_struct, ty_enum};
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck::{method_map, method_origin, method_param};
|
use middle::typeck::{method_map, method_origin, method_param};
|
||||||
use middle::typeck::{method_static, method_trait};
|
use middle::typeck::{method_static, method_object};
|
||||||
|
|
||||||
use std::util::ignore;
|
use std::util::ignore;
|
||||||
use syntax::ast::{decl_item, def, def_fn, def_id, def_static_method};
|
use syntax::ast::{decl_item, def, def_fn, def_id, def_static_method};
|
||||||
@ -280,10 +280,14 @@ impl PrivacyVisitor {
|
|||||||
}
|
}
|
||||||
method_param(method_param {
|
method_param(method_param {
|
||||||
trait_id: trait_id,
|
trait_id: trait_id,
|
||||||
method_num: method_num,
|
method_num: method_num,
|
||||||
_
|
_
|
||||||
}) |
|
}) |
|
||||||
method_trait(trait_id, method_num) => {
|
method_object(method_object {
|
||||||
|
trait_id: trait_id,
|
||||||
|
method_num: method_num,
|
||||||
|
_
|
||||||
|
}) => {
|
||||||
if trait_id.crate == LOCAL_CRATE {
|
if trait_id.crate == LOCAL_CRATE {
|
||||||
match self.tcx.items.find(&trait_id.node) {
|
match self.tcx.items.find(&trait_id.node) {
|
||||||
Some(&node_item(item, _)) => {
|
Some(&node_item(item, _)) => {
|
||||||
|
@ -1015,6 +1015,8 @@ pub fn node_vtables(bcx: @mut Block, id: ast::NodeId)
|
|||||||
raw_vtables.map_move(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
|
raw_vtables.map_move(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply the typaram substitutions in the FunctionContext to some
|
||||||
|
// vtables. This should eliminate any vtable_params.
|
||||||
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
|
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
|
||||||
-> typeck::vtable_res {
|
-> typeck::vtable_res {
|
||||||
resolve_vtables_under_param_substs(fcx.ccx.tcx,
|
resolve_vtables_under_param_substs(fcx.ccx.tcx,
|
||||||
@ -1047,15 +1049,6 @@ pub fn resolve_param_vtables_under_param_substs(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Apply the typaram substitutions in the FunctionContext to a vtable. This should
|
|
||||||
// eliminate any vtable_params.
|
|
||||||
pub fn resolve_vtable_in_fn_ctxt(fcx: &FunctionContext, vt: &typeck::vtable_origin)
|
|
||||||
-> typeck::vtable_origin {
|
|
||||||
resolve_vtable_under_param_substs(fcx.ccx.tcx,
|
|
||||||
fcx.param_substs,
|
|
||||||
vt)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
|
pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
|
||||||
param_substs: Option<@param_substs>,
|
param_substs: Option<@param_substs>,
|
||||||
vt: &typeck::vtable_origin)
|
vt: &typeck::vtable_origin)
|
||||||
@ -1081,8 +1074,8 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
tcx.sess.bug(fmt!(
|
tcx.sess.bug(fmt!(
|
||||||
"resolve_vtable_in_fn_ctxt: asked to lookup but \
|
"resolve_vtable_under_param_substs: asked to lookup \
|
||||||
no vtables in the fn_ctxt!"))
|
but no vtables in the fn_ctxt!"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ pub struct CrateContext {
|
|||||||
// Cache computed type parameter uses (see type_use.rs)
|
// Cache computed type parameter uses (see type_use.rs)
|
||||||
type_use_cache: HashMap<ast::def_id, @~[type_use::type_uses]>,
|
type_use_cache: HashMap<ast::def_id, @~[type_use::type_uses]>,
|
||||||
// Cache generated vtables
|
// Cache generated vtables
|
||||||
vtables: HashMap<mono_id, ValueRef>,
|
vtables: HashMap<(ty::t, mono_id), ValueRef>,
|
||||||
// Cache of constant strings,
|
// Cache of constant strings,
|
||||||
const_cstr_cache: HashMap<@str, ValueRef>,
|
const_cstr_cache: HashMap<@str, ValueRef>,
|
||||||
|
|
||||||
|
@ -186,10 +186,10 @@ pub fn trans_method_callee(bcx: @mut Block,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typeck::method_trait(_, off) => {
|
typeck::method_object(ref mt) => {
|
||||||
trans_trait_callee(bcx,
|
trans_trait_callee(bcx,
|
||||||
callee_id,
|
callee_id,
|
||||||
off,
|
mt.real_index,
|
||||||
this)
|
this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,7 +398,6 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block,
|
|||||||
return (ty_substs, vtables);
|
return (ty_substs, vtables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn trans_trait_callee(bcx: @mut Block,
|
pub fn trans_trait_callee(bcx: @mut Block,
|
||||||
callee_id: ast::NodeId,
|
callee_id: ast::NodeId,
|
||||||
n_method: uint,
|
n_method: uint,
|
||||||
@ -506,20 +505,35 @@ pub fn vtable_id(ccx: @mut CrateContext,
|
|||||||
/// This is used only for objects.
|
/// This is used only for objects.
|
||||||
pub fn get_vtable(bcx: @mut Block,
|
pub fn get_vtable(bcx: @mut Block,
|
||||||
self_ty: ty::t,
|
self_ty: ty::t,
|
||||||
origin: typeck::vtable_origin)
|
origins: typeck::vtable_param_res)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let hash_id = vtable_id(bcx.ccx(), &origin);
|
let ccx = bcx.ccx();
|
||||||
match bcx.ccx().vtables.find(&hash_id) {
|
let _icx = push_ctxt("impl::get_vtable");
|
||||||
Some(&val) => val,
|
|
||||||
None => {
|
// Check the cache.
|
||||||
match origin {
|
let hash_id = (self_ty, vtable_id(ccx, &origins[0]));
|
||||||
typeck::vtable_static(id, substs, sub_vtables) => {
|
match ccx.vtables.find(&hash_id) {
|
||||||
make_impl_vtable(bcx, id, self_ty, substs, sub_vtables)
|
Some(&val) => { return val }
|
||||||
}
|
None => { }
|
||||||
_ => fail!("get_vtable: expected a static origin"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not in the cache. Actually build it.
|
||||||
|
let methods = do origins.flat_map |origin| {
|
||||||
|
match *origin {
|
||||||
|
typeck::vtable_static(id, ref substs, sub_vtables) => {
|
||||||
|
emit_vtable_methods(bcx, id, *substs, sub_vtables)
|
||||||
|
}
|
||||||
|
_ => ccx.sess.bug("get_vtable: expected a static origin"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a type descriptor for the vtable.
|
||||||
|
let tydesc = get_tydesc(ccx, self_ty);
|
||||||
|
glue::lazily_emit_all_tydesc_glue(ccx, tydesc);
|
||||||
|
|
||||||
|
let vtable = make_vtable(ccx, tydesc, methods);
|
||||||
|
ccx.vtables.insert(hash_id, vtable);
|
||||||
|
return vtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to declare and initialize the vtable.
|
/// Helper function to declare and initialize the vtable.
|
||||||
@ -547,15 +561,12 @@ pub fn make_vtable(ccx: &mut CrateContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a dynamic vtable for objects.
|
fn emit_vtable_methods(bcx: @mut Block,
|
||||||
pub fn make_impl_vtable(bcx: @mut Block,
|
impl_id: ast::def_id,
|
||||||
impl_id: ast::def_id,
|
substs: &[ty::t],
|
||||||
self_ty: ty::t,
|
vtables: typeck::vtable_res)
|
||||||
substs: &[ty::t],
|
-> ~[ValueRef] {
|
||||||
vtables: typeck::vtable_res)
|
|
||||||
-> ValueRef {
|
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let _icx = push_ctxt("impl::make_impl_vtable");
|
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
|
|
||||||
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
|
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
|
||||||
@ -565,7 +576,7 @@ pub fn make_impl_vtable(bcx: @mut Block,
|
|||||||
};
|
};
|
||||||
|
|
||||||
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
||||||
let methods = do trait_method_def_ids.map |method_def_id| {
|
do trait_method_def_ids.map |method_def_id| {
|
||||||
let im = ty::method(tcx, *method_def_id);
|
let im = ty::method(tcx, *method_def_id);
|
||||||
let fty = ty::subst_tps(tcx,
|
let fty = ty::subst_tps(tcx,
|
||||||
substs,
|
substs,
|
||||||
@ -583,13 +594,7 @@ pub fn make_impl_vtable(bcx: @mut Block,
|
|||||||
trans_fn_ref_with_vtables(bcx, m_id, 0,
|
trans_fn_ref_with_vtables(bcx, m_id, 0,
|
||||||
substs, Some(vtables)).llfn
|
substs, Some(vtables)).llfn
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Generate a type descriptor for the vtable.
|
|
||||||
let tydesc = get_tydesc(ccx, self_ty);
|
|
||||||
glue::lazily_emit_all_tydesc_glue(ccx, tydesc);
|
|
||||||
|
|
||||||
make_vtable(ccx, tydesc, methods)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_trait_cast(bcx: @mut Block,
|
pub fn trans_trait_cast(bcx: @mut Block,
|
||||||
@ -621,9 +626,13 @@ pub fn trans_trait_cast(bcx: @mut Block,
|
|||||||
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
||||||
|
|
||||||
// Store the vtable into the pair or triple.
|
// Store the vtable into the pair or triple.
|
||||||
let orig = ccx.maps.vtable_map.get(&id)[0][0].clone();
|
// This is structured a bit funny because of dynamic borrow failures.
|
||||||
let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, &orig);
|
let origins = {
|
||||||
let vtable = get_vtable(bcx, v_ty, orig);
|
let res = ccx.maps.vtable_map.get(&id);
|
||||||
|
let res = resolve_vtables_in_fn_ctxt(bcx.fcx, *res);
|
||||||
|
res[0]
|
||||||
|
};
|
||||||
|
let vtable = get_vtable(bcx, v_ty, origins);
|
||||||
Store(bcx, vtable, PointerCast(bcx,
|
Store(bcx, vtable, PointerCast(bcx,
|
||||||
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
|
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
|
||||||
val_ty(vtable).ptr_to()));
|
val_ty(vtable).ptr_to()));
|
||||||
|
@ -59,6 +59,7 @@ pub struct field {
|
|||||||
mt: mt
|
mt: mt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct Method {
|
pub struct Method {
|
||||||
ident: ast::ident,
|
ident: ast::ident,
|
||||||
generics: ty::Generics,
|
generics: ty::Generics,
|
||||||
@ -3136,12 +3137,14 @@ pub fn method_call_type_param_defs(tcx: ctxt,
|
|||||||
typeck::method_param(typeck::method_param {
|
typeck::method_param(typeck::method_param {
|
||||||
trait_id: trt_id,
|
trait_id: trt_id,
|
||||||
method_num: n_mth, _}) |
|
method_num: n_mth, _}) |
|
||||||
typeck::method_trait(trt_id, n_mth) => {
|
typeck::method_object(typeck::method_object {
|
||||||
|
trait_id: trt_id,
|
||||||
|
method_num: n_mth, _}) => {
|
||||||
// ...trait methods bounds, in contrast, include only the
|
// ...trait methods bounds, in contrast, include only the
|
||||||
// method bounds, so we must preprend the tps from the
|
// method bounds, so we must preprend the tps from the
|
||||||
// trait itself. This ought to be harmonized.
|
// trait itself. This ought to be harmonized.
|
||||||
let trait_type_param_defs =
|
let trait_type_param_defs =
|
||||||
ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
|
lookup_trait_def(tcx, trt_id).generics.type_param_defs;
|
||||||
@vec::append(
|
@vec::append(
|
||||||
(*trait_type_param_defs).clone(),
|
(*trait_type_param_defs).clone(),
|
||||||
*ty::trait_method(tcx,
|
*ty::trait_method(tcx,
|
||||||
|
@ -90,7 +90,7 @@ use middle::typeck::check::vtable;
|
|||||||
use middle::typeck::check;
|
use middle::typeck::check;
|
||||||
use middle::typeck::infer;
|
use middle::typeck::infer;
|
||||||
use middle::typeck::{method_map_entry, method_origin, method_param};
|
use middle::typeck::{method_map_entry, method_origin, method_param};
|
||||||
use middle::typeck::{method_static, method_trait};
|
use middle::typeck::{method_static, method_object};
|
||||||
use middle::typeck::{param_numbered, param_self, param_index};
|
use middle::typeck::{param_numbered, param_self, param_index};
|
||||||
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
@ -298,7 +298,7 @@ impl<'self> LookupContext<'self> {
|
|||||||
loop {
|
loop {
|
||||||
match get(self_ty).sty {
|
match get(self_ty).sty {
|
||||||
ty_trait(did, ref substs, _, _, _) => {
|
ty_trait(did, ref substs, _, _, _) => {
|
||||||
self.push_inherent_candidates_from_trait(did, substs);
|
self.push_inherent_candidates_from_object(did, substs);
|
||||||
self.push_inherent_impl_candidates_for_type(did);
|
self.push_inherent_impl_candidates_for_type(did);
|
||||||
}
|
}
|
||||||
ty_enum(did, _) | ty_struct(did, _) => {
|
ty_enum(did, _) | ty_struct(did, _) => {
|
||||||
@ -363,53 +363,85 @@ impl<'self> LookupContext<'self> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_inherent_candidates_from_trait(&self,
|
// Determine the index of a method in the list of all methods belonging
|
||||||
did: def_id,
|
// to a trait and its supertraits.
|
||||||
substs: &ty::substs) {
|
fn get_method_index(&self,
|
||||||
debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
|
trait_ref: @TraitRef,
|
||||||
|
subtrait_id: ast::def_id,
|
||||||
|
n_method: uint) -> uint {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
// We need to figure the "real index" of the method in a
|
||||||
|
// listing of all the methods of an object. We do this by
|
||||||
|
// iterating down the supertraits of the object's trait until
|
||||||
|
// we find the trait the method came from, counting up the
|
||||||
|
// methods from them.
|
||||||
|
let mut method_count = 0;
|
||||||
|
do ty::each_bound_trait_and_supertraits(tcx, &[trait_ref])
|
||||||
|
|bound_ref| {
|
||||||
|
if bound_ref.def_id == subtrait_id { false }
|
||||||
|
else {
|
||||||
|
method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return method_count + n_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn push_inherent_candidates_from_object(&self,
|
||||||
|
did: def_id,
|
||||||
|
substs: &ty::substs) {
|
||||||
|
debug!("push_inherent_candidates_from_object(did=%s, substs=%s)",
|
||||||
self.did_to_str(did),
|
self.did_to_str(did),
|
||||||
substs_to_str(self.tcx(), substs));
|
substs_to_str(self.tcx(), substs));
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
let tcx = self.tcx();
|
|
||||||
let ms = ty::trait_methods(tcx, did);
|
|
||||||
let index = match ms.iter().position(|m| m.ident == self.m_name) {
|
|
||||||
Some(i) => i,
|
|
||||||
None => { return; } // no method with the right name
|
|
||||||
};
|
|
||||||
let method = ms[index];
|
|
||||||
|
|
||||||
match method.explicit_self {
|
|
||||||
ast::sty_static => {
|
|
||||||
return; // not a method we can call with dot notation
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is illegal to invoke a method on a trait instance that
|
// It is illegal to invoke a method on a trait instance that
|
||||||
// refers to the `self` type. An error will be reported by
|
// refers to the `self` type. An error will be reported by
|
||||||
// `enforce_object_limitations()` if the method refers
|
// `enforce_object_limitations()` if the method refers
|
||||||
// to the `Self` type. Substituting ty_err here allows
|
// to the `Self` type. Substituting ty_err here allows
|
||||||
// compiler to soldier on.
|
// compiler to soldier on.
|
||||||
//
|
//
|
||||||
// NOTE: `confirm_candidate()` also relies upon this substitution
|
// `confirm_candidate()` also relies upon this substitution
|
||||||
// for Self. (fix)
|
// for Self. (fix)
|
||||||
let rcvr_substs = substs {
|
let rcvr_substs = substs {
|
||||||
self_ty: Some(ty::mk_err()),
|
self_ty: Some(ty::mk_err()),
|
||||||
..(*substs).clone()
|
..(*substs).clone()
|
||||||
};
|
};
|
||||||
|
let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
|
||||||
|
|
||||||
self.inherent_candidates.push(Candidate {
|
do self.push_inherent_candidates_from_bounds_inner(&[trait_ref])
|
||||||
rcvr_match_condition: RcvrMatchesIfObject(did),
|
|trait_ref, m, method_num, _bound_num| {
|
||||||
rcvr_substs: rcvr_substs,
|
let vtable_index =
|
||||||
method_ty: method,
|
self.get_method_index(trait_ref, trait_ref.def_id, method_num);
|
||||||
origin: method_trait(did, index)
|
// We need to fix up the transformed self type.
|
||||||
});
|
let transformed_self_ty =
|
||||||
|
self.construct_transformed_self_ty_for_object(
|
||||||
|
did, &rcvr_substs, m);
|
||||||
|
let m = @Method {
|
||||||
|
transformed_self_ty: Some(transformed_self_ty),
|
||||||
|
.. (*m).clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
Candidate {
|
||||||
|
rcvr_match_condition: RcvrMatchesIfObject(did),
|
||||||
|
rcvr_substs: trait_ref.substs.clone(),
|
||||||
|
method_ty: m,
|
||||||
|
origin: method_object(method_object {
|
||||||
|
trait_id: trait_ref.def_id,
|
||||||
|
object_trait_id: did,
|
||||||
|
method_num: method_num,
|
||||||
|
real_index: vtable_index
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_inherent_candidates_from_param(&self,
|
fn push_inherent_candidates_from_param(&self,
|
||||||
rcvr_ty: ty::t,
|
rcvr_ty: ty::t,
|
||||||
param_ty: param_ty) {
|
param_ty: param_ty) {
|
||||||
debug!("push_inherent_candidates_from_param(param_ty=%?)",
|
debug!("push_inherent_candidates_from_param(param_ty=%?)",
|
||||||
param_ty);
|
param_ty);
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
@ -441,9 +473,34 @@ impl<'self> LookupContext<'self> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push_inherent_candidates_from_bounds(&self,
|
fn push_inherent_candidates_from_bounds(&self,
|
||||||
self_ty: ty::t,
|
self_ty: ty::t,
|
||||||
bounds: &[@TraitRef],
|
bounds: &[@TraitRef],
|
||||||
param: param_index) {
|
param: param_index) {
|
||||||
|
do self.push_inherent_candidates_from_bounds_inner(bounds)
|
||||||
|
|trait_ref, m, method_num, bound_num| {
|
||||||
|
Candidate {
|
||||||
|
rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
|
||||||
|
rcvr_substs: trait_ref.substs.clone(),
|
||||||
|
method_ty: m,
|
||||||
|
origin: method_param(
|
||||||
|
method_param {
|
||||||
|
trait_id: trait_ref.def_id,
|
||||||
|
method_num: method_num,
|
||||||
|
param_num: param,
|
||||||
|
bound_num: bound_num,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a search through a list of bounds, using a callback to actually
|
||||||
|
// create the candidates.
|
||||||
|
fn push_inherent_candidates_from_bounds_inner(
|
||||||
|
&self,
|
||||||
|
bounds: &[@TraitRef],
|
||||||
|
mk_cand: &fn(trait_ref: @TraitRef, m: @ty::Method, method_num: uint,
|
||||||
|
bound_num: uint) -> Candidate) {
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let mut next_bound_idx = 0; // count only trait bounds
|
let mut next_bound_idx = 0; // count only trait bounds
|
||||||
|
|
||||||
@ -459,18 +516,8 @@ impl<'self> LookupContext<'self> {
|
|||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
let method = trait_methods[pos];
|
let method = trait_methods[pos];
|
||||||
|
|
||||||
let cand = Candidate {
|
let cand = mk_cand(bound_trait_ref, method,
|
||||||
rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
|
pos, this_bound_idx);
|
||||||
rcvr_substs: bound_trait_ref.substs.clone(),
|
|
||||||
method_ty: method,
|
|
||||||
origin: method_param(
|
|
||||||
method_param {
|
|
||||||
trait_id: bound_trait_ref.def_id,
|
|
||||||
method_num: pos,
|
|
||||||
param_num: param,
|
|
||||||
bound_num: this_bound_idx,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!("pushing inherent candidate for param: %?", cand);
|
debug!("pushing inherent candidate for param: %?", cand);
|
||||||
self.inherent_candidates.push(cand);
|
self.inherent_candidates.push(cand);
|
||||||
@ -879,7 +926,7 @@ impl<'self> LookupContext<'self> {
|
|||||||
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||||
-> method_map_entry {
|
-> method_map_entry {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let fty = self.fn_ty_from_origin(&candidate.origin);
|
let fty = ty::mk_bare_fn(tcx, candidate.method_ty.fty.clone());
|
||||||
|
|
||||||
debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)",
|
debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)",
|
||||||
self.expr.repr(tcx),
|
self.expr.repr(tcx),
|
||||||
@ -891,17 +938,9 @@ impl<'self> LookupContext<'self> {
|
|||||||
|
|
||||||
// static methods should never have gotten this far:
|
// static methods should never have gotten this far:
|
||||||
assert!(candidate.method_ty.explicit_self != sty_static);
|
assert!(candidate.method_ty.explicit_self != sty_static);
|
||||||
|
let transformed_self_ty =
|
||||||
let transformed_self_ty = match candidate.origin {
|
ty::subst(tcx, &candidate.rcvr_substs,
|
||||||
method_trait(trait_def_id, _) => {
|
candidate.method_ty.transformed_self_ty.unwrap());
|
||||||
self.construct_transformed_self_ty_for_object(
|
|
||||||
trait_def_id, candidate)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let t = candidate.method_ty.transformed_self_ty.unwrap();
|
|
||||||
ty::subst(tcx, &candidate.rcvr_substs, t)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine the values for the type parameters of the method.
|
// Determine the values for the type parameters of the method.
|
||||||
// If they were not explicitly supplied, just construct fresh
|
// If they were not explicitly supplied, just construct fresh
|
||||||
@ -992,9 +1031,11 @@ impl<'self> LookupContext<'self> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_transformed_self_ty_for_object(&self,
|
fn construct_transformed_self_ty_for_object(
|
||||||
trait_def_id: ast::def_id,
|
&self,
|
||||||
candidate: &Candidate) -> ty::t
|
trait_def_id: ast::def_id,
|
||||||
|
rcvr_substs: &ty::substs,
|
||||||
|
method_ty: &ty::Method) -> ty::t
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
* This is a bit tricky. We have a match against a trait method
|
* This is a bit tricky. We have a match against a trait method
|
||||||
@ -1010,17 +1051,17 @@ impl<'self> LookupContext<'self> {
|
|||||||
* result to be `&'a Foo`. Assuming that `m_method` is being
|
* result to be `&'a Foo`. Assuming that `m_method` is being
|
||||||
* called, we want the result to be `@mut Foo`. Of course,
|
* called, we want the result to be `@mut Foo`. Of course,
|
||||||
* this transformation has already been done as part of
|
* this transformation has already been done as part of
|
||||||
* `candidate.method_ty.transformed_self_ty`, but there the
|
* `method_ty.transformed_self_ty`, but there the
|
||||||
* type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`).
|
* type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`).
|
||||||
* Because objects are not standalone types, we can't just substitute
|
* Because objects are not standalone types, we can't just substitute
|
||||||
* `s/Self/Foo/`, so we must instead perform this kind of hokey
|
* `s/Self/Foo/`, so we must instead perform this kind of hokey
|
||||||
* match below.
|
* match below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let substs = ty::substs {regions: candidate.rcvr_substs.regions.clone(),
|
let substs = ty::substs {regions: rcvr_substs.regions.clone(),
|
||||||
self_ty: None,
|
self_ty: None,
|
||||||
tps: candidate.rcvr_substs.tps.clone()};
|
tps: rcvr_substs.tps.clone()};
|
||||||
match candidate.method_ty.explicit_self {
|
match method_ty.explicit_self {
|
||||||
ast::sty_static => {
|
ast::sty_static => {
|
||||||
self.bug(~"static method for object type receiver");
|
self.bug(~"static method for object type receiver");
|
||||||
}
|
}
|
||||||
@ -1029,7 +1070,7 @@ impl<'self> LookupContext<'self> {
|
|||||||
}
|
}
|
||||||
ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
|
ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
|
||||||
let transformed_self_ty =
|
let transformed_self_ty =
|
||||||
candidate.method_ty.transformed_self_ty.clone().unwrap();
|
method_ty.transformed_self_ty.clone().unwrap();
|
||||||
match ty::get(transformed_self_ty).sty {
|
match ty::get(transformed_self_ty).sty {
|
||||||
ty::ty_rptr(r, mt) => { // must be sty_region
|
ty::ty_rptr(r, mt) => { // must be sty_region
|
||||||
ty::mk_trait(self.tcx(), trait_def_id,
|
ty::mk_trait(self.tcx(), trait_def_id,
|
||||||
@ -1072,7 +1113,7 @@ impl<'self> LookupContext<'self> {
|
|||||||
method_static(*) | method_param(*) => {
|
method_static(*) | method_param(*) => {
|
||||||
return; // not a call to a trait instance
|
return; // not a call to a trait instance
|
||||||
}
|
}
|
||||||
method_trait(*) => {}
|
method_object(*) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match candidate.method_ty.explicit_self {
|
match candidate.method_ty.explicit_self {
|
||||||
@ -1117,7 +1158,7 @@ impl<'self> LookupContext<'self> {
|
|||||||
// XXX: does this properly enforce this on everything now
|
// XXX: does this properly enforce this on everything now
|
||||||
// that self has been merged in? -sully
|
// that self has been merged in? -sully
|
||||||
method_param(method_param { trait_id: trait_id, _ }) |
|
method_param(method_param { trait_id: trait_id, _ }) |
|
||||||
method_trait(trait_id, _) => {
|
method_object(method_object { trait_id: trait_id, _ }) => {
|
||||||
bad = self.tcx().destructor_for_type.contains_key(&trait_id);
|
bad = self.tcx().destructor_for_type.contains_key(&trait_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1235,27 +1276,6 @@ impl<'self> LookupContext<'self> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
|
|
||||||
return match *origin {
|
|
||||||
method_static(did) => {
|
|
||||||
ty::lookup_item_type(self.tcx(), did).ty
|
|
||||||
}
|
|
||||||
method_param(ref mp) => {
|
|
||||||
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
|
|
||||||
}
|
|
||||||
method_trait(did, idx) => {
|
|
||||||
type_of_trait_method(self.tcx(), did, idx)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fn type_of_trait_method(tcx: ty::ctxt,
|
|
||||||
trait_did: def_id,
|
|
||||||
method_num: uint) -> ty::t {
|
|
||||||
let trait_methods = ty::trait_methods(tcx, trait_did);
|
|
||||||
ty::mk_bare_fn(tcx, trait_methods[method_num].fty.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_candidate(&self, idx: uint, origin: &method_origin) {
|
fn report_candidate(&self, idx: uint, origin: &method_origin) {
|
||||||
match *origin {
|
match *origin {
|
||||||
method_static(impl_did) => {
|
method_static(impl_did) => {
|
||||||
@ -1264,8 +1284,8 @@ impl<'self> LookupContext<'self> {
|
|||||||
method_param(ref mp) => {
|
method_param(ref mp) => {
|
||||||
self.report_param_candidate(idx, (*mp).trait_id)
|
self.report_param_candidate(idx, (*mp).trait_id)
|
||||||
}
|
}
|
||||||
method_trait(trait_did, _) => {
|
method_object(ref mo) => {
|
||||||
self.report_trait_candidate(idx, trait_did)
|
self.report_trait_candidate(idx, mo.trait_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,30 +647,21 @@ pub fn early_resolve_expr(ex: @ast::expr,
|
|||||||
self_ty: Some(mt.ty)
|
self_ty: Some(mt.ty)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let vtable_opt =
|
|
||||||
lookup_vtable(&vcx,
|
let param_bounds = ty::ParamBounds {
|
||||||
location_info,
|
builtin_bounds: ty::EmptyBuiltinBounds(),
|
||||||
mt.ty,
|
trait_bounds: ~[target_trait_ref]
|
||||||
target_trait_ref,
|
};
|
||||||
is_early);
|
let vtables =
|
||||||
match vtable_opt {
|
lookup_vtables_for_param(&vcx,
|
||||||
Some(vtable) => {
|
location_info,
|
||||||
// Map this expression to that
|
None,
|
||||||
// vtable (that is: "ex has vtable
|
¶m_bounds,
|
||||||
// <vtable>")
|
mt.ty,
|
||||||
if !is_early {
|
is_early);
|
||||||
insert_vtables(fcx, ex.id,
|
|
||||||
@~[@~[vtable]]);
|
if !is_early {
|
||||||
}
|
insert_vtables(fcx, ex.id, @~[vtables]);
|
||||||
}
|
|
||||||
None => {
|
|
||||||
fcx.tcx().sess.span_err(
|
|
||||||
ex.span,
|
|
||||||
fmt!("failed to find an implementation \
|
|
||||||
of trait %s for %s",
|
|
||||||
fcx.infcx().ty_to_str(target_ty),
|
|
||||||
fcx.infcx().ty_to_str(mt.ty)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, if this is &trait, we need to link the
|
// Now, if this is &trait, we need to link the
|
||||||
|
@ -88,7 +88,7 @@ pub enum method_origin {
|
|||||||
method_param(method_param),
|
method_param(method_param),
|
||||||
|
|
||||||
// method invoked on a trait instance
|
// method invoked on a trait instance
|
||||||
method_trait(ast::def_id, uint),
|
method_object(method_object),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +110,26 @@ pub struct method_param {
|
|||||||
bound_num: uint,
|
bound_num: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// details for a method invoked with a receiver whose type is an object
|
||||||
|
#[deriving(Clone, Encodable, Decodable)]
|
||||||
|
pub struct method_object {
|
||||||
|
// the (super)trait containing the method to be invoked
|
||||||
|
trait_id: ast::def_id,
|
||||||
|
|
||||||
|
// the actual base trait id of the object
|
||||||
|
object_trait_id: ast::def_id,
|
||||||
|
|
||||||
|
// index of the method to be invoked amongst the trait's methods
|
||||||
|
method_num: uint,
|
||||||
|
|
||||||
|
// index into the actual runtime vtable.
|
||||||
|
// the vtable is formed by concatenating together the method lists of
|
||||||
|
// the base object trait and all supertraits; this is the index into
|
||||||
|
// that vtable
|
||||||
|
real_index: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct method_map_entry {
|
pub struct method_map_entry {
|
||||||
// the type of the self parameter, which is not reflected in the fn type
|
// the type of the self parameter, which is not reflected in the fn type
|
||||||
|
@ -747,8 +747,8 @@ impl Repr for typeck::method_origin {
|
|||||||
&typeck::method_param(ref p) => {
|
&typeck::method_param(ref p) => {
|
||||||
p.repr(tcx)
|
p.repr(tcx)
|
||||||
}
|
}
|
||||||
&typeck::method_trait(def_id, n) => {
|
&typeck::method_object(ref p) => {
|
||||||
fmt!("method_trait(%s, %?)", def_id.repr(tcx), n)
|
p.repr(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -764,6 +764,16 @@ impl Repr for typeck::method_param {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repr for typeck::method_object {
|
||||||
|
fn repr(&self, tcx: ctxt) -> ~str {
|
||||||
|
fmt!("method_object(%s,%?,%?)",
|
||||||
|
self.trait_id.repr(tcx),
|
||||||
|
self.method_num,
|
||||||
|
self.real_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Repr for ty::RegionVid {
|
impl Repr for ty::RegionVid {
|
||||||
fn repr(&self, _tcx: ctxt) -> ~str {
|
fn repr(&self, _tcx: ctxt) -> ~str {
|
||||||
fmt!("%?", *self)
|
fmt!("%?", *self)
|
||||||
|
@ -38,7 +38,7 @@ impl Logger for StdErrLogger {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Truncate the string
|
// Truncate the string
|
||||||
let buf_bytes = 256;
|
let buf_bytes = 2048;
|
||||||
if s.len() > buf_bytes {
|
if s.len() > buf_bytes {
|
||||||
let s = s.slice(0, buf_bytes) + "[...]";
|
let s = s.slice(0, buf_bytes) + "[...]";
|
||||||
print(s);
|
print(s);
|
||||||
|
Loading…
Reference in New Issue
Block a user