about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/rustc/middle/check_const.rs1
-rw-r--r--src/rustc/middle/const_eval.rs1
-rw-r--r--src/rustc/middle/trans/consts.rs26
-rw-r--r--src/test/run-pass/const-struct.rs14
4 files changed, 42 insertions, 0 deletions
diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs
index 0cddd359b55..e8f3ecb35ac 100644
--- a/src/rustc/middle/check_const.rs
+++ b/src/rustc/middle/check_const.rs
@@ -103,6 +103,7 @@ fn check_expr(sess: session, def_map: resolve3::DefMap,
           expr_vec(_, m_imm) |
           expr_addr_of(m_imm, _) |
           expr_tup(*) |
+          expr_struct(*) |
           expr_rec(*) => { }
           expr_addr_of(*) => {
                 sess.span_err(
diff --git a/src/rustc/middle/const_eval.rs b/src/rustc/middle/const_eval.rs
index e15ef586042..01b07d2b34e 100644
--- a/src/rustc/middle/const_eval.rs
+++ b/src/rustc/middle/const_eval.rs
@@ -95,6 +95,7 @@ fn classify(e: @expr,
                 }
               }
 
+              ast::expr_struct(_, fs, none) |
               ast::expr_rec(fs, none) => {
                 let cs = do vec::map(fs) |f| {
                     if f.node.mutbl == ast::m_imm {
diff --git a/src/rustc/middle/trans/consts.rs b/src/rustc/middle/trans/consts.rs
index 3f17352b915..f4c67efdd77 100644
--- a/src/rustc/middle/trans/consts.rs
+++ b/src/rustc/middle/trans/consts.rs
@@ -153,6 +153,32 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
       ast::expr_tup(es) => {
         C_struct(es.map(|e| const_expr(cx, e)))
       }
+      ast::expr_struct(_, fs, _) => {
+          let ety = ty::expr_ty(cx.tcx, e);
+          let llty = type_of::type_of(cx, ety);
+          let class_fields =
+              match ty::get(ety).struct {
+              ty::ty_class(clsid, _) =>
+                  ty::lookup_class_fields(cx.tcx, clsid),
+              _ =>
+                  cx.tcx.sess.span_bug(e.span,
+                                       ~"didn't resolve to a struct")
+          };
+          let mut cs = ~[];
+          for class_fields.each |class_field| {
+              let mut found = false;
+              for fs.each |field| {
+                  if class_field.ident == field.node.ident  {
+                      found = true;
+                      vec::push(cs, const_expr(cx, field.node.expr));
+                  }
+              }
+              if !found {
+                  cx.tcx.sess.span_bug(e.span, ~"missing struct field");
+              }
+          }
+          C_named_struct(llty, cs)
+      }
       ast::expr_rec(fs, none) => {
         C_struct(fs.map(|f| const_expr(cx, f.node.expr)))
       }
diff --git a/src/test/run-pass/const-struct.rs b/src/test/run-pass/const-struct.rs
new file mode 100644
index 00000000000..132ecb935cf
--- /dev/null
+++ b/src/test/run-pass/const-struct.rs
@@ -0,0 +1,14 @@
+
+struct foo { a: int; b: int; c: int; }
+
+const x : foo = foo { a:1, b:2, c: 3 };
+const y : foo = foo { b:2, c:3, a: 1 };
+const z : &foo = &foo { a: 10, b: 22, c: 12 };
+
+fn main() {
+    assert x.b == 2;
+    assert x == y;
+    assert z.b == 22;
+    io::println(fmt!{"0x%x", x.b as uint});
+    io::println(fmt!{"0x%x", z.c as uint});
+}