Skip to content
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

A bundle of default method fixes and related changes #7471

Closed
wants to merge 10 commits into from
23 changes: 17 additions & 6 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2149,18 +2149,24 @@ impl TypeNames {
self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
}

pub fn type_to_str(&self, ty: Type) -> ~str {
// We have a depth count, because we seem to make infinite types.
pub fn type_to_str_depth(&self, ty: Type, depth: int) -> ~str {
match self.find_name(&ty) {
option::Some(name) => return name.to_owned(),
None => ()
}

if depth == 0 {
return ~"###";
}

unsafe {
let kind = ty.kind();

match kind {
Void => ~"Void",
Half => ~"Half",
Float => ~"Float",
Double => ~"Double",
X86_FP80 => ~"X86_FP80",
FP128 => ~"FP128",
Expand All @@ -2175,31 +2181,36 @@ impl TypeNames {
Function => {
let out_ty = ty.return_type();
let args = ty.func_params();
let args = args.map(|&ty| self.type_to_str(ty)).connect(", ");
let out_ty = self.type_to_str(out_ty);
let args =
args.map(|&ty| self.type_to_str_depth(ty, depth-1)).connect(", ");
let out_ty = self.type_to_str_depth(out_ty, depth-1);
fmt!("fn(%s) -> %s", args, out_ty)
}
Struct => {
let tys = ty.field_types();
let tys = tys.map(|&ty| self.type_to_str(ty)).connect(", ");
let tys = tys.map(|&ty| self.type_to_str_depth(ty, depth-1)).connect(", ");
fmt!("{%s}", tys)
}
Array => {
let el_ty = ty.element_type();
let el_ty = self.type_to_str(el_ty);
let el_ty = self.type_to_str_depth(el_ty, depth-1);
let len = ty.array_length();
fmt!("[%s x %u]", el_ty, len)
}
Pointer => {
let el_ty = ty.element_type();
let el_ty = self.type_to_str(el_ty);
let el_ty = self.type_to_str_depth(el_ty, depth-1);
fmt!("*%s", el_ty)
}
_ => fail!("Unknown Type Kind (%u)", kind as uint)
}
}
}

pub fn type_to_str(&self, ty: Type) -> ~str {
self.type_to_str_depth(ty, 30)
}

pub fn val_to_str(&self, val: ValueRef) -> ~str {
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(val));
Expand Down
28 changes: 24 additions & 4 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,10 @@ fn encode_vtable_res(ecx: &e::EncodeContext,
// ty::t doesn't work, and there is no way (atm) to have
// hand-written encoding routines combine with auto-generated
// ones. perhaps we should fix this.
do ebml_w.emit_from_vec(*dr) |ebml_w, vtable_origin| {
encode_vtable_origin(ecx, ebml_w, vtable_origin)
do ebml_w.emit_from_vec(*dr) |ebml_w, param_tables| {
do ebml_w.emit_from_vec(**param_tables) |ebml_w, vtable_origin| {
encode_vtable_origin(ecx, ebml_w, vtable_origin)
}
}
}

Expand Down Expand Up @@ -632,6 +634,13 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
}
}
}
typeck::vtable_self(def_id) => {
do ebml_w.emit_enum_variant("vtable_self", 2u, 1u) |ebml_w| {
do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
ebml_w.emit_def_id(def_id)
}
}
}
}
}
}
Expand All @@ -646,13 +655,17 @@ trait vtable_decoder_helpers {
impl vtable_decoder_helpers for reader::Decoder {
fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
-> typeck::vtable_res {
@self.read_to_vec(|this| this.read_vtable_origin(xcx))
@self.read_to_vec(|this|
@this.read_to_vec(|this|
this.read_vtable_origin(xcx)))
}

fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
-> typeck::vtable_origin {
do self.read_enum("vtable_origin") |this| {
do this.read_enum_variant(["vtable_static", "vtable_param"])
do this.read_enum_variant(["vtable_static",
"vtable_param",
"vtable_self"])
|this, i| {
match i {
0 => {
Expand All @@ -678,6 +691,13 @@ impl vtable_decoder_helpers for reader::Decoder {
}
)
}
2 => {
typeck::vtable_self(
do this.read_enum_variant_arg(0u) |this| {
this.read_def_id(xcx)
}
)
}
// hard to avoid - user input
_ => fail!("bad enum variant")
}
Expand Down
15 changes: 3 additions & 12 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
&tsubsts,
None,
None,
None,
None);

val
Expand Down Expand Up @@ -1544,17 +1545,15 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
llfndecl: ValueRef,
id: ast::node_id,
output_type: ty::t,
impl_id: Option<ast::def_id>,
param_substs: Option<@param_substs>,
sp: Option<span>)
-> fn_ctxt {
for param_substs.iter().advance |p| { p.validate(); }

debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \
debug!("new_fn_ctxt_w_id(path=%s, id=%?, \
param_substs=%s)",
path_str(ccx.sess, path),
id,
impl_id,
param_substs.repr(ccx.tcx));

let llbbs = mk_standard_basic_blocks(llfndecl);
Expand Down Expand Up @@ -1583,7 +1582,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
lllocals: @mut HashMap::new(),
llupvars: @mut HashMap::new(),
id: id,
impl_id: impl_id,
param_substs: param_substs,
span: sp,
path: path,
Expand All @@ -1604,7 +1602,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
output_type: ty::t,
sp: Option<span>)
-> fn_ctxt {
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp)
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, sp)
}

