Skip to content

Commit ce3cc46

Browse files
committed
Fix generation of generic methods with explicit self
There used to be two distinct code paths. Now there is one.
1 parent b5411f7 commit ce3cc46

File tree

4 files changed

+105
-34
lines changed

4 files changed

+105
-34
lines changed

src/rustc/middle/trans/base.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,10 +2246,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
22462246
ast_map::node_method(mth, impl_def_id, _) => {
22472247
let d = mk_lldecl();
22482248
set_inline_hint_if_appr(mth.attrs, d);
2249-
let selfty = ty::node_id_to_type(ccx.tcx, mth.self_id);
2250-
let selfty = ty::subst_tps(ccx.tcx, substs, selfty);
2251-
trans_fn(ccx, pt, mth.decl, mth.body, d,
2252-
impl_self(selfty), psubsts, fn_id.node);
2249+
impl::trans_method(ccx, pt, mth, psubsts, d);
22532250
d
22542251
}
22552252
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 {
53215318
}
53225319
ast::provided(m) => {
53235320
exprt = true;
5324-
trans_method(ccx, id, pth, m)
5321+
register_method(ccx, id, pth, m)
53255322
}
53265323
}
53275324
}
53285325
ast_map::node_method(m, _, pth) => {
53295326
exprt = true;
5330-
trans_method(ccx, id, pth, m)
5327+
register_method(ccx, id, pth, m)
53315328
}
53325329
ast_map::node_foreign_item(ni, _, pth) => {
53335330
exprt = true;
@@ -5397,7 +5394,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
53975394
}
53985395
}
53995396

5400-
fn trans_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
5397+
fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
54015398
m: @ast::method) -> ValueRef {
54025399
let mty = ty::node_id_to_type(ccx.tcx, id);
54035400
let pth = vec::append(*pth, ~[path_name(@ccx.names(~"meth")),

src/rustc/middle/trans/impl.rs

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,41 +18,82 @@ import util::ppaux::{ty_to_str, tys_to_str};
1818

1919
import syntax::print::pprust::expr_to_str;
2020

21+
/**
22+
The main "translation" pass for methods. Generates code
23+
for non-monomorphized methods only. Other methods will
24+
be generated once they are invoked with specific type parameters,
25+
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
26+
*/
2127
fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
2228
methods: ~[@ast::method], tps: ~[ast::ty_param]) {
2329
let _icx = ccx.insn_ctxt("impl::trans_impl");
2430
if tps.len() > 0u { return; }
2531
let sub_path = vec::append_one(path, path_name(name));
26-
for vec::each(methods) |m| {
27-
if m.tps.len() == 0u {
28-
let llfn = get_item_val(ccx, m.id);
29-
let self_ty = ty::node_id_to_type(ccx.tcx, m.self_id);
30-
let self_arg = match m.self_ty.node {
31-
ast::sty_static => { no_self }
32-
ast::sty_box(_) => {
33-
impl_self(ty::mk_imm_box(ccx.tcx, self_ty))
34-
}
35-
ast::sty_uniq(_) => {
36-
impl_self(ty::mk_imm_uniq(ccx.tcx, self_ty))
37-
}
38-
ast::sty_region(*) => {
39-
impl_self(ty::mk_imm_ptr(ccx.tcx, self_ty))
40-
}
41-
ast::sty_value => {
42-
impl_owned_self(self_ty)
43-
}
44-
ast::sty_by_ref => { impl_self(self_ty) }
45-
};
46-
47-
trans_fn(ccx,
48-
vec::append_one(sub_path, path_name(m.ident)),
49-
m.decl, m.body,
50-
llfn, self_arg,
51-
none, m.id);
32+
for vec::each(methods) |method| {
33+
if method.tps.len() == 0u {
34+
let llfn = get_item_val(ccx, method.id);
35+
let path = vec::append_one(sub_path, path_name(method.ident));
36+
trans_method(ccx, path, method, none, llfn);
5237
}
5338
}
5439
}
5540

41+
/**
42+
Translates a (possibly monomorphized) method body.
43+
44+
# Parameters
45+
46+
- `path`: the path to the method
47+
- `method`: the AST node for the method
48+
- `param_substs`: if this is a generic method, the current values for
49+
type parameters and so forth, else none
50+
- `llfn`: the LLVM ValueRef for the method
51+
*/
52+
fn trans_method(ccx: @crate_ctxt,
53+
path: path,
54+
method: &ast::method,
55+
param_substs: option<param_substs>,
56+
llfn: ValueRef) {
57+
// determine the (monomorphized) type that `self` maps to for this method
58+
let self_ty = ty::node_id_to_type(ccx.tcx, method.self_id);
59+
let self_ty = match param_substs {
60+
none => self_ty,
61+
some({tys: ref tys, _}) => ty::subst_tps(ccx.tcx, *tys, self_ty)
62+
};
63+
64+
// apply any transformations from the explicit self declaration
65+
let self_arg = match method.self_ty.node {
66+
ast::sty_static => {
67+
no_self
68+
}
69+
ast::sty_box(_) => {
70+
impl_self(ty::mk_imm_box(ccx.tcx, self_ty))
71+
}
72+
ast::sty_uniq(_) => {
73+
impl_self(ty::mk_imm_uniq(ccx.tcx, self_ty))
74+
}
75+
ast::sty_region(*) => {
76+
impl_self(ty::mk_imm_ptr(ccx.tcx, self_ty))
77+
}
78+
ast::sty_value => {
79+
impl_owned_self(self_ty)
80+
}
81+
ast::sty_by_ref => {
82+
impl_self(self_ty)
83+
}
84+
};
85+
86+
// generate the actual code
87+
trans_fn(ccx,
88+
path,
89+
method.decl,
90+
method.body,
91+
llfn,
92+
self_arg,
93+
param_substs,
94+
method.id);
95+
}
96+
5697
fn trans_self_arg(bcx: block, base: @ast::expr,
5798
mentry: typeck::method_map_entry) -> result {
5899
let _icx = bcx.insn_ctxt("impl::trans_self_arg");

src/rustc/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t {
11061106
}
11071107

11081108
// Substitute *only* type parameters. Used in trans where regions are erased.
1109-
fn subst_tps(cx: ctxt, tps: ~[t], typ: t) -> t {
1109+
fn subst_tps(cx: ctxt, tps: &[t], typ: t) -> t {
11101110
if tps.len() == 0u { return typ; }
11111111
let tb = ty::get(typ);
11121112
if !tbox_has_flag(tb, has_params) { return typ; }
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use std;
2+
3+
/**
4+
* A function that returns a hash of a value
5+
*
6+
* The hash should concentrate entropy in the lower bits.
7+
*/
8+
type HashFn<K> = pure fn~(K) -> uint;
9+
type EqFn<K> = pure fn~(K, K) -> bool;
10+
11+
enum LinearMap<K,V> {
12+
LinearMap_({
13+
resize_at: uint,
14+
size: uint})
15+
}
16+
17+
fn linear_map<K,V>() -> LinearMap<K,V> {
18+
LinearMap_({
19+
resize_at: 32,
20+
size: 0})
21+
}
22+
23+
impl<K,V> LinearMap<K,V> {
24+
fn len(&mut self) -> uint {
25+
self.size
26+
}
27+
}
28+
29+
fn main() {
30+
let mut m = ~linear_map::<(),()>();
31+
assert m.len() == 0;
32+
}
33+

0 commit comments

Comments
 (0)