about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-06-21 22:46:27 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-06-23 18:00:32 -0700
commit8fdc8f392c3f5d1bdf601756bfe442b7698e6315 (patch)
tree09175a847c4f73b5804195e60e3638f9aeee67c4
parent1841b31c61c2cca9c54264edd2a78b994b9638e9 (diff)
downloadrust-8fdc8f392c3f5d1bdf601756bfe442b7698e6315.tar.gz
rust-8fdc8f392c3f5d1bdf601756bfe442b7698e6315.zip
Support foreign 'static mut' variables as well
-rw-r--r--src/librustc/metadata/encoder.rs8
-rw-r--r--src/librustc/middle/lint.rs48
-rw-r--r--src/librustc/middle/resolve.rs6
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/librustc/middle/trans/foreign.rs2
-rw-r--r--src/librustc/middle/typeck/collect.rs2
-rw-r--r--src/librustdoc/extract.rs2
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse/parser.rs5
-rw-r--r--src/libsyntax/print/pprust.rs5
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/rt/rust_builtin.cpp10
-rw-r--r--src/rt/rustrt.def.in4
-rw-r--r--src/test/compile-fail/static-mut-foreign-requires-unsafe.rs21
-rw-r--r--src/test/run-pass/static-mut-foreign.rs46
16 files changed, 129 insertions, 40 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 96cf7284169..7d18bdb77ef 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1111,9 +1111,13 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         }
         encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
       }
-      foreign_item_const(*) => {
+      foreign_item_static(_, mutbl) => {
         encode_def_id(ebml_w, local_def(nitem.id));
-        encode_family(ebml_w, 'c');
+        if mutbl {
+            encode_family(ebml_w, 'b');
+        } else {
+            encode_family(ebml_w, 'c');
+        }
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
         encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 821aed731c2..17ff5930078 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -709,28 +709,31 @@ fn check_item_default_methods(cx: &Context, item: @ast::item) {
 }
 
 fn check_item_ctypes(cx: &Context, it: @ast::item) {
+    fn check_ty(cx: &Context, ty: @ast::Ty) {
+        match ty.node {
+            ast::ty_path(_, _, id) => {
+                match cx.tcx.def_map.get_copy(&id) {
+                    ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
+                        cx.span_lint(ctypes, ty.span,
+                                "found rust type `int` in foreign module, while \
+                                libc::c_int or libc::c_long should be used");
+                    }
+                    ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => {
+                        cx.span_lint(ctypes, ty.span,
+                                "found rust type `uint` in foreign module, while \
+                                libc::c_uint or libc::c_ulong should be used");
+                    }
+                    _ => ()
+                }
+            }
+            _ => ()
+        }
+    }
 
     fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
         let tys = vec::map(decl.inputs, |a| a.ty );
         for vec::each(vec::append_one(tys, decl.output)) |ty| {
-            match ty.node {
-              ast::ty_path(_, _, id) => {
-                match cx.tcx.def_map.get_copy(&id) {
-                  ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
-                    cx.span_lint(ctypes, ty.span,
-                        "found rust type `int` in foreign module, while \
-                         libc::c_int or libc::c_long should be used");
-                  }
-                  ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => {
-                    cx.span_lint(ctypes, ty.span,
-                        "found rust type `uint` in foreign module, while \
-                         libc::c_uint or libc::c_ulong should be used");
-                  }
-                  _ => ()
-                }
-              }
-              _ => ()
-            }
+            check_ty(cx, *ty);
         }
     }
 
@@ -738,11 +741,10 @@ fn check_item_ctypes(cx: &Context, it: @ast::item) {
       ast::item_foreign_mod(ref nmod) if !nmod.abis.is_intrinsic() => {
         for nmod.items.iter().advance |ni| {
             match ni.node {
-              ast::foreign_item_fn(ref decl, _, _) => {
-                check_foreign_fn(cx, decl);
-              }
-              // FIXME #4622: Not implemented.
-              ast::foreign_item_const(*) => {}
+                ast::foreign_item_fn(ref decl, _, _) => {
+                    check_foreign_fn(cx, decl);
+                }
+                ast::foreign_item_static(t, _) => { check_ty(cx, t); }
             }
         }
       }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 7f9086be81d..ed385ae5421 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1566,8 +1566,8 @@ impl Resolver {
                     visit_foreign_item(foreign_item, (new_parent, visitor));
                 }
             }