// NB: must keep 4 fns in sync:
Expand Down Expand Up @@ -1773,7 +1771,6 @@ pub fn trans_closure(ccx: @mut CrateContext,
self_arg: self_arg,
param_substs: Option<@param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>,
attributes: &[ast::attribute],
output_type: ty::t,
maybe_load_env: &fn(fn_ctxt),
Expand All @@ -1791,7 +1788,6 @@ pub fn trans_closure(ccx: @mut CrateContext,
llfndecl,
id,
output_type,
impl_id,
param_substs,
Some(body.span));
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
Expand Down Expand Up @@ -1850,7 +1846,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
self_arg: self_arg,
param_substs: Option<@param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>,
attrs: &[ast::attribute]) {
let do_time = ccx.sess.trans_stats();
let start = if do_time { time::get_time() }
Expand All @@ -1870,7 +1865,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
self_arg,
param_substs,
id,
impl_id,
attrs,
output_type,
|fcx| {
Expand Down Expand Up @@ -1920,7 +1914,6 @@ pub fn trans_enum_variant(ccx: @mut CrateContext,
llfndecl,
variant.node.id,
enum_ty,
None,
param_substs,
None);

Expand Down Expand Up @@ -2000,7 +1993,6 @@ pub fn trans_tuple_struct(ccx: @mut CrateContext,
llfndecl,
ctor_id,
tup_ty,
None,
param_substs,
None);

Expand Down Expand Up @@ -2080,7 +2072,6 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
no_self,
None,
item.id,
None,
item.attrs);
} else {
for body.node.stmts.iter().advance |stmt| {
Expand Down
98 changes: 90 additions & 8 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// closure.

use core::prelude::*;
use core::vec;

use back::abi;
use driver::session;
Expand Down Expand Up @@ -194,6 +195,58 @@ pub fn trans_fn_ref_with_vtables_to_callee(
type_params, vtables))}
}

fn get_impl_resolutions(bcx: block,
impl_id: ast::def_id)
-> typeck::vtable_res {
if impl_id.crate == ast::local_crate {
*bcx.ccx().maps.vtable_map.get(&impl_id.node)
} else {
// XXX: This is a temporary hack to work around not properly
// exporting information about resolutions for impls.
// This doesn't actually work if the trait has param bounds,
// but it does allow us to survive the case when it does not.
let trait_ref = ty::impl_trait_ref(bcx.tcx(), impl_id).get();
@vec::from_elem(trait_ref.substs.tps.len(), @~[])
}
}

