From 1841b31c61c2cca9c54264edd2a78b994b9638e9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Jun 2013 18:46:34 -0700 Subject: [PATCH 1/3] Add 'static mut' items to the language --- src/librustc/metadata/decoder.rs | 16 ++++--- src/librustc/metadata/encoder.rs | 10 ++-- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/check_const.rs | 6 +-- src/librustc/middle/check_match.rs | 10 ++-- src/librustc/middle/const_eval.rs | 6 +-- src/librustc/middle/effect.rs | 10 +++- src/librustc/middle/mem_categorization.rs | 28 +++++++---- src/librustc/middle/pat_util.rs | 2 +- src/librustc/middle/resolve.rs | 17 +++---- src/librustc/middle/trans/_match.rs | 9 ++-- src/librustc/middle/trans/base.rs | 12 +++-- src/librustc/middle/trans/callee.rs | 2 +- src/librustc/middle/trans/consts.rs | 12 +++-- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/reachable.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 4 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustdoc/extract.rs | 2 +- src/librustdoc/tystr_pass.rs | 2 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/ast_map.rs | 2 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/parser.rs | 5 +- src/libsyntax/print/pprust.rs | 5 +- src/libsyntax/visit.rs | 2 +- src/test/auxiliary/static_mut_xc.rs | 1 + src/test/compile-fail/static-mut-bad-types.rs | 17 +++++++ .../compile-fail/static-mut-not-constant.rs | 13 ++++++ src/test/compile-fail/static-mut-not-pat.rs | 26 +++++++++++ .../static-mut-requires-unsafe.rs | 17 +++++++ src/test/run-pass/static-mut-xc.rs | 46 +++++++++++++++++++ 34 files changed, 230 insertions(+), 70 deletions(-) create mode 100644 src/test/auxiliary/static_mut_xc.rs create mode 100644 src/test/compile-fail/static-mut-bad-types.rs create mode 100644 src/test/compile-fail/static-mut-not-constant.rs create mode 100644 src/test/compile-fail/static-mut-not-pat.rs create mode 100644 src/test/compile-fail/static-mut-requires-unsafe.rs create mode 100644 src/test/run-pass/static-mut-xc.rs diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 9ace8677dab..83e59d98085 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -97,7 +97,8 @@ fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { #[deriving(Eq)] enum Family { - Const, // c + ImmStatic, // c + MutStatic, // b Fn, // f UnsafeFn, // u PureFn, // p @@ -122,7 +123,8 @@ enum Family { fn item_family(item: ebml::Doc) -> Family { let fam = reader::get_doc(item, tag_items_data_item_family); match reader::doc_as_u8(fam) as char { - 'c' => Const, + 'c' => ImmStatic, + 'b' => MutStatic, 'f' => Fn, 'u' => UnsafeFn, 'p' => PureFn, @@ -321,7 +323,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) -> def_like { let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), + ImmStatic => dl_def(ast::def_static(did, false)), + MutStatic => dl_def(ast::def_static(did, true)), Struct => dl_def(ast::def_struct(did)), UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), Fn => dl_def(ast::def_fn(did, ast::impure_fn)), @@ -900,8 +903,8 @@ pub fn get_item_visibility(cdata: cmd, id: ast::node_id) fn family_has_type_params(fam: Family) -> bool { match fam { - Const | ForeignType | Mod | ForeignMod | PublicField | PrivateField - | ForeignFn => false, + ImmStatic | ForeignType | Mod | ForeignMod | PublicField | PrivateField + | ForeignFn | MutStatic => false, _ => true } } @@ -931,7 +934,8 @@ fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str { fn item_family_to_str(fam: Family) -> ~str { match fam { - Const => ~"const", + ImmStatic => ~"static", + MutStatic => ~"static mut", Fn => ~"fn", UnsafeFn => ~"unsafe fn", PureFn => ~"pure fn", diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 94cad18ece2..96cf7284169 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -785,7 +785,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let must_write = match item.node { item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) | - item_mod(*) | item_foreign_mod(*) | item_const(*) => true, + item_mod(*) | item_foreign_mod(*) | item_static(*) => true, _ => false }; if !must_write && !reachable(ecx, item.id) { return; } @@ -800,11 +800,15 @@ fn add_to_index_(item: @item, ebml_w: &writer::Encoder, ecx.tcx.sess.codemap.span_to_str(item.span)); match item.node { - item_const(_, _) => { + item_static(_, m, _) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); - encode_family(ebml_w, 'c'); + if m == ast::m_mutbl { + encode_family(ebml_w, 'b'); + } else { + encode_family(ebml_w, 'c'); + } 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)); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 925b1f506d7..5aad0d894da 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -384,7 +384,7 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def { ast::def_self(nid, i) => { ast::def_self(xcx.tr_id(nid), i) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) } - ast::def_const(did) => { ast::def_const(did.tr(xcx)) } + ast::def_static(did, m) => { ast::def_static(did.tr(xcx), m) } ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) } ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) } ast::def_variant(e_did, v_did) => { diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 126d2db6879..c1906820883 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -43,7 +43,7 @@ pub fn check_item(sess: Session, (_is_const, v): (bool, visit::vt)) { match it.node { - item_const(_, ex) => { + item_static(_, _, ex) => { (v.visit_expr)(ex, (true, v)); check_item_recursion(sess, ast_map, def_map, it); } @@ -124,7 +124,7 @@ pub fn check_expr(sess: Session, items without type parameters"); } match def_map.find(&e.id) { - Some(&def_const(_)) | + Some(&def_static(*)) | Some(&def_fn(_, _)) | Some(&def_variant(_, _)) | Some(&def_struct(_)) => { } @@ -237,7 +237,7 @@ fn visit_expr(e: @expr, (env, v): (env, visit::vt)) { match e.node { expr_path(*) => { match env.def_map.find(&e.id) { - Some(&def_const(def_id)) => { + Some(&def_static(def_id, _)) => { if ast_util::is_local(def_id) { match env.ast_map.get_copy(&def_id.node) { ast_map::node_item(it, _) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index a2532405870..b4c8a6b19c2 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -304,7 +304,7 @@ pub fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option { pat_ident(_, _, _) | pat_enum(_, _) => { match cx.tcx.def_map.find(&pat.id) { Some(&def_variant(_, id)) => Some(variant(id)), - Some(&def_const(did)) => { + Some(&def_static(did, false)) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); Some(val(eval_const_expr(cx.tcx, const_expr))) } @@ -339,7 +339,7 @@ pub fn is_wild(cx: @MatchCheckCtxt, p: @pat) -> bool { pat_wild => { true } pat_ident(_, _, _) => { match cx.tcx.def_map.find(&pat.id) { - Some(&def_variant(_, _)) | Some(&def_const(*)) => { false } + Some(&def_variant(_, _)) | Some(&def_static(*)) => { false } _ => { true } } } @@ -499,7 +499,7 @@ pub fn specialize(cx: @MatchCheckCtxt, None } } - Some(&def_const(did)) => { + Some(&def_static(did, _)) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); @@ -549,7 +549,7 @@ pub fn specialize(cx: @MatchCheckCtxt, } pat_enum(_, args) => { match cx.tcx.def_map.get_copy(&pat_id) { - def_const(did) => { + def_static(did, _) => { let const_expr = lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); @@ -790,7 +790,7 @@ pub fn is_refutable(cx: @MatchCheckCtxt, pat: &pat) -> bool { return true; } } - Some(&def_const(*)) => return true, + Some(&def_static(*)) => return true, _ => () } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 988ad519f42..1a7cd856bed 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -166,7 +166,7 @@ pub fn classify(e: @expr, pub fn lookup_const(tcx: ty::ctxt, e: @expr) -> Option<@expr> { match tcx.def_map.find(&e.id) { - Some(&ast::def_const(def_id)) => lookup_const_by_id(tcx, def_id), + Some(&ast::def_static(def_id, false)) => lookup_const_by_id(tcx, def_id), _ => None } } @@ -178,7 +178,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, match tcx.items.find(&def_id.node) { None => None, Some(&ast_map::node_item(it, _)) => match it.node { - item_const(_, const_expr) => Some(const_expr), + item_static(_, ast::m_imm, const_expr) => Some(const_expr), _ => None }, Some(_) => None @@ -195,7 +195,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, match csearch::maybe_get_item_ast(tcx, def_id, |a, b, c, d| astencode::decode_inlined_item(a, b, maps, /*bar*/ copy c, d)) { csearch::found(ast::ii_item(item)) => match item.node { - item_const(_, const_expr) => Some(const_expr), + item_static(_, ast::m_imm, const_expr) => Some(const_expr), _ => None }, _ => None diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index d9481c26dad..513b2015a83 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -17,7 +17,7 @@ use util::ppaux; use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call}; -use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn}; +use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn, expr_path}; use syntax::ast; use syntax::codemap::span; use syntax::visit::{fk_item_fn, fk_method}; @@ -143,6 +143,14 @@ pub fn check_crate(tcx: ty::ctxt, expr_inline_asm(*) => { require_unsafe(expr.span, "use of inline assembly") } + expr_path(*) => { + match ty::resolve_expr(tcx, expr) { + ast::def_static(_, true) => { + require_unsafe(expr.span, "use of mutable static") + } + _ => {} + } + } _ => {} } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 2ced57dc885..f93cb265d78 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -447,19 +447,29 @@ pub fn cat_def(&self, -> cmt { match def { ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) | - ast::def_foreign_mod(_) | ast::def_const(_) | + ast::def_foreign_mod(_) | ast::def_static(_, false) | ast::def_use(_) | ast::def_variant(*) | ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*) | ast::def_struct(*) | ast::def_typaram_binder(*) | ast::def_region(_) | ast::def_label(_) | ast::def_self_ty(*) => { - @cmt_ { - id:id, - span:span, - cat:cat_static_item, - mutbl: McImmutable, - ty:expr_ty - } + @cmt_ { + id:id, + span:span, + cat:cat_static_item, + mutbl: McImmutable, + ty:expr_ty + } + } + + ast::def_static(_, true) => { + @cmt_ { + id:id, + span:span, + cat:cat_static_item, + mutbl: McDeclared, + ty:expr_ty + } } ast::def_arg(vid, mutbl) => { @@ -894,7 +904,7 @@ pub fn cat_pattern(&self, self.cat_pattern(cmt_field, subpat, op); } } - Some(&ast::def_const(*)) => { + Some(&ast::def_static(*)) => { for subpats.iter().advance |&subpat| { self.cat_pattern(cmt, subpat, op); } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 1237e9fb4a2..5bd39e85863 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -45,7 +45,7 @@ pub fn pat_is_const(dm: resolve::DefMap, pat: &pat) -> bool { match pat.node { pat_ident(_, _, None) | pat_enum(*) => { match dm.find(&pat.id) { - Some(&def_const(*)) => true, + Some(&def_static(_, false)) => true, _ => false } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index eed0b12b9e1..7f9086be81d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1146,12 +1146,13 @@ pub fn build_reduced_graph_for_item(@mut self, } // These items live in the value namespace. - item_const(*) => { + item_static(_, m, _) => { let (name_bindings, _) = self.add_child(ident, parent, ForbidDuplicateValues, sp); + let mutbl = m == ast::m_mutbl; name_bindings.define_value - (privacy, def_const(local_def(item.id)), sp); + (privacy, def_static(local_def(item.id), mutbl), sp); } item_fn(_, purity, _, _, _) => { let (name_bindings, new_parent) = @@ -1566,7 +1567,7 @@ pub fn build_reduced_graph_for_foreign_item(@mut self, } } foreign_item_const(*) => { - let def = def_const(local_def(foreign_item.id)); + let def = def_static(local_def(foreign_item.id), false); name_bindings.define_value(Public, def, foreign_item.span); visit_foreign_item(foreign_item, (new_parent, visitor)); @@ -1673,7 +1674,7 @@ pub fn handle_external_def(@mut self, let privacy = variant_visibility_to_privacy(visibility, true); child_name_bindings.define_value(privacy, def, dummy_sp()); } - def_fn(*) | def_static_method(*) | def_const(*) => { + def_fn(*) | def_static_method(*) | def_static(*) => { debug!("(building reduced graph for external \ crate) building value %s", final_ident); child_name_bindings.define_value(privacy, def, dummy_sp()); @@ -3686,7 +3687,7 @@ pub fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { visitor); } - item_const(*) => { + item_static(*) => { self.with_constant_rib(|| { visit_item(item, ((), visitor)); }); @@ -4344,7 +4345,7 @@ struct in scope", Some(def @ def_struct(*)) => { self.record_def(pattern.id, def); } - Some(def @ def_const(*)) => { + Some(def @ def_static(*)) => { self.enforce_default_binding_mode( pattern, binding_mode, @@ -4376,7 +4377,7 @@ struct in scope", Some(def @ def_fn(*)) | Some(def @ def_variant(*)) | Some(def @ def_struct(*)) | - Some(def @ def_const(*)) => { + Some(def @ def_static(*)) => { self.record_def(pattern.id, def); } Some(_) => { @@ -4459,7 +4460,7 @@ pub fn resolve_bare_identifier_pattern(@mut self, name: ident) def @ def_variant(*) | def @ def_struct(*) => { return FoundStructOrEnumVariant(def); } - def @ def_const(*) => { + def @ def_static(_, false) => { return FoundConst(def); } _ => { diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index ab2f0c84d02..71b416ffe85 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -820,7 +820,7 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) { add_to_set(ccx.tcx, &mut found, lit(UnitLikeStructLit(cur.id))); } - Some(&ast::def_const(const_did)) => { + Some(&ast::def_static(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -836,7 +836,7 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) { add_to_set(ccx.tcx, &mut found, variant_opt(bcx, cur.id)); } - Some(&ast::def_const(const_did)) => { + Some(&ast::def_static(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -1831,8 +1831,9 @@ pub fn bind_irrefutable_pat(bcx: block, } } } - Some(&ast::def_const(*)) => { - bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, binding_mode); + Some(&ast::def_static(_, false)) => { + bcx = bind_irrefutable_pat(bcx, pat, val, make_copy, + binding_mode); } _ => { // Nothing to do here. diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ec77fe359b5..0f6c7dbe754 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2122,14 +2122,19 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { trans_enum_def(ccx, enum_definition, item.id, vi, &mut i); } } - ast::item_const(_, expr) => { - consts::trans_const(ccx, expr, item.id); + ast::item_static(_, m, expr) => { + consts::trans_const(ccx, m, item.id); // Do static_assert checking. It can't really be done much earlier because we need to get // the value of the bool out of LLVM for item.attrs.iter().advance |attr| { match attr.node.value.node { ast::meta_word(x) => { if x.slice(0, x.len()) == "static_assert" { + if m == ast::m_mutbl { + ccx.sess.span_fatal(expr.span, + "cannot have static_assert \ + on a mutable static"); + } let v = ccx.const_values.get_copy(&item.id); unsafe { if !(llvm::LLVMConstIntGetZExtValue(v) as bool) { @@ -2398,13 +2403,14 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef { let my_path = vec::append(/*bad*/copy *pth, [path_name(i.ident)]); match i.node { - ast::item_const(_, expr) => { + ast::item_static(_, m, expr) => { let typ = ty::node_id_to_type(ccx.tcx, i.id); let s = mangle_exported_name(ccx, my_path, typ); // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. let v = consts::const_expr(ccx, expr); ccx.const_values.insert(id, v); + exprt = m == ast::m_mutbl; unsafe { let llty = llvm::LLVMTypeOf(v); let g = str::as_c_str(s, |buf| { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 6120e1e6581..593d0beb88c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -143,7 +143,7 @@ fn trans_def(bcx: block, def: ast::def, ref_expr: @ast::expr) -> Callee { datum_callee(bcx, ref_expr) } ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) | - ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) | + ast::def_static(*) | ast::def_ty(*) | ast::def_prim_ty(*) | ast::def_use(*) | ast::def_typaram_binder(*) | ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) | ast::def_self_ty(*) => { diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e40534773c2..98eb858be55 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -164,9 +164,9 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::def_id) -> ValueRef } match cx.tcx.items.get_copy(&def_id.node) { ast_map::node_item(@ast::item { - node: ast::item_const(_, subexpr), _ + node: ast::item_static(_, ast::m_imm, _), _ }, _) => { - trans_const(cx, subexpr, def_id.node); + trans_const(cx, ast::m_imm, def_id.node); } _ => cx.tcx.sess.bug("expected a const to be an item") } @@ -538,7 +538,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef { base::get_item_val(cx, def_id.node) } } - Some(&ast::def_const(def_id)) => { + Some(&ast::def_static(def_id, false)) => { get_const_val(cx, def_id) } Some(&ast::def_variant(enum_did, variant_did)) => { @@ -587,7 +587,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef { } } -pub fn trans_const(ccx: @mut CrateContext, _e: @ast::expr, id: ast::node_id) { +pub fn trans_const(ccx: @mut CrateContext, m: ast::mutability, id: ast::node_id) { unsafe { let _icx = push_ctxt("trans_const"); let g = base::get_item_val(ccx, id); @@ -595,6 +595,8 @@ pub fn trans_const(ccx: @mut CrateContext, _e: @ast::expr, id: ast::node_id) { // constant's initializer to determine its LLVM type. let v = ccx.const_values.get_copy(&id); llvm::LLVMSetInitializer(g, v); - llvm::LLVMSetGlobalConstant(g, True); + if m != ast::m_mutbl { + llvm::LLVMSetGlobalConstant(g, True); + } } } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 7d86f743a8e..1aebf73b81a 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -945,7 +945,7 @@ fn trans_def_lvalue(bcx: block, let _icx = push_ctxt("trans_def_lvalue"); let ccx = bcx.ccx(); match def { - ast::def_const(did) => { + ast::def_static(did, _) => { let const_ty = expr_ty(bcx, ref_expr); fn get_did(ccx: @mut CrateContext, did: ast::def_id) diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 6a40c1f75e9..e950c24c49e 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -146,7 +146,7 @@ fn traverse_public_item(cx: @mut ctx, item: @item) { visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, ..*visit::default_visitor()}))) } - item_const(*) | + item_static(*) | item_enum(*) | item_trait(*) => (), item_mac(*) => fail!("item macros unimplemented") } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 90cd8a8665e..f3c0d4bd8f4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3269,7 +3269,7 @@ pub fn expr_kind(tcx: ctxt, // Note: there is actually a good case to be made that // def_args, particularly those of immediate type, ought to // considered rvalues. - ast::def_const(*) | + ast::def_static(*) | ast::def_binding(*) | ast::def_upvar(*) | ast::def_arg(*) | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fa7959c7872..1acf806f21e 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -585,7 +585,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { let _indenter = indenter(); match it.node { - ast::item_const(_, e) => check_const(ccx, it.span, e, it.id), + ast::item_static(_, _, e) => check_const(ccx, it.span, e, it.id), ast::item_enum(ref enum_definition, _) => { check_enum_variants(ccx, it.span, @@ -3216,7 +3216,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, } ast::def_fn(id, _) | ast::def_static_method(id, _, _) | - ast::def_const(id) | ast::def_variant(_, id) | + ast::def_static(id, _) | ast::def_variant(_, id) | ast::def_struct(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 7f820d11ac6..aef148830a9 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1060,7 +1060,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) } let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x); match it.node { - ast::item_const(t, _) => { + ast::item_static(t, _, _) => { let typ = ccx.to_ty(&empty_rscope, t); let tpt = no_params(typ); tcx.tcache.insert(local_def(it.id), tpt); diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index b6131dce9c8..f12f612b036 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -102,7 +102,7 @@ fn moddoc_from_mod( fndoc_from_fn(ItemDoc) )) } - ast::item_const(_, _) => { + ast::item_static(*) => { Some(doc::ConstTag( constdoc_from_const(ItemDoc) )) diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index e3abe6e926a..459daaa468f 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -96,7 +96,7 @@ fn fold_const( do astsrv::exec(srv) |ctxt| { match ctxt.ast_map.get_copy(&doc.id()) { ast_map::node_item(@ast::item { - node: ast::item_const(ty, _), _ + node: ast::item_static(ty, _, _), _ }, _) => { pprust::ty_to_str(ty, extract::interner()) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2e3d557daa9..012a1e76228 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -190,7 +190,7 @@ pub enum def { def_self_ty(/* trait id */ node_id), def_mod(def_id), def_foreign_mod(def_id), - def_const(def_id), + def_static(def_id, bool /* is_mutbl */), def_arg(node_id, bool /* is_mutbl */), def_local(node_id, bool /* is_mutbl */), def_variant(def_id /* enum */, def_id /* variant */), @@ -1095,7 +1095,7 @@ pub struct item { #[deriving(Eq, Encodable, Decodable)] pub enum item_ { - item_const(@Ty, @expr), + item_static(@Ty, mutability, @expr), item_fn(fn_decl, purity, AbiSet, Generics, blk), item_mod(_mod), item_foreign_mod(foreign_mod), diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index a0e1ec69350..421c4c566b5 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -339,7 +339,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { Some(&node_item(item, path)) => { let path_str = path_ident_to_str(path, item.ident, itr); let item_str = match item.node { - item_const(*) => ~"const", + item_static(*) => ~"static", item_fn(*) => ~"fn", item_mod(*) => ~"mod", item_foreign_mod(*) => ~"foreign mod", diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 24cf5662a36..227d700452b 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -59,7 +59,7 @@ pub fn variant_def_ids(d: def) -> Option<(def_id, def_id)> { pub fn def_id_of_def(d: def) -> def_id { match d { def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) | - def_foreign_mod(id) | def_const(id) | + def_foreign_mod(id) | def_static(id, _) | def_variant(_, id) | def_ty(id) | def_ty_param(id, _) | def_use(id) | def_struct(id) | def_trait(id) => { id diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4bd2c0a3de1..8a22dbe9178 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -270,7 +270,7 @@ fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold) pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ { match *i { - item_const(t, e) => item_const(fld.fold_ty(t), fld.fold_expr(e)), + item_static(t, m, e) => item_static(fld.fold_ty(t), m, fld.fold_expr(e)), item_fn(ref decl, purity, abi, ref generics, ref body) => { item_fn( fold_fn_decl(decl, fld), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f2443f9e533..a726b3b27d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -34,7 +34,7 @@ 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::{ident, impure_fn, inherited, item, item_, item_const}; +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_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; @@ -3556,13 +3556,14 @@ fn parse_mod_items(&self, term: token::Token, } fn parse_item_const(&self) -> item_info { + let m = if self.eat_keyword(keywords::Mut) {m_mutbl} else {m_imm}; let id = self.parse_ident(); self.expect(&token::COLON); let ty = self.parse_ty(false); self.expect(&token::EQ); let e = self.parse_expr(); self.expect(&token::SEMI); - (id, item_const(ty, e), None) + (id, item_static(ty, m, e), None) } // parse a mod { ...} item diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index fa22b7ceb71..c21c0a0afee 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -477,8 +477,11 @@ pub fn print_item(s: @ps, item: @ast::item) { let ann_node = node_item(s, item); (s.ann.pre)(ann_node); match item.node { - ast::item_const(ty, expr) => { + ast::item_static(ty, m, expr) => { head(s, visibility_qualified(item.vis, "static")); + if m == ast::m_mutbl { + word_space(s, "mut"); + } print_ident(s, item.ident); word_space(s, ":"); print_type(s, ty); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5aa38c0348c..fd9350e0005 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -148,7 +148,7 @@ fn visit_trait_ref(tref: @ast::trait_ref, (e, v): (E, vt)) { pub fn visit_item(i: @item, (e, v): (E, vt)) { match i.node { - item_const(t, ex) => { + item_static(t, _, ex) => { (v.visit_ty)(t, (copy e, v)); (v.visit_expr)(ex, (copy e, v)); } diff --git a/src/test/auxiliary/static_mut_xc.rs b/src/test/auxiliary/static_mut_xc.rs new file mode 100644 index 00000000000..8dc45c681bf --- /dev/null +++ b/src/test/auxiliary/static_mut_xc.rs @@ -0,0 +1 @@ +pub static mut a: int = 3; diff --git a/src/test/compile-fail/static-mut-bad-types.rs b/src/test/compile-fail/static-mut-bad-types.rs new file mode 100644 index 00000000000..7aed3ce30bc --- /dev/null +++ b/src/test/compile-fail/static-mut-bad-types.rs @@ -0,0 +1,17 @@ +// 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. + +static mut a: int = 3; + +fn main() { + unsafe { + a = true; //~ ERROR: mismatched types + } +} diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs new file mode 100644 index 00000000000..61d3ed7fd18 --- /dev/null +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -0,0 +1,13 @@ +// 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. + +static mut a: ~int = ~3; //~ ERROR: disallowed operator in constant + +fn main() {} diff --git a/src/test/compile-fail/static-mut-not-pat.rs b/src/test/compile-fail/static-mut-not-pat.rs new file mode 100644 index 00000000000..997003a28d4 --- /dev/null +++ b/src/test/compile-fail/static-mut-not-pat.rs @@ -0,0 +1,26 @@ +// 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. + +static mut a: int = 3; + +fn main() { + // If they can't be matched against, then it's possible to capture the same + // name as a variable, hence this should be an unreachable pattern situation + // instead of spitting out a custom error about some identifier collisions + // (we should allow shadowing) + match 4 { + a => {} + _ => {} //~ ERROR: unreachable pattern + } +} diff --git a/src/test/compile-fail/static-mut-requires-unsafe.rs b/src/test/compile-fail/static-mut-requires-unsafe.rs new file mode 100644 index 00000000000..7337920cce6 --- /dev/null +++ b/src/test/compile-fail/static-mut-requires-unsafe.rs @@ -0,0 +1,17 @@ +// 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. + +static mut a: int = 3; + +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-xc.rs b/src/test/run-pass/static-mut-xc.rs new file mode 100644 index 00000000000..72f44fcd501 --- /dev/null +++ b/src/test/run-pass/static-mut-xc.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. + +// xfail-fast +// aux-build:static_mut_xc.rs + +extern mod static_mut_xc; + +unsafe fn static_bound(_: &'static int) {} + +fn static_bound_set(a: &'static mut int) { + *a = 3; +} + +unsafe fn run() { + assert!(static_mut_xc::a == 3); + static_mut_xc::a = 4; + assert!(static_mut_xc::a == 4); + static_mut_xc::a += 1; + assert!(static_mut_xc::a == 5); + static_mut_xc::a *= 3; + assert!(static_mut_xc::a == 15); + static_mut_xc::a = -3; + assert!(static_mut_xc::a == -3); + static_bound(&static_mut_xc::a); + static_bound_set(&mut static_mut_xc::a); +} + +fn main() { + unsafe { run() } +} + +pub mod inner { + pub static mut a: int = 4; +} From 8fdc8f392c3f5d1bdf601756bfe442b7698e6315 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Jun 2013 22:46:27 -0700 Subject: [PATCH 2/3] Support foreign 'static mut' variables as well --- src/librustc/metadata/encoder.rs | 8 +++- src/librustc/middle/lint.rs | 48 ++++++++++--------- src/librustc/middle/resolve.rs | 6 +-- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/foreign.rs | 2 +- src/librustc/middle/typeck/collect.rs | 2 +- src/librustdoc/extract.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/parser.rs | 5 +- src/libsyntax/print/pprust.rs | 5 +- src/libsyntax/visit.rs | 2 +- src/rt/rust_builtin.cpp | 10 ++++ src/rt/rustrt.def.in | 4 +- .../static-mut-foreign-requires-unsafe.rs | 21 ++++++++ src/test/run-pass/static-mut-foreign.rs | 46 ++++++++++++++++++ 16 files changed, 129 insertions(+), 40 deletions(-) create mode 100644 src/test/compile-fail/static-mut-foreign-requires-unsafe.rs create mode 100644 src/test/run-pass/static-mut-foreign.rs 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_foreign_fn(cx: &Context, decl: &ast::fn_decl) { 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 @@ pub fn build_reduced_graph_for_foreign_item(@mut self, 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 @@ pub fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { || 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_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 @@ fn parse_item_foreign_const(&self, vis: ast::visibility, } 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 @@ fn parse_item_foreign_const(&self, vis: ast::visibility, 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(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 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 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 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 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() } +} From b94f89fffc0c31a2e9048a824a66ff121c908818 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 Jun 2013 07:42:22 -0700 Subject: [PATCH 3/3] Fix 'static mut' tests --- src/test/run-pass/static-mut-foreign.rs | 2 +- src/test/run-pass/static-mut-xc.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs index 66d34c7e454..7af143a1529 100644 --- a/src/test/run-pass/static-mut-foreign.rs +++ b/src/test/run-pass/static-mut-foreign.rs @@ -41,6 +41,6 @@ unsafe fn run() { static_bound_set(&mut debug_static_mut); } -fn main() { +pub fn main() { unsafe { run() } } diff --git a/src/test/run-pass/static-mut-xc.rs b/src/test/run-pass/static-mut-xc.rs index 72f44fcd501..ab6bdc20c49 100644 --- a/src/test/run-pass/static-mut-xc.rs +++ b/src/test/run-pass/static-mut-xc.rs @@ -37,7 +37,7 @@ unsafe fn run() { static_bound_set(&mut static_mut_xc::a); } -fn main() { +pub fn main() { unsafe { run() } }