-            foreign_item_const(*) => {
-                let def = def_static(local_def(foreign_item.id), false);
+            foreign_item_static(_, m) => {
+                let def = def_static(local_def(foreign_item.id), m);
                 name_bindings.define_value(Public, def, foreign_item.span);
 
                 visit_foreign_item(foreign_item, (new_parent, visitor));
@@ -3665,7 +3665,7 @@ impl Resolver {
                                     || visit_foreign_item(*foreign_item,
                                                           ((), visitor)));
                             }
-                            foreign_item_const(_) => {
+                            foreign_item_static(*) => {
                                 visit_foreign_item(*foreign_item,
                                                    ((), visitor));
                             }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 0f6c7dbe754..0e322c187af 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2463,7 +2463,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
                                 ni.id,
                                 ni.attrs)
                 }
-                ast::foreign_item_const(*) => {
+                ast::foreign_item_static(*) => {
                     let typ = ty::node_id_to_type(ccx.tcx, ni.id);
                     let ident = token::ident_to_str(&ni.ident);
                     let g = do str::as_c_str(ident) |buf| {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 10e63e6af77..54bfc25244f 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -332,7 +332,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
                     }
                 }
             }
-            ast::foreign_item_const(*) => {
+            ast::foreign_item_static(*) => {
                 let ident = token::ident_to_str(&foreign_item.ident);
                 ccx.item_symbols.insert(foreign_item.id, /* bad */ident.to_owned());
             }
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index aef148830a9..33e483e552a 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -1153,7 +1153,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
                                   generics,
                                   abis)
         }