fn resolve_default_method_vtables(bcx: block,
impl_id: ast::def_id,
method: &ty::Method,
substs: &ty::substs,
impl_vtables: Option<typeck::vtable_res>)
-> typeck::vtable_res {

// Get the vtables that the impl implements the trait at
let trait_vtables = get_impl_resolutions(bcx, impl_id);

// Build up a param_substs that we are going to resolve the
// trait_vtables under.
let param_substs = Some(@param_substs {
tys: copy substs.tps,
self_ty: substs.self_ty,
vtables: impl_vtables,
self_vtable: None
});

let trait_vtables_fixed = resolve_vtables_under_param_substs(
bcx.tcx(), param_substs, trait_vtables);

// Now we pull any vtables for parameters on the actual method.
let num_method_vtables = method.generics.type_param_defs.len();
let method_vtables = match impl_vtables {
Some(vtables) => {
let num_impl_type_parameters =
vtables.len() - num_method_vtables;
vtables.tailn(num_impl_type_parameters).to_owned()
},
None => vec::from_elem(num_method_vtables, @~[])
};

@(*trait_vtables_fixed + method_vtables)
}


pub fn trans_fn_ref_with_vtables(
bcx: block, //
def_id: ast::def_id, // def id of fn
Expand Down Expand Up @@ -233,15 +286,21 @@ pub fn trans_fn_ref_with_vtables(
// Polytype of the function item (may have type params)
let fn_tpt = ty::lookup_item_type(tcx, def_id);

let substs = ty::substs { self_r: None, self_ty: None,
// For simplicity, we want to use the Subst trait when composing
// substitutions for default methods. The subst trait does
// substitutions with regions, though, so we put a dummy self
// region parameter in to keep it from failing. This is a hack.
let substs = ty::substs { self_r: Some(ty::re_empty),
self_ty: None,
tps: /*bad*/ type_params.to_owned() };


// We need to do a bunch of special handling for default methods.
// We need to modify the def_id and our substs in order to monomorphize
// the function.
let (def_id, opt_impl_did, substs) = match tcx.provided_method_sources.find(&def_id) {
None => (def_id, None, substs),
let (def_id, opt_impl_did, substs, self_vtable, vtables) =
match tcx.provided_method_sources.find(&def_id) {
None => (def_id, None, substs, None, vtables),
Some(source) => {
// There are two relevant substitutions when compiling
// default methods. First, there is the substitution for
Expand All @@ -261,20 +320,42 @@ pub fn trans_fn_ref_with_vtables(
default methods");
let method = ty::method(tcx, source.method_id);

// Get all of the type params for the receiver
let param_defs = method.generics.type_param_defs;
let receiver_substs =
type_params.initn(param_defs.len()).to_owned();
let receiver_vtables = match vtables {
None => @~[],
Some(call_vtables) => {
@call_vtables.initn(param_defs.len()).to_owned()
}
};

let self_vtable =
typeck::vtable_static(source.impl_id, receiver_substs,
receiver_vtables);
// Compute the first substitution
let first_subst = make_substs_for_receiver_types(
tcx, source.impl_id, trait_ref, method);

// And compose them
let new_substs = first_subst.subst(tcx, &substs);


let vtables =
resolve_default_method_vtables(bcx, source.impl_id,
method, &new_substs, vtables);

debug!("trans_fn_with_vtables - default method: \
substs = %s, trait_subst = %s, \
first_subst = %s, new_subst = %s",
first_subst = %s, new_subst = %s, \
self_vtable = %s, vtables = %s",
substs.repr(tcx), trait_ref.substs.repr(tcx),
first_subst.repr(tcx), new_substs.repr(tcx));

first_subst.repr(tcx), new_substs.repr(tcx),
self_vtable.repr(tcx), vtables.repr(tcx));

(source.method_id, Some(source.impl_id), new_substs)
(source.method_id, Some(source.impl_id),
new_substs, Some(self_vtable), Some(vtables))
}
};

Expand Down Expand Up @@ -321,7 +402,8 @@ pub fn trans_fn_ref_with_vtables(

let (val, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs,
vtables, opt_impl_did, Some(ref_id));
vtables, self_vtable,
opt_impl_did, Some(ref_id));
let mut val = val;
if must_cast && ref_id != 0 {
// Monotype of the REFERENCE to the function (type params
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,6 @@ pub fn trans_expr_fn(bcx: block,
no_self,
/*bad*/ copy bcx.fcx.param_substs,
user_id,
None,
[],
real_return_type,
|fcx| load_environment(fcx, cdata_ty, cap_vars,
Expand Down
Loading