diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 2e3967021c1d..3a419ac9f59b 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -382,6 +382,7 @@ pub extern mod llvm { pub unsafe fn LLVMGetUsedValue(U: UseRef) -> ValueRef; /* Operations on Users */ + pub unsafe fn LLVMGetNumOperands(Val: ValueRef) -> c_int; pub unsafe fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef; pub unsafe fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef); diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 0176e5ab3204..5af62eda1fe4 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -285,15 +285,17 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { // call. Despite that being "a const", it's not the kind of // const you can ask for the integer-value of, evidently. This // might be an LLVM bug, not sure. In any case, to work around - // this we drop down to the array-type level here and just ask - // how long the array-type itself is, ignoring the length we - // pulled out of the slice. This in turn only works because we - // picked out the original globalvar via const_deref and so can - // recover the array-size of the underlying array, and all this - // will hold together exactly as long as we _don't_ support - // const sub-slices (that is, slices that represent something - // other than a whole array). At that point we'll have more and - // uglier work to do here, but for now this should work. + // this we obtain the initializer and count how many elements it + // has, ignoring the length we pulled out of the slice. (Note + // that the initializer might be a struct rather than an array, + // if enums are involved.) This only works because we picked out + // the original globalvar via const_deref and so can recover the + // array-size of the underlying array (or the element count of + // the underlying struct), and all this will hold together + // exactly as long as we _don't_ support const sub-slices (that + // is, slices that represent something other than a whole + // array). At that point we'll have more and uglier work to do + // here, but for now this should work. // // In the future, what we should be doing here is the // moral equivalent of: @@ -305,7 +307,7 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { // not want to consider sizeof() a constant expression // we can get the value (as a number) out of. - let len = llvm::LLVMGetArrayLength(val_ty(arr)) as u64; + let len = llvm::LLVMGetNumOperands(arr) as u64; let len = match ty::get(bt).sty { ty::ty_estr(*) => {assert len > 0; len - 1}, _ => len diff --git a/src/test/run-pass/const-enum-vec-index.rs b/src/test/run-pass/const-enum-vec-index.rs new file mode 100644 index 000000000000..b386bbf7f5e7 --- /dev/null +++ b/src/test/run-pass/const-enum-vec-index.rs @@ -0,0 +1,25 @@ +// 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. + +enum E { V1(int), V0 } +const C: &[E] = &[V0, V1(0xDEADBEE)]; +const C0: E = C[0]; +const C1: E = C[1]; + +fn main() { + match C0 { + V0 => (), + _ => die!() + } + match C1 { + V1(n) => assert(n == 0xDEADBEE), + _ => die!() + } +}