diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 96cf7284169d..7d18bdb77efe 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 821aed731c22..17ff5930078d 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 7f9086be81d5..ed385ae54215 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 0f6c7dbe7543..0e322c187af2 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 10e63e6af777..54bfc25244f0 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 aef148830a99..33e483e552a7 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 f12f612b036b..b7b2b70769bb 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 012a1e76228a..c7f3b41475f0 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 8a22dbe9178c..25839fb46339 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 a726b3b27d2e..cc4a1f457226 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 c21c0a0afeed..1a3155337a5e 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 fd9350e00051..d7914832835a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -326,7 +326,7 @@ pub fn visit_foreign_item(ni: @foreign_item, (e, v): (E, vt)) { 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 e476fa0ad5e0..6ae5e978106e 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 ba7ada04a275..505de6e20b70 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 000000000000..7b371cf708dc --- /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 or the MIT license +// , 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 000000000000..66d34c7e454d --- /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 or the MIT license +// , 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() } +}