diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index c7084138c98a0..60e5f0db9a9d4 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -264,6 +264,7 @@ options: --test build test harness --gc garbage collect shared data (experimental/temporary) --stack-growth perform stack checks (experimental) + --check-unsafe disallow unsafe actions in non-unsafe functions "); } @@ -322,6 +323,7 @@ fn build_session_options(match: getopts::match) let parse_only = opt_present(match, "parse-only"); let no_trans = opt_present(match, "no-trans"); + let check_unsafe = opt_present(match, "check-unsafe"); let output_type = if parse_only || no_trans { @@ -393,7 +395,8 @@ fn build_session_options(match: getopts::match) parse_only: parse_only, no_trans: no_trans, do_gc: do_gc, - stack_growth: stack_growth}; + stack_growth: stack_growth, + check_unsafe: check_unsafe}; ret sopts; } @@ -432,7 +435,7 @@ fn opts() -> [getopts::opt] { optflag("no-typestate"), optflag("noverify"), optmulti("cfg"), optflag("test"), optflag("lib"), optflag("static"), optflag("gc"), - optflag("stack-growth")]; + optflag("stack-growth"), optflag("check-unsafe")]; } fn main(args: [str]) { diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs index 1f3f9baab8a90..6ba2148e8a4c8 100644 --- a/src/comp/driver/session.rs +++ b/src/comp/driver/session.rs @@ -41,7 +41,8 @@ type options = parse_only: bool, no_trans: bool, do_gc: bool, - stack_growth: bool}; + stack_growth: bool, + check_unsafe: bool}; type crate_metadata = {name: str, data: [u8]}; diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 6f7270f4396f8..70985f108060d 100644 --- a/src/comp/front/test.rs +++ b/src/comp/front/test.rs @@ -184,7 +184,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item { let test_descs = mk_test_desc_vec(cx); let body_: ast::blk_ = - checked_blk([], option::some(test_descs), cx.next_node_id()); + default_block([], option::some(test_descs), cx.next_node_id()); let body = nospan(body_); let fn_ = {decl: decl, proto: proto, body: body}; @@ -303,7 +303,8 @@ fn mk_main(cx: test_ctxt) -> @ast::item { let test_main_call_expr = mk_test_main_call(cx); let body_: ast::blk_ = - checked_blk([], option::some(test_main_call_expr), cx.next_node_id()); + default_block([], option::some(test_main_call_expr), + cx.next_node_id()); let body = {node: body_, span: dummy_sp()}; let fn_ = {decl: decl, proto: proto, body: body}; diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index ca3b4f4e2c5e6..ee0b7f6c758a3 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -175,6 +175,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) -> let def = alt fam_ch as char { 'c' { ast::def_const(did) } + 'u' { ast::def_fn(did, ast::unsafe_fn) } 'f' { ast::def_fn(did, ast::impure_fn) } 'p' { ast::def_fn(did, ast::pure_fn) } 'F' { ast::def_native_fn(did) } @@ -250,6 +251,7 @@ fn family_has_type_params(fam_ch: u8) -> bool { ret alt fam_ch as char { 'c' { false } 'f' { true } + 'u' { true } 'p' { true } 'F' { true } 'y' { true } @@ -278,6 +280,7 @@ fn item_family_to_str(fam: u8) -> str { alt fam as char { 'c' { ret "const"; } 'f' { ret "fn"; } + 'u' { ret "unsafe fn"; } 'p' { ret "pure fn"; } 'F' { ret "native fn"; } 'y' { ret "type"; } diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index 7850b4139a1aa..b67114d3d9a3d 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -252,6 +252,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, alt fd.decl.purity { + unsafe_fn. { 'u' } pure_fn. { 'p' } impure_fn. { 'f' } } as u8); diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 27021c2a20824..3314fb890a2ce 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -29,10 +29,10 @@ tag ret_info { by_ref(bool, node_id); other; } type scope = {bs: [binding], ret_info: ret_info}; fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option::t, - unsafe: [unsafe_ty]) -> binding { + unsafe_tys: [unsafe_ty]) -> binding { ret @{node_id: id, span: span, root_var: root_var, local_id: local_id_of_node(cx, id), - unsafe_tys: unsafe, mutable ok: valid, + unsafe_tys: unsafe_tys, mutable ok: valid, mutable copied: not_copied}; } @@ -284,12 +284,12 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] { } let j = 0u; for b in bindings { - for unsafe in b.unsafe_tys { + for unsafe_ty in b.unsafe_tys { let i = 0u; for arg_t: ty::arg in arg_ts { let mut_alias = arg_t.mode == ast::by_mut_ref; if i != j && - ty_can_unsafely_include(cx, unsafe, arg_t.ty, + ty_can_unsafely_include(cx, unsafe_ty, arg_t.ty, mut_alias) && cant_copy(cx, b) { cx.tcx.sess.span_err @@ -397,24 +397,28 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope, let new_bs = sc.bs; let root_var = path_def_id(cx, root.ex); let pat_id_map = ast_util::pat_id_map(a.pats[0]); - type info = {id: node_id, mutable unsafe: [unsafe_ty], span: span}; + type info = { + id: node_id, + mutable unsafe_tys: [unsafe_ty], + span: span}; let binding_info: [info] = []; for pat in a.pats { for proot in pattern_roots(cx.tcx, root.mut, pat) { let canon_id = pat_id_map.get(proot.name); alt vec::find({|x| x.id == canon_id}, binding_info) { - some(s) { s.unsafe += unsafe_set(proot.mut); } + some(s) { s.unsafe_tys += unsafe_set(proot.mut); } none. { - binding_info += [{id: canon_id, - mutable unsafe: unsafe_set(proot.mut), - span: proot.span}]; + binding_info += [ + {id: canon_id, + mutable unsafe_tys: unsafe_set(proot.mut), + span: proot.span}]; } } } } for info in binding_info { new_bs += [mk_binding(cx, info.id, info.span, root_var, - copy info.unsafe)]; + copy info.unsafe_tys)]; } visit::visit_arm(a, {bs: new_bs with sc}, v); } @@ -470,8 +474,8 @@ fn check_var(cx: ctx, ex: @ast::expr, p: ast::path, id: ast::node_id, for b in sc.bs { // excludes variables introduced since the alias was made if my_local_id < b.local_id { - for unsafe in b.unsafe_tys { - if ty_can_unsafely_include(cx, unsafe, var_t, assign) { + for unsafe_ty in b.unsafe_tys { + if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) { b.ok = val_taken(ex.span, p); } } @@ -689,9 +693,9 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t, pat: @ast::pat) fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) -> {ex: @ast::expr, mut: option::t} { let base_root = mut::expr_root(cx.tcx, ex, autoderef); - let unsafe = none; + let unsafe_ty = none; for d in *base_root.ds { - if d.mut { unsafe = some(contains(d.outer_t)); break; } + if d.mut { unsafe_ty = some(contains(d.outer_t)); break; } } if is_none(path_def_id(cx, base_root.ex)) { alt base_root.ex.node { @@ -703,10 +707,10 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) let arg_root = expr_root(cx, arg, false); if mut { let ret_ty = ty::expr_ty(cx.tcx, base_root.ex); - unsafe = some(mut_contains(ret_ty)); + unsafe_ty = some(mut_contains(ret_ty)); } - if !is_none(arg_root.mut) { unsafe = arg_root.mut; } - ret {ex: arg_root.ex, mut: unsafe}; + if !is_none(arg_root.mut) { unsafe_ty = arg_root.mut; } + ret {ex: arg_root.ex, mut: unsafe_ty}; } _ {} } @@ -714,7 +718,7 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) _ {} } } - ret {ex: base_root.ex, mut: unsafe}; + ret {ex: base_root.ex, mut: unsafe_ty}; } fn unsafe_set(from: option::t) -> [unsafe_ty] { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8e2fa8fedf048..1b0b4366fd122 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4367,11 +4367,11 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt { assert dest == ignore; ret trans_check_expr(bcx, a, "Assertion"); } - ast::expr_check(ast::checked., a) { + ast::expr_check(ast::checked_expr., a) { assert dest == ignore; ret trans_check_expr(bcx, a, "Predicate"); } - ast::expr_check(ast::unchecked., a) { + ast::expr_check(ast::claimed_expr., a) { assert dest == ignore; /* Claims are turned on and off by a global variable that the RTS sets. This case generates code to diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index d284ffdadca1e..55d9cddfee934 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1523,8 +1523,22 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat, } } +fn require_unsafe(sess: session::session, f_purity: ast::purity, sp: span) { + if sess.get_opts().check_unsafe { + alt f_purity { + ast::unsafe_fn. { ret; } + _ { + sess.span_fatal( + sp, + "Found unsafe expression in safe function decl"); + } + } + } +} + fn require_impure(sess: session::session, f_purity: ast::purity, sp: span) { alt f_purity { + ast::unsafe_fn. { ret; } ast::impure_fn. { ret; } ast::pure_fn. { sess.span_fatal(sp, "Found impure expression in pure function decl"); @@ -1535,7 +1549,29 @@ fn require_impure(sess: session::session, f_purity: ast::purity, sp: span) { fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity, callee: @ast::expr, sp: span) { alt caller_purity { - ast::impure_fn. { ret; } + ast::unsafe_fn. { ret; } + ast::impure_fn. { + let sess = ccx.tcx.sess; + alt ccx.tcx.def_map.find(callee.id) { + some(ast::def_fn(_, ast::unsafe_fn.)) { + if sess.get_opts().check_unsafe { + ccx.tcx.sess.span_fatal( + sp, + "safe function calls function marked unsafe"); + } + } + some(ast::def_native_fn(_)) { + if sess.get_opts().check_unsafe { + ccx.tcx.sess.span_fatal( + sp, + "native functions can only be invoked from unsafe code"); + } + } + _ { + } + } + ret; + } ast::pure_fn. { alt ccx.tcx.def_map.find(callee.id) { some(ast::def_fn(_, ast::pure_fn.)) { ret; } @@ -2063,12 +2099,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, } ast::expr_block(b) { // If this is an unchecked block, turn off purity-checking - let fcx_for_block = - alt b.node.rules { - ast::unchecked. { @{purity: ast::impure_fn with *fcx} } - _ { fcx } - }; - bot = check_block(fcx_for_block, b); + bot = check_block(fcx, b); let typ = alt b.node.expr { some(expr) { expr_ty(tcx, expr) } @@ -2514,7 +2545,12 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool { ret bot; } -fn check_block(fcx: @fn_ctxt, blk: ast::blk) -> bool { +fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool { + let fcx = alt blk.node.rules { + ast::unchecked_blk. { @{purity: ast::impure_fn with *fcx0} } + ast::unsafe_blk. { @{purity: ast::unsafe_fn with *fcx0} } + ast::default_blk. { fcx0 } + }; let bot = false; let warned = false; for s: @ast::stmt in blk.node.stmts { diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 1864af6de9e11..6ad66e244f1f9 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -78,7 +78,8 @@ tag meta_item_ { type blk = spanned; type blk_ = - {stmts: [@stmt], expr: option::t<@expr>, id: node_id, rules: check_mode}; + {stmts: [@stmt], expr: option::t<@expr>, id: node_id, + rules: blk_check_mode}; type pat = {id: node_id, node: pat_, span: span}; @@ -165,7 +166,9 @@ type field_ = {mut: mutability, ident: ident, expr: @expr}; type field = spanned; -tag check_mode { checked; unchecked; } +tag blk_check_mode { default_blk; unchecked_blk; unsafe_blk; } + +tag expr_check_mode { claimed_expr; checked_expr; } type expr = {id: node_id, node: expr_, span: span}; @@ -214,7 +217,7 @@ tag expr_ { expr_assert(@expr); /* preds that typestate is aware of */ - expr_check(check_mode, @expr); + expr_check(expr_check_mode, @expr); /* FIXME Would be nice if expr_check desugared to expr_if_check. */ @@ -382,6 +385,7 @@ type fn_decl = tag purity { pure_fn; // declared with "pure fn" + unsafe_fn; // declared with "unsafe fn" impure_fn; // declared with "fn" } diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index d70b63dac6759..32c381d909015 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -185,13 +185,13 @@ fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); } fn hash_ty(&&t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; } fn block_from_expr(e: @expr) -> blk { - let blk_ = checked_blk([], option::some::<@expr>(e), e.id); + let blk_ = default_block([], option::some::<@expr>(e), e.id); ret {node: blk_, span: e.span}; } -fn checked_blk(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) -> +fn default_block(stmts1: [@stmt], expr1: option::t<@expr>, id1: node_id) -> blk_ { - ret {stmts: stmts1, expr: expr1, id: id1, rules: checked}; + ret {stmts: stmts1, expr: expr1, id: id1, rules: default_blk}; } fn obj_field_from_anon_obj_field(f: anon_obj_field) -> obj_field { diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 8c9097961aded..fd94ee5d8597b 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -165,6 +165,7 @@ fn bad_expr_word_table() -> hashmap { words.insert("fn", ()); words.insert("lambda", ()); words.insert("pure", ()); + words.insert("unsafe", ()); words.insert("iter", ()); words.insert("block", ()); words.insert("import", ()); @@ -826,7 +827,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { p.peek() == token::OROR { ret parse_fn_block_expr(p); } else { - let blk = parse_block_tail(p, lo, ast::checked); + let blk = parse_block_tail(p, lo, ast::default_blk); ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk)); } } else if eat_word(p, "if") { @@ -850,9 +851,9 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { } else if eat_word(p, "lambda") { ret parse_fn_expr(p, ast::proto_closure); } else if eat_word(p, "unchecked") { - expect(p, token::LBRACE); - let blk = parse_block_tail(p, lo, ast::unchecked); - ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk)); + ret parse_block_expr(p, lo, ast::unchecked_blk); + } else if eat_word(p, "unsafe") { + ret parse_block_expr(p, lo, ast::unsafe_blk); } else if p.peek() == token::LBRACKET { p.bump(); let mut = parse_mutability(p); @@ -869,7 +870,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ret mk_mac_expr(p, lo, p.get_hi_pos(), ast::mac_embed_type(ty)); } else if p.peek() == token::POUND_LBRACE { p.bump(); - let blk = ast::mac_embed_block(parse_block_tail(p, lo, ast::checked)); + let blk = ast::mac_embed_block( + parse_block_tail(p, lo, ast::default_blk)); ret mk_mac_expr(p, lo, p.get_hi_pos(), blk); } else if p.peek() == token::ELLIPSIS { p.bump(); @@ -945,7 +947,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { let e = parse_expr(p); hi = e.span.hi; - ex = ast::expr_check(ast::checked, e); + ex = ast::expr_check(ast::checked_expr, e); } else if eat_word(p, "claim") { /* Same rules as check, except that if check-claims is enabled (a command-line flag), then the parser turns @@ -953,7 +955,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { let e = parse_expr(p); hi = e.span.hi; - ex = ast::expr_check(ast::unchecked, e); + ex = ast::expr_check(ast::claimed_expr, e); } else if eat_word(p, "ret") { if can_begin_expr(p.peek()) { let e = parse_expr(p); @@ -1011,6 +1013,14 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ret mk_expr(p, lo, hi, ex); } +fn parse_block_expr(p: parser, + lo: uint, + blk_mode: ast::blk_check_mode) -> @ast::expr { + expect(p, token::LBRACE); + let blk = parse_block_tail(p, lo, blk_mode); + ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk)); +} + fn parse_syntax_ext(p: parser) -> @ast::expr { let lo = p.get_lo_pos(); expect(p, token::POUND); @@ -1308,7 +1318,7 @@ fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr { fn parse_fn_block_expr(p: parser) -> @ast::expr { let lo = p.get_last_lo_pos(); let decl = parse_fn_block_decl(p); - let body = parse_block_tail(p, lo, ast::checked); + let body = parse_block_tail(p, lo, ast::default_blk); let _fn = {decl: decl, proto: ast::proto_block, body: body}; ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn)); } @@ -1672,10 +1682,14 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool { fn parse_block(p: parser) -> ast::blk { let lo = p.get_lo_pos(); if eat_word(p, "unchecked") { - be parse_block_tail(p, lo, ast::unchecked); + expect(p, token::LBRACE); + be parse_block_tail(p, lo, ast::unchecked_blk); + } else if eat_word(p, "unsafe") { + expect(p, token::LBRACE); + be parse_block_tail(p, lo, ast::unsafe_blk); } else { expect(p, token::LBRACE); - be parse_block_tail(p, lo, ast::checked); + be parse_block_tail(p, lo, ast::default_blk); } } @@ -1692,7 +1706,7 @@ fn parse_block_no_value(p: parser) -> ast::blk { // I guess that also means "already parsed the 'impure'" if // necessary, and this should take a qualifier. // some blocks start with "#{"... -fn parse_block_tail(p: parser, lo: uint, s: ast::check_mode) -> ast::blk { +fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk { let stmts: [@ast::stmt] = []; let expr: option::t<@ast::expr> = none; while p.peek() != token::RBRACE { @@ -2139,6 +2153,11 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> { expect_word(p, "fn"); ret some(parse_item_fn_or_iter(p, ast::pure_fn, ast::proto_fn, attrs, ast::il_normal)); + } else if is_word(p, "unsafe") && p.look_ahead(1u) != token::LBRACE { + p.bump(); + expect_word(p, "fn"); + ret some(parse_item_fn_or_iter(p, ast::unsafe_fn, ast::proto_fn, + attrs, ast::il_normal)); } else if eat_word(p, "iter") { ret some(parse_item_fn_or_iter(p, ast::impure_fn, ast::proto_iter, attrs, ast::il_normal)); diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index f20dc407ec8a5..3e90ebc70fd25 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -572,7 +572,11 @@ tag embed_type { block_macro; block_block_fn; block_normal; } fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type, indented: uint) { - alt blk.node.rules { ast::unchecked. { word(s.s, "unchecked"); } _ { } } + alt blk.node.rules { + ast::unchecked_blk. { word(s.s, "unchecked"); } + ast::unsafe_blk. { word(s.s, "unsafe"); } + ast::default_blk. { } + } maybe_print_comment(s, blk.span.lo); let ann_node = node_block(s, blk); @@ -934,8 +938,8 @@ fn print_expr(s: ps, &&expr: @ast::expr) { } ast::expr_check(m, expr) { alt m { - ast::unchecked. { word_nbsp(s, "claim"); } - ast::checked. { word_nbsp(s, "check"); } + ast::claimed_expr. { word_nbsp(s, "claim"); } + ast::checked_expr. { word_nbsp(s, "check"); } } popen(s); print_expr(s, expr); diff --git a/src/lib/io.rs b/src/lib/io.rs index d8f7f36b24f6e..c2ee7ff53ca5c 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -263,7 +263,7 @@ obj fd_buf_writer(fd: int, res: option::t<@fd_res>) { let nout = os::libc::write(fd, vbuf, len); if nout < 0 { log_err "error dumping buffer"; - log_err sys::rustrt::last_os_error(); + log_err sys::last_os_error(); fail; } count += nout as uint; @@ -299,7 +299,7 @@ fn file_buf_writer(path: str, flags: [fileflag]) -> buf_writer { }); if fd < 0 { log_err "error opening file for writing"; - log_err sys::rustrt::last_os_error(); + log_err sys::last_os_error(); fail; } ret fd_buf_writer(fd, option::some(@fd_res(fd))); diff --git a/src/lib/sys.rs b/src/lib/sys.rs index 7bec897ab02c3..c366e7c4ce52c 100644 --- a/src/lib/sys.rs +++ b/src/lib/sys.rs @@ -1,11 +1,8 @@ -import rustrt::size_of; - -export rustrt; -export size_of; +//export rustrt; +//export size_of; native "rust" mod rustrt { - // Explicitly re-export native stuff we want to be made // available outside this crate. Otherwise it's // visible-in-crate, but not re-exported. @@ -17,6 +14,42 @@ native "rust" mod rustrt { fn unsupervise(); } +fn last_os_error() -> str { + //unsafe { + ret rustrt::last_os_error(); + //} +} + +fn size_of() -> uint { + //unsafe { + ret rustrt::size_of::(); + //} +} + +fn align_of() -> uint { + //unsafe { + ret rustrt::align_of::(); + //} +} + +fn refcount(t: @T) -> uint { + //unsafe { + ret rustrt::refcount::(t); + //} +} + +fn do_gc() -> () { + //unsafe { + ret rustrt::do_gc(); + //} +} + +fn unsupervise() -> () { + //unsafe { + ret rustrt::unsupervise(); + //} +} + // Local Variables: // mode: rust; // fill-column: 78; diff --git a/src/lib/uint.rs b/src/lib/uint.rs index d992ade5a7273..12a512e1de829 100644 --- a/src/lib/uint.rs +++ b/src/lib/uint.rs @@ -32,7 +32,7 @@ iter range(lo: uint, hi: uint) -> uint { } fn next_power_of_two(n: uint) -> uint { - let halfbits: uint = sys::rustrt::size_of::() * 4u; + let halfbits: uint = sys::size_of::() * 4u; let tmp: uint = n - 1u; let shift: uint = 1u; while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; } diff --git a/src/lib/vec.rs b/src/lib/vec.rs index bf21e056f6c84..b2d19d9ed54e2 100644 --- a/src/lib/vec.rs +++ b/src/lib/vec.rs @@ -15,7 +15,9 @@ native "rust" mod rustrt { /// Reserves space for `n` elements in the given vector. fn reserve<@T>(&v: [mutable? T], n: uint) { - rustrt::vec_reserve_shared(v, n); + //unsafe { + rustrt::vec_reserve_shared(v, n); + //} } pure fn len(v: [mutable? T]) -> uint { unchecked { rusti::vec_len(v) } } diff --git a/src/test/compile-fail/unsafe-fn-called-from-safe.rs b/src/test/compile-fail/unsafe-fn-called-from-safe.rs new file mode 100644 index 0000000000000..62fcfa689d97f --- /dev/null +++ b/src/test/compile-fail/unsafe-fn-called-from-safe.rs @@ -0,0 +1,8 @@ +// -*- rust -*- +// error-pattern: safe function calls function marked unsafe + +unsafe fn f() { ret; } + +fn main() { + f(); +} diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk new file mode 100755 index 0000000000000..a57f8f90ca9eb Binary files /dev/null and b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk differ diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs new file mode 100644 index 0000000000000..af2b09cc37aee --- /dev/null +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs @@ -0,0 +1,18 @@ +// -*- rust -*- +// +// See also: compile-fail/unsafe-fn-called-from-safe.rs + +unsafe fn f() { ret; } + +fn g() { + unsafe { + f(); + } +} + +fn h() unsafe { + f(); +} + +fn main() { +} diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs new file mode 100644 index 0000000000000..445fdff80aadd --- /dev/null +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs @@ -0,0 +1,13 @@ +// -*- rust -*- +// +// See also: compile-fail/unsafe-fn-called-from-safe.rs + +unsafe fn f() { ret; } + +unsafe fn g() { + f(); +} + +fn main() { + ret; +}