diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 7e313ca6965..f31ee2b07ae 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -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, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 853b3a3c28f..3b5cdc51c94 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -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) } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 470e05223db..51c47acff0e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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), diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs new file mode 100644 index 00000000000..adda356298d --- /dev/null +++ b/src/test/compile-fail/struct-base-wrong-type.rs @@ -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 or the MIT license +// , 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` +} diff --git a/src/test/run-pass/const-struct.rs b/src/test/run-pass/const-struct.rs index c62fcd8980f..684111c4917 100644 --- a/src/test/run-pass/const-struct.rs +++ b/src/test/run-pass/const-struct.rs @@ -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); }