Skip to content

Commit 92e3a8c

Browse files
committed
rustc: reuse const vals, translate fn paths as consts. Close #2530.
1 parent b0ed151 commit 92e3a8c

File tree

6 files changed

+62
-43
lines changed

6 files changed

+62
-43
lines changed

src/libcore/condition.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,16 @@ struct Guard<T, U:Copy> {
9696
mod test {
9797

9898
fn sadness_key(_x: @Handler<int,int>) { }
99+
const sadness_condition : Condition<int,int> =
100+
Condition { key: sadness_key };
101+
99102
fn trouble(i: int) {
100-
// Condition should work as a const, just limitations in consts.
101-
let sadness_condition : Condition<int,int> =
102-
Condition { key: sadness_key };
103103
debug!("trouble: raising conition");
104104
let j = sadness_condition.raise(&i);
105105
debug!("trouble: handler recovered with %d", j);
106106
}
107107

108108
fn nested_trap_test_inner() {
109-
let sadness_condition : Condition<int,int> =
110-
Condition { key: sadness_key };
111109

112110
let mut inner_trapped = false;
113111

@@ -126,9 +124,6 @@ mod test {
126124
#[test]
127125
fn nested_trap_test_outer() {
128126

129-
let sadness_condition : Condition<int,int> =
130-
Condition { key: sadness_key };
131-
132127
let mut outer_trapped = false;
133128

134129
do sadness_condition.trap(|_j| {
@@ -144,8 +139,6 @@ mod test {
144139
}
145140

146141
fn nested_reraise_trap_test_inner() {
147-
let sadness_condition : Condition<int,int> =
148-
Condition { key: sadness_key };
149142

150143
let mut inner_trapped = false;
151144

@@ -166,9 +159,6 @@ mod test {
166159
#[test]
167160
fn nested_reraise_trap_test_outer() {
168161

169-
let sadness_condition : Condition<int,int> =
170-
Condition { key: sadness_key };
171-
172162
let mut outer_trapped = false;
173163

174164
do sadness_condition.trap(|_j| {
@@ -184,8 +174,6 @@ mod test {
184174

185175
#[test]
186176
fn test_default() {
187-
let sadness_condition : Condition<int,int> =
188-
Condition { key: sadness_key };
189177

190178
let mut trapped = false;
191179

src/rustc/middle/check_const.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,30 @@ fn check_expr(sess: Session, def_map: resolve::DefMap,
8282
~"` in a constant expression");
8383
}
8484
}
85-
expr_path(_) => {
85+
expr_path(pth) => {
86+
// NB: In the future you might wish to relax this slightly
87+
// to handle on-demand instantiation of functions via
88+
// foo::<bar> in a const. Currently that is only done on
89+
// a path in trans::callee that only works in block contexts.
90+
if pth.types.len() != 0 {
91+
sess.span_err(
92+
e.span, ~"paths in constants may only refer to \
93+
items without type parameters");
94+
}
8695
match def_map.find(e.id) {
87-
Some(def_const(def_id)) => {
96+
Some(def_const(def_id)) |
97+
Some(def_fn(def_id, _)) => {
8898
if !ast_util::is_local(def_id) {
8999
sess.span_err(
90100
e.span, ~"paths in constants may only refer to \
91-
crate-local constants");
101+
crate-local constants or functions");
92102
}
93103
}
94104
_ => {
95105
sess.span_err(
96106
e.span,
97-
~"paths in constants may only refer to constants");
107+
~"paths in constants may only refer to \
108+
constants or functions");
98109
}
99110
}
100111
}

src/rustc/middle/trans/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,6 +2688,7 @@ fn trans_crate(sess: session::Session,
26882688
vtables: map::HashMap(),
26892689
const_cstr_cache: HashMap(),
26902690
const_globals: HashMap(),
2691+
const_values: HashMap(),
26912692
module_data: HashMap(),
26922693
lltypes: ty::new_ty_hash(),
26932694
names: new_namegen(sess.parse_sess.interner),

src/rustc/middle/trans/common.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,19 @@ type crate_ctxt = {
140140
vtables: HashMap<mono_id, ValueRef>,
141141
// Cache of constant strings,
142142
const_cstr_cache: HashMap<~str, ValueRef>,
143-
// Reverse-direction for const ptrs cast from globals,
144-
// since the ptr -> init association is lost any
145-
// time a GlobalValue is cast.
143+
144+
// Reverse-direction for const ptrs cast from globals.
145+
// Key is an int, cast from a ValueRef holding a *T,
146+
// Val is a ValueRef holding a *[T].
147+
//
148+
// Needed because LLVM loses pointer->pointee association
149+
// when we ptrcast, and we have to ptrcast during translation
150+
// of a [T] const because we form a slice, a [*T,int] pair, not
151+
// a pointer to an LLVM array type.
146152
const_globals: HashMap<int, ValueRef>,
153+
154+
// Cache of emitted const values
155+
const_values: HashMap<ast::node_id, ValueRef>,
147156
module_data: HashMap<~str, ValueRef>,
148157
lltypes: HashMap<ty::t, TypeRef>,
149158
names: namegen,

src/rustc/middle/trans/consts.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
2828
}
2929
}
3030

31-
// FIXME (#2530): this should do some structural hash-consing to avoid
32-
// duplicate constants. I think. Maybe LLVM has a magical mode that does so
33-
// later on?
34-
3531
fn const_ptrcast(cx: @crate_ctxt, a: ValueRef, t: TypeRef) -> ValueRef {
3632
let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
3733
assert cx.const_globals.insert(b as int, a);
@@ -341,24 +337,29 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
341337
~"bad const-slice expr")
342338
}
343339
}
344-
ast::expr_path(_) => {
340+
ast::expr_path(pth) => {
341+
assert pth.types.len() == 0;
345342
match cx.tcx.def_map.find(e.id) {
343+
Some(ast::def_fn(def_id, _)) => {
344+
assert ast_util::is_local(def_id);
345+
let f = base::get_item_val(cx, def_id.node);
346+
C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
347+
}
346348
Some(ast::def_const(def_id)) => {
347-
// Don't know how to handle external consts
348349
assert ast_util::is_local(def_id);
349-
match cx.tcx.items.get(def_id.node) {
350-
ast_map::node_item(@{
351-
node: ast::item_const(_, subexpr), _
352-
}, _) => {
353-
// FIXME (#2530): Instead of recursing here to regenerate
354-
// the values for other constants, we should just look up
355-
// the already-defined value.
356-
const_expr(cx, subexpr)
357-
}
358-
_ => cx.sess.span_bug(e.span, ~"expected item")
350+
if ! cx.const_values.contains_key(def_id.node) {
351+
match cx.tcx.items.get(def_id.node) {
352+
ast_map::node_item(@{
353+
node: ast::item_const(_, subexpr), _
354+
}, _) => {
355+
trans_const(cx, subexpr, def_id.node);
356+
}
357+
_ => cx.sess.span_bug(e.span, ~"expected item")
358+
}
359359
}
360+
cx.const_values.get(def_id.node)
360361
}
361-
_ => cx.sess.span_bug(e.span, ~"expected to find a const def")
362+
_ => cx.sess.span_bug(e.span, ~"expected a const or fn def")
362363
}
363364
}
364365
ast::expr_paren(e) => { return const_expr(cx, e); }
@@ -369,11 +370,9 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
369370

370371
fn trans_const(ccx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
371372
let _icx = ccx.insn_ctxt("trans_const");
372-
let v = const_expr(ccx, e);
373-
374-
// The scalars come back as 1st class LLVM vals
375-
// which we have to stick into global constants.
376373
let g = base::get_item_val(ccx, id);
374+
let v = const_expr(ccx, e);
375+
ccx.const_values.insert(id, v);
377376
llvm::LLVMSetInitializer(g, v);
378377
llvm::LLVMSetGlobalConstant(g, True);
379378
}

src/test/run-pass/const-fn-val.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn foo() -> int {
2+
return 0xca7f000d;
3+
}
4+
5+
struct Bar { f: &fn() -> int }
6+
7+
const b : Bar = Bar { f: foo };
8+
9+
fn main() {
10+
assert (b.f)() == 0xca7f000d;
11+
}

0 commit comments

Comments
 (0)