Skip to content

Make supertrait methods callable on object types #8519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,13 @@ impl tr for method_origin {
}
)
}
typeck::method_trait(did, m) => {
typeck::method_trait(did.tr(xcx), m)
typeck::method_object(ref mo) => {
typeck::method_object(
typeck::method_object {
trait_id: mo.trait_id.tr(xcx),
.. *mo
}
)
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use metadata::csearch;
use middle::ty::{ty_struct, ty_enum};
use middle::ty;
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 syntax::ast::{decl_item, def, def_fn, def_id, def_static_method};
Expand Down Expand Up @@ -280,10 +280,14 @@ impl PrivacyVisitor {
}
method_param(method_param {
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 {
match self.tcx.items.find(&trait_id.node) {
Some(&node_item(item, _)) => {
Expand Down
15 changes: 4 additions & 11 deletions src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}

// 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)
-> typeck::vtable_res {
resolve_vtables_under_param_substs(fcx.ccx.tcx,
Expand Down Expand Up @@ -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,
param_substs: Option<@param_substs>,
vt: &typeck::vtable_origin)
Expand All @@ -1081,8 +1074,8 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
}
_ => {
tcx.sess.bug(fmt!(
"resolve_vtable_in_fn_ctxt: asked to lookup but \
no vtables in the fn_ctxt!"))
"resolve_vtable_under_param_substs: asked to lookup \
but no vtables in the fn_ctxt!"))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub struct CrateContext {
// Cache computed type parameter uses (see type_use.rs)
type_use_cache: HashMap<ast::def_id, @~[type_use::type_uses]>,
// Cache generated vtables
vtables: HashMap<mono_id, ValueRef>,
vtables: HashMap<(ty::t, mono_id), ValueRef>,
// Cache of constant strings,
const_cstr_cache: HashMap<@str, ValueRef>,

Expand Down
75 changes: 42 additions & 33 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
callee_id,
off,
mt.real_index,
this)
}
}
Expand Down Expand Up @@ -398,7 +398,6 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block,
return (ty_substs, vtables);
}


pub fn trans_trait_callee(bcx: @mut Block,
callee_id: ast::NodeId,
n_method: uint,
Expand Down Expand Up @@ -506,20 +505,35 @@ pub fn vtable_id(ccx: @mut CrateContext,
/// This is used only for objects.
pub fn get_vtable(bcx: @mut Block,
self_ty: ty::t,
origin: typeck::vtable_origin)
origins: typeck::vtable_param_res)
-> ValueRef {
let hash_id = vtable_id(bcx.ccx(), &origin);
match bcx.ccx().vtables.find(&hash_id) {
Some(&val) => val,
None => {
match origin {
typeck::vtable_static(id, substs, sub_vtables) => {
make_impl_vtable(bcx, id, self_ty, substs, sub_vtables)
}
_ => fail!("get_vtable: expected a static origin"),
let ccx = bcx.ccx();
let _icx = push_ctxt("impl::get_vtable");

// Check the cache.
let hash_id = (self_ty, vtable_id(ccx, &origins[0]));
match ccx.vtables.find(&hash_id) {
Some(&val) => { return val }
None => { }
}

// 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.
Expand Down Expand Up @@ -547,15 +561,12 @@ pub fn make_vtable(ccx: &mut CrateContext,
}
}

/// Generates a dynamic vtable for objects.
pub fn make_impl_vtable(bcx: @mut Block,
impl_id: ast::def_id,
self_ty: ty::t,
substs: &[ty::t],
vtables: typeck::vtable_res)
-> ValueRef {
fn emit_vtable_methods(bcx: @mut Block,
impl_id: ast::def_id,
substs: &[ty::t],
vtables: typeck::vtable_res)
-> ~[ValueRef] {
let ccx = bcx.ccx();
let _icx = push_ctxt("impl::make_impl_vtable");
let tcx = ccx.tcx;

let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
Expand All @@ -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 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 fty = ty::subst_tps(tcx,
substs,
Expand All @@ -583,13 +594,7 @@ pub fn make_impl_vtable(bcx: @mut Block,
trans_fn_ref_with_vtables(bcx, m_id, 0,
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,
Expand Down Expand Up @@ -621,9 +626,13 @@ pub fn trans_trait_cast(bcx: @mut Block,
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));

// Store the vtable into the pair or triple.
let orig = ccx.maps.vtable_map.get(&id)[0][0].clone();
let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, &orig);
let vtable = get_vtable(bcx, v_ty, orig);
// This is structured a bit funny because of dynamic borrow failures.
let origins = {
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,
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
val_ty(vtable).ptr_to()));
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub struct field {
mt: mt
}

#[deriving(Clone)]
pub struct Method {
ident: ast::ident,
generics: ty::Generics,
Expand Down Expand Up @@ -3136,12 +3137,14 @@ pub fn method_call_type_param_defs(tcx: ctxt,
typeck::method_param(typeck::method_param {
trait_id: trt_id,
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
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
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(
(*trait_type_param_defs).clone(),
*ty::trait_method(tcx,
Expand Down
Loading