From 1b658a48eafeaaa0d8945d79b8b659d06c77b086 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 5 Oct 2011 15:25:50 -0700 Subject: [PATCH 01/11] remove pthread_exit() from rust_start() as it was causing OS X Lion to hang and (according to Apple) is undefined in any case --- src/rt/rust.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 6d9243b8558c0..122c7b306bf0f 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -109,12 +109,6 @@ rust_start(uintptr_t main_fn, int argc, char **argv, free_env(env); -#if !defined(__WIN32__) - // Don't take down the process if the main thread exits without an - // error. - if (!ret) - pthread_exit(NULL); -#endif return ret; } From 04c850c3779a731cf1bfd062020789c27fb72645 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 6 Oct 2011 15:29:54 -0700 Subject: [PATCH 02/11] expand purity to include unsafe --- src/comp/middle/alias.rs | 40 ++++++++++++++++++--------------- src/comp/middle/typeck.rs | 1 + src/comp/syntax/ast.rs | 1 + src/comp/syntax/parse/parser.rs | 5 +++++ 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 03a060a57fd57..5b69e7e7c967c 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}; } @@ -277,12 +277,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 @@ -390,24 +390,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); } @@ -463,8 +467,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); } } @@ -682,9 +686,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 { @@ -696,10 +700,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}; } _ {} } @@ -707,7 +711,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/typeck.rs b/src/comp/middle/typeck.rs index bdf8b91c8ff70..41ba58ce5e412 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1509,6 +1509,7 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat, 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"); diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 52aa6cb31d929..28ec94f90ad02 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -382,6 +382,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/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 53c3aa01bf064..8ef0d4eb0c437 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", ()); @@ -2141,6 +2142,10 @@ 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 eat_word(p, "unsafe") { + 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)); From e8c2bf5dcd56261724c6e188ac1552ae806eba2c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 6 Oct 2011 16:42:27 -0700 Subject: [PATCH 03/11] Extend the unchecked block stuff to allow unsafe blocks as well. --- src/comp/front/test.rs | 5 ++-- src/comp/metadata/decoder.rs | 1 + src/comp/metadata/encoder.rs | 1 + src/comp/middle/trans.rs | 4 +-- src/comp/middle/typeck.rs | 31 +++++++++++++++++++++--- src/comp/syntax/ast.rs | 9 ++++--- src/comp/syntax/ast_util.rs | 6 ++--- src/comp/syntax/parse/parser.rs | 33 ++++++++++++++++--------- src/comp/syntax/print/pprust.rs | 10 +++++--- src/lib/io.rs | 4 +-- src/lib/sys.rs | 43 +++++++++++++++++++++++++++++---- src/lib/uint.rs | 2 +- 12 files changed, 114 insertions(+), 35 deletions(-) diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 9aed642a2d5dd..3fa016e748a11 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()); + checked_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()); + checked_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..d62a9572ecc46 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) } diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index bf43b158be726..e82f63cae6cee 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/trans.rs b/src/comp/middle/trans.rs index 10418cdfc5422..6a461df9b48d5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4331,11 +4331,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 41ba58ce5e412..547f875417267 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1507,6 +1507,15 @@ 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) { + 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; } @@ -1520,7 +1529,22 @@ 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. { + alt ccx.tcx.def_map.find(callee.id) { + some(ast::def_fn(_, ast::unsafe_fn.)) { + ccx.tcx.sess.span_fatal + (sp, "safe function calls function marked unsafe"); + } + //some(ast::def_native_fn(_)) { + // 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; } @@ -2047,8 +2071,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, // 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 } + ast::unchecked_blk. { @{purity: ast::impure_fn with *fcx} } + ast::unsafe_blk. { @{purity: ast::unsafe_fn with *fcx} } + ast::checked_blk. { fcx } }; bot = check_block(fcx_for_block, b); let typ = diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 28ec94f90ad02..58b03dfea4951 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 { checked_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. */ diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index c4d0272b95fa1..888d542e37ed7 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_ = checked_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 checked_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: checked_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 8ef0d4eb0c437..1c1cbe570689f 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -842,7 +842,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::checked_blk); ret mk_expr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk)); } } else if eat_word(p, "if") { @@ -866,9 +866,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); @@ -885,7 +885,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::checked_blk)); ret mk_mac_expr(p, lo, p.get_hi_pos(), blk); } else if p.peek() == token::ELLIPSIS { p.bump(); @@ -961,7 +962,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 @@ -969,7 +970,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); @@ -1027,6 +1028,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); @@ -1312,7 +1321,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::checked_blk); let _fn = {decl: decl, proto: ast::proto_block, body: body}; ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn)); } @@ -1676,10 +1685,12 @@ 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); + be parse_block_tail(p, lo, ast::unchecked_blk); + } else if eat_word(p, "unsafe") { + 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::checked_blk); } } @@ -1696,7 +1707,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 { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 555cd7fddeea3..b1c201001e1d5 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::checked_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 73460e50588e5..0de057efeeb84 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -266,7 +266,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; @@ -302,7 +302,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; } From dfe1d5f186fc3a3dcda213aa303a9c57134c4dd8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 6 Oct 2011 21:33:04 -0700 Subject: [PATCH 04/11] Add unsafe blocks, unsafe functions, and two rudimentary tests related to them --- src/comp/middle/typeck.rs | 10 ++++++---- src/comp/syntax/parse/parser.rs | 3 ++- src/lib/vec.rs | 4 +++- src/test/compile-fail/unsafe-fn-called-from-safe.rs | 8 ++++++++ src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs | 11 +++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/unsafe-fn-called-from-safe.rs create mode 100644 src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 547f875417267..9882f3f41c8b8 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1536,10 +1536,12 @@ fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity, ccx.tcx.sess.span_fatal (sp, "safe function calls function marked unsafe"); } - //some(ast::def_native_fn(_)) { - // ccx.tcx.sess.span_fatal - // (sp, "native functions can only be invoked from unsafe code"); - //} + /* Temporarily disable until unsafe blocks parse! + some(ast::def_native_fn(_)) { + ccx.tcx.sess.span_fatal + (sp, "native functions can only be invoked from unsafe code"); + } + */ _ { } } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 1c1cbe570689f..adf51db4af5c6 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -2153,7 +2153,8 @@ 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 eat_word(p, "unsafe") { + } 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)); diff --git a/src/lib/vec.rs b/src/lib/vec.rs index 59f29d40d7c1f..e8ea4e1f64065 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.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs new file mode 100644 index 0000000000000..39cdd19a794a2 --- /dev/null +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs @@ -0,0 +1,11 @@ +// -*- rust -*- +// +// See also: compile-fail/unsafe-fn-called-from-safe.rs + +unsafe fn f() { ret; } + +fn main() { + unsafe { + f(); + } +} From 9d645853bbeb363cf0adcfcf87772802598592d3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 6 Oct 2011 21:36:04 -0700 Subject: [PATCH 05/11] it is also legal to call unsafe functions from other unsafe functions --- src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs 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..e19bee45cfc10 --- /dev/null +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs @@ -0,0 +1,10 @@ +// -*- rust -*- +// +// See also: compile-fail/unsafe-fn-called-from-safe.rs + +unsafe fn f() { ret; } + +unsafe fn g() { + f(); +} + From 47a4ff89642a712a64419cf68e8c0eac62e1c702 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Oct 2011 09:01:24 -0700 Subject: [PATCH 06/11] fix test to include a main() function --- src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs | 3 +++ 1 file changed, 3 insertions(+) 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 index e19bee45cfc10..445fdff80aadd 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs @@ -8,3 +8,6 @@ unsafe fn g() { f(); } +fn main() { + ret; +} From 6df42cda8f672084e94ea63b27bdd5fd2bec6b5b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Oct 2011 11:04:22 -0700 Subject: [PATCH 07/11] add 'u' to decoder (kinda' important) --- src/comp/metadata/decoder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index d62a9572ecc46..c4a7d7fef99bb 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -251,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 } From 90fd75bdac84301b649159a013382d2c1c5ea5e3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Oct 2011 11:04:54 -0700 Subject: [PATCH 08/11] add 'u' to one other place it was missing --- src/comp/metadata/decoder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index c4a7d7fef99bb..ee0b7f6c758a3 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -280,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"; } From eccab49c4e519edf92b16b6ee5ce415abc74e7e9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Oct 2011 15:51:55 -0700 Subject: [PATCH 09/11] make treatment of unchecked/unsafe blocks more uniform; also repair various errors in the parser related to such blocks. rename checked_blk to default_blk to reflect the fact that it inherits its purity from the surrounding context. --- src/comp/front/test.rs | 4 ++-- src/comp/middle/typeck.rs | 15 +++++++-------- src/comp/syntax/ast.rs | 2 +- src/comp/syntax/ast_util.rs | 6 +++--- src/comp/syntax/parse/parser.rs | 10 ++++++---- src/comp/syntax/print/pprust.rs | 2 +- .../run-pass/unsafe-fn-called-from-unsafe-blk | Bin 0 -> 9936 bytes .../run-pass/unsafe-fn-called-from-unsafe-blk.rs | 9 ++++++++- 8 files changed, 28 insertions(+), 20 deletions(-) create mode 100755 src/test/run-pass/unsafe-fn-called-from-unsafe-blk diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 3fa016e748a11..08ab86fb7e57f 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_block([], 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,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item { let test_main_call_expr = mk_test_main_call(cx); let body_: ast::blk_ = - checked_block([], option::some(test_main_call_expr), + default_block([], option::some(test_main_call_expr), cx.next_node_id()); let body = {node: body_, span: dummy_sp()}; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 9882f3f41c8b8..8919427db112a 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2071,13 +2071,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_blk. { @{purity: ast::impure_fn with *fcx} } - ast::unsafe_blk. { @{purity: ast::unsafe_fn with *fcx} } - ast::checked_blk. { 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) } @@ -2522,7 +2516,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 58b03dfea4951..dbd6ed1d6c2d0 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -166,7 +166,7 @@ type field_ = {mut: mutability, ident: ident, expr: @expr}; type field = spanned; -tag blk_check_mode { checked_blk; unchecked_blk; unsafe_blk; } +tag blk_check_mode { default_blk; unchecked_blk; unsafe_blk; } tag expr_check_mode { claimed_expr; checked_expr; } diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index 888d542e37ed7..e22da862c7734 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_block([], option::some::<@expr>(e), e.id); + let blk_ = default_block([], option::some::<@expr>(e), e.id); ret {node: blk_, span: e.span}; } -fn checked_block(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_blk}; + 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 adf51db4af5c6..2bd703eb90a7c 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -842,7 +842,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_blk); + 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") { @@ -886,7 +886,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { } else if p.peek() == token::POUND_LBRACE { p.bump(); let blk = ast::mac_embed_block( - parse_block_tail(p, lo, ast::checked_blk)); + 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(); @@ -1321,7 +1321,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_blk); + 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)); } @@ -1685,12 +1685,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") { + 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_blk); + be parse_block_tail(p, lo, ast::default_blk); } } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index b1c201001e1d5..28f8ee7b18c16 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -575,7 +575,7 @@ fn print_possibly_embedded_block(s: ps, blk: ast::blk, embedded: embed_type, alt blk.node.rules { ast::unchecked_blk. { word(s.s, "unchecked"); } ast::unsafe_blk. { word(s.s, "unsafe"); } - ast::checked_blk. { } + ast::default_blk. { } } maybe_print_comment(s, blk.span.lo); 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 0000000000000000000000000000000000000000..a57f8f90ca9eb2a486976b28935c5f795bf5d161 GIT binary patch literal 9936 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 Date: Mon, 10 Oct 2011 10:17:14 -0700 Subject: [PATCH 10/11] enable unsafe checking but only with a flag --check-unsafe --- src/comp/driver/rustc.rs | 7 +++++-- src/comp/driver/session.rs | 3 ++- src/comp/middle/typeck.rs | 29 ++++++++++++++++++----------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 46865d10fa2a2..949dffc8508a1 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 (temporary option) "); } @@ -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/middle/typeck.rs b/src/comp/middle/typeck.rs index 8919427db112a..0432b16e5ab56 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1508,11 +1508,13 @@ 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) { - alt f_purity { - ast::unsafe_fn. { ret; } - _ { - sess.span_fatal(sp, "Found unsafe expression in safe function decl"); - } + if sess.get_opts().check_unsafe { + alt f_purity { + ast::unsafe_fn. { ret; } + _ { + sess.span_fatal(sp, "Found unsafe expression in safe function decl"); + } + } } } @@ -1531,17 +1533,22 @@ fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity, alt caller_purity { 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.)) { - ccx.tcx.sess.span_fatal - (sp, "safe function calls function marked unsafe"); + if sess.get_opts().check_unsafe { + ccx.tcx.sess.span_fatal( + sp, + "safe function calls function marked unsafe"); + } } - /* Temporarily disable until unsafe blocks parse! some(ast::def_native_fn(_)) { - ccx.tcx.sess.span_fatal - (sp, "native functions can only be invoked from unsafe code"); + if sess.get_opts().check_unsafe { + ccx.tcx.sess.span_fatal( + sp, + "native functions can only be invoked from unsafe code"); + } } - */ _ { } } From d75421bca054b5b59669ebc499a9fbb567dbdd00 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 10 Oct 2011 16:24:22 -0700 Subject: [PATCH 11/11] correct lines over 78 chars --- src/comp/driver/rustc.rs | 2 +- src/comp/middle/typeck.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 3d908dc7ebe07..60e5f0db9a9d4 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -264,7 +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 (temporary option) + --check-unsafe disallow unsafe actions in non-unsafe functions "); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 48cbcbc2126fe..55d9cddfee934 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1528,7 +1528,9 @@ fn require_unsafe(sess: session::session, f_purity: ast::purity, sp: span) { alt f_purity { ast::unsafe_fn. { ret; } _ { - sess.span_fatal(sp, "Found unsafe expression in safe function decl"); + sess.span_fatal( + sp, + "Found unsafe expression in safe function decl"); } } }