about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-28 20:34:29 -0700
committerbors <bors@rust-lang.org>2013-07-28 20:34:29 -0700
commit27812ea5e025ed36dc80379b86bb249b33c528a2 (patch)
treed70ce8e8d3067076d66a4e6458cd6cfd1e439398 /src
parent52dbe138cfd462f443fe209bcab12de418786e45 (diff)
parent1493141bfdb478c42fb073ef6872540de3b125f0 (diff)
downloadrust-27812ea5e025ed36dc80379b86bb249b33c528a2.tar.gz
rust-27812ea5e025ed36dc80379b86bb249b33c528a2.zip
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`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/check_const.rs2
-rw-r--r--src/librustc/middle/trans/consts.rs18
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/test/compile-fail/struct-base-wrong-type.rs22
-rw-r--r--src/test/run-pass/const-struct.rs3
5 files changed, 41 insertions, 6 deletions
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 <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`
+}
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);
 }