Skip to content

Commit 29e10c9

Browse files
committed
librustc: Pass through extra parameters in automatically-derived methods. r=brson
1 parent b7c04d1 commit 29e10c9

File tree

2 files changed

+77
-13
lines changed

2 files changed

+77
-13
lines changed

src/librustc/middle/trans/deriving.rs

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Translation of automatically-derived trait implementations. This handles
22
// enums and structs only; other types cannot be automatically derived.
33

4-
use lib::llvm::llvm;
4+
use lib::llvm::llvm::{LLVMCountParams, LLVMGetParam};
55
use middle::trans::base::{GEP_enum, finish_fn, get_insn_ctxt, get_item_val};
66
use middle::trans::base::{new_fn_ctxt, sub_block, top_scope_block};
77
use middle::trans::build::{AddCase, Br, CondBr, GEPi, Load, PointerCast};
@@ -11,6 +11,7 @@ use middle::trans::callee::{ArgVals, Callee, DontAutorefArg, Method};
1111
use middle::trans::callee::{MethodData};
1212
use middle::trans::common;
1313
use middle::trans::common::{C_bool, C_int, T_ptr, block, crate_ctxt};
14+
use middle::trans::common::{fn_ctxt};
1415
use middle::trans::expr::SaveIn;
1516
use middle::trans::type_of::type_of;
1617
use middle::ty::DerivedFieldInfo;
@@ -21,6 +22,10 @@ use syntax::ast_map::path;
2122
use syntax::ast_util;
2223
use syntax::ast_util::local_def;
2324

25+
use core::dvec::DVec;
26+
use core::dvec;
27+
use core::libc::c_uint;
28+
2429
/// The kind of deriving method this is.
2530
enum DerivingKind {
2631
BoolKind, // fn f(&self, other: &other) -> bool
@@ -93,6 +98,23 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt,
9398
}
9499
}
95100

101+
fn get_extra_params(llfn: ValueRef, kind: DerivingKind) -> ~[ValueRef] {
102+
let n_params = LLVMCountParams(llfn) as uint;
103+
104+
let initial_extra_param;
105+
match kind {
106+
BoolKind => initial_extra_param = 3,
107+
UnitKind => initial_extra_param = 2,
108+
}
109+
110+
let extra_params = DVec();
111+
for uint::range(initial_extra_param, n_params) |i| {
112+
extra_params.push(LLVMGetParam(llfn, i as c_uint));
113+
}
114+
115+
return dvec::unwrap(move extra_params);
116+
}
117+
96118
fn trans_deriving_struct_method(ccx: @crate_ctxt,
97119
llfn: ValueRef,
98120
impl_did: def_id,
@@ -104,14 +126,16 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
104126
let lltop = top_bcx.llbb;
105127
let mut bcx = top_bcx;
106128

129+
let llextraparams = get_extra_params(llfn, kind);
130+
107131
let llselfty = type_of(ccx, self_ty);
108132
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
109133

110134
// If there is an "other" value, then get it. The "other" value is the
111135
// value we're comparing against in the case of Eq and Ord.
112136
let llotherval_opt;
113137
match kind {
114-
BoolKind => llotherval_opt = Some(llvm::LLVMGetParam(llfn, 2)),
138+
BoolKind => llotherval_opt = Some(LLVMGetParam(llfn, 2)),
115139
UnitKind => llotherval_opt = None
116140
}
117141

@@ -136,8 +160,12 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
136160
|llotherval| GEPi(bcx, *llotherval, [0, 0, i]));
137161

138162
let self_ty = struct_field_tys[i].mt.ty;
139-
bcx = call_substructure_method(bcx, derived_method_info, self_ty,
140-
llselfval, llotherval_opt);
163+
bcx = call_substructure_method(bcx,
164+
derived_method_info,
165+
self_ty,
166+
llselfval,
167+
llotherval_opt,
168+
llextraparams);
141169

142170
// If this derived method is of boolean kind, return immediately if
143171
// the call to the substructure method returned false.
@@ -176,13 +204,15 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
176204
let lltop = top_bcx.llbb;
177205
let mut bcx = top_bcx;
178206

207+
let llextraparams = get_extra_params(llfn, kind);
208+
179209
let llselfty = type_of(ccx, self_ty);
180210
let llselfval = PointerCast(bcx, fcx.llenv, T_ptr(llselfty));
181211

182212
let llotherval_opt;
183213
match kind {
184214
UnitKind => llotherval_opt = None,
185-
BoolKind => llotherval_opt = Some(llvm::LLVMGetParam(llfn, 2))
215+
BoolKind => llotherval_opt = Some(LLVMGetParam(llfn, 2))
186216
}
187217

188218
let enum_id, enum_substs, enum_variant_infos;
@@ -260,7 +290,8 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
260290
derived_method_info,
261291
self_ty,
262292
llselfval,
263-
llotherval_opt);
293+
llotherval_opt,
294+
llextraparams);
264295

265296
// If this is a boolean-kind deriving method, then return
266297
// immediately if the call to the substructure returned false.
@@ -339,7 +370,8 @@ fn call_substructure_method(bcx: block,
339370
derived_field_info: &DerivedFieldInfo,
340371
self_ty: ty::t,
341372
llselfval: ValueRef,
342-
llotherval_opt: Option<ValueRef>) -> block {
373+
llotherval_opt: Option<ValueRef>,
374+
llextraparams: &[ValueRef]) -> block {
343375
let fcx = bcx.fcx;
344376
let ccx = fcx.ccx;
345377

@@ -367,6 +399,7 @@ fn call_substructure_method(bcx: block,
367399
vtable_result);
368400
let llfn = fn_data.llfn;
369401

402+
// Create the callee.
370403
let cb: &fn(block) -> Callee = |bloc| {
371404
Callee {
372405
bcx: bloc,
@@ -379,18 +412,18 @@ fn call_substructure_method(bcx: block,
379412
}
380413
};
381414

382-
let arg_values;
383-
match llotherval_opt {
384-
None => arg_values = ArgVals(~[]),
385-
Some(copy llotherval) => arg_values = ArgVals(~[llotherval])
386-
}
415+
// Build up the argument list.
416+
let llargvals = DVec();
417+
for llotherval_opt.each |llotherval| { llargvals.push(*llotherval); }
418+
for llextraparams.each |llextraparam| { llargvals.push(*llextraparam); }
387419

420+
// And perform the call.
388421
callee::trans_call_inner(bcx,
389422
None,
390423
fn_expr_tpbt.ty,
391424
ty::mk_bool(ccx.tcx),
392425
cb,
393-
move arg_values,
426+
ArgVals(dvec::unwrap(move llargvals)),
394427
SaveIn(fcx.llretptr),
395428
DontAutorefArg)
396429
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
trait Trait {
2+
#[derivable]
3+
fn f(x: int, y: &str);
4+
}
5+
6+
impl int : Trait {
7+
fn f(x: int, y: &str) {
8+
assert x == 42;
9+
assert y == "hello";
10+
}
11+
}
12+
13+
impl float : Trait {
14+
fn f(x: int, y: &str) {
15+
assert x == 42;
16+
assert y == "hello";
17+
}
18+
}
19+
20+
struct Foo {
21+
x: int,
22+
y: float
23+
}
24+
25+
impl Foo : Trait;
26+
27+
fn main() {
28+
let a: Foo = Foo { x: 1, y: 2.0 };
29+
a.f(42, "hello");
30+
}
31+

0 commit comments

Comments
 (0)