fix enum variants with multiple fields
This commit is contained in:
parent
8c666b30ed
commit
c9914cd3ae
@ -819,11 +819,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Field(field, field_ty) => {
|
||||
let field_ty = self.monomorphize(field_ty, self.substs());
|
||||
use rustc::ty::layout::Layout::*;
|
||||
let variant = match *base_layout {
|
||||
Univariant { ref variant, .. } => variant,
|
||||
let field = field.index();
|
||||
let offset = match *base_layout {
|
||||
Univariant { ref variant, .. } => variant.field_offset(field),
|
||||
General { ref variants, .. } => {
|
||||
if let LvalueExtra::DowncastVariant(variant_idx) = base.extra {
|
||||
&variants[variant_idx]
|
||||
// +1 for the discriminant, which is field 0
|
||||
variants[variant_idx].field_offset(field + 1)
|
||||
} else {
|
||||
bug!("field access on enum had no variant index");
|
||||
}
|
||||
@ -832,12 +834,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
assert_eq!(field.index(), 0);
|
||||
return Ok(base);
|
||||
}
|
||||
StructWrappedNullablePointer { ref nonnull, .. } => nonnull,
|
||||
StructWrappedNullablePointer { ref nonnull, .. } => nonnull.field_offset(field),
|
||||
_ => bug!("field access on non-product type: {:?}", base_layout),
|
||||
};
|
||||
|
||||
let offset = variant.field_offset(field.index()).bytes();
|
||||
let ptr = base.ptr.offset(offset as isize);
|
||||
let ptr = base.ptr.offset(offset.bytes() as isize);
|
||||
if self.type_is_sized(field_ty) {
|
||||
ptr
|
||||
} else {
|
||||
@ -857,9 +858,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Downcast(_, variant) => {
|
||||
use rustc::ty::layout::Layout::*;
|
||||
match *base_layout {
|
||||
General { ref variants, .. } => {
|
||||
General { .. } => {
|
||||
return Ok(Lvalue {
|
||||
ptr: base.ptr.offset(variants[variant].field_offset(1).bytes() as isize),
|
||||
ptr: base.ptr,
|
||||
extra: LvalueExtra::DowncastVariant(variant),
|
||||
});
|
||||
}
|
||||
|
208
tests/run-pass/deriving-associated-types.rs
Normal file
208
tests/run-pass/deriving-associated-types.rs
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub trait DeclaredTrait {
|
||||
type Type;
|
||||
}
|
||||
|
||||
impl DeclaredTrait for i32 {
|
||||
type Type = i32;
|
||||
}
|
||||
|
||||
pub trait WhereTrait {
|
||||
type Type;
|
||||
}
|
||||
|
||||
impl WhereTrait for i32 {
|
||||
type Type = i32;
|
||||
}
|
||||
|
||||
// Make sure we don't add a bound that just shares a name with an associated
|
||||
// type.
|
||||
pub mod module {
|
||||
pub type Type = i32;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct PrivateStruct<T>(T);
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct TupleStruct<A, B: DeclaredTrait, C>(
|
||||
module::Type,
|
||||
Option<module::Type>,
|
||||
A,
|
||||
PrivateStruct<A>,
|
||||
B,
|
||||
B::Type,
|
||||
Option<B::Type>,
|
||||
<B as DeclaredTrait>::Type,
|
||||
Option<<B as DeclaredTrait>::Type>,
|
||||
C,
|
||||
C::Type,
|
||||
Option<C::Type>,
|
||||
<C as WhereTrait>::Type,
|
||||
Option<<C as WhereTrait>::Type>,
|
||||
<i32 as DeclaredTrait>::Type,
|
||||
) where C: WhereTrait;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait {
|
||||
m1: module::Type,
|
||||
m2: Option<module::Type>,
|
||||
a1: A,
|
||||
a2: PrivateStruct<A>,
|
||||
b: B,
|
||||
b1: B::Type,
|
||||
b2: Option<B::Type>,
|
||||
b3: <B as DeclaredTrait>::Type,
|
||||
b4: Option<<B as DeclaredTrait>::Type>,
|
||||
c: C,
|
||||
c1: C::Type,
|
||||
c2: Option<C::Type>,
|
||||
c3: <C as WhereTrait>::Type,
|
||||
c4: Option<<C as WhereTrait>::Type>,
|
||||
d: <i32 as DeclaredTrait>::Type,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait {
|
||||
Unit,
|
||||
Seq(
|
||||
module::Type,
|
||||
Option<module::Type>,
|
||||
A,
|
||||
PrivateStruct<A>,
|
||||
B,
|
||||
B::Type,
|
||||
Option<B::Type>,
|
||||
<B as DeclaredTrait>::Type,
|
||||
Option<<B as DeclaredTrait>::Type>,
|
||||
C,
|
||||
C::Type,
|
||||
Option<C::Type>,
|
||||
<C as WhereTrait>::Type,
|
||||
Option<<C as WhereTrait>::Type>,
|
||||
<i32 as DeclaredTrait>::Type,
|
||||
),
|
||||
Map {
|
||||
m1: module::Type,
|
||||
m2: Option<module::Type>,
|
||||
a1: A,
|
||||
a2: PrivateStruct<A>,
|
||||
b: B,
|
||||
b1: B::Type,
|
||||
b2: Option<B::Type>,
|
||||
b3: <B as DeclaredTrait>::Type,
|
||||
b4: Option<<B as DeclaredTrait>::Type>,
|
||||
c: C,
|
||||
c1: C::Type,
|
||||
c2: Option<C::Type>,
|
||||
c3: <C as WhereTrait>::Type,
|
||||
c4: Option<<C as WhereTrait>::Type>,
|
||||
d: <i32 as DeclaredTrait>::Type,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let e: Enum<
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
> = Enum::Seq(
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
PrivateStruct(0),
|
||||
0,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
);
|
||||
assert_eq!(e, e);
|
||||
|
||||
let e: Enum<
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
> = Enum::Map {
|
||||
m1: 0,
|
||||
m2: None,
|
||||
a1: 0,
|
||||
a2: PrivateStruct(0),
|
||||
b: 0,
|
||||
b1: 0,
|
||||
b2: None,
|
||||
b3: 0,
|
||||
b4: None,
|
||||
c: 0,
|
||||
c1: 0,
|
||||
c2: None,
|
||||
c3: 0,
|
||||
c4: None,
|
||||
d: 0,
|
||||
};
|
||||
assert_eq!(e, e);
|
||||
let e: TupleStruct<
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
> = TupleStruct(
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
PrivateStruct(0),
|
||||
0,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
0,
|
||||
);
|
||||
assert_eq!(e, e);
|
||||
|
||||
let e: Struct<
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
> = Struct {
|
||||
m1: 0,
|
||||
m2: None,
|
||||
a1: 0,
|
||||
a2: PrivateStruct(0),
|
||||
b: 0,
|
||||
b1: 0,
|
||||
b2: None,
|
||||
b3: 0,
|
||||
b4: None,
|
||||
c: 0,
|
||||
c1: 0,
|
||||
c2: None,
|
||||
c3: 0,
|
||||
c4: None,
|
||||
d: 0,
|
||||
};
|
||||
assert_eq!(e, e);
|
||||
|
||||
let e = Enum::Unit::<i32, i32, i32>;
|
||||
assert_eq!(e, e);
|
||||
}
|
34
tests/run-pass/enums.rs
Normal file
34
tests/run-pass/enums.rs
Normal file
@ -0,0 +1,34 @@
|
||||
enum MyEnum {
|
||||
MyEmptyVariant,
|
||||
MyNewtypeVariant(i32),
|
||||
MyTupleVariant(i32, i32),
|
||||
MyStructVariant {
|
||||
my_first_field: i32,
|
||||
my_second_field: i32,
|
||||
}
|
||||
}
|
||||
|
||||
fn test(me: MyEnum) {
|
||||
match me {
|
||||
MyEnum::MyEmptyVariant => {},
|
||||
MyEnum::MyNewtypeVariant(ref val) => assert_eq!(val, &42),
|
||||
MyEnum::MyTupleVariant(ref a, ref b) => {
|
||||
assert_eq!(a, &43);
|
||||
assert_eq!(b, &44);
|
||||
},
|
||||
MyEnum::MyStructVariant { ref my_first_field, ref my_second_field } => {
|
||||
assert_eq!(my_first_field, &45);
|
||||
assert_eq!(my_second_field, &46);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(MyEnum::MyEmptyVariant);
|
||||
test(MyEnum::MyNewtypeVariant(42));
|
||||
test(MyEnum::MyTupleVariant(43, 44));
|
||||
test(MyEnum::MyStructVariant{
|
||||
my_first_field: 45,
|
||||
my_second_field: 46,
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user