auto merge of #8091 : kevinmehall/rust/const-struct-base, r=alexcrichton

With an expression like

    static w : foo = foo { a:5, ..x };

Rust currently gives the error "constant contains unimplemented expression type". This branch implements support for constant structs with `..base`.
This commit is contained in:
bors 2013-07-28 20:34:29 -07:00
commit 27812ea5e0
5 changed files with 41 additions and 6 deletions

View File

@ -160,7 +160,7 @@ pub fn check_expr(sess: Session,
expr_field(*) |
expr_index(*) |
expr_tup(*) |
expr_struct(_, _, None) => { }
expr_struct(*) => { }
expr_addr_of(*) => {
sess.span_err(
e.span,

View File

@ -485,20 +485,30 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
let vals = es.map(|&e| const_expr(cx, e));
adt::trans_const(cx, repr, 0, vals)
}
ast::expr_struct(_, ref fs, None) => {
ast::expr_struct(_, ref fs, ref base_opt) => {
let ety = ty::expr_ty(cx.tcx, e);
let repr = adt::represent_type(cx, ety);
let tcx = cx.tcx;
let base_val = match *base_opt {
Some(base) => Some(const_expr(cx, base)),
None => None
};
do expr::with_field_tys(tcx, ety, Some(e.id))
|discr, field_tys| {
let cs = field_tys.map(|field_ty| {
let cs: ~[ValueRef] = field_tys.iter().enumerate()
.transform(|(ix, &field_ty)| {
match fs.iter().find_(|f| field_ty.ident == f.ident) {
Some(f) => const_expr(cx, (*f).expr),
None => {
cx.tcx.sess.span_bug(e.span, "missing struct field");
match base_val {
Some(bv) => adt::const_get_field(cx, repr, bv, discr, ix),
None => cx.tcx.sess.span_bug(e.span, "missing struct field")
}
}
}
});
}).collect();
adt::trans_const(cx, repr, discr, cs)
}
}

View File

@ -498,7 +498,7 @@ pub enum expr_ {
expr_mac(mac),
// A struct literal expression.
expr_struct(Path, ~[Field], Option<@expr>),
expr_struct(Path, ~[Field], Option<@expr> /* base */),
// A vector literal constructed from one repeated element.
expr_repeat(@expr /* element */, @expr /* count */, mutability),

View File

@ -0,0 +1,22 @@
// Copyright 2013 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.
struct Foo { a: int, b: int }
struct Bar { x: int }
static bar: Bar = Bar { x: 5 };
static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types: expected `Foo` but found `Bar`
static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
fn main() {
let b = Bar { x: 5 };
let f = Foo { a: 2, ..b }; //~ ERROR mismatched types: expected `Foo` but found `Bar`
let f_i = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
}

View File

@ -25,11 +25,14 @@ impl cmp::Eq for foo {
static x : foo = foo { a:1, b:2, c: 3 };
static y : foo = foo { b:2, c:3, a: 1 };
static z : &'static foo = &foo { a: 10, b: 22, c: 12 };
static w : foo = foo { a:5, ..x };
pub fn main() {
assert_eq!(x.b, 2);
assert_eq!(x, y);
assert_eq!(z.b, 22);
assert_eq!(w.a, 5);
assert_eq!(w.c, 3);
printfln!("0x%x", x.b as uint);
printfln!("0x%x", z.c as uint);
}