2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2013-03-26 15:38:07 -05:00
|
|
|
use back::abi;
|
2012-09-04 13:54:36 -05:00
|
|
|
use lib::llvm::llvm;
|
2013-03-26 15:38:07 -05:00
|
|
|
use lib::llvm::ValueRef;
|
2012-12-23 16:41:37 -06:00
|
|
|
use lib;
|
2012-12-13 15:05:22 -06:00
|
|
|
use metadata::csearch;
|
|
|
|
use middle::trans::base::*;
|
|
|
|
use middle::trans::build::*;
|
|
|
|
use middle::trans::callee::*;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::trans::callee;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::trans::common::*;
|
2013-06-27 18:40:27 -05:00
|
|
|
use middle::trans::datum::*;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::trans::expr::{SaveIn, Ignore};
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::trans::expr;
|
|
|
|
use middle::trans::glue;
|
|
|
|
use middle::trans::monomorphize;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::trans::type_of::*;
|
2013-02-25 13:11:21 -06:00
|
|
|
use middle::ty;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::typeck;
|
2013-02-25 13:11:21 -06:00
|
|
|
use util::common::indenter;
|
2013-06-29 00:07:24 -05:00
|
|
|
use util::ppaux::Repr;
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
use middle::trans::type_::Type;
|
|
|
|
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::vec;
|
2013-03-26 15:38:07 -05:00
|
|
|
use syntax::ast_map::{path, path_mod, path_name};
|
2013-02-25 13:11:21 -06:00
|
|
|
use syntax::ast_util;
|
2012-12-13 15:05:22 -06:00
|
|
|
use syntax::{ast, ast_map};
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2012-08-21 21:51:43 -05:00
|
|
|
/**
|
|
|
|
The main "translation" pass for methods. Generates code
|
|
|
|
for non-monomorphized methods only. Other methods will
|
|
|
|
be generated once they are invoked with specific type parameters,
|
|
|
|
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
|
|
|
|
*/
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn trans_impl(ccx: @mut CrateContext,
|
2013-05-15 19:38:52 -05:00
|
|
|
path: path,
|
|
|
|
name: ast::ident,
|
|
|
|
methods: &[@ast::method],
|
|
|
|
generics: &ast::Generics,
|
2013-07-27 03:25:59 -05:00
|
|
|
id: ast::NodeId) {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_impl");
|
2013-03-15 14:24:24 -05:00
|
|
|
let tcx = ccx.tcx;
|
|
|
|
|
2013-06-19 20:03:02 -05:00
|
|
|
debug!("trans_impl(path=%s, name=%s, id=%?)",
|
|
|
|
path.repr(tcx), name.repr(tcx), id);
|
2013-03-15 14:24:24 -05:00
|
|
|
|
2013-02-14 23:50:03 -06:00
|
|
|
if !generics.ty_params.is_empty() { return; }
|
2012-06-28 15:52:13 -05:00
|
|
|
let sub_path = vec::append_one(path, path_name(name));
|
2013-08-03 11:45:23 -05:00
|
|
|
for method in methods.iter() {
|
2013-02-14 23:50:03 -06:00
|
|
|
if method.generics.ty_params.len() == 0u {
|
2012-08-21 21:51:43 -05:00
|
|
|
let llfn = get_item_val(ccx, method.id);
|
2013-07-02 14:47:32 -05:00
|
|
|
let path = vec::append_one(sub_path.clone(),
|
2013-01-07 16:16:52 -06:00
|
|
|
path_name(method.ident));
|
2012-10-08 14:39:30 -05:00
|
|
|
|
2013-04-26 21:10:28 -05:00
|
|
|
trans_method(ccx,
|
|
|
|
path,
|
|
|
|
*method,
|
2013-06-19 20:03:02 -05:00
|
|
|
None,
|
2013-06-28 13:11:47 -05:00
|
|
|
llfn);
|
2012-03-08 06:30:22 -06:00
|
|
|
}
|
2012-01-02 05:21:44 -06:00
|
|
|
}
|
|
|
|
}
|
2012-01-02 06:26:51 -06:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
/// Translates a (possibly monomorphized) method body.
|
|
|
|
///
|
|
|
|
/// Parameters:
|
|
|
|
/// * `path`: the path to the method
|
|
|
|
/// * `method`: the AST node for the method
|
|
|
|
/// * `param_substs`: if this is a generic method, the current values for
|
|
|
|
/// type parameters and so forth, else none
|
|
|
|
/// * `llfn`: the LLVM ValueRef for the method
|
|
|
|
/// * `impl_id`: the node ID of the impl this method is inside
|
|
|
|
///
|
|
|
|
/// XXX(pcwalton) Can we take `path` by reference?
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn trans_method(ccx: @mut CrateContext,
|
2013-04-17 11:15:37 -05:00
|
|
|
path: path,
|
2013-01-30 13:46:19 -06:00
|
|
|
method: &ast::method,
|
2013-02-18 14:36:30 -06:00
|
|
|
param_substs: Option<@param_substs>,
|
2013-06-28 13:11:47 -05:00
|
|
|
llfn: ValueRef) {
|
2012-08-22 15:18:29 -05:00
|
|
|
// figure out how self is being passed
|
2013-04-30 10:49:48 -05:00
|
|
|
let self_arg = match method.explicit_self.node {
|
2012-08-21 21:51:43 -05:00
|
|
|
ast::sty_static => {
|
|
|
|
no_self
|
|
|
|
}
|
2012-08-22 15:18:29 -05:00
|
|
|
_ => {
|
|
|
|
// determine the (monomorphized) type that `self` maps to for
|
|
|
|
// this method
|
2013-06-19 20:03:02 -05:00
|
|
|
let self_ty = ty::node_id_to_type(ccx.tcx, method.self_id);
|
2012-08-22 15:18:29 -05:00
|
|
|
let self_ty = match param_substs {
|
2012-10-08 14:39:30 -05:00
|
|
|
None => self_ty,
|
2013-06-24 12:34:18 -05:00
|
|
|
Some(@param_substs {tys: ref tys, self_ty: ref self_sub, _}) => {
|
|
|
|
ty::subst_tps(ccx.tcx, *tys, *self_sub, self_ty)
|
2012-10-08 14:39:30 -05:00
|
|
|
}
|
2012-08-22 15:18:29 -05:00
|
|
|
};
|
2013-06-19 20:03:02 -05:00
|
|
|
debug!("calling trans_fn with self_ty %s",
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
self_ty.repr(ccx.tcx));
|
2013-04-30 10:49:48 -05:00
|
|
|
match method.explicit_self.node {
|
2013-06-27 18:40:27 -05:00
|
|
|
ast::sty_value => impl_self(self_ty, ty::ByRef),
|
|
|
|
_ => impl_self(self_ty, ty::ByCopy),
|
2012-08-22 15:18:29 -05:00
|
|
|
}
|
2012-08-21 21:51:43 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// generate the actual code
|
|
|
|
trans_fn(ccx,
|
|
|
|
path,
|
2013-01-31 19:12:29 -06:00
|
|
|
&method.decl,
|
|
|
|
&method.body,
|
2012-08-21 21:51:43 -05:00
|
|
|
llfn,
|
|
|
|
self_arg,
|
|
|
|
param_substs,
|
2012-10-08 14:39:30 -05:00
|
|
|
method.id,
|
2013-03-29 18:55:04 -05:00
|
|
|
[]);
|
2012-08-21 21:51:43 -05:00
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_self_arg(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
base: @ast::expr,
|
2013-06-29 10:45:59 -05:00
|
|
|
temp_cleanups: &mut ~[ValueRef],
|
2013-01-30 13:46:19 -06:00
|
|
|
mentry: typeck::method_map_entry) -> Result {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_self_arg");
|
2012-02-24 19:45:16 -06:00
|
|
|
|
2013-06-29 09:43:39 -05:00
|
|
|
// self is passed as an opaque box in the environment slot
|
|
|
|
let self_ty = ty::mk_opaque_box(bcx.tcx());
|
2013-06-29 10:45:59 -05:00
|
|
|
trans_arg_expr(bcx,
|
|
|
|
self_ty,
|
|
|
|
mentry.self_mode,
|
|
|
|
base,
|
|
|
|
temp_cleanups,
|
|
|
|
DontAutorefArg)
|
2012-01-02 09:50:51 -06:00
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_method_callee(bcx: @mut Block,
|
2013-07-27 03:25:59 -05:00
|
|
|
callee_id: ast::NodeId,
|
2013-05-10 17:15:06 -05:00
|
|
|
this: @ast::expr,
|
2013-01-30 13:46:19 -06:00
|
|
|
mentry: typeck::method_map_entry)
|
2013-05-10 17:15:06 -05:00
|
|
|
-> Callee {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_method_callee");
|
2012-10-08 14:39:30 -05:00
|
|
|
|
2013-05-10 17:15:06 -05:00
|
|
|
debug!("trans_method_callee(callee_id=%?, this=%s, mentry=%s)",
|
|
|
|
callee_id,
|
|
|
|
bcx.expr_to_str(this),
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
mentry.repr(bcx.tcx()));
|
2013-03-21 07:33:52 -05:00
|
|
|
|
2013-07-22 19:42:45 -05:00
|
|
|
match mentry.origin {
|
2012-08-28 17:54:45 -05:00
|
|
|
typeck::method_static(did) => {
|
|
|
|
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
|
2013-06-29 10:45:59 -05:00
|
|
|
let mut temp_cleanups = ~[];
|
|
|
|
let Result {bcx, val} = trans_self_arg(bcx, this, &mut temp_cleanups, mentry);
|
2012-08-28 17:54:45 -05:00
|
|
|
Callee {
|
|
|
|
bcx: bcx,
|
|
|
|
data: Method(MethodData {
|
|
|
|
llfn: callee_fn.llfn,
|
|
|
|
llself: val,
|
2013-06-29 10:45:59 -05:00
|
|
|
temp_cleanup: temp_cleanups.head_opt().map(|&v| *v),
|
2013-05-10 17:15:06 -05:00
|
|
|
self_ty: node_id_type(bcx, this.id),
|
2013-04-24 03:29:46 -05:00
|
|
|
self_mode: mentry.self_mode,
|
2012-08-28 17:54:45 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2013-01-16 21:24:10 -06:00
|
|
|
typeck::method_param(typeck::method_param {
|
|
|
|
trait_id: trait_id,
|
|
|
|
method_num: off,
|
|
|
|
param_num: p,
|
|
|
|
bound_num: b
|
|
|
|
}) => {
|
2012-08-28 17:54:45 -05:00
|
|
|
match bcx.fcx.param_substs {
|
2013-02-18 14:36:30 -06:00
|
|
|
Some(substs) => {
|
2013-07-22 19:42:45 -05:00
|
|
|
let vtbl = find_vtable(bcx.tcx(), substs,
|
|
|
|
p, b);
|
2013-05-10 17:15:06 -05:00
|
|
|
trans_monomorphized_callee(bcx, callee_id, this, mentry,
|
2012-08-28 17:54:45 -05:00
|
|
|
trait_id, off, vtbl)
|
|
|
|
}
|
|
|
|
// how to get rid of this?
|
2013-05-05 17:18:51 -05:00
|
|
|
None => fail!("trans_method_callee: missing param_substs")
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
}
|
2013-06-20 11:29:24 -05:00
|
|
|
|
2013-03-08 23:16:09 -06:00
|
|
|
typeck::method_trait(_, off, store) => {
|
2012-11-28 19:33:30 -06:00
|
|
|
trans_trait_callee(bcx,
|
|
|
|
callee_id,
|
|
|
|
off,
|
2013-05-10 17:15:06 -05:00
|
|
|
this,
|
2013-03-08 23:16:09 -06:00
|
|
|
store,
|
2012-11-28 19:33:30 -06:00
|
|
|
mentry.explicit_self)
|
2012-02-09 04:17:11 -06:00
|
|
|
}
|
2012-01-26 05:26:14 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_static_method_callee(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
method_id: ast::def_id,
|
|
|
|
trait_id: ast::def_id,
|
2013-07-27 03:25:59 -05:00
|
|
|
callee_id: ast::NodeId)
|
2013-01-30 13:46:19 -06:00
|
|
|
-> FnData {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_static_method_callee");
|
2012-08-02 18:01:38 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
|
2012-10-12 19:00:08 -05:00
|
|
|
debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \
|
|
|
|
callee_id=%?)",
|
|
|
|
method_id,
|
|
|
|
ty::item_path_str(bcx.tcx(), trait_id),
|
|
|
|
callee_id);
|
|
|
|
let _indenter = indenter();
|
|
|
|
|
|
|
|
// When we translate a static fn defined in a trait like:
|
|
|
|
//
|
|
|
|
// trait<T1...Tn> Trait {
|
2013-03-21 21:07:54 -05:00
|
|
|
// fn foo<M1...Mn>(...) {...}
|
2012-10-12 19:00:08 -05:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
// this winds up being translated as something like:
|
|
|
|
//
|
|
|
|
// fn foo<T1...Tn,self: Trait<T1...Tn>,M1...Mn>(...) {...}
|
|
|
|
//
|
|
|
|
// So when we see a call to this function foo, we have to figure
|
|
|
|
// out which impl the `Trait<T1...Tn>` bound on the type `self` was
|
2013-06-26 19:20:53 -05:00
|
|
|
// bound to.
|
|
|
|
let bound_index = ty::lookup_trait_def(bcx.tcx(), trait_id).
|
|
|
|
generics.type_param_defs.len();
|
2012-10-12 19:00:08 -05:00
|
|
|
|
2013-07-27 03:25:59 -05:00
|
|
|
let mname = if method_id.crate == ast::LOCAL_CRATE {
|
2013-05-05 11:17:59 -05:00
|
|
|
match bcx.tcx().items.get_copy(&method_id.node) {
|
2012-08-28 17:54:45 -05:00
|
|
|
ast_map::node_trait_method(trait_method, _, _) => {
|
2013-02-18 00:20:36 -06:00
|
|
|
ast_util::trait_method_to_ty_method(trait_method).ident
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2013-05-05 17:18:51 -05:00
|
|
|
_ => fail!("callee is not a trait method")
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let path = csearch::get_item_path(bcx.tcx(), method_id);
|
|
|
|
match path[path.len()-1] {
|
2012-08-28 17:54:45 -05:00
|
|
|
path_name(s) => { s }
|
2013-05-05 17:18:51 -05:00
|
|
|
path_mod(_) => { fail!("path doesn't have a name?") }
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
debug!("trans_static_method_callee: method_id=%?, callee_id=%?, \
|
2013-06-12 12:02:55 -05:00
|
|
|
name=%s", method_id, callee_id, ccx.sess.str_of(mname));
|
2012-08-02 18:01:38 -05:00
|
|
|
|
|
|
|
let vtbls = resolve_vtables_in_fn_ctxt(
|
2013-05-05 11:17:59 -05:00
|
|
|
bcx.fcx, ccx.maps.vtable_map.get_copy(&callee_id));
|
2012-08-02 18:01:38 -05:00
|
|
|
|
2013-06-26 19:20:53 -05:00
|
|
|
match vtbls[bound_index][0] {
|
2013-03-20 00:17:42 -05:00
|
|
|
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
2013-06-17 18:43:22 -05:00
|
|
|
assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-07-15 16:19:36 -05:00
|
|
|
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
|
2013-06-26 19:20:53 -05:00
|
|
|
let (callee_substs, callee_origins) =
|
|
|
|
combine_impl_and_methods_tps(
|
2013-07-15 16:19:36 -05:00
|
|
|
bcx, mth_id, callee_id,
|
2013-06-26 19:20:53 -05:00
|
|
|
*rcvr_substs, rcvr_origins);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
let FnData {llfn: lval} =
|
2012-09-10 17:12:37 -05:00
|
|
|
trans_fn_ref_with_vtables(bcx,
|
|
|
|
mth_id,
|
|
|
|
callee_id,
|
|
|
|
callee_substs,
|
|
|
|
Some(callee_origins));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
let callee_ty = node_id_type(bcx, callee_id);
|
2013-06-15 22:45:48 -05:00
|
|
|
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
2012-08-28 17:54:45 -05:00
|
|
|
FnData {llfn: PointerCast(bcx, lval, llty)}
|
|
|
|
}
|
|
|
|
_ => {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("vtable_param left in monomorphized \
|
2013-01-31 19:51:01 -06:00
|
|
|
function's vtable substs");
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-15 16:19:36 -05:00
|
|
|
pub fn method_with_name(ccx: &mut CrateContext,
|
|
|
|
impl_id: ast::def_id,
|
|
|
|
name: ast::ident) -> ast::def_id {
|
|
|
|
let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name));
|
|
|
|
match meth_id_opt {
|
2013-06-12 16:22:17 -05:00
|
|
|
Some(m) => return m,
|
|
|
|
None => {}
|
|
|
|
}
|
2013-06-14 00:38:17 -05:00
|
|
|
|
2013-07-15 16:19:36 -05:00
|
|
|
let imp = ccx.tcx.impls.find(&impl_id)
|
|
|
|
.expect("could not find impl while translating");
|
|
|
|
let meth = imp.methods.iter().find_(|m| m.ident == name)
|
|
|
|
.expect("could not find method while translating");
|
2012-03-08 05:15:02 -06:00
|
|
|
|
2013-07-15 17:24:16 -05:00
|
|
|
ccx.impl_method_cache.insert((impl_id, name), meth.def_id);
|
|
|
|
meth.def_id
|
2012-03-09 01:44:53 -06:00
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_monomorphized_callee(bcx: @mut Block,
|
2013-07-27 03:25:59 -05:00
|
|
|
callee_id: ast::NodeId,
|
2013-01-30 13:46:19 -06:00
|
|
|
base: @ast::expr,
|
|
|
|
mentry: typeck::method_map_entry,
|
|
|
|
trait_id: ast::def_id,
|
|
|
|
n_method: uint,
|
2013-04-17 11:15:37 -05:00
|
|
|
vtbl: typeck::vtable_origin)
|
2013-04-24 03:29:46 -05:00
|
|
|
-> Callee {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_monomorphized_callee");
|
2012-09-10 14:25:45 -05:00
|
|
|
return match vtbl {
|
2013-03-20 00:17:42 -05:00
|
|
|
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
2012-08-28 17:54:45 -05:00
|
|
|
let ccx = bcx.ccx();
|
2013-03-27 09:26:57 -05:00
|
|
|
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
|
2013-07-15 16:19:36 -05:00
|
|
|
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// obtain the `self` value:
|
2013-06-29 10:45:59 -05:00
|
|
|
let mut temp_cleanups = ~[];
|
2012-08-28 17:54:45 -05:00
|
|
|
let Result {bcx, val: llself_val} =
|
2013-06-29 10:45:59 -05:00
|
|
|
trans_self_arg(bcx, base, &mut temp_cleanups, mentry);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// create a concatenated set of substitutions which includes
|
|
|
|
// those from the impl and those from the method:
|
2013-06-26 19:20:53 -05:00
|
|
|
let (callee_substs, callee_origins) =
|
|
|
|
combine_impl_and_methods_tps(
|
2013-07-15 16:19:36 -05:00
|
|
|
bcx, mth_id, callee_id,
|
2013-06-26 19:20:53 -05:00
|
|
|
*rcvr_substs, rcvr_origins);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// translate the function
|
2013-04-24 03:29:46 -05:00
|
|
|
let callee = trans_fn_ref_with_vtables(bcx,
|
|
|
|
mth_id,
|
|
|
|
callee_id,
|
|
|
|
callee_substs,
|
|
|
|
Some(callee_origins));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// create a llvalue that represents the fn ptr
|
|
|
|
let fn_ty = node_id_type(bcx, callee_id);
|
2013-06-16 05:52:44 -05:00
|
|
|
let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).ptr_to();
|
2012-08-28 17:54:45 -05:00
|
|
|
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
|
|
|
|
|
|
|
|
// combine the self environment with the rest
|
|
|
|
Callee {
|
|
|
|
bcx: bcx,
|
|
|
|
data: Method(MethodData {
|
|
|
|
llfn: llfn_val,
|
|
|
|
llself: llself_val,
|
2013-06-29 10:45:59 -05:00
|
|
|
temp_cleanup: temp_cleanups.head_opt().map(|&v| *v),
|
2012-08-28 17:54:45 -05:00
|
|
|
self_ty: node_id_type(bcx, base.id),
|
2013-04-24 03:29:46 -05:00
|
|
|
self_mode: mentry.self_mode,
|
2012-08-28 17:54:45 -05:00
|
|
|
})
|
|
|
|
}
|
2012-02-09 04:17:11 -06:00
|
|
|
}
|
2012-08-26 11:58:45 -05:00
|
|
|
typeck::vtable_param(*) => {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("vtable_param left in monomorphized function's vtable substs");
|
2012-02-09 04:17:11 -06:00
|
|
|
}
|
2012-09-10 14:25:45 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn combine_impl_and_methods_tps(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
mth_did: ast::def_id,
|
2013-07-27 03:25:59 -05:00
|
|
|
callee_id: ast::NodeId,
|
2013-06-26 19:20:53 -05:00
|
|
|
rcvr_substs: &[ty::t],
|
|
|
|
rcvr_origins: typeck::vtable_res)
|
|
|
|
-> (~[ty::t], typeck::vtable_res) {
|
2012-09-10 14:25:45 -05:00
|
|
|
/*!
|
|
|
|
*
|
|
|
|
* Creates a concatenated set of substitutions which includes
|
|
|
|
* those from the impl and those from the method. This are
|
|
|
|
* some subtle complications here. Statically, we have a list
|
|
|
|
* of type parameters like `[T0, T1, T2, M1, M2, M3]` where
|
|
|
|
* `Tn` are type parameters that appear on the receiver. For
|
|
|
|
* example, if the receiver is a method parameter `A` with a
|
|
|
|
* bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
|
|
|
|
*
|
|
|
|
* The weird part is that the type `A` might now be bound to
|
|
|
|
* any other type, such as `foo<X>`. In that case, the vector
|
|
|
|
* we want is: `[X, M1, M2, M3]`. Therefore, what we do now is
|
|
|
|
* to slice off the method type parameters and append them to
|
|
|
|
* the type parameters from the type that the receiver is
|
|
|
|
* mapped to. */
|
|
|
|
|
|
|
|
let ccx = bcx.ccx();
|
2013-07-15 16:19:36 -05:00
|
|
|
let method = ty::method(ccx.tcx, mth_did);
|
|
|
|
let n_m_tps = method.generics.type_param_defs.len();
|
2012-09-10 14:25:45 -05:00
|
|
|
let node_substs = node_id_type_params(bcx, callee_id);
|
2013-07-15 16:19:36 -05:00
|
|
|
debug!("rcvr_substs=%?", rcvr_substs.repr(ccx.tcx));
|
2012-09-10 14:25:45 -05:00
|
|
|
let ty_substs
|
2013-06-17 18:43:22 -05:00
|
|
|
= vec::append(rcvr_substs.to_owned(),
|
2013-06-27 07:36:27 -05:00
|
|
|
node_substs.tailn(node_substs.len() - n_m_tps));
|
2012-09-10 14:25:45 -05:00
|
|
|
debug!("n_m_tps=%?", n_m_tps);
|
2013-07-15 16:19:36 -05:00
|
|
|
debug!("node_substs=%?", node_substs.repr(ccx.tcx));
|
|
|
|
debug!("ty_substs=%?", ty_substs.repr(ccx.tcx));
|
2012-09-10 14:25:45 -05:00
|
|
|
|
|
|
|
|
2013-06-26 19:20:53 -05:00
|
|
|
// Now, do the same work for the vtables. The vtables might not
|
|
|
|
// exist, in which case we need to make them.
|
2012-09-10 14:25:45 -05:00
|
|
|
let r_m_origins = match node_vtables(bcx, callee_id) {
|
|
|
|
Some(vt) => vt,
|
2013-06-26 19:20:53 -05:00
|
|
|
None => @vec::from_elem(node_substs.len(), @~[])
|
2012-09-10 14:25:45 -05:00
|
|
|
};
|
2013-06-26 19:20:53 -05:00
|
|
|
let vtables
|
|
|
|
= @vec::append(rcvr_origins.to_owned(),
|
|
|
|
r_m_origins.tailn(r_m_origins.len() - n_m_tps));
|
2012-09-10 14:25:45 -05:00
|
|
|
|
2013-06-26 19:20:53 -05:00
|
|
|
return (ty_substs, vtables);
|
2012-02-09 04:17:11 -06:00
|
|
|
}
|
|
|
|
|
2012-09-10 14:25:45 -05:00
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_trait_callee(bcx: @mut Block,
|
2013-07-27 03:25:59 -05:00
|
|
|
callee_id: ast::NodeId,
|
2013-01-30 13:46:19 -06:00
|
|
|
n_method: uint,
|
|
|
|
self_expr: @ast::expr,
|
2013-03-08 23:16:09 -06:00
|
|
|
store: ty::TraitStore,
|
2013-04-30 10:49:48 -05:00
|
|
|
explicit_self: ast::explicit_self_)
|
2013-07-02 14:47:32 -05:00
|
|
|
-> Callee {
|
2012-08-28 17:54:45 -05:00
|
|
|
//!
|
|
|
|
//
|
|
|
|
// Create a method callee where the method is coming from a trait
|
|
|
|
// instance (e.g., @Trait type). In this case, we must pull the
|
|
|
|
// fn pointer out of the vtable that is packaged up with the
|
2012-10-05 18:55:42 -05:00
|
|
|
// @/~/&Trait instance. @/~/&Traits are represented as a pair, so we
|
|
|
|
// first evaluate the self expression (expected a by-ref result) and then
|
2012-08-28 17:54:45 -05:00
|
|
|
// extract the self data and vtable out of the pair.
|
|
|
|
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_trait_callee");
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut bcx = bcx;
|
2012-12-13 15:09:38 -06:00
|
|
|
let self_datum = unpack_datum!(bcx,
|
|
|
|
expr::trans_to_datum(bcx, self_expr));
|
2012-08-28 17:54:45 -05:00
|
|
|
let llpair = self_datum.to_ref_llval(bcx);
|
2012-12-13 15:09:38 -06:00
|
|
|
|
|
|
|
let llpair = match explicit_self {
|
2013-03-09 18:43:53 -06:00
|
|
|
ast::sty_region(*) => Load(bcx, llpair),
|
2013-03-26 05:05:40 -05:00
|
|
|
ast::sty_static | ast::sty_value |
|
2013-06-23 23:12:17 -05:00
|
|
|
ast::sty_box(_) | ast::sty_uniq => llpair
|
2012-12-13 15:09:38 -06:00
|
|
|
};
|
|
|
|
|
2012-08-28 17:54:45 -05:00
|
|
|
let callee_ty = node_id_type(bcx, callee_id);
|
2012-11-28 19:33:30 -06:00
|
|
|
trans_trait_callee_from_llval(bcx,
|
|
|
|
callee_ty,
|
|
|
|
n_method,
|
|
|
|
llpair,
|
2013-03-08 23:16:09 -06:00
|
|
|
store,
|
2012-11-28 19:33:30 -06:00
|
|
|
explicit_self)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_trait_callee_from_llval(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
callee_ty: ty::t,
|
|
|
|
n_method: uint,
|
|
|
|
llpair: ValueRef,
|
2013-03-08 23:16:09 -06:00
|
|
|
store: ty::TraitStore,
|
2013-04-30 10:49:48 -05:00
|
|
|
explicit_self: ast::explicit_self_)
|
2013-01-30 13:46:19 -06:00
|
|
|
-> Callee {
|
2012-08-28 17:54:45 -05:00
|
|
|
//!
|
|
|
|
//
|
|
|
|
// Same as `trans_trait_callee()` above, except that it is given
|
|
|
|
// a by-ref pointer to the @Trait pair.
|
|
|
|
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_trait_callee");
|
2012-05-14 17:48:58 -05:00
|
|
|
let ccx = bcx.ccx();
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// Load the vtable from the @Trait pair
|
2012-11-28 19:33:30 -06:00
|
|
|
debug!("(translating trait callee) loading vtable from pair %s",
|
2013-06-14 22:16:03 -05:00
|
|
|
bcx.val_to_str(llpair));
|
2012-08-28 17:54:45 -05:00
|
|
|
let llvtable = Load(bcx,
|
|
|
|
PointerCast(bcx,
|
2013-05-01 03:59:36 -05:00
|
|
|
GEPi(bcx, llpair,
|
|
|
|
[0u, abi::trt_field_vtable]),
|
2013-06-15 22:45:48 -05:00
|
|
|
Type::vtable().ptr_to().ptr_to()));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2012-10-05 18:55:42 -05:00
|
|
|
// Load the box from the @Trait pair and GEP over the box header if
|
|
|
|
// necessary:
|
2012-11-28 19:33:30 -06:00
|
|
|
let mut llself;
|
|
|
|
debug!("(translating trait callee) loading second index from pair");
|
2013-06-27 18:40:27 -05:00
|
|
|
let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]);
|
|
|
|
let llbox = Load(bcx, llboxptr);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2012-11-28 19:33:30 -06:00
|
|
|
// Munge `llself` appropriately for the type of `self` in the method.
|
|
|
|
match explicit_self {
|
|
|
|
ast::sty_static => {
|
2013-05-19 00:07:44 -05:00
|
|
|
bcx.tcx().sess.bug("shouldn't see static method here");
|
2012-11-28 19:33:30 -06:00
|
|
|
}
|
|
|
|
ast::sty_value => {
|
2013-05-19 00:07:44 -05:00
|
|
|
bcx.tcx().sess.bug("methods with by-value self should not be \
|
|
|
|
called on objects");
|
2012-11-28 19:33:30 -06:00
|
|
|
}
|
2013-03-09 18:43:53 -06:00
|
|
|
ast::sty_region(*) => {
|
2013-03-08 23:16:09 -06:00
|
|
|
match store {
|
2013-07-02 18:51:39 -05:00
|
|
|
ty::UniqTraitStore
|
|
|
|
if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
|
|
|
|
llself = llbox;
|
|
|
|
}
|
2013-03-08 23:16:09 -06:00
|
|
|
ty::BoxTraitStore |
|
|
|
|
ty::UniqTraitStore => {
|
2012-11-29 12:59:49 -06:00
|
|
|
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
|
|
|
}
|
2013-03-08 23:16:09 -06:00
|
|
|
ty::RegionTraitStore(_) => {
|
2012-11-29 12:59:49 -06:00
|
|
|
llself = llbox;
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 19:33:30 -06:00
|
|
|
}
|
|
|
|
ast::sty_box(_) => {
|
|
|
|
// Bump the reference count on the box.
|
|
|
|
debug!("(translating trait callee) callee type is `%s`",
|
|
|
|
bcx.ty_to_str(callee_ty));
|
2013-06-27 18:40:27 -05:00
|
|
|
glue::incr_refcnt_of_boxed(bcx, llbox);
|
2012-11-29 12:59:49 -06:00
|
|
|
|
|
|
|
// Pass a pointer to the box.
|
2013-03-08 23:16:09 -06:00
|
|
|
match store {
|
2013-03-27 05:16:28 -05:00
|
|
|
ty::BoxTraitStore => llself = llbox,
|
2013-05-19 00:07:44 -05:00
|
|
|
_ => bcx.tcx().sess.bug("@self receiver with non-@Trait")
|
2012-11-29 12:59:49 -06:00
|
|
|
}
|
|
|
|
}
|
2013-06-23 23:12:17 -05:00
|
|
|
ast::sty_uniq => {
|
2012-11-29 12:59:49 -06:00
|
|
|
// Pass the unique pointer.
|
2013-03-08 23:16:09 -06:00
|
|
|
match store {
|
|
|
|
ty::UniqTraitStore => llself = llbox,
|
2013-05-19 00:07:44 -05:00
|
|
|
_ => bcx.tcx().sess.bug("~self receiver with non-~Trait")
|
2012-11-29 12:59:49 -06:00
|
|
|
}
|
|
|
|
|
2013-06-27 18:40:27 -05:00
|
|
|
zero_mem(bcx, llboxptr, ty::mk_opaque_box(bcx.tcx()));
|
2012-11-28 19:33:30 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-27 18:40:27 -05:00
|
|
|
llself = PointerCast(bcx, llself, Type::opaque_box(ccx).ptr_to());
|
2013-06-24 12:30:35 -05:00
|
|
|
let scratch = scratch_datum(bcx, ty::mk_opaque_box(bcx.tcx()),
|
|
|
|
"__trait_callee", false);
|
2013-06-27 18:40:27 -05:00
|
|
|
Store(bcx, llself, scratch.val);
|
|
|
|
scratch.add_clean(bcx);
|
2013-06-29 09:43:39 -05:00
|
|
|
|
2012-08-28 17:54:45 -05:00
|
|
|
// Load the function from the vtable and cast it to the expected type.
|
2012-11-28 19:33:30 -06:00
|
|
|
debug!("(translating trait callee) loading method");
|
2013-02-25 13:11:21 -06:00
|
|
|
let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
|
2013-05-15 19:38:52 -05:00
|
|
|
|
|
|
|
// Plus one in order to skip past the type descriptor.
|
|
|
|
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
|
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
return Callee {
|
|
|
|
bcx: bcx,
|
|
|
|
data: Method(MethodData {
|
|
|
|
llfn: mptr,
|
2013-06-27 18:40:27 -05:00
|
|
|
llself: scratch.to_value_llval(bcx),
|
|
|
|
temp_cleanup: Some(scratch.val),
|
|
|
|
self_ty: scratch.ty,
|
|
|
|
self_mode: ty::ByCopy,
|
2012-08-28 17:54:45 -05:00
|
|
|
/* XXX: Some(llbox) */
|
|
|
|
})
|
|
|
|
};
|
2012-01-07 15:44:14 -06:00
|
|
|
}
|
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn vtable_id(ccx: @mut CrateContext,
|
2013-05-17 19:27:44 -05:00
|
|
|
origin: &typeck::vtable_origin)
|
2013-01-30 13:46:19 -06:00
|
|
|
-> mono_id {
|
2012-08-23 19:39:07 -05:00
|
|
|
match origin {
|
2013-05-17 19:27:44 -05:00
|
|
|
&typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
|
2013-07-01 20:38:41 -05:00
|
|
|
let psubsts = param_substs {
|
2013-07-02 14:47:32 -05:00
|
|
|
tys: (*substs).clone(),
|
2013-07-01 20:38:41 -05:00
|
|
|
vtables: Some(sub_vtables),
|
|
|
|
self_ty: None,
|
2013-07-22 18:40:31 -05:00
|
|
|
self_vtables: None
|
2013-07-01 20:38:41 -05:00
|
|
|
};
|
|
|
|
|
2012-08-28 17:54:45 -05:00
|
|
|
monomorphize::make_mono_id(
|
2012-10-08 14:39:30 -05:00
|
|
|
ccx,
|
|
|
|
impl_id,
|
2013-07-01 20:38:41 -05:00
|
|
|
&psubsts,
|
2012-10-08 14:39:30 -05:00
|
|
|
None)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2013-03-05 16:49:50 -06:00
|
|
|
|
2012-08-28 17:54:45 -05:00
|
|
|
// can't this be checked at the callee?
|
2013-05-05 17:18:51 -05:00
|
|
|
_ => fail!("vtable_id")
|
2012-03-08 09:10:25 -06:00
|
|
|
}
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|
|
|
|
|
2013-05-15 19:38:52 -05:00
|
|
|
/// Creates a returns a dynamic vtable for the given type and vtable origin.
|
|
|
|
/// This is used only for objects.
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn get_vtable(bcx: @mut Block,
|
2013-05-15 19:38:52 -05:00
|
|
|
self_ty: ty::t,
|
2013-04-17 11:15:37 -05:00
|
|
|
origin: typeck::vtable_origin)
|
2013-05-15 19:38:52 -05:00
|
|
|
-> ValueRef {
|
2013-06-07 12:29:21 -05:00
|
|
|
let hash_id = vtable_id(bcx.ccx(), &origin);
|
|
|
|
match bcx.ccx().vtables.find(&hash_id) {
|
2013-05-15 19:38:52 -05:00
|
|
|
Some(&val) => val,
|
|
|
|
None => {
|
|
|
|
match origin {
|
|
|
|
typeck::vtable_static(id, substs, sub_vtables) => {
|
2013-06-07 12:29:21 -05:00
|
|
|
make_impl_vtable(bcx, id, self_ty, substs, sub_vtables)
|
2013-05-15 19:38:52 -05:00
|
|
|
}
|
|
|
|
_ => fail!("get_vtable: expected a static origin"),
|
|
|
|
}
|
2012-01-02 09:50:51 -06:00
|
|
|
}
|
|
|
|
}
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|
2012-01-02 06:26:51 -06:00
|
|
|
|
2013-05-15 19:38:52 -05:00
|
|
|
/// Helper function to declare and initialize the vtable.
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn make_vtable(ccx: &mut CrateContext,
|
|
|
|
tydesc: &tydesc_info,
|
2013-05-15 19:38:52 -05:00
|
|
|
ptrs: &[ValueRef])
|
|
|
|
-> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::make_vtable");
|
2013-05-15 19:38:52 -05:00
|
|
|
|
|
|
|
let mut components = ~[ tydesc.tydesc ];
|
2013-08-03 11:45:23 -05:00
|
|
|
for &ptr in ptrs.iter() {
|
2013-05-15 19:38:52 -05:00
|
|
|
components.push(ptr)
|
|
|
|
}
|
|
|
|
|
|
|
|
let tbl = C_struct(components);
|
2013-06-29 00:07:24 -05:00
|
|
|
let vtable = ccx.sess.str_of(gensym_name("vtable"));
|
|
|
|
let vt_gvar = do vtable.as_c_str |buf| {
|
2013-06-16 05:52:44 -05:00
|
|
|
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
|
2013-02-10 18:33:16 -06:00
|
|
|
};
|
2013-01-10 23:23:07 -06:00
|
|
|
llvm::LLVMSetInitializer(vt_gvar, tbl);
|
|
|
|
llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
|
|
|
|
lib::llvm::SetLinkage(vt_gvar, lib::llvm::InternalLinkage);
|
|
|
|
vt_gvar
|
|
|
|
}
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|
2012-01-02 06:26:51 -06:00
|
|
|
|
2013-05-15 19:38:52 -05:00
|
|
|
/// Generates a dynamic vtable for objects.
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn make_impl_vtable(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
impl_id: ast::def_id,
|
2013-05-15 19:38:52 -05:00
|
|
|
self_ty: ty::t,
|
2013-06-27 08:04:22 -05:00
|
|
|
substs: &[ty::t],
|
2013-01-30 13:46:19 -06:00
|
|
|
vtables: typeck::vtable_res)
|
2013-05-15 19:38:52 -05:00
|
|
|
-> ValueRef {
|
2013-06-07 12:29:21 -05:00
|
|
|
let ccx = bcx.ccx();
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::make_impl_vtable");
|
2012-03-08 09:10:25 -06:00
|
|
|
let tcx = ccx.tcx;
|
2012-07-18 18:49:55 -05:00
|
|
|
|
2013-05-16 17:54:51 -05:00
|
|
|
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
|
|
|
|
Some(t_id) => t_id.def_id,
|
|
|
|
None => ccx.sess.bug("make_impl_vtable: don't know how to \
|
|
|
|
make a vtable for a type impl!")
|
|
|
|
};
|
2013-03-27 05:16:28 -05:00
|
|
|
|
2013-05-15 19:38:52 -05:00
|
|
|
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
|
|
|
let methods = do trait_method_def_ids.map |method_def_id| {
|
2013-03-27 09:26:57 -05:00
|
|
|
let im = ty::method(tcx, *method_def_id);
|
2013-05-15 19:38:52 -05:00
|
|
|
let fty = ty::subst_tps(tcx,
|
|
|
|
substs,
|
|
|
|
None,
|
2013-07-02 14:47:32 -05:00
|
|
|
ty::mk_bare_fn(tcx, im.fty.clone()));
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
if im.generics.has_type_params() || ty::type_has_self(fty) {
|
2012-11-28 19:33:30 -06:00
|
|
|
debug!("(making impl vtable) method has self or type params: %s",
|
2013-06-12 12:02:55 -05:00
|
|
|
tcx.sess.str_of(im.ident));
|
2013-06-15 22:45:48 -05:00
|
|
|
C_null(Type::nil().ptr_to())
|
2012-03-08 09:10:25 -06:00
|
|
|
} else {
|
2012-11-28 19:33:30 -06:00
|
|
|
debug!("(making impl vtable) adding method to vtable: %s",
|
2013-06-12 12:02:55 -05:00
|
|
|
tcx.sess.str_of(im.ident));
|
2013-07-15 16:19:36 -05:00
|
|
|
let m_id = method_with_name(ccx, impl_id, im.ident);
|
2013-06-07 12:29:21 -05:00
|
|
|
|
|
|
|
trans_fn_ref_with_vtables(bcx, m_id, 0,
|
|
|
|
substs, Some(vtables)).llfn
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|
2013-05-15 19:38:52 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// 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)
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|
|
|
|
|
2013-07-17 05:12:08 -05:00
|
|
|
pub fn trans_trait_cast(bcx: @mut Block,
|
2013-01-30 13:46:19 -06:00
|
|
|
val: @ast::expr,
|
2013-07-27 03:25:59 -05:00
|
|
|
id: ast::NodeId,
|
2013-01-30 13:46:19 -06:00
|
|
|
dest: expr::Dest,
|
2013-05-23 11:39:10 -05:00
|
|
|
_store: ty::TraitStore)
|
2013-07-17 05:12:08 -05:00
|
|
|
-> @mut Block {
|
2012-10-03 17:18:50 -05:00
|
|
|
let mut bcx = bcx;
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("impl::trans_cast");
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
let lldest = match dest {
|
|
|
|
Ignore => {
|
|
|
|
return expr::trans_into(bcx, val, Ignore);
|
|
|
|
}
|
|
|
|
SaveIn(dest) => dest
|
|
|
|
};
|
|
|
|
|
2012-02-21 07:20:18 -06:00
|
|
|
let ccx = bcx.ccx();
|
2012-02-10 04:32:03 -06:00
|
|
|
let v_ty = expr_ty(bcx, val);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-05-15 19:38:52 -05:00
|
|
|
let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
|
|
|
|
// Just store the pointer into the pair. (Region/borrowed
|
|
|
|
// and boxed trait objects are represented as pairs, and
|
|
|
|
// have no type descriptor field.)
|
|
|
|
llboxdest = PointerCast(bcx,
|
|
|
|
llboxdest,
|
2013-06-15 22:45:48 -05:00
|
|
|
type_of(bcx.ccx(), v_ty).ptr_to());
|
2013-05-15 19:38:52 -05:00
|
|
|
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2012-10-31 17:09:26 -05:00
|
|
|
// Store the vtable into the pair or triple.
|
2013-07-02 14:47:32 -05:00
|
|
|
let orig = ccx.maps.vtable_map.get(&id)[0][0].clone();
|
|
|
|
let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, &orig);
|
2013-06-07 12:29:21 -05:00
|
|
|
let vtable = get_vtable(bcx, v_ty, orig);
|
2012-08-28 17:54:45 -05:00
|
|
|
Store(bcx, vtable, PointerCast(bcx,
|
2013-05-01 03:59:36 -05:00
|
|
|
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
|
2013-06-15 22:45:48 -05:00
|
|
|
val_ty(vtable).ptr_to()));
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2012-02-10 04:32:03 -06:00
|
|
|
bcx
|
2012-01-07 15:44:14 -06:00
|
|
|
}
|