Skip to content

Commit 6d4fbd4

Browse files
committed
core: fix remaining repr bugs, r=burningtree.
1 parent b46e25b commit 6d4fbd4

File tree

2 files changed

+103
-10
lines changed

2 files changed

+103
-10
lines changed

src/libcore/reflect.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ use libc::c_void;
2828
*/
2929
pub trait MovePtr {
3030
fn move_ptr(adjustment: fn(*c_void) -> *c_void);
31+
fn push_ptr();
32+
fn pop_ptr();
3133
}
3234

3335
/// Helper function for alignment calculation.
@@ -402,6 +404,7 @@ impl<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor {
402404
disr_val: int,
403405
n_fields: uint,
404406
name: &str) -> bool {
407+
self.inner.push_ptr();
405408
if ! self.inner.visit_enter_enum_variant(variant, disr_val,
406409
n_fields, name) {
407410
return false;
@@ -410,7 +413,9 @@ impl<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor {
410413
}
411414

412415
fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool {
416+
unsafe { self.align((*inner).align); }
413417
if ! self.inner.visit_enum_variant_field(i, inner) { return false; }
418+
unsafe { self.bump((*inner).size); }
414419
true
415420
}
416421

@@ -422,13 +427,15 @@ impl<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor {
422427
n_fields, name) {
423428
return false;
424429
}
430+
self.inner.pop_ptr();
425431
true
426432
}
427433

428434
fn visit_leave_enum(n_variants: uint, sz: uint, align: uint) -> bool {
429435
if ! self.inner.visit_leave_enum(n_variants, sz, align) {
430436
return false;
431437
}
438+
self.bump(sz);
432439
true
433440
}
434441

src/libcore/repr.rs

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use reflect::{MovePtr, MovePtrAdaptor, align};
2626
use vec::UnboxedVecRepr;
2727
use vec::raw::{VecRepr, SliceRepr};
2828
pub use managed::raw::BoxRepr;
29+
use dvec::DVec;
2930

3031
/// Helpers
3132
@@ -121,19 +122,36 @@ impl char : Repr {
121122

122123
// New implementation using reflect::MovePtr
123124

125+
enum VariantState {
126+
Degenerate,
127+
TagMatch,
128+
TagMismatch,
129+
}
130+
124131
pub struct ReprVisitor {
125132
mut ptr: *c_void,
133+
ptr_stk: DVec<*c_void>,
134+
var_stk: DVec<VariantState>,
126135
writer: @Writer
127136
}
128137
pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor {
129-
ReprVisitor { ptr: ptr, writer: writer }
138+
ReprVisitor { ptr: ptr,
139+
ptr_stk: DVec(),
140+
var_stk: DVec(),
141+
writer: writer }
130142
}
131143

132144
impl ReprVisitor : MovePtr {
133145
#[inline(always)]
134146
fn move_ptr(adjustment: fn(*c_void) -> *c_void) {
135147
self.ptr = adjustment(self.ptr);
136148
}
149+
fn push_ptr() {
150+
self.ptr_stk.push(self.ptr);
151+
}
152+
fn pop_ptr() {
153+
self.ptr = self.ptr_stk.pop();
154+
}
137155
}
138156

139157
impl ReprVisitor {
@@ -148,6 +166,18 @@ impl ReprVisitor {
148166
true
149167
}
150168

169+
#[inline(always)]
170+
fn bump(sz: uint) {
171+
do self.move_ptr() |p| {
172+
((p as uint) + sz) as *c_void
173+
};
174+
}
175+
176+
#[inline(always)]
177+
fn bump_past<T>() {
178+
self.bump(sys::size_of::<T>());
179+
}
180+
151181
#[inline(always)]
152182
fn visit_inner(inner: *TyDesc) -> bool {
153183
self.visit_ptr_inner(self.ptr, inner)
@@ -402,23 +432,79 @@ impl ReprVisitor : TyVisitor {
402432
true
403433
}
404434

405-
fn visit_enter_enum(_n_variants: uint,
435+
fn visit_enter_enum(n_variants: uint,
406436
_sz: uint, _align: uint) -> bool {
437+
if n_variants == 1 {
438+
self.var_stk.push(Degenerate)
439+
} else {
440+
self.var_stk.push(TagMatch)
441+
}
407442
true
408443
}
409444
fn visit_enter_enum_variant(_variant: uint,
410-
_disr_val: int,
411-
_n_fields: uint,
412-
_name: &str) -> bool { true }
413-
fn visit_enum_variant_field(_i: uint, inner: *TyDesc) -> bool {
414-
self.visit_inner(inner)
445+
disr_val: int,
446+
n_fields: uint,
447+
name: &str) -> bool {
448+
let mut write = false;
449+
match self.var_stk.pop() {
450+
Degenerate => {
451+
write = true;
452+
self.var_stk.push(Degenerate);
453+
}
454+
TagMatch | TagMismatch => {
455+
do self.get::<int>() |t| {
456+
if disr_val == *t {
457+
write = true;
458+
self.var_stk.push(TagMatch);
459+
} else {
460+
self.var_stk.push(TagMismatch);
461+
}
462+
};
463+
self.bump_past::<int>();
464+
}
465+
}
466+
467+
if write {
468+
self.writer.write_str(name);
469+
if n_fields > 0 {
470+
self.writer.write_char('(');
471+
}
472+
}
473+
true
474+
}
475+
fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool {
476+
match self.var_stk.last() {
477+
Degenerate | TagMatch => {
478+
if i != 0 {
479+
self.writer.write_str(", ");
480+
}
481+
if ! self.visit_inner(inner) {
482+
return false;
483+
}
484+
}
485+
TagMismatch => ()
486+
}
487+
true
415488
}
416489
fn visit_leave_enum_variant(_variant: uint,
417490
_disr_val: int,
418-
_n_fields: uint,
419-
_name: &str) -> bool { true }
491+
n_fields: uint,
492+
_name: &str) -> bool {
493+
match self.var_stk.last() {
494+
Degenerate | TagMatch => {
495+
if n_fields > 0 {
496+
self.writer.write_char(')');
497+
}
498+
}
499+
TagMismatch => ()
500+
}
501+
true
502+
}
420503
fn visit_leave_enum(_n_variants: uint,
421-
_sz: uint, _align: uint) -> bool { true }
504+
_sz: uint, _align: uint) -> bool {
505+
self.var_stk.pop();
506+
true
507+
}
422508

423509
fn visit_enter_fn(_purity: uint, _proto: uint,
424510
_n_inputs: uint, _retstyle: uint) -> bool { true }

0 commit comments

Comments
 (0)