From 8fa306a0adb9ef3677bfad9bbd21bb620d4dc5b5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 30 Nov 2012 16:29:28 -0800 Subject: [PATCH] librustc: Implement tuple struct constants. r=brson --- src/librustc/middle/check_const.rs | 27 ++++++++++++++++++++----- src/librustc/middle/trans/consts.rs | 17 +++++++++++++++- src/test/run-pass/const-tuple-struct.rs | 13 ++++++++++++ 3 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/const-tuple-struct.rs diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 2348c79ce66b..77197a1db0d5 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -95,19 +95,36 @@ fn check_expr(sess: Session, def_map: resolve::DefMap, match def_map.find(e.id) { Some(def_const(def_id)) | Some(def_fn(def_id, _)) | - Some(def_variant(_, def_id)) => { + Some(def_variant(_, def_id)) | + Some(def_class(def_id)) => { if !ast_util::is_local(def_id) { sess.span_err( e.span, ~"paths in constants may only refer to \ - crate-local constants or functions"); + crate-local constants, functions, or \ + structs"); } } - _ => { + Some(def) => { + debug!("(checking const) found bad def: %?", def); sess.span_err( e.span, - ~"paths in constants may only refer to \ - constants or functions"); + fmt!("paths in constants may only refer to \ + constants or functions")); } + None => { + sess.span_bug(e.span, ~"unbound path in const?!"); + } + } + } + expr_call(callee, _, false) => { + match def_map.find(callee.id) { + Some(def_class(*)) => {} // OK. + _ => { + sess.span_err( + e.span, + ~"function calls in constants are limited to \ + structure constructors"); + } } } expr_paren(e) => { check_expr(sess, def_map, method_map, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 17282e91d160..e2466c1c4c65 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -416,7 +416,22 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { } } } - ast::expr_paren(e) => { return const_expr(cx, e); } + ast::expr_call(callee, args, _) => { + match cx.tcx.def_map.find(callee.id) { + Some(ast::def_class(def_id)) => { + let ety = ty::expr_ty(cx.tcx, e); + let llty = type_of::type_of(cx, ety); + let llstructbody = C_struct(args.map(|a| const_expr(cx, *a))); + if ty::ty_dtor(cx.tcx, def_id).is_present() { + C_named_struct(llty, ~[ llstructbody, C_u8(0) ]) + } else { + C_named_struct(llty, ~[ llstructbody ]) + } + } + _ => cx.sess.span_bug(e.span, ~"expected a struct def") + } + } + ast::expr_paren(e) => { return const_expr(cx, e); } _ => cx.sess.span_bug(e.span, ~"bad constant expression type in consts::const_expr") }; diff --git a/src/test/run-pass/const-tuple-struct.rs b/src/test/run-pass/const-tuple-struct.rs new file mode 100644 index 000000000000..d10d490740be --- /dev/null +++ b/src/test/run-pass/const-tuple-struct.rs @@ -0,0 +1,13 @@ +struct Bar(int, int); + +const X: Bar = Bar(1, 2); + +fn main() { + match X { + Bar(x, y) => { + assert x == 1; + assert y == 2; + } + } +} +