Skip to content

Commit

Permalink
Make supertrait methods callable on object types.
Browse files Browse the repository at this point in the history
This requires changes to method search and to codegen. We now emit a
vtable for objects that includes methods from all supertraits.
Closes #4100.

Also, actually populate the cache for vtables, and also key it by type
so that it actually works.
  • Loading branch information
msullivan committed Aug 19, 2013
1 parent dc9b3e3 commit 6a6d3b6
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 170 deletions.
9 changes: 7 additions & 2 deletions src/librustc/middle/astencode.rs
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
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
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
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
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
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

5 comments on commit 6a6d3b6

@bors
Copy link
Contributor

@bors bors commented on 6a6d3b6 Aug 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from catamorphism
at msullivan@6a6d3b6

@bors
Copy link
Contributor

@bors bors commented on 6a6d3b6 Aug 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging msullivan/rust/objects = 6a6d3b6 into auto

@bors
Copy link
Contributor

@bors bors commented on 6a6d3b6 Aug 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msullivan/rust/objects = 6a6d3b6 merged ok, testing candidate = 293660d

@bors
Copy link
Contributor

@bors bors commented on 6a6d3b6 Aug 20, 2013

@bors
Copy link
Contributor

@bors bors commented on 6a6d3b6 Aug 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 293660d

Please sign in to comment.