about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/encoder.rs3
-rw-r--r--src/librustc/middle/check_const.rs26
-rw-r--r--src/librustc/middle/trans/consts.rs29
-rw-r--r--src/librustc/middle/trans/expr.rs50
-rw-r--r--src/librustc/middle/typeck/check/mod.rs50
-rw-r--r--src/test/auxiliary/cci_const.rs16
-rw-r--r--src/test/compile-fail/cast-vector-to-unsafe-nonstatic.rs14
-rw-r--r--src/test/compile-fail/const-cast-different-types.rs16
-rw-r--r--src/test/compile-fail/const-cast-wrong-type.rs15
-rw-r--r--src/test/run-pass/const-cast-ptr-int.rs15
-rw-r--r--src/test/run-pass/const-cast.rs21
-rw-r--r--src/test/run-pass/const-cross-crate-const.rs25
-rw-r--r--src/test/run-pass/const-cross-crate-extern.rs20
-rw-r--r--src/test/run-pass/const-str-ptr.rs22
14 files changed, 293 insertions, 29 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 3d81b01a0c9..67d25637093 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -616,7 +616,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
     let must_write =
         match item.node {
           item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) |
-          item_mod(*) | item_foreign_mod(*) => true,
+          item_mod(*) | item_foreign_mod(*) | item_const(*) => true,
           _ => false
         };
     if !must_write && !reachable(ecx, item.id) { return; }
