auto merge of #5215 : jld/rust/fn-const-env, r=graydon

Fixes #5210; unblocks #5183.
This commit is contained in:
bors 2013-03-05 03:12:43 -08:00
commit 65986ba0c0
2 changed files with 60 additions and 5 deletions

View File

@ -20,6 +20,7 @@ use middle::trans::expr;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use util::ppaux::{expr_repr, ty_to_str};
use core::libc::c_uint;
use syntax::{ast, ast_util, codemap, ast_map};
@ -150,6 +151,24 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
}
pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
let ety = ty::expr_ty_adjusted(cx.tcx, e);
let llty = type_of::sizing_type_of(cx, ety);
let llconst = const_expr_unchecked(cx, e);
let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
let tsize = machine::llsize_of_alloc(cx, llty);
if csize != tsize {
unsafe {
llvm::LLVMDumpValue(llconst);
llvm::LLVMDumpValue(C_null(llty));
}
cx.sess.bug(fmt!("const %s of type %s has size %u instead of %u",
expr_repr(cx.tcx, e), ty_to_str(cx.tcx, ety),
csize, tsize));
}
llconst
}
fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
unsafe {
let _icx = cx.insn_ctxt("const_expr");
return match /*bad*/copy e.node {
@ -394,13 +413,22 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
ast::expr_path(pth) => {
assert pth.types.len() == 0;
match cx.tcx.def_map.find(&e.id) {
Some(ast::def_fn(def_id, purity)) => {
Some(ast::def_fn(def_id, _purity)) => {
assert ast_util::is_local(def_id);
let f = base::get_item_val(cx, def_id.node);
match purity {
ast::extern_fn =>
llvm::LLVMConstPointerCast(f, T_ptr(T_i8())),
_ => C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
let ety = ty::expr_ty_adjusted(cx.tcx, e);
match ty::get(ety).sty {
ty::ty_bare_fn(*) | ty::ty_ptr(*) => {
llvm::LLVMConstPointerCast(f, T_ptr(T_i8()))
}
ty::ty_closure(*) => {
C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
}
_ => {
cx.sess.span_bug(e.span, fmt!(
"unexpected const fn type: %s",
ty_to_str(cx.tcx, ety)))
}
}
}
Some(ast::def_const(def_id)) => {

View File

@ -0,0 +1,27 @@
// 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.
/*!
* Try to double-check that const fns have the right size (with or
* without dummy env ptr, as appropriate) by iterating a size-2 array.
* If the const size differs from the runtime size, the second element
* should be read as a null or otherwise wrong pointer and crash.
*/
fn f() { }
const bare_fns: &[extern fn()] = &[f, f];
// NOTE Why does this not type without the struct?
struct S(&fn());
const closures: &[S] = &[S(f), S(f)];
pub fn main() {
for bare_fns.each |&bare_fn| { bare_fn() }
for closures.each |&closure| { (*closure)() }
}