aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2011-04-15 18:14:29 -0700
committerPatrick Walton <[email protected]>2011-04-15 18:14:29 -0700
commit0c288720b6d02f67a6f8002041a305f1986abc5c (patch)
tree02bf7928870af373db76c5256399e810012fe8d8 /src
parentrustc: Use a regular vector instead of a hash table for type descriptors (diff)
downloadrust-0c288720b6d02f67a6f8002041a305f1986abc5c.tar.xz
rust-0c288720b6d02f67a6f8002041a305f1986abc5c.zip
rustc: Capture type parameters into for-each blocks. Add a test case.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs35
-rw-r--r--src/test/run-pass/type-params-in-for-each.rs11
2 files changed, 44 insertions, 2 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 3d6b547c..9181e52a 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3298,8 +3298,9 @@ fn trans_for_each(@block_ctxt cx,
}
// Create an environment and populate it with the bindings.
+ auto tydesc_count = _vec.len[ValueRef](cx.fcx.lltydescs);
auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()),
- val_ty(llbindingsptr), 0u);
+ val_ty(llbindingsptr), tydesc_count);
auto llenvptr = alloca(cx, llvm.LLVMGetElementType(llenvptrty));
auto llbindingsptrptr = cx.build.GEP(llenvptr,
@@ -3308,6 +3309,20 @@ fn trans_for_each(@block_ctxt cx,
C_int(2)));
cx.build.Store(llbindingsptr, llbindingsptrptr);
+ // Copy in our type descriptors, in case the iterator body needs to refer
+ // to them.
+ auto lltydescsptr = cx.build.GEP(llenvptr,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body),
+ C_int(3)));
+ auto i = 0u;
+ while (i < tydesc_count) {
+ auto lltydescptr = cx.build.GEP(lltydescsptr,
+ vec(C_int(0), C_int(i as int)));
+ cx.build.Store(cx.fcx.lltydescs.(i), lltydescptr);
+ i += 1u;
+ }
+
// Step 2: Declare foreach body function.
let str s = mangle_name_by_seq(cx.fcx.ccx, "foreach");
@@ -3339,7 +3354,7 @@ fn trans_for_each(@block_ctxt cx,
vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2)));
auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr);
- auto i = 0u;
+ i = 0u;
while (i < upvar_count) {
auto upvar_id = upvars.(i);
auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr,
@@ -3350,6 +3365,22 @@ fn trans_for_each(@block_ctxt cx,
i += 1u;
}
+ // Populate the type parameters from the environment.
+ auto llremotetydescsptr = bcx.build.GEP(llremoteenvptr,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body),
+ C_int(3)));
+
+ i = 0u;
+ while (i < tydesc_count) {
+ auto llremotetydescptr = bcx.build.GEP(llremotetydescsptr,
+ vec(C_int(0),
+ C_int(i as int)));
+ auto llremotetydesc = bcx.build.Load(llremotetydescptr);
+ fcx.lltydescs += vec(llremotetydesc);
+ i += 1u;
+ }
+
// Treat the loop variable as an upvar as well. We copy it to an alloca
// as usual.
auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u);
diff --git a/src/test/run-pass/type-params-in-for-each.rs b/src/test/run-pass/type-params-in-for-each.rs
new file mode 100644
index 00000000..74f69aca
--- /dev/null
+++ b/src/test/run-pass/type-params-in-for-each.rs
@@ -0,0 +1,11 @@
+use std;
+import std._uint;
+
+fn create_index[T](vec[tup(T, uint)] index, fn(&T) -> uint hash_fn) {
+ for each (uint i in _uint.range(0u, 256u)) {
+ let vec[T] bucket = vec();
+ }
+}
+
+fn main() {}
+