diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 6f7270f4396f8a652ff0df2262ebf2d5ab1d0443..fcef6e551f122c4a1225f45082801cdeee6e6e26 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 ca3b4f4e2c5e6286918b5ef10c8cf2b7d1ea57bd..d62a9572ecc466e9e49acc84e5169da23846e170 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 7850b4139a1aa4b6b428a79e807be05cf09f0f4c..b67114d3d9a3ddb1e60668f336a25635a6924411 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 9d80a97eb86c718c0ba5b8c71c324c30035ec6d0..4199c81123d5b3fdada58c06ef35f7ca94b695d1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4380,11 +4380,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 ee25c59a7892e462f698bf70ad7ff9c0a61f7b10..411a8ed213f9a978fdcc6531c8e630d0aa065343 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1523,6 +1523,15 @@ fn matches(name: str, f: ty::field) -> bool { } } +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; } @@ -1536,7 +1545,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; } @@ -2066,8 +2090,9 @@ fn check_binop_type_compat(fcx: @fn_ctxt, span: span, ty: ty::t, // 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 36791c10cb27863621f299a9cbfe1bb57387243c..6b72a4b67c375e6e09ed2557c57d1abaed7bf54b 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -78,7 +78,8 @@ 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}; @@ -173,7 +174,9 @@ 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}; @@ -222,7 +225,7 @@ 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 d70b63dac67593bfa7774ed12ae0d51cd330ac4b..5d2a143a946a886521eef214c2246644a6b58e55 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -185,13 +185,13 @@ fn is_constraint_arg(e: @expr) -> bool { 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 5a4c5d78772adbb9f4f39d38bfb2a4f3334b0730..25344a8b2cffed5ff778f9d5a660577cf0505ada 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -828,7 +828,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") { @@ -853,9 +853,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); @@ -872,7 +872,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(); @@ -948,7 +949,7 @@ fn parse_expr_opt(p: parser) -> option::t<@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 @@ -956,7 +957,7 @@ fn parse_expr_opt(p: parser) -> option::t<@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); @@ -1014,6 +1015,14 @@ fn parse_expr_opt(p: parser) -> option::t<@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); @@ -1311,7 +1320,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)); } @@ -1675,10 +1684,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); } } @@ -1695,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 { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index f1b8dc69d1296c4cff337fed935acd24967f52a7..10b5db1e12900202b886568c622c791abb22bbf2 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -572,7 +572,11 @@ fn print_block(s: ps, blk: ast::blk) { 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_opt(s: ps, expr: option::t<@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 d8f7f36b24f6e831c9cea04cb5f99550ec60ebf4..c2ee7ff53ca5c65416f0fca705a5b224cb6e4ac0 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -263,7 +263,7 @@ fn write(v: [u8]) { 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 7bec897ab02c384cd64d7a8129077eae5431bd2d..c366e7c4ce52c57607aa6abb91249fcc273be9c3 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 @@ 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 d992ade5a7273ede2535f52af2fd7eb04ffb45a2..12a512e1de8292ff972a24b8b1126a0e86bdb8a6 100644 --- a/src/lib/uint.rs +++ b/src/lib/uint.rs @@ -32,7 +32,7 @@ } 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; }