fix enum variants with multiple fields
This commit is contained in:
parent
8c666b30ed
commit
c9914cd3ae
3 changed files with 251 additions and 8 deletions
|
@ -819,11 +819,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
Field(field, field_ty) => {
|
Field(field, field_ty) => {
|
||||||
let field_ty = self.monomorphize(field_ty, self.substs());
|
let field_ty = self.monomorphize(field_ty, self.substs());
|
||||||
use rustc::ty::layout::Layout::*;
|
use rustc::ty::layout::Layout::*;
|
||||||
let variant = match *base_layout {
|
let field = field.index();
|
||||||
Univariant { ref variant, .. } => variant,
|
let offset = match *base_layout {
|
||||||
|
Univariant { ref variant, .. } => variant.field_offset(field),
|
||||||
General { ref variants, .. } => {
|
General { ref variants, .. } => {
|
||||||
if let LvalueExtra::DowncastVariant(variant_idx) = base.extra {
|
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 {
|
} else {
|
||||||
bug!("field access on enum had no variant index");
|
bug!("field access on enum had no variant index");
|
||||||
}
|
}
|
||||||
|
@ -832,12 +834,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
assert_eq!(field.index(), 0);
|
assert_eq!(field.index(), 0);
|
||||||
return Ok(base);
|
return Ok(base);
|
||||||
}
|
}
|
||||||
StructWrappedNullablePointer { ref nonnull, .. } => nonnull,
|
StructWrappedNullablePointer { ref nonnull, .. } => nonnull.field_offset(field),
|
||||||
_ => bug!("field access on non-product type: {:?}", base_layout),
|
_ => bug!("field access on non-product type: {:?}", base_layout),
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = variant.field_offset(field.index()).bytes();
|
let ptr = base.ptr.offset(offset.bytes() as isize);
|
||||||
let ptr = base.ptr.offset(offset as isize);
|
|
||||||
if self.type_is_sized(field_ty) {
|
if self.type_is_sized(field_ty) {
|
||||||
ptr
|
ptr
|
||||||
} else {
|
} else {
|
||||||
|
@ -857,9 +858,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
Downcast(_, variant) => {
|
Downcast(_, variant) => {
|
||||||
use rustc::ty::layout::Layout::*;
|
use rustc::ty::layout::Layout::*;
|
||||||
match *base_layout {
|
match *base_layout {
|
||||||
General { ref variants, .. } => {
|
General { .. } => {
|
||||||
return Ok(Lvalue {
|
return Ok(Lvalue {
|
||||||
ptr: base.ptr.offset(variants[variant].field_offset(1).bytes() as isize),
|
ptr: base.ptr,
|
||||||
extra: LvalueExtra::DowncastVariant(variant),
|
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…
Add table
Add a link
Reference in a new issue