-        ast::foreign_item_const(t) => {
+        ast::foreign_item_static(t, _) => {
             ty::ty_param_bounds_and_ty {
                 generics: ty::Generics {
                     type_param_defs: @~[],
diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs
index f12f612b036..b7b2b70769b 100644
--- a/src/librustdoc/extract.rs
+++ b/src/librustdoc/extract.rs
@@ -150,7 +150,7 @@ fn nmoddoc_from_mod(
           ast::foreign_item_fn(*) => {
             fns.push(fndoc_from_fn(ItemDoc));
           }
-          ast::foreign_item_const(*) => {} // XXX: Not implemented.
+          ast::foreign_item_static(*) => {} // XXX: Not implemented.
         }
     }
     doc::NmodDoc {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 012a1e76228..c7f3b41475f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1124,7 +1124,7 @@ pub struct foreign_item {
 #[deriving(Eq, Encodable, Decodable)]
 pub enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, Generics),
-    foreign_item_const(@Ty)
+    foreign_item_static(@Ty, /* is_mutbl */ bool),
 }
 
 // The data we save and restore about an inlined item or method.  This is not
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8a22dbe9178..25839fb4633 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -236,8 +236,8 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
                         purity,
                         fold_generics(generics, fld))
                 }
-                foreign_item_const(t) => {
-                    foreign_item_const(fld.fold_ty(t))
+                foreign_item_static(t, m) => {
+                    foreign_item_static(fld.fold_ty(t), m)
                 }
             },
         id: fld.new_id(ni.id),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a726b3b27d2..cc4a1f45722 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -33,7 +33,7 @@ use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
 use ast::{expr_vstore_slice, expr_vstore_box};
 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
 use ast::{expr_vstore_uniq, Onceness, Once, Many};
-use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
+use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
 use ast::{ident, impure_fn, inherited, item, item_, item_static};
 use ast::{item_enum, item_fn, item_foreign_mod, item_impl};
 use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
@@ -3684,6 +3684,7 @@ impl Parser {
         } else {
             self.expect_keyword(keywords::Static);
         }
+        let mutbl = self.eat_keyword(keywords::Mut);
 
         let ident = self.parse_ident();
         self.expect(&token::COLON);
@@ -3692,7 +3693,7 @@ impl Parser {
         self.expect(&token::SEMI);
         @ast::foreign_item { ident: ident,
                              attrs: attrs,
-                             node: foreign_item_const(ty),
+                             node: foreign_item_static(ty, mutbl),
                              id: self.get_id(),
                              span: mk_sp(lo, hi),
                              vis: vis }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c21c0a0afee..1a3155337a5 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -458,8 +458,11 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) {
         word(s.s, ";");
         end(s); // end the outer fn box
       }
-      ast::foreign_item_const(t) => {
+      ast::foreign_item_static(t, m) => {
         head(s, "static");
+        if m {
+            word_space(s, "mut");
+        }
         print_ident(s, item.ident);
         word_space(s, ":");
         print_type(s, t);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fd9350e0005..d7914832835 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -326,7 +326,7 @@ pub fn visit_foreign_item<E: Copy>(ni: @foreign_item, (e, v): (E, vt<E>)) {
             visit_fn_decl(fd, (copy e, v));
             (v.visit_generics)(generics, (e, v));
         }
-        foreign_item_const(t) => {
+        foreign_item_static(t, _) => {
             (v.visit_ty)(t, (e, v));
         }
     }
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index e476fa0ad5e..6ae5e978106 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -154,6 +154,16 @@ debug_abi_2(floats f) {
     return ff;
 }
 
+extern "C" int
+debug_static_mut;
+
+int debug_static_mut = 3;
+
+extern "C" void
+debug_static_mut_check_four() {
+    assert(debug_static_mut == 4);
+}
+
 /* Debug builtins for std::dbg. */
 
 static void
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index ba7ada04a27..505de6e20b7 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -7,6 +7,8 @@ debug_tydesc
 debug_get_stk_seg
 debug_abi_1
 debug_abi_2
+debug_static_mut
+debug_static_mut_check_four
 get_task_id
 get_time
 rust_tzset
@@ -239,4 +241,4 @@ rust_valgrind_stack_deregister
 rust_take_env_lock
 rust_drop_env_lock
 rust_update_log_settings
-rust_running_on_valgrind
\ No newline at end of file
+rust_running_on_valgrind
diff --git a/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs b/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs
new file mode 100644
index 00000000000..7b371cf708d
--- /dev/null
+++ b/src/test/compile-fail/static-mut-foreign-requires-unsafe.rs
@@ -0,0 +1,21 @@
+// 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.
+
+use std::libc;
+
+extern {
+    static mut a: libc::c_int;
+}
+
+fn main() {
+    a += 3;     //~ ERROR: requires unsafe
+    a = 4;      //~ ERROR: requires unsafe
+    let _b = a; //~ ERROR: requires unsafe
+}
diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs
new file mode 100644
index 00000000000..66d34c7e454
--- /dev/null
+++ b/src/test/run-pass/static-mut-foreign.rs
@@ -0,0 +1,46 @@
+// 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.
+
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+use std::libc;
+
+#[nolink]
+extern {
+    static mut debug_static_mut: libc::c_int;
+    pub fn debug_static_mut_check_four();
+}
+
+unsafe fn static_bound(_: &'static libc::c_int) {}
+
+fn static_bound_set(a: &'static mut libc::c_int) {
+    *a = 3;
+}
+
+unsafe fn run() {
+    assert!(debug_static_mut == 3);
+    debug_static_mut = 4;
+    assert!(debug_static_mut == 4);
+    debug_static_mut_check_four();
+    debug_static_mut += 1;
+    assert!(debug_static_mut == 5);
+    debug_static_mut *= 3;
+    assert!(debug_static_mut == 15);
+    debug_static_mut = -3;
+    assert!(debug_static_mut == -3);
+    static_bound(&debug_static_mut);
+    static_bound_set(&mut debug_static_mut);
+}
+
+fn main() {
+    unsafe { run() }
+}