Skip to content

Commit 7140d7c

Browse files
committed
auto merge of #5227 : jdm/rust/newconst, r=pcwalton
All comments from previous pull requests addressed.
2 parents 2bc301f + 27668fb commit 7140d7c

14 files changed

+293
-29
lines changed

src/librustc/metadata/encoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
616616
let must_write =
617617
match item.node {
618618
item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) |
619-
item_mod(*) | item_foreign_mod(*) => true,
619+
item_mod(*) | item_foreign_mod(*) | item_const(*) => true,
620620
_ => false
621621
};
622622
if !must_write && !reachable(ecx, item.id) { return; }
@@ -639,6 +639,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
639639
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
640640
encode_symbol(ecx, ebml_w, item.id);
641641
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
642+
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
642643
ebml_w.end_tag();
643644
}
644645
item_fn(_, purity, ref generics, _) => {

src/librustc/middle/check_const.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub fn check_expr(sess: Session,
107107
expr_lit(_) => (),
108108
expr_cast(_, _) => {
109109
let ety = ty::expr_ty(tcx, e);
110-
if !ty::type_is_numeric(ety) {
110+
if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
111111
sess.span_err(e.span, ~"can not cast to `" +
112112
ppaux::ty_to_str(tcx, ety) +
113113
~"` in a constant expression");
@@ -124,17 +124,11 @@ pub fn check_expr(sess: Session,
124124
items without type parameters");
125125
}
126126
match def_map.find(&e.id) {
127-
Some(def_variant(_, _)) |
128-
Some(def_struct(_)) => { }
127+
Some(def_const(_)) |
128+
Some(def_fn(_, _)) |
129+
Some(def_variant(_, _)) |
130+
Some(def_struct(_)) => { }
129131

130-
Some(def_const(def_id)) |
131-
Some(def_fn(def_id, _)) => {
132-
if !ast_util::is_local(def_id) {
133-
sess.span_err(
134-
e.span, ~"paths in constants may only refer to \
135-
crate-local constants or functions");
136-
}
137-
}
138132
Some(def) => {
139133
debug!("(checking const) found bad def: %?", def);
140134
sess.span_err(
@@ -246,11 +240,13 @@ pub fn check_item_recursion(sess: Session,
246240
expr_path(*) => {
247241
match env.def_map.find(&e.id) {
248242
Some(def_const(def_id)) => {
249-
match env.ast_map.get(&def_id.node) {
250-
ast_map::node_item(it, _) => {
251-
(v.visit_item)(it, env, v);
243+
if ast_util::is_local(def_id) {
244+
match env.ast_map.get(&def_id.node) {
245+
ast_map::node_item(it, _) => {
246+
(v.visit_item)(it, env, v);
247+
}
248+
_ => fail!(~"const not bound to an item")
252249
}
253-
_ => fail!(~"const not bound to an item")
254250
}
255251
}
256252
_ => ()

src/librustc/middle/trans/consts.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
use core::prelude::*;
1212

1313
use lib::llvm::{llvm, ValueRef, TypeRef, Bool, True, False};
14+
use metadata::csearch;
1415
use middle::const_eval;
1516
use middle::trans::adt;
1617
use middle::trans::base;
1718
use middle::trans::base::get_insn_ctxt;
1819
use middle::trans::common::*;
1920
use middle::trans::consts;
2021
use middle::trans::expr;
22+
use middle::trans::inline;
2123
use middle::trans::machine;
2224
use middle::trans::type_of;
2325
use middle::ty;
@@ -110,7 +112,7 @@ pub fn const_autoderef(cx: @CrateContext, ty: ty::t, v: ValueRef)
110112
let mut v1 = v;
111113
loop {
112114
// Only rptrs can be autoderef'ed in a const context.
113-
match ty::get(ty).sty {
115+
match ty::get(t1).sty {
114116
ty::ty_rptr(_, mt) => {
115117
t1 = mt.ty;
116118
v1 = const_deref(cx, v1);
@@ -121,10 +123,12 @@ pub fn const_autoderef(cx: @CrateContext, ty: ty::t, v: ValueRef)
121123
}
122124

123125
pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
124-
if !ast_util::is_local(def_id) {
125-
cx.tcx.sess.bug(~"cross-crate constants");
126-
}
127-
if !cx.const_values.contains_key(&def_id.node) {
126+
let mut def_id = def_id;
127+
if !ast_util::is_local(def_id) ||
128+
!cx.const_values.contains_key(&def_id.node) {
129+
if !ast_util::is_local(def_id) {
130+
def_id = inline::maybe_instantiate_inline(cx, def_id, true);
131+
}
128132
match cx.tcx.items.get(&def_id.node) {
129133
ast_map::node_item(@ast::item {
130134
node: ast::item_const(_, subexpr), _
@@ -338,6 +342,12 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
338342
integral or float")
339343
}
340344
}
345+
(expr::cast_pointer, expr::cast_pointer) => {
346+
llvm::LLVMConstPointerCast(v, llty)
347+
}
348+
(expr::cast_integral, expr::cast_pointer) => {
349+
llvm::LLVMConstIntToPtr(v, llty)
350+
}
341351
_ => {
342352
cx.sess.impossible_case(e.span,
343353
~"bad combination of types for cast")
@@ -416,8 +426,13 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
416426
assert pth.types.len() == 0;
417427
match cx.tcx.def_map.find(&e.id) {
418428
Some(ast::def_fn(def_id, _purity)) => {
419-
assert ast_util::is_local(def_id);
420-
let f = base::get_item_val(cx, def_id.node);
429+
let f = if !ast_util::is_local(def_id) {
430+
let ty = csearch::get_type(cx.tcx, def_id).ty;
431+
base::trans_external_path(cx, def_id, ty)
432+
} else {
433+
assert ast_util::is_local(def_id);
434+
base::get_item_val(cx, def_id.node)
435+
};
421436
let ety = ty::expr_ty_adjusted(cx.tcx, e);
422437
match ty::get(ety).sty {
423438
ty::ty_bare_fn(*) | ty::ty_ptr(*) => {

src/librustc/middle/trans/expr.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ use middle::trans::consts;
138138
use middle::trans::controlflow;
139139
use middle::trans::datum::*;
140140
use middle::trans::debuginfo;
141+
use middle::trans::inline;
141142
use middle::trans::machine;
142143
use middle::trans::meth;
143144
use middle::trans::tvec;
@@ -984,15 +985,54 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
984985
match def {
985986
ast::def_const(did) => {
986987
let const_ty = expr_ty(bcx, ref_expr);
987-
let val = if did.crate == ast::local_crate {
988+
989+
#[cfg(stage0)]
990+
fn get_did(_ccx: @CrateContext, did: ast::def_id)
991+
-> ast::def_id {
992+
did
993+
}
994+
995+
#[cfg(stage1)]
996+
#[cfg(stage2)]
997+
#[cfg(stage3)]
998+
fn get_did(ccx: @CrateContext, did: ast::def_id)
999+
-> ast::def_id {
1000+
if did.crate != ast::local_crate {
1001+
inline::maybe_instantiate_inline(ccx, did, true)
1002+
} else {
1003+
did
1004+
}
1005+
}
1006+
1007+
#[cfg(stage0)]
1008+
fn get_val(bcx: block, did: ast::def_id, const_ty: ty::t)
1009+
-> ValueRef {
1010+
let ccx = bcx.ccx();
1011+
if did.crate == ast::local_crate {
1012+
// The LLVM global has the type of its initializer,
1013+
// which may not be equal to the enum's type for
1014+
// non-C-like enums.
1015+
PointerCast(bcx, base::get_item_val(ccx, did.node),
1016+
T_ptr(type_of(bcx.ccx(), const_ty)))
1017+
} else {
1018+
base::trans_external_path(ccx, did, const_ty)
1019+
}
1020+
}
1021+
1022+
#[cfg(stage1)]
1023+
#[cfg(stage2)]
1024+
#[cfg(stage3)]
1025+
fn get_val(bcx: block, did: ast::def_id, const_ty: ty::t)
1026+
-> ValueRef {
9881027
// The LLVM global has the type of its initializer,
9891028
// which may not be equal to the enum's type for
9901029
// non-C-like enums.
991-
PointerCast(bcx, base::get_item_val(ccx, did.node),
1030+
PointerCast(bcx, base::get_item_val(bcx.ccx(), did.node),
9921031
T_ptr(type_of(bcx.ccx(), const_ty)))
993-
} else {
994-
base::trans_external_path(ccx, did, const_ty)
995-
};
1032+
}
1033+
1034+
let did = get_did(ccx, did);
1035+
let val = get_val(bcx, did, const_ty);
9961036
DatumBlock {
9971037
bcx: bcx,
9981038
datum: Datum {val: val,

src/librustc/middle/typeck/check/mod.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ use middle::typeck::check::method::TransformTypeNormally;
9393
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
9494
use middle::typeck::check::vtable::{LocationInfo, VtableContext};
9595
use middle::typeck::CrateCtxt;
96-
use middle::typeck::infer::{resolve_type, force_tvar};
96+
use middle::typeck::infer::{resolve_type, force_tvar, mk_eqty};
9797
use middle::typeck::infer;
9898
use middle::typeck::rscope::{binding_rscope, bound_self_region};
9999
use middle::typeck::rscope::{RegionError};
@@ -2452,6 +2452,44 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
24522452
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
24532453
if type_is_c_like_enum(fcx,expr.span,t_e) && t_1_is_scalar {
24542454
/* this case is allowed */
2455+
} else if type_is_region_ptr(fcx, expr.span, t_e) &&
2456+
type_is_unsafe_ptr(fcx, expr.span, t_1) {
2457+
2458+
fn is_vec(t: ty::t) -> bool {
2459+
match ty::get(t).sty {
2460+
ty::ty_evec(_,_) => true,
2461+
_ => false
2462+
}
2463+
}
2464+
fn types_compatible(fcx: @mut FnCtxt, sp: span, t1: ty::t,
2465+
t2: ty::t) -> bool {
2466+
if !is_vec(t1) {
2467+
false
2468+
} else {
2469+
let el = ty::sequence_element_type(fcx.tcx(), t1);
2470+
infer::mk_eqty(fcx.infcx(), false, sp, el, t2).is_ok()
2471+
}
2472+
}
2473+
2474+
// Due to the limitations of LLVM global constants,
2475+
// region pointers end up pointing at copies of
2476+
// vector elements instead of the original values.
2477+
// To allow unsafe pointers to work correctly, we
2478+
// need to special-case obtaining an unsafe pointer
2479+
// from a region pointer to a vector.
2480+
2481+
/* this cast is only allowed from &[T] to *T or
2482+
&T to *T. */
2483+
let te = structurally_resolved_type(fcx, e.span, t_e);
2484+
match (&ty::get(te).sty, &ty::get(t_1).sty) {
2485+
(&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
2486+
if types_compatible(fcx, e.span, mt1.ty, mt2.ty) => {
2487+
/* this case is allowed */
2488+
}
2489+
_ => {
2490+
demand::coerce(fcx, e.span, t_1, e);
2491+
}
2492+
}
24552493
} else if !(type_is_scalar(fcx,expr.span,t_e) && t_1_is_scalar) {
24562494
/*
24572495
If more type combinations should be supported than are
@@ -3081,6 +3119,16 @@ pub fn type_is_scalar(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
30813119
return ty::type_is_scalar(typ_s);
30823120
}
30833121

3122+
pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
3123+
let typ_s = structurally_resolved_type(fcx, sp, typ);
3124+
return ty::type_is_unsafe_ptr(typ_s);
3125+
}
3126+
3127+
pub fn type_is_region_ptr(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
3128+
let typ_s = structurally_resolved_type(fcx, sp, typ);
3129+
return ty::type_is_region_ptr(typ_s);
3130+
}
3131+
30843132
pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
30853133
let typ_s = structurally_resolved_type(fcx, sp, typ);
30863134
return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);

src/test/auxiliary/cci_const.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub extern fn bar() {
12+
}
13+
14+
pub const foopy: &static/str = "hi there";
15+
pub const uint_val: uint = 12;
16+
pub const uint_expr: uint = (1 << uint_val) - 1;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
let foo = ['h' as u8, 'i' as u8, 0 as u8];
13+
let bar = &foo as *u8; //~ ERROR mismatched types
14+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
const a: &static/str = &"foo";
12+
const b: *u8 = a as *u8; //~ ERROR non-scalar cast
13+
const c: *u8 = &a as *u8; //~ ERROR mismatched types
14+
15+
fn main() {
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
const a: [u8 * 3] = ['h' as u8, 'i' as u8, 0 as u8];
12+
const b: *i8 = &a as *i8; //~ ERROR mismatched types
13+
14+
fn main() {
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
const a: *u8 = 0 as *u8;
12+
13+
fn main() {
14+
assert a == ptr::null();
15+
}

src/test/run-pass/const-cast.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern fn foo() {}
12+
13+
const x: *u8 = foo;
14+
const y: *libc::c_void = x as *libc::c_void;
15+
const a: &static/int = &10;
16+
const b: *int = a as *int;
17+
18+
fn main() {
19+
assert x as *libc::c_void == y;
20+
assert a as *int == b;
21+
}

0 commit comments

Comments
 (0)