auto merge of #6201 : pcwalton/rust/inhtwama-serializer, r=graydon

This PR removes mutable fields from the serializer and makes the encoder and decoder use INHTWAMA properly (i.e. `&mut self`).

r? @graydon
This commit is contained in:
bors 2013-05-02 20:39:36 -07:00
commit b37a685958
21 changed files with 5382 additions and 558 deletions

View File

@ -272,12 +272,21 @@ fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
@bounds
}
#[cfg(stage0)]
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
reader::maybe_get_doc(item, tag_region_param).map(|doc| {
Decodable::decode(&reader::Decoder(*doc))
})
}
#[cfg(not(stage0))]
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
reader::maybe_get_doc(item, tag_region_param).map(|doc| {
let mut decoder = reader::Decoder(*doc);
Decodable::decode(&mut decoder)
})
}
fn item_ty_param_count(item: ebml::Doc) -> uint {
let mut n = 0u;
reader::tagged_docs(item, tag_items_data_item_ty_param_bounds,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,11 +32,11 @@
// overhead when initializing plain-old-data and means we don't need
// to waste time running the destructors of POD.
use list::{MutList, MutCons, MutNil};
use list;
use list::{List, Cons, Nil};
use core::at_vec;
use core::cast::transmute;
use core::cast::{transmute, transmute_mut_region};
use core::cast;
use core::libc::size_t;
use core::ptr;
@ -74,7 +74,7 @@ static tydesc_drop_glue_index: size_t = 3 as size_t;
// will always stay at 0.
struct Chunk {
data: @[u8],
mut fill: uint,
fill: uint,
is_pod: bool,
}
@ -82,9 +82,9 @@ pub struct Arena {
// The head is seperated out from the list as a unbenchmarked
// microoptimization, to avoid needing to case on the list to
// access the head.
priv mut head: Chunk,
priv mut pod_head: Chunk,
priv mut chunks: @List<Chunk>,
priv head: Chunk,
priv pod_head: Chunk,
priv chunks: @mut MutList<Chunk>,
}
#[unsafe_destructor]
@ -92,8 +92,10 @@ impl Drop for Arena {
fn finalize(&self) {
unsafe {
destroy_chunk(&self.head);
for list::each(self.chunks) |chunk| {
if !chunk.is_pod { destroy_chunk(chunk); }
for self.chunks.each |chunk| {
if !chunk.is_pod {
destroy_chunk(chunk);
}
}
}
}
@ -113,7 +115,7 @@ pub fn arena_with_size(initial_size: uint) -> Arena {
Arena {
head: chunk(initial_size, false),
pod_head: chunk(initial_size, true),
chunks: @Nil,
chunks: @mut MutNil,
}
}
@ -170,11 +172,11 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) {
pub impl Arena {
// Functions for the POD part of the arena
priv fn alloc_pod_grow(&self, n_bytes: uint, align: uint) -> *u8 {
priv fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 {
// Allocate a new chunk.
let chunk_size = at_vec::capacity(self.pod_head.data);
let new_min_chunk_size = uint::max(n_bytes, chunk_size);
self.chunks = @Cons(copy self.pod_head, self.chunks);
self.chunks = @mut MutCons(copy self.pod_head, self.chunks);
self.pod_head =
chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true);
@ -182,27 +184,28 @@ pub impl Arena {
}
#[inline(always)]
priv fn alloc_pod_inner(&self, n_bytes: uint, align: uint) -> *u8 {
let head = &mut self.pod_head;
let start = round_up_to(head.fill, align);
let end = start + n_bytes;
if end > at_vec::capacity(head.data) {
return self.alloc_pod_grow(n_bytes, align);
}
head.fill = end;
//debug!("idx = %u, size = %u, align = %u, fill = %u",
// start, n_bytes, align, head.fill);
priv fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 {
unsafe {
// XXX: Borrow check
let head = transmute_mut_region(&mut self.pod_head);
let start = round_up_to(head.fill, align);
let end = start + n_bytes;
if end > at_vec::capacity(head.data) {
return self.alloc_pod_grow(n_bytes, align);
}
head.fill = end;
//debug!("idx = %u, size = %u, align = %u, fill = %u",
// start, n_bytes, align, head.fill);
ptr::offset(vec::raw::to_ptr(head.data), start)
}
}
#[inline(always)]
#[cfg(stage0)]
priv fn alloc_pod<T>(&self, op: &fn() -> T) -> &'self T {
priv fn alloc_pod<T>(&mut self, op: &fn() -> T) -> &'self T {
unsafe {
let tydesc = sys::get_type_desc::<T>();
let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
@ -216,7 +219,7 @@ pub impl Arena {
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
priv fn alloc_pod<'a, T>(&'a self, op: &fn() -> T) -> &'a T {
priv fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
unsafe {
let tydesc = sys::get_type_desc::<T>();
let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
@ -227,11 +230,12 @@ pub impl Arena {
}
// Functions for the non-POD part of the arena
priv fn alloc_nonpod_grow(&self, n_bytes: uint, align: uint) -> (*u8, *u8) {
priv fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint)
-> (*u8, *u8) {
// Allocate a new chunk.
let chunk_size = at_vec::capacity(self.head.data);
let new_min_chunk_size = uint::max(n_bytes, chunk_size);
self.chunks = @Cons(copy self.head, self.chunks);
self.chunks = @mut MutCons(copy self.head, self.chunks);
self.head =
chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false);
@ -239,22 +243,23 @@ pub impl Arena {
}
#[inline(always)]
priv fn alloc_nonpod_inner(&self, n_bytes: uint, align: uint) -> (*u8, *u8) {
let head = &mut self.head;
let tydesc_start = head.fill;
let after_tydesc = head.fill + sys::size_of::<*TypeDesc>();
let start = round_up_to(after_tydesc, align);
let end = start + n_bytes;
if end > at_vec::capacity(head.data) {
return self.alloc_nonpod_grow(n_bytes, align);
}
head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>());
//debug!("idx = %u, size = %u, align = %u, fill = %u",
// start, n_bytes, align, head.fill);
priv fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint)
-> (*u8, *u8) {
unsafe {
let head = transmute_mut_region(&mut self.head);
let tydesc_start = head.fill;
let after_tydesc = head.fill + sys::size_of::<*TypeDesc>();
let start = round_up_to(after_tydesc, align);
let end = start + n_bytes;
if end > at_vec::capacity(head.data) {
return self.alloc_nonpod_grow(n_bytes, align);
}
head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>());
//debug!("idx = %u, size = %u, align = %u, fill = %u",
// start, n_bytes, align, head.fill);
let buf = vec::raw::to_ptr(head.data);
return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start));
}
@ -262,7 +267,7 @@ pub impl Arena {
#[inline(always)]
#[cfg(stage0)]
priv fn alloc_nonpod<T>(&self, op: &fn() -> T) -> &'self T {
priv fn alloc_nonpod<T>(&mut self, op: &fn() -> T) -> &'self T {
unsafe {
let tydesc = sys::get_type_desc::<T>();
let (ty_ptr, ptr) =
@ -286,7 +291,7 @@ pub impl Arena {
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
priv fn alloc_nonpod<'a, T>(&'a self, op: &fn() -> T) -> &'a T {
priv fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
unsafe {
let tydesc = sys::get_type_desc::<T>();
let (ty_ptr, ptr) =
@ -309,13 +314,16 @@ pub impl Arena {
// The external interface
#[inline(always)]
#[cfg(stage0)]
fn alloc<T>(&self, op: &fn() -> T) -> &'self T {
fn alloc<T>(&mut self, op: &fn() -> T) -> &'self T {
unsafe {
// XXX: Borrow check
let this = transmute_mut_region(self);
if !rusti::needs_drop::<T>() {
self.alloc_pod(op)
} else {
self.alloc_nonpod(op)
return this.alloc_pod(op);
}
// XXX: Borrow check
let this = transmute_mut_region(self);
this.alloc_nonpod(op)
}
}
@ -324,20 +332,23 @@ pub impl Arena {
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn alloc<'a, T>(&'a self, op: &fn() -> T) -> &'a T {
fn alloc<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
unsafe {
// XXX: Borrow check
let this = transmute_mut_region(self);
if !rusti::needs_drop::<T>() {
self.alloc_pod(op)
} else {
self.alloc_nonpod(op)
return this.alloc_pod(op);
}
// XXX: Borrow check
let this = transmute_mut_region(self);
this.alloc_nonpod(op)
}
}
}
#[test]
fn test_arena_destructors() {
let arena = Arena();
let mut arena = Arena();
for uint::range(0, 10) |i| {
// Arena allocate something with drop glue to make sure it
// doesn't leak.
@ -348,9 +359,11 @@ fn test_arena_destructors() {
}
}
#[test] #[should_fail] #[ignore(cfg(windows))]
#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_arena_destructors_fail() {
let arena = Arena();
let mut arena = Arena();
// Put some stuff in the arena.
for uint::range(0, 10) |i| {
// Arena allocate something with drop glue to make sure it

File diff suppressed because it is too large Load Diff

View File

@ -438,8 +438,11 @@ pub mod flatteners {
SerializingFlattener
*/
#[cfg(stage0)]
pub fn deserialize_buffer<D: Decoder + FromReader,
T: Decodable<D>>(buf: &[u8]) -> T {
T: Decodable<D>>(
buf: &[u8])
-> T {
let buf = vec::from_slice(buf);
let buf_reader = @BufReader::new(buf);
let reader = buf_reader as @Reader;
@ -447,14 +450,40 @@ pub mod flatteners {
Decodable::decode(&deser)
}
#[cfg(not(stage0))]
pub fn deserialize_buffer<D: Decoder + FromReader,
T: Decodable<D>>(
buf: &[u8])
-> T {
let buf = vec::from_slice(buf);
let buf_reader = @BufReader::new(buf);
let reader = buf_reader as @Reader;
let mut deser: D = FromReader::from_reader(reader);
Decodable::decode(&mut deser)
}
#[cfg(stage0)]
pub fn serialize_value<D: Encoder + FromWriter,
T: Encodable<D>>(val: &T) -> ~[u8] {
T: Encodable<D>>(
val: &T)
-> ~[u8] {
do io::with_bytes_writer |writer| {
let ser = FromWriter::from_writer(writer);
val.encode(&ser);
}
}
#[cfg(not(stage0))]
pub fn serialize_value<D: Encoder + FromWriter,
T: Encodable<D>>(
val: &T)
-> ~[u8] {
do io::with_bytes_writer |writer| {
let mut ser = FromWriter::from_writer(writer);
val.encode(&mut ser);
}
}
pub trait FromReader {
fn from_reader(r: @Reader) -> Self;
}

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,12 @@ pub enum List<T> {
Nil,
}
#[deriving(Eq)]
pub enum MutList<T> {
MutCons(T, @mut MutList<T>),
MutNil,
}
/// Create a list from a vector
pub fn from_vec<T:Copy>(v: &[T]) -> @List<T> {
vec::foldr(v, @Nil::<T>, |h, t| @Cons(*h, t))
@ -147,6 +153,25 @@ pub fn each<T>(l: @List<T>, f: &fn(&T) -> bool) {
}
}
impl<T> MutList<T> {
/// Iterate over a mutable list
pub fn each(@mut self, f: &fn(&mut T) -> bool) {
let mut cur = self;
loop {
let borrowed = &mut *cur;
cur = match *borrowed {
MutCons(ref mut hd, tl) => {
if !f(hd) {
return;
}
tl
}
MutNil => break
}
}
}
}
#[cfg(test)]
mod tests {
use list::*;

File diff suppressed because it is too large Load Diff

View File

@ -140,6 +140,7 @@ impl WorkMap {
fn new() -> WorkMap { WorkMap(HashMap::new()) }
}
#[cfg(stage0)]
impl<S:Encoder> Encodable<S> for WorkMap {
fn encode(&self, s: &S) {
let mut d = ~[];
@ -151,6 +152,19 @@ impl<S:Encoder> Encodable<S> for WorkMap {
}
}
#[cfg(not(stage0))]
impl<S:Encoder> Encodable<S> for WorkMap {
fn encode(&self, s: &mut S) {
let mut d = ~[];
for self.each |k, v| {
d.push((copy *k, copy *v))
}
sort::tim_sort(d);
d.encode(s)
}
}
#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for WorkMap {
fn decode(d: &D) -> WorkMap {
let v : ~[(WorkKey,~str)] = Decodable::decode(d);
@ -162,6 +176,18 @@ impl<D:Decoder> Decodable<D> for WorkMap {
}
}
#[cfg(not(stage0))]
impl<D:Decoder> Decodable<D> for WorkMap {
fn decode(d: &mut D) -> WorkMap {
let v : ~[(WorkKey,~str)] = Decodable::decode(d);
let mut w = WorkMap::new();
for v.each |&(k, v)| {
w.insert(copy k, copy v);
}
w
}
}
struct Database {
db_filename: Path,
db_cache: HashMap<~str, ~str>,
@ -171,8 +197,8 @@ struct Database {
pub impl Database {
fn prepare(&mut self,
fn_name: &str,
declared_inputs: &WorkMap) -> Option<(WorkMap, WorkMap, ~str)>
{
declared_inputs: &WorkMap)
-> Option<(WorkMap, WorkMap, ~str)> {
let k = json_encode(&(fn_name, declared_inputs));
match self.db_cache.find(&k) {
None => None,
@ -229,17 +255,38 @@ struct Work<T> {
res: Option<Either<T,PortOne<(Exec,T)>>>
}
#[cfg(stage0)]
fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
do io::with_str_writer |wr| {
t.encode(&json::Encoder(wr));
}
}
#[cfg(not(stage0))]
fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
do io::with_str_writer |wr| {
let mut encoder = json::Encoder(wr);
t.encode(&mut encoder);
}
}
// FIXME(#5121)
#[cfg(stage0)]
fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
do io::with_str_reader(s) |rdr| {
let j = result::unwrap(json::from_reader(rdr));
Decodable::decode(&json::Decoder(j))
let decoder = json::Decoder(j);
Decodable::decode(&decoder)
}
}
// FIXME(#5121)
#[cfg(not(stage0))]
fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
do io::with_str_reader(s) |rdr| {
let j = result::unwrap(json::from_reader(rdr));
let mut decoder = json::Decoder(j);
Decodable::decode(&mut decoder)
}
}

View File

@ -70,19 +70,37 @@ pub type Name = uint;
// with a macro expansion
pub type Mrk = uint;
#[cfg(stage0)]
impl<S:Encoder> Encodable<S> for ident {
fn encode(&self, s: &S) {
let intr = match unsafe {
task::local_data::local_data_get(interner_key!())
} {
None => fail!(~"encode: TLS interner not set up"),
Some(intr) => intr
};
unsafe {
let intr =
match task::local_data::local_data_get(interner_key!()) {
None => fail!(~"encode: TLS interner not set up"),
Some(intr) => intr
};
s.emit_str(*(*intr).get(*self));
s.emit_str(*(*intr).get(*self));
}
}
}
#[cfg(not(stage0))]
impl<S:Encoder> Encodable<S> for ident {
fn encode(&self, s: &mut S) {
unsafe {
let intr =
match task::local_data::local_data_get(interner_key!()) {
None => fail!(~"encode: TLS interner not set up"),
Some(intr) => intr
};
s.emit_str(*(*intr).get(*self));
}
}
}
#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for ident {
fn decode(d: &D) -> ident {
let intr = match unsafe {
@ -96,6 +114,20 @@ impl<D:Decoder> Decodable<D> for ident {
}
}
#[cfg(not(stage0))]
impl<D:Decoder> Decodable<D> for ident {
fn decode(d: &mut D) -> ident {
let intr = match unsafe {
task::local_data::local_data_get(interner_key!())
} {
None => fail!(~"decode: TLS interner not set up"),
Some(intr) => intr
};
(*intr).intern(@d.read_str())
}
}
impl to_bytes::IterBytes for ident {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
self.repr.iter_bytes(lsb0, f)

View File

@ -125,17 +125,34 @@ impl cmp::Eq for span {
fn ne(&self, other: &span) -> bool { !(*self).eq(other) }
}
#[cfg(stage0)]
impl<S:Encoder> Encodable<S> for span {
/* Note #1972 -- spans are encoded but not decoded */
fn encode(&self, _s: &S) { _s.emit_nil() }
}
#[cfg(not(stage0))]
impl<S:Encoder> Encodable<S> for span {
/* Note #1972 -- spans are encoded but not decoded */
fn encode(&self, s: &mut S) {
s.emit_nil()
}
}
#[cfg(stage0)]
impl<D:Decoder> Decodable<D> for span {
fn decode(_d: &D) -> span {
dummy_sp()
}
}
#[cfg(not(stage0))]
impl<D:Decoder> Decodable<D> for span {
fn decode(_d: &mut D) -> span {
dummy_sp()
}
}
pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> spanned<T> {
respan(mk_sp(lo, hi), t)
}

View File

@ -238,7 +238,8 @@ trait ExtCtxtMethods {
fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
fn lambda(&self, blk: ast::blk) -> @ast::expr;
fn lambda0(&self, blk: ast::blk) -> @ast::expr;
fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr;
fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
@ -254,8 +255,15 @@ trait ExtCtxtMethods {
ident: ast::ident,
args: ~[@ast::expr])
-> @ast::expr;
fn lambda_expr(&self, expr: @ast::expr) -> @ast::expr;
fn lambda_stmts(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr;
fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
-> @ast::expr;
fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
fn lambda_stmts_1(&self,
span: span,
stmts: ~[@ast::stmt],
ident: ast::ident)
-> @ast::expr;
}
impl ExtCtxtMethods for @ext_ctxt {
@ -388,12 +396,18 @@ impl ExtCtxtMethods for @ext_ctxt {
span: span}))
}
fn lambda(&self, blk: ast::blk) -> @ast::expr {
fn lambda0(&self, blk: ast::blk) -> @ast::expr {
let ext_cx = *self;
let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
quote_expr!( || $blk_e )
}
fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr {
let ext_cx = *self;
let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
quote_expr!( |$ident| $blk_e )
}
fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk {
codemap::spanned {
node: ast::blk_ {
@ -461,15 +475,29 @@ impl ExtCtxtMethods for @ext_ctxt {
ident: ast::ident,
args: ~[@ast::expr]
) -> @ast::expr {
self.expr(span, ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
self.expr(span,
ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
}
fn lambda_expr(&self, expr: @ast::expr) -> @ast::expr {
self.lambda(self.expr_blk(expr))
fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr {
self.lambda0(self.expr_blk(expr))
}
fn lambda_stmts(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
self.lambda(self.blk(span, stmts))
fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
-> @ast::expr {
self.lambda1(self.expr_blk(expr), ident)
}
fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
self.lambda0(self.blk(span, stmts))
}
fn lambda_stmts_1(&self,
span: span,
stmts: ~[@ast::stmt],
ident: ast::ident)
-> @ast::expr {
self.lambda1(self.blk(span, stmts), ident)
}
}
@ -644,7 +672,7 @@ fn mk_ser_method(
None,
ast::mt {
ty: cx.ty_path(span, ~[cx.ident_of(~"__S")], ~[]),
mutbl: ast::m_imm
mutbl: ast::m_mutbl
}
),
span: span,
@ -706,7 +734,7 @@ fn mk_deser_method(
None,
ast::mt {
ty: cx.ty_path(span, ~[cx.ident_of(~"__D")], ~[]),
mutbl: ast::m_imm
mutbl: ast::m_mutbl
}
),
span: span,
@ -758,8 +786,8 @@ fn mk_struct_ser_impl(
generics: &ast::Generics
) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| self.$(name).encode(__s)`
let expr_lambda = cx.lambda_expr(
// ast for `|__s| self.$(name).encode(__s)`
let expr_lambda = cx.lambda_expr_1(
cx.expr_method_call(
span,
cx.expr_field(
@ -769,7 +797,8 @@ fn mk_struct_ser_impl(
),
cx.ident_of(~"encode"),
~[cx.expr_var(span, ~"__s")]
)
),
cx.ident_of(~"__s")
);
// ast for `__s.emit_struct_field($(name), $(idx), $(expr_lambda))`
@ -787,7 +816,7 @@ fn mk_struct_ser_impl(
)
};
// ast for `__s.emit_struct($(name), || $(fields))`
// ast for `__s.emit_struct($(name), |__s| $(fields))`
let ser_body = cx.expr_method_call(
span,
cx.expr_var(span, ~"__s"),
@ -795,7 +824,7 @@ fn mk_struct_ser_impl(
~[
cx.lit_str(span, @cx.str_of(ident)),
cx.lit_uint(span, vec::len(fields)),
cx.lambda_stmts(span, fields),
cx.lambda_stmts_1(span, fields, cx.ident_of(~"__s")),
]
);
@ -810,8 +839,8 @@ fn mk_struct_deser_impl(
generics: &ast::Generics
) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| std::serialize::decode(__d)`
let expr_lambda = cx.lambda(
// ast for `|__d| std::serialize::decode(__d)`
let expr_lambda = cx.lambda1(
cx.expr_blk(
cx.expr_call(
span,
@ -823,7 +852,8 @@ fn mk_struct_deser_impl(
]),
~[cx.expr_var(span, ~"__d")]
)
)
),
cx.ident_of(~"__d")
);
// ast for `__d.read_struct_field($(name), $(idx), $(expr_lambda))`
@ -848,7 +878,7 @@ fn mk_struct_deser_impl(
}
};
// ast for `read_struct($(name), || $(fields))`
// ast for `read_struct($(name), |__d| $(fields))`
let body = cx.expr_method_call(
span,
cx.expr_var(span, ~"__d"),
@ -856,7 +886,7 @@ fn mk_struct_deser_impl(
~[
cx.lit_str(span, @cx.str_of(ident)),
cx.lit_uint(span, vec::len(fields)),
cx.lambda_expr(
cx.lambda_expr_1(
cx.expr(
span,
ast::expr_struct(
@ -864,7 +894,8 @@ fn mk_struct_deser_impl(
fields,
None
)
)
),
cx.ident_of(~"__d")
),
]
);
@ -974,14 +1005,15 @@ fn ser_variant(
cx.ident_of(~"emit_enum_variant_arg")
);
// ast for `|| $(v).encode(__s)`
let expr_encode = cx.lambda_expr(
cx.expr_method_call(
// ast for `|__s| $(v).encode(__s)`
let expr_encode = cx.lambda_expr_1(
cx.expr_method_call(
span,
cx.expr_path(span, ~[names[a_idx]]),
cx.ident_of(~"encode"),
~[cx.expr_var(span, ~"__s")]
)
),
cx.ident_of(~"__s")
);
// ast for `$(expr_emit)($(a_idx), $(expr_encode))`
@ -1003,7 +1035,7 @@ fn ser_variant(
cx.lit_str(span, @cx.str_of(v_name)),
cx.lit_uint(span, v_idx),
cx.lit_uint(span, stmts.len()),
cx.lambda_stmts(span, stmts),
cx.lambda_stmts_1(span, stmts, cx.ident_of(~"__s")),
]
);
@ -1050,7 +1082,7 @@ fn mk_enum_ser_body(
cx.ident_of(~"emit_enum"),
~[
cx.lit_str(span, @cx.str_of(name)),
cx.lambda_expr(match_expr),
cx.lambda_expr_1(match_expr, cx.ident_of(~"__s")),
]
)
}
@ -1062,8 +1094,8 @@ fn mk_enum_deser_variant_nary(
args: ~[ast::variant_arg]
) -> @ast::expr {
let args = do args.mapi |idx, _arg| {
// ast for `|| std::serialize::decode(__d)`
let expr_lambda = cx.lambda_expr(
// ast for `|__s| std::serialize::decode(__d)`
let expr_lambda = cx.lambda_expr_1(
cx.expr_call(
span,
cx.expr_path_global(span, ~[
@ -1073,7 +1105,8 @@ fn mk_enum_deser_variant_nary(
cx.ident_of(~"decode"),
]),
~[cx.expr_var(span, ~"__d")]
)
),
cx.ident_of(~"__d")
);
// ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))`
@ -1163,24 +1196,44 @@ fn mk_enum_deser_body(
span,
ast::expr_fn_block(
ast::fn_decl {
inputs: ~[ast::arg {
is_mutbl: false,
ty: @ast::Ty {
inputs: ~[
ast::arg {
is_mutbl: false,
ty: @ast::Ty {
id: ext_cx.next_id(),
node: ast::ty_infer,
span: span
},
pat: @ast::pat {
id: ext_cx.next_id(),
node: ast::pat_ident(
ast::bind_by_copy,
ast_util::ident_to_path(span,
ext_cx.ident_of(~"__d")),
None),
span: span,
},
id: ext_cx.next_id(),
node: ast::ty_infer,
span: span
},
pat: @ast::pat {
ast::arg {
is_mutbl: false,
ty: @ast::Ty {
id: ext_cx.next_id(),
node: ast::ty_infer,
span: span
},
pat: @ast::pat {
id: ext_cx.next_id(),
node: ast::pat_ident(
ast::bind_by_copy,
ast_util::ident_to_path(span,
ext_cx.ident_of(~"i")),
None),
span: span,
},
id: ext_cx.next_id(),
node: ast::pat_ident(
ast::bind_by_copy,
ast_util::ident_to_path(span,
ext_cx.ident_of(~"i")),
None),
span: span,
},
id: ext_cx.next_id(),
}],
}
],
output: @ast::Ty {
id: ext_cx.next_id(),
node: ast::ty_infer,
@ -1198,13 +1251,14 @@ fn mk_enum_deser_body(
);
// ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))`
let expr_lambda = ext_cx.lambda_expr(
let expr_lambda = ext_cx.lambda_expr_1(
ext_cx.expr_method_call(
span,
ext_cx.expr_var(span, ~"__d"),
ext_cx.ident_of(~"read_enum_variant"),
~[expr_arm_names, expr_lambda]
)
),
ext_cx.ident_of(~"__d")
);
// ast for `__d.read_enum($(e_name), $(expr_lambda))`
@ -1256,105 +1310,147 @@ mod test {
}
impl Encoder for TestEncoder {
fn emit_nil(&self) { self.add_to_log(CallToEmitNil) }
fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) }
fn emit_uint(&self, v: uint) {self.add_to_log(CallToEmitUint(v)); }
fn emit_u64(&self, _v: u64) { self.add_unknown_to_log(); }
fn emit_u32(&self, _v: u32) { self.add_unknown_to_log(); }
fn emit_u16(&self, _v: u16) { self.add_unknown_to_log(); }
fn emit_u8(&self, _v: u8) { self.add_unknown_to_log(); }
fn emit_uint(&mut self, v: uint) {
self.add_to_log(CallToEmitUint(v));
}
fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); }
fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); }
fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); }
fn emit_u8(&mut self, _v: u8) { self.add_unknown_to_log(); }
fn emit_int(&self, _v: int) { self.add_unknown_to_log(); }
fn emit_i64(&self, _v: i64) { self.add_unknown_to_log(); }
fn emit_i32(&self, _v: i32) { self.add_unknown_to_log(); }
fn emit_i16(&self, _v: i16) { self.add_unknown_to_log(); }
fn emit_i8(&self, _v: i8) { self.add_unknown_to_log(); }
fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); }
fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); }
fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); }
fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); }
fn emit_i8(&mut self, _v: i8) { self.add_unknown_to_log(); }
fn emit_bool(&self, _v: bool) { self.add_unknown_to_log(); }
fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); }
fn emit_f64(&self, _v: f64) { self.add_unknown_to_log(); }
fn emit_f32(&self, _v: f32) { self.add_unknown_to_log(); }
fn emit_float(&self, _v: float) { self.add_unknown_to_log(); }
fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); }
fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); }
fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); }
fn emit_char(&self, _v: char) { self.add_unknown_to_log(); }
fn emit_str(&self, _v: &str) { self.add_unknown_to_log(); }
fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); }
fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); }
fn emit_enum(&self, name: &str, f: &fn()) {
self.add_to_log(CallToEmitEnum(name.to_str())); f(); }
fn emit_enum_variant(&self, name: &str, id: uint,
cnt: uint, f: &fn()) {
self.add_to_log(CallToEmitEnumVariant (name.to_str(),id,cnt));
f();
fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitEnum(name.to_str()));
f(self);
}
fn emit_enum_variant_arg(&self, idx: uint, f: &fn()) {
self.add_to_log(CallToEmitEnumVariantArg (idx)); f();
fn emit_enum_variant(&mut self,
name: &str,
id: uint,
cnt: uint,
f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt));
f(self);
}
fn emit_enum_struct_variant(&self, name: &str, id: uint, cnt: uint, f: &fn()) {
fn emit_enum_variant_arg(&mut self,
idx: uint,
f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitEnumVariantArg(idx));
f(self);
}
fn emit_enum_struct_variant(&mut self,
name: &str,
id: uint,
cnt: uint,
f: &fn(&mut TestEncoder)) {
self.emit_enum_variant(name, id, cnt, f)
}
fn emit_enum_struct_variant_field(&self, _name: &str, idx: uint, f: &fn()) {
fn emit_enum_struct_variant_field(&mut self,
_name: &str,
idx: uint,
f: &fn(&mut TestEncoder)) {
self.emit_enum_variant_arg(idx, f)
}
fn emit_struct(&self, name: &str, len: uint, f: &fn()) {
self.add_to_log(CallToEmitStruct (name.to_str(),len)); f();
fn emit_struct(&mut self,
name: &str,
len: uint,
f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitStruct (name.to_str(),len));
f(self);
}
fn emit_struct_field(&self, name: &str, idx: uint, f: &fn()) {
self.add_to_log(CallToEmitField (name.to_str(),idx)); f();
fn emit_struct_field(&mut self,
name: &str,
idx: uint,
f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitField (name.to_str(),idx));
f(self);
}
fn emit_tuple(&self, _len: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_tuple_arg(&self, _idx: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_tuple_struct(&self, _name: &str, _len: uint, f: &fn()) {
self.add_unknown_to_log(); f();
}
fn emit_tuple_struct_arg(&self, _idx: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_tuple_struct(&mut self,
_name: &str,
_len: uint,
f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_option(&self, f: &fn()) {
fn emit_tuple_struct_arg(&mut self,
_idx: uint,
f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_option(&mut self, f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitOption);
f();
f(self);
}
fn emit_option_none(&self) {
fn emit_option_none(&mut self) {
self.add_to_log(CallToEmitOptionNone);
}
fn emit_option_some(&self, f: &fn()) {
fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) {
self.add_to_log(CallToEmitOptionSome);
f();
f(self);
}
fn emit_seq(&self, _len: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_seq_elt(&self, _idx: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_map(&self, _len: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_map_elt_key(&self, _idx: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
fn emit_map_elt_val(&self, _idx: uint, f: &fn()) {
self.add_unknown_to_log(); f();
fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
self.add_unknown_to_log();
f(self);
}
}
fn to_call_log<E:Encodable<TestEncoder>>(val: E) -> ~[call] {
let mut te = TestEncoder {call_log: @mut ~[]};
val.encode(&te);
let mut te = TestEncoder {
call_log: @mut ~[]
};
val.encode(&mut te);
copy *te.call_log
}

View File

@ -96,7 +96,7 @@ fn create_decode_method(
cx,
span,
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__D")),
ast::m_imm
ast::m_mutbl
);
let d_ident = cx.ident_of(~"__d");
let d_arg = build::mk_arg(cx, span, d_ident, d_arg_type);
@ -219,6 +219,11 @@ fn create_read_struct_field(
// Call the substructure method.
let decode_expr = call_substructure_decode_method(cx, span);
let d_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__d"),
build::mk_ty_infer(cx, span));
let call_expr = build::mk_method_call(
cx,
span,
@ -227,7 +232,11 @@ fn create_read_struct_field(
~[
build::mk_base_str(cx, span, cx.str_of(ident)),
build::mk_uint(cx, span, idx),
build::mk_lambda_no_args(cx, span, decode_expr),
build::mk_lambda(cx,
span,
build::mk_fn_decl(~[d_arg],
build::mk_ty_infer(cx, span)),
decode_expr),
]
);
@ -282,6 +291,11 @@ fn expand_deriving_decodable_struct_method(
i += 1;
}
let d_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__d"),
build::mk_ty_infer(cx, span));
let read_struct_expr = build::mk_method_call(
cx,
span,
@ -294,9 +308,10 @@ fn expand_deriving_decodable_struct_method(
~[
build::mk_base_str(cx, span, cx.str_of(type_ident)),
build::mk_uint(cx, span, fields.len()),
build::mk_lambda_no_args(
build::mk_lambda(
cx,
span,
build::mk_fn_decl(~[d_arg], build::mk_ty_infer(cx, span)),
build::mk_struct_e(
cx,
span,
@ -334,6 +349,12 @@ fn create_read_variant_arg(
// Call the substructure method.
let expr = call_substructure_decode_method(cx, span);
let d_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__d"),
build::mk_ty_infer(cx, span));
let t_infer = build::mk_ty_infer(cx, span);
let call_expr = build::mk_method_call(
cx,
span,
@ -341,7 +362,10 @@ fn create_read_variant_arg(
cx.ident_of(~"read_enum_variant_arg"),
~[
build::mk_uint(cx, span, j),
build::mk_lambda_no_args(cx, span, expr),
build::mk_lambda(cx,
span,
build::mk_fn_decl(~[d_arg], t_infer),
expr),
]
);
@ -399,6 +423,12 @@ fn create_read_enum_variant(
span,
build::mk_fn_decl(
~[
build::mk_arg(
cx,
span,
cx.ident_of(~"__d"),
build::mk_ty_infer(cx, span)
),
build::mk_arg(
cx,
span,
@ -434,6 +464,11 @@ fn expand_deriving_decodable_enum_method(
enum_definition
);
let d_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__d"),
build::mk_ty_infer(cx, span));
// Create the read_enum expression
let read_enum_expr = build::mk_method_call(
cx,
@ -442,7 +477,11 @@ fn expand_deriving_decodable_enum_method(
cx.ident_of(~"read_enum"),
~[
build::mk_base_str(cx, span, cx.str_of(type_ident)),
build::mk_lambda_no_args(cx, span, read_enum_variant_expr),
build::mk_lambda(cx,
span,
build::mk_fn_decl(~[d_arg],
build::mk_ty_infer(cx, span)),
read_enum_variant_expr),
]
);

View File

@ -94,10 +94,9 @@ fn create_encode_method(
cx,
span,
build::mk_simple_ty_path(cx, span, cx.ident_of(~"__E")),
ast::m_imm
ast::m_mutbl
);
let e_ident = cx.ident_of(~"__e");
let e_arg = build::mk_arg(cx, span, e_ident, e_arg_type);
let e_arg = build::mk_arg(cx, span, cx.ident_of(~"__e"), e_arg_type);
// Create the type of the return value.
let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
@ -226,10 +225,16 @@ fn expand_deriving_encodable_struct_method(
self_field
);
let e_ident = cx.ident_of(~"__e");
let e_arg = build::mk_arg(cx,
span,
e_ident,
build::mk_ty_infer(cx, span));
let blk_expr = build::mk_lambda(
cx,
span,
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)),
encode_expr
);
@ -257,6 +262,11 @@ fn expand_deriving_encodable_struct_method(
idx += 1;
}
let e_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__e"),
build::mk_ty_infer(cx, span));
let emit_struct_stmt = build::mk_method_call(
cx,
span,
@ -272,7 +282,7 @@ fn expand_deriving_encodable_struct_method(
build::mk_lambda_stmts(
cx,
span,
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)),
statements
),
]
@ -309,10 +319,16 @@ fn expand_deriving_encodable_enum_method(
// Call the substructure method.
let expr = call_substructure_encode_method(cx, span, field);
let e_ident = cx.ident_of(~"__e");
let e_arg = build::mk_arg(cx,
span,
e_ident,
build::mk_ty_infer(cx, span));
let blk_expr = build::mk_lambda(
cx,
span,
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)),
expr
);
@ -331,6 +347,10 @@ fn expand_deriving_encodable_enum_method(
}
// Create the pattern body.
let e_arg = build::mk_arg(cx,
span,
cx.ident_of(~"__e"),
build::mk_ty_infer(cx, span));
let call_expr = build::mk_method_call(
cx,
span,
@ -343,7 +363,7 @@ fn expand_deriving_encodable_enum_method(
build::mk_lambda_stmts(
cx,
span,
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)),
stmts
)
]
@ -359,11 +379,17 @@ fn expand_deriving_encodable_enum_method(
}
};
let e_ident = cx.ident_of(~"__e");
let e_arg = build::mk_arg(cx,
span,
e_ident,
build::mk_ty_infer(cx, span));
// Create the method body.
let lambda_expr = build::mk_lambda(
cx,
span,
build::mk_fn_decl(~[], build::mk_ty_infer(cx, span)),
build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)),
expand_enum_or_struct_match(cx, span, arms)
);

View File

@ -420,7 +420,8 @@ mod test {
#[cfg(test)] fn to_json_str<E : Encodable<std::json::Encoder>>(val: @E) -> ~str {
do io::with_str_writer |writer| {
val.encode(~std::json::Encoder(writer));
let mut encoder = std::json::Encoder(writer);
val.encode(&mut encoder);
}
}

View File

@ -1,3 +1,7 @@
// xfail-test
// Broken due to arena API problems.
// 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.
@ -10,7 +14,6 @@
extern mod std;
use std::arena;
use methods = std::arena::Arena;
enum tree<'self> {
nil,
@ -26,9 +29,7 @@ fn item_check(t: &tree) -> int {
}
}
fn bottom_up_tree<'r>(arena: &'r arena::Arena,
item: int,
depth: int)
fn bottom_up_tree<'r>(arena: &'r mut arena::Arena, item: int, depth: int)
-> &'r tree<'r> {
if depth > 0 {
return arena.alloc(
@ -58,25 +59,25 @@ fn main() {
max_depth = n;
}
let stretch_arena = arena::Arena();
let mut stretch_arena = arena::Arena();
let stretch_depth = max_depth + 1;
let stretch_tree = bottom_up_tree(&stretch_arena, 0, stretch_depth);
let stretch_tree = bottom_up_tree(&mut stretch_arena, 0, stretch_depth);
io::println(fmt!("stretch tree of depth %d\t check: %d",
stretch_depth,
item_check(stretch_tree)));
let long_lived_arena = arena::Arena();
let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth);
let mut long_lived_arena = arena::Arena();
let long_lived_tree = bottom_up_tree(&mut long_lived_arena, 0, max_depth);
let mut depth = min_depth;
while depth <= max_depth {
let iterations = int::pow(2, (max_depth - depth + min_depth) as uint);
let mut chk = 0;
let mut i = 1;
while i <= iterations {
let mut temp_tree = bottom_up_tree(&long_lived_arena, i, depth);
let mut temp_tree = bottom_up_tree(&mut long_lived_arena, i, depth);
chk += item_check(temp_tree);
temp_tree = bottom_up_tree(&long_lived_arena, -i, depth);
temp_tree = bottom_up_tree(&mut long_lived_arena, -i, depth);
chk += item_check(temp_tree);
i += 1;
}
@ -87,5 +88,5 @@ fn main() {
}
io::println(fmt!("long lived trees of depth %d\t check: %d",
max_depth,
item_check(long_lived_tree)));
item_check(long_lived_tree)));
}

View File

@ -31,11 +31,12 @@ fn test_ebml<A:
Decodable<EBReader::Decoder>
>(a1: &A) {
let bytes = do io::with_bytes_writer |wr| {
let ebml_w = &EBWriter::Encoder(wr);
a1.encode(ebml_w)
let mut ebml_w = EBWriter::Encoder(wr);
a1.encode(&mut ebml_w)
};
let d = EBReader::Doc(@bytes);
let a2: A = Decodable::decode(&EBReader::Decoder(d));
let mut decoder = EBReader::Decoder(d);
let a2: A = Decodable::decode(&mut decoder);
assert!(*a1 == a2);
}

View File

@ -17,5 +17,6 @@ use self::std::serialize;
pub fn main() {
let json = json::from_str("[1]").unwrap();
let _x: ~[int] = serialize::Decodable::decode(&json::Decoder(json));
let mut decoder = json::Decoder(json);
let _x: ~[int] = serialize::Decodable::decode(&mut decoder);
}

View File

@ -14,7 +14,8 @@ extern mod std;
use std::arena;
pub fn main() {
let p = &arena::Arena();
let mut arena = arena::Arena();
let p = &mut arena;
let x = p.alloc(|| 4u);
io::print(fmt!("%u", *x));
assert!(*x == 4u);

View File

@ -21,7 +21,7 @@ struct Bcx<'self> {
}
struct Fcx<'self> {
arena: &'self Arena,
arena: &'self mut Arena,
ccx: &'self Ccx
}
@ -29,23 +29,27 @@ struct Ccx {
x: int
}
fn h<'r>(bcx : &'r Bcx<'r>) -> &'r Bcx<'r> {
return bcx.fcx.arena.alloc(|| Bcx { fcx: bcx.fcx });
fn h<'r>(bcx : &'r mut Bcx<'r>) -> &'r mut Bcx<'r> {
// XXX: Arena has a bad interface here; it should return mutable pointers.
// But this patch is too big to roll that in.
unsafe {
cast::transmute(bcx.fcx.arena.alloc(|| Bcx { fcx: bcx.fcx }))
}
}
fn g(fcx : &Fcx) {
let bcx = Bcx { fcx: fcx };
h(&bcx);
fn g(fcx: &mut Fcx) {
let mut bcx = Bcx { fcx: fcx };
h(&mut bcx);
}
fn f(ccx : &Ccx) {
let a = Arena();
let fcx = &Fcx { arena: &a, ccx: ccx };
return g(fcx);
fn f(ccx: &mut Ccx) {
let mut a = Arena();
let mut fcx = Fcx { arena: &mut a, ccx: ccx };
return g(&mut fcx);
}
pub fn main() {
let ccx = Ccx { x: 0 };
f(&ccx);
let mut ccx = Ccx { x: 0 };
f(&mut ccx);
}