提交 ce3cc46c 编写于 作者: N Niko Matsakis

Fix generation of generic methods with explicit self

There used to be two distinct code paths.  Now there is one.
上级 b5411f76
......@@ -2246,10 +2246,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
ast_map::node_method(mth, impl_def_id, _) => {
let d = mk_lldecl();
set_inline_hint_if_appr(mth.attrs, d);
let selfty = ty::node_id_to_type(ccx.tcx, mth.self_id);
let selfty = ty::subst_tps(ccx.tcx, substs, selfty);
trans_fn(ccx, pt, mth.decl, mth.body, d,
impl_self(selfty), psubsts, fn_id.node);
impl::trans_method(ccx, pt, mth, psubsts, d);
d
}
ast_map::node_ctor(nm, tps, ctor, parent_id, _) => {
......@@ -5321,13 +5318,13 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
}
ast::provided(m) => {
exprt = true;
trans_method(ccx, id, pth, m)
register_method(ccx, id, pth, m)
}
}
}
ast_map::node_method(m, _, pth) => {
exprt = true;
trans_method(ccx, id, pth, m)
register_method(ccx, id, pth, m)
}
ast_map::node_foreign_item(ni, _, pth) => {
exprt = true;
......@@ -5397,7 +5394,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
}
}
fn trans_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
m: @ast::method) -> ValueRef {
let mty = ty::node_id_to_type(ccx.tcx, id);
let pth = vec::append(*pth, ~[path_name(@ccx.names(~"meth")),
......
......@@ -18,41 +18,82 @@
import syntax::print::pprust::expr_to_str;
/**
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()`.
*/
fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
methods: ~[@ast::method], tps: ~[ast::ty_param]) {
let _icx = ccx.insn_ctxt("impl::trans_impl");
if tps.len() > 0u { return; }
let sub_path = vec::append_one(path, path_name(name));
for vec::each(methods) |m| {
if m.tps.len() == 0u {
let llfn = get_item_val(ccx, m.id);
let self_ty = ty::node_id_to_type(ccx.tcx, m.self_id);
let self_arg = match m.self_ty.node {
ast::sty_static => { no_self }
ast::sty_box(_) => {
impl_self(ty::mk_imm_box(ccx.tcx, self_ty))
}
ast::sty_uniq(_) => {
impl_self(ty::mk_imm_uniq(ccx.tcx, self_ty))
}
ast::sty_region(*) => {
impl_self(ty::mk_imm_ptr(ccx.tcx, self_ty))
}
ast::sty_value => {
impl_owned_self(self_ty)
}
ast::sty_by_ref => { impl_self(self_ty) }
};
trans_fn(ccx,
vec::append_one(sub_path, path_name(m.ident)),
m.decl, m.body,
llfn, self_arg,
none, m.id);
for vec::each(methods) |method| {
if method.tps.len() == 0u {
let llfn = get_item_val(ccx, method.id);
let path = vec::append_one(sub_path, path_name(method.ident));
trans_method(ccx, path, method, none, llfn);
}
}
}
/**
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
*/
fn trans_method(ccx: @crate_ctxt,
path: path,
method: &ast::method,
param_substs: option<param_substs>,
llfn: ValueRef) {
// determine the (monomorphized) type that `self` maps to for this method
let self_ty = ty::node_id_to_type(ccx.tcx, method.self_id);
let self_ty = match param_substs {
none => self_ty,
some({tys: ref tys, _}) => ty::subst_tps(ccx.tcx, *tys, self_ty)
};
// apply any transformations from the explicit self declaration
let self_arg = match method.self_ty.node {
ast::sty_static => {
no_self
}
ast::sty_box(_) => {
impl_self(ty::mk_imm_box(ccx.tcx, self_ty))
}
ast::sty_uniq(_) => {
impl_self(ty::mk_imm_uniq(ccx.tcx, self_ty))
}
ast::sty_region(*) => {
impl_self(ty::mk_imm_ptr(ccx.tcx, self_ty))
}
ast::sty_value => {
impl_owned_self(self_ty)
}
ast::sty_by_ref => {
impl_self(self_ty)
}
};
// generate the actual code
trans_fn(ccx,
path,
method.decl,
method.body,
llfn,
self_arg,
param_substs,
method.id);
}
fn trans_self_arg(bcx: block, base: @ast::expr,
mentry: typeck::method_map_entry) -> result {
let _icx = bcx.insn_ctxt("impl::trans_self_arg");
......
......@@ -1106,7 +1106,7 @@ fn do_fold(cx: ctxt, t0: t, under_r: bool,
}
// Substitute *only* type parameters. Used in trans where regions are erased.
fn subst_tps(cx: ctxt, tps: ~[t], typ: t) -> t {
fn subst_tps(cx: ctxt, tps: &[t], typ: t) -> t {
if tps.len() == 0u { return typ; }
let tb = ty::get(typ);
if !tbox_has_flag(tb, has_params) { return typ; }
......
use std;
/**
* A function that returns a hash of a value
*
* The hash should concentrate entropy in the lower bits.
*/
type HashFn<K> = pure fn~(K) -> uint;
type EqFn<K> = pure fn~(K, K) -> bool;
enum LinearMap<K,V> {
LinearMap_({
resize_at: uint,
size: uint})
}
fn linear_map<K,V>() -> LinearMap<K,V> {
LinearMap_({
resize_at: 32,
size: 0})
}
impl<K,V> LinearMap<K,V> {
fn len(&mut self) -> uint {
self.size
}
}
fn main() {
let mut m = ~linear_map::<(),()>();
assert m.len() == 0;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册