Skip to content

Commit 27812ea

Browse files
committed
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`.
2 parents 52dbe13 + 1493141 commit 27812ea

File tree

5 files changed

+41
-6
lines changed

5 files changed

+41
-6
lines changed

src/librustc/middle/check_const.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub fn check_expr(sess: Session,
160160
expr_field(*) |
161161
expr_index(*) |
162162
expr_tup(*) |
163-
expr_struct(_, _, None) => { }
163+
expr_struct(*) => { }
164164
expr_addr_of(*) => {
165165
sess.span_err(
166166
e.span,

src/librustc/middle/trans/consts.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,20 +485,30 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
485485
let vals = es.map(|&e| const_expr(cx, e));
486486
adt::trans_const(cx, repr, 0, vals)
487487
}
488-
ast::expr_struct(_, ref fs, None) => {
488+
ast::expr_struct(_, ref fs, ref base_opt) => {
489489
let ety = ty::expr_ty(cx.tcx, e);
490490
let repr = adt::represent_type(cx, ety);
491491
let tcx = cx.tcx;
492+
493+
let base_val = match *base_opt {
494+
Some(base) => Some(const_expr(cx, base)),
495+
None => None
496+
};
497+
492498
do expr::with_field_tys(tcx, ety, Some(e.id))
493499
|discr, field_tys| {
494-
let cs = field_tys.map(|field_ty| {
500+
let cs: ~[ValueRef] = field_tys.iter().enumerate()
501+
.transform(|(ix, &field_ty)| {
495502
match fs.iter().find_(|f| field_ty.ident == f.ident) {
496503
Some(f) => const_expr(cx, (*f).expr),
497504
None => {
498-
cx.tcx.sess.span_bug(e.span, "missing struct field");
505+
match base_val {
506+
Some(bv) => adt::const_get_field(cx, repr, bv, discr, ix),
507+
None => cx.tcx.sess.span_bug(e.span, "missing struct field")
508+
}
499509
}
500510
}
501-
});
511+
}).collect();
502512
adt::trans_const(cx, repr, discr, cs)
503513
}
504514
}

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ pub enum expr_ {
498498
expr_mac(mac),
499499

500500
// A struct literal expression.
501-
expr_struct(Path, ~[Field], Option<@expr>),
501+
expr_struct(Path, ~[Field], Option<@expr> /* base */),
502502

503503
// A vector literal constructed from one repeated element.
504504
expr_repeat(@expr /* element */, @expr /* count */, mutability),
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo { a: int, b: int }
12+
struct Bar { x: int }
13+
14+
static bar: Bar = Bar { x: 5 };
15+
static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types: expected `Foo` but found `Bar`
16+
static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
17+
18+
fn main() {
19+
let b = Bar { x: 5 };
20+
let f = Foo { a: 2, ..b }; //~ ERROR mismatched types: expected `Foo` but found `Bar`
21+
let f_i = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
22+
}

src/test/run-pass/const-struct.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ impl cmp::Eq for foo {
2525
static x : foo = foo { a:1, b:2, c: 3 };
2626
static y : foo = foo { b:2, c:3, a: 1 };
2727
static z : &'static foo = &foo { a: 10, b: 22, c: 12 };
28+
static w : foo = foo { a:5, ..x };
2829

2930
pub fn main() {
3031
assert_eq!(x.b, 2);
3132
assert_eq!(x, y);
3233
assert_eq!(z.b, 22);
34+
assert_eq!(w.a, 5);
35+
assert_eq!(w.c, 3);
3336
printfln!("0x%x", x.b as uint);
3437
printfln!("0x%x", z.c as uint);
3538
}

0 commit comments

Comments
 (0)