@@ -639,6 +639,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+        (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
         ebml_w.end_tag();
       }
       item_fn(_, purity, ref generics, _) => {
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index c00856a0a98..58099574126 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -107,7 +107,7 @@ pub fn check_expr(sess: Session,
           expr_lit(_) => (),
           expr_cast(_, _) => {
             let ety = ty::expr_ty(tcx, e);
-            if !ty::type_is_numeric(ety) {
+            if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
                 sess.span_err(e.span, ~"can not cast to `" +
                               ppaux::ty_to_str(tcx, ety) +
                               ~"` in a constant expression");
@@ -124,17 +124,11 @@ pub fn check_expr(sess: Session,
                               items without type parameters");
             }
             match def_map.find(&e.id) {
-                Some(def_variant(_, _)) |
-                Some(def_struct(_)) => { }
+              Some(def_const(_)) |
+              Some(def_fn(_, _)) |
+              Some(def_variant(_, _)) |
+              Some(def_struct(_)) => { }
 
-                Some(def_const(def_id)) |
-                Some(def_fn(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");
-                }
-              }
               Some(def) => {
                 debug!("(checking const) found bad def: %?", def);
                 sess.span_err(
@@ -246,11 +240,13 @@ pub fn check_item_recursion(sess: Session,
           expr_path(*) => {
             match env.def_map.find(&e.id) {
               Some(def_const(def_id)) => {
-                match env.ast_map.get(&def_id.node) {
-                  ast_map::node_item(it, _) => {
-                    (v.visit_item)(it, env, v);
+                if ast_util::is_local(def_id) {
+                  match env.ast_map.get(&def_id.node) {
+                    ast_map::node_item(it, _) => {
+                      (v.visit_item)(it, env, v);
+                    }
+                    _ => fail!(~"const not bound to an item")
                   }
-                  _ => fail!(~"const not bound to an item")
                 }
               }
               _ => ()
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index d19ffe8cb21..b7a536aa3a2 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -11,6 +11,7 @@
 use core::prelude::*;
 
 use lib::llvm::{llvm, ValueRef, TypeRef, Bool, True, False};
+use metadata::csearch;
 use middle::const_eval;
 use middle::trans::adt;
 use middle::trans::base;
@@ -18,6 +19,7 @@ use middle::trans::base::get_insn_ctxt;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::expr;
+use middle::trans::inline;
 use middle::trans::machine;
 use middle::trans::type_of;
 use middle::ty;
@@ -110,7 +112,7 @@ pub fn const_autoderef(cx: @CrateContext, ty: ty::t, v: ValueRef)
     let mut v1 = v;
     loop {
         // Only rptrs can be autoderef'ed in a const context.
-        match ty::get(ty).sty {
+        match ty::get(t1).sty {
             ty::ty_rptr(_, mt) => {
                 t1 = mt.ty;
                 v1 = const_deref(cx, v1);
@@ -121,10 +123,12 @@ pub fn const_autoderef(cx: @CrateContext, ty: ty::t, v: ValueRef)
 }
 
 pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef {
-    if !ast_util::is_local(def_id) {
-        cx.tcx.sess.bug(~"cross-crate constants");
-    }
-    if !cx.const_values.contains_key(&def_id.node) {
+    let mut def_id = def_id;
+    if !ast_util::is_local(def_id) ||
+       !cx.const_values.contains_key(&def_id.node) {
+        if !ast_util::is_local(def_id) {
+            def_id = inline::maybe_instantiate_inline(cx, def_id, true);
+        }
         match cx.tcx.items.get(&def_id.node) {
             ast_map::node_item(@ast::item {
                 node: ast::item_const(_, subexpr), _
@@ -338,6 +342,12 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
                                        integral or float")
                 }
               }
+              (expr::cast_pointer, expr::cast_pointer) => {
+                llvm::LLVMConstPointerCast(v, llty)
+              }
+              (expr::cast_integral, expr::cast_pointer) => {
+                llvm::LLVMConstIntToPtr(v, llty)
+              }
               _ => {
                 cx.sess.impossible_case(e.span,
                                         ~"bad combination of types for cast")
@@ -416,8 +426,13 @@ fn const_expr_unchecked(cx: @CrateContext, e: @ast::expr) -> ValueRef {
             assert pth.types.len() == 0;
             match cx.tcx.def_map.find(&e.id) {
                 Some(ast::def_fn(def_id, _purity)) => {
-                    assert ast_util::is_local(def_id);
-                    let f = base::get_item_val(cx, def_id.node);
+                    let f = if !ast_util::is_local(def_id) {
+                        let ty = csearch::get_type(cx.tcx, def_id).ty;
+                        base::trans_external_path(cx, def_id, ty)
+                    } else {
+                        assert ast_util::is_local(def_id);
+                        base::get_item_val(cx, def_id.node)
+                    };
                     let ety = ty::expr_ty_adjusted(cx.tcx, e);
                     match ty::get(ety).sty {
                         ty::ty_bare_fn(*) | ty::ty_ptr(*) => {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 1dae9fccc62..5fb07d6e7d8 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -138,6 +138,7 @@ use middle::trans::consts;
 use middle::trans::controlflow;
 use middle::trans::datum::*;
 use middle::trans::debuginfo;
+use middle::trans::inline;
 use middle::trans::machine;
 use middle::trans::meth;
 use middle::trans::tvec;
@@ -984,15 +985,54 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
         match def {
             ast::def_const(did) => {
                 let const_ty = expr_ty(bcx, ref_expr);
-                let val = if did.crate == ast::local_crate {
+
+                #[cfg(stage0)]
+                fn get_did(_ccx: @CrateContext, did: ast::def_id)
+                    -> ast::def_id {
+                    did
+                }
+
+                #[cfg(stage1)]
+                #[cfg(stage2)]
+                #[cfg(stage3)]
+                fn get_did(ccx: @CrateContext, did: ast::def_id)
+                    -> ast::def_id {
+                    if did.crate != ast::local_crate {
+                        inline::maybe_instantiate_inline(ccx, did, true)
+                    } else {
+                        did
+                    }
+                }
+
+                #[cfg(stage0)]
+                fn get_val(bcx: block, did: ast::def_id, const_ty: ty::t)
+                    -> ValueRef {
+                    let ccx = bcx.ccx();
+                    if did.crate == ast::local_crate {
+                        // The LLVM global has the type of its initializer,
+                        // which may not be equal to the enum's type for
+                        // non-C-like enums.
+                        PointerCast(bcx, base::get_item_val(ccx, did.node),
+                                    T_ptr(type_of(bcx.ccx(), const_ty)))
+                    } else {
+                        base::trans_external_path(ccx, did, const_ty)
+                    }
+                }
+
+                #[cfg(stage1)]
+                #[cfg(stage2)]
+                #[cfg(stage3)]
+                fn get_val(bcx: block, did: ast::def_id, const_ty: ty::t)
+                    -> ValueRef {
                     // The LLVM global has the type of its initializer,
                     // which may not be equal to the enum's type for
                     // non-C-like enums.
-                    PointerCast(bcx, base::get_item_val(ccx, did.node),
+                    PointerCast(bcx, base::get_item_val(bcx.ccx(), did.node),
                                 T_ptr(type_of(bcx.ccx(), const_ty)))
-                } else {
-                    base::trans_external_path(ccx, did, const_ty)
-                };
+                }
+
+                let did = get_did(ccx, did);
+                let val = get_val(bcx, did, const_ty);
                 DatumBlock {
                     bcx: bcx,
                     datum: Datum {val: val,
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 66c2a28da3d..80b13341e54 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -93,7 +93,7 @@ use middle::typeck::check::method::TransformTypeNormally;
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
 use middle::typeck::check::vtable::{LocationInfo, VtableContext};
 use middle::typeck::CrateCtxt;
-use middle::typeck::infer::{resolve_type, force_tvar};
+use middle::typeck::infer::{resolve_type, force_tvar, mk_eqty};
 use middle::typeck::infer;
 use middle::typeck::rscope::{binding_rscope, bound_self_region};
 use middle::typeck::rscope::{RegionError};
@@ -2452,6 +2452,44 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
             if type_is_c_like_enum(fcx,expr.span,t_e) && t_1_is_scalar {
                 /* this case is allowed */
+            } else if type_is_region_ptr(fcx, expr.span, t_e) &&
+                      type_is_unsafe_ptr(fcx, expr.span, t_1) {
+
+                fn is_vec(t: ty::t) -> bool {
+                    match ty::get(t).sty {
+                      ty::ty_evec(_,_) => true,
+                      _ => false
+                    }
+                }
+                fn types_compatible(fcx: @mut FnCtxt, sp: span, t1: ty::t,
+                                    t2: ty::t) -> bool {
+                    if !is_vec(t1) {
+                        false
+                    } else {
+                        let el = ty::sequence_element_type(fcx.tcx(), t1);
+                        infer::mk_eqty(fcx.infcx(), false, sp, el, t2).is_ok()
+                    }
+                }
+
+                // Due to the limitations of LLVM global constants,
+                // region pointers end up pointing at copies of
+                // vector elements instead of the original values.
+                // To allow unsafe pointers to work correctly, we
+                // need to special-case obtaining an unsafe pointer
+                // from a region pointer to a vector.
+
+                /* this cast is only allowed from &[T] to *T or
+                   &T to *T. */
+                let te = structurally_resolved_type(fcx, e.span, t_e);
+                match (&ty::get(te).sty, &ty::get(t_1).sty) {
+                  (&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
+                    if types_compatible(fcx, e.span, mt1.ty, mt2.ty) => {
+                      /* this case is allowed */
+                  }
+                  _ => {
+                    demand::coerce(fcx, e.span, t_1, e);
+                  }
+                }
             } else if !(type_is_scalar(fcx,expr.span,t_e) && t_1_is_scalar) {
                 /*
                 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 {
     return ty::type_is_scalar(typ_s);
 }
 
+pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_unsafe_ptr(typ_s);
+}
+
+pub fn type_is_region_ptr(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    return ty::type_is_region_ptr(typ_s);
+}
+
 pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
diff --git a/src/test/auxiliary/cci_const.rs b/src/test/auxiliary/cci_const.rs
new file mode 100644
index 00000000000..b2dd0cc8e58
--- /dev/null
+++ b/src/test/auxiliary/cci_const.rs
@@ -0,0 +1,16 @@
+// 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.
+
+pub extern fn bar() {
+}
+
+pub const foopy: &static/str = "hi there";
+pub const uint_val: uint = 12;
+pub const uint_expr: uint = (1 << uint_val) - 1;
diff --git a/src/test/compile-fail/cast-vector-to-unsafe-nonstatic.rs b/src/test/compile-fail/cast-vector-to-unsafe-nonstatic.rs
new file mode 100644
index 00000000000..a083757a0eb
--- /dev/null
+++ b/src/test/compile-fail/cast-vector-to-unsafe-nonstatic.rs
@@ -0,0 +1,14 @@
+// Copyright 2012 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.
+
+fn main() {
+    let foo = ['h' as u8, 'i' as u8, 0 as u8];
+    let bar = &foo as *u8; //~ ERROR mismatched types
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/const-cast-different-types.rs b/src/test/compile-fail/const-cast-different-types.rs
new file mode 100644
index 00000000000..08fa6915106
--- /dev/null
+++ b/src/test/compile-fail/const-cast-different-types.rs
@@ -0,0 +1,16 @@
+// Copyright 2012 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.
+
+const a: &static/str = &"foo";
+const b: *u8 = a as *u8; //~ ERROR non-scalar cast
+const c: *u8 = &a as *u8; //~ ERROR mismatched types
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/const-cast-wrong-type.rs b/src/test/compile-fail/const-cast-wrong-type.rs
new file mode 100644
index 00000000000..fe91056d47b
--- /dev/null
+++ b/src/test/compile-fail/const-cast-wrong-type.rs
@@ -0,0 +1,15 @@
+// Copyright 2012 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.
+
+const a: [u8 * 3] = ['h' as u8, 'i' as u8, 0 as u8];
+const b: *i8 = &a as *i8; //~ ERROR mismatched types
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/const-cast-ptr-int.rs b/src/test/run-pass/const-cast-ptr-int.rs
new file mode 100644
index 00000000000..559e11efcff
--- /dev/null
+++ b/src/test/run-pass/const-cast-ptr-int.rs
@@ -0,0 +1,15 @@
+// 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.
+
+const a: *u8 = 0 as *u8;
+
+fn main() {
+    assert a == ptr::null();
+}
\ No newline at end of file
diff --git a/src/test/run-pass/const-cast.rs b/src/test/run-pass/const-cast.rs
new file mode 100644
index 00000000000..9174b45d100
--- /dev/null
+++ b/src/test/run-pass/const-cast.rs
@@ -0,0 +1,21 @@
+// Copyright 2012 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.
+
+extern fn foo() {}
+
+const x: *u8 = foo;
+const y: *libc::c_void = x as *libc::c_void;
+const a: &static/int = &10;
+const b: *int = a as *int;
+
+fn main() {
+    assert x as *libc::c_void == y;
+    assert a as *int == b;
+}
\ No newline at end of file
diff --git a/src/test/run-pass/const-cross-crate-const.rs b/src/test/run-pass/const-cross-crate-const.rs
new file mode 100644
index 00000000000..eb3c482737c
--- /dev/null
+++ b/src/test/run-pass/const-cross-crate-const.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 <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.
+
+// xfail-fast
+// aux-build:cci_const.rs
+
+extern mod cci_const;
+const foo: &static/str = cci_const::foopy;
+const a: uint = cci_const::uint_val;
+const b: uint = cci_const::uint_expr + 5;
+
+fn main() {
+    assert a == 12;
+    let foo2 = a;
+    assert foo2 == cci_const::uint_val;
+    assert b == cci_const::uint_expr + 5;
+    assert foo == cci_const::foopy;
+}
diff --git a/src/test/run-pass/const-cross-crate-extern.rs b/src/test/run-pass/const-cross-crate-extern.rs
new file mode 100644
index 00000000000..e86118f3c43
--- /dev/null
+++ b/src/test/run-pass/const-cross-crate-extern.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// xfail-fast
+// aux-build:cci_const.rs
+
+extern mod cci_const;
+use cci_const::bar;
+const foo: *u8 = bar;
+
+fn main() {
+    assert foo == cci_const::bar;
+}
diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs
new file mode 100644
index 00000000000..3438e65f05f
--- /dev/null
+++ b/src/test/run-pass/const-str-ptr.rs
@@ -0,0 +1,22 @@
+// Copyright 2012 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.
+
+const a: [u8 * 3] = ['h' as u8, 'i' as u8, 0 as u8];
+const c: &static/[u8 * 3] = &a;
+const b: *u8 = c as *u8;
+
+fn main() {
+    let foo = &a as *u8;
+    assert unsafe { str::raw::from_bytes(a) } == ~"hi\x00";
+    assert unsafe { str::raw::from_buf(foo) } == ~"hi";
+    assert unsafe { str::raw::from_buf(b) } == ~"hi";
+    assert unsafe { *b == a[0] };
+    assert unsafe { *(&c[0] as *u8) == a[0] };
+}
\ No newline at end of file