about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-10-12 13:31:41 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-12 16:33:07 -0700
commite8a0e592da3e8f5cadc0c854c61b0934d10bc0a4 (patch)
tree2811bd2cbb435c064a999537d3b24082ce67e906
parentf994871a3daaa52c22b89057c575e0f65ffae013 (diff)
reimplement some of the unsafe stuff which got lost
  - blocks inherit unsafety
  - remove the --check-unsafe flag
  - add unsafe annotations where needed to get things to compile
-rw-r--r--src/comp/back/link.rs17
-rw-r--r--src/comp/driver/rustc.rs4
-rw-r--r--src/comp/driver/session.rs3
-rw-r--r--src/comp/lib/llvm.rs4
-rw-r--r--src/comp/metadata/creader.rs36
-rw-r--r--src/comp/metadata/decoder.rs4
-rw-r--r--src/comp/middle/gc.rs6
-rw-r--r--src/comp/middle/shape.rs6
-rw-r--r--src/comp/middle/trans_build.rs6
-rw-r--r--src/comp/middle/trans_common.rs86
-rw-r--r--src/comp/middle/trans_objects.rs4
-rw-r--r--src/comp/middle/typeck.rs36
-rw-r--r--src/compiletest/procsrv.rs6
-rw-r--r--src/lib/aio.rs4
-rw-r--r--src/lib/dbg.rs6
-rw-r--r--src/lib/generic_os.rs2
-rw-r--r--src/lib/io.rs6
-rw-r--r--src/lib/run_program.rs2
-rw-r--r--src/lib/str.rs8
-rw-r--r--src/lib/sys.rs24
-rw-r--r--src/lib/task.rs2
-rw-r--r--src/lib/vec.rs12
-rw-r--r--src/test/compile-fail/unsafe-fn-used-in-bind.rs9
23 files changed, 137 insertions, 156 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index fbf1f4b7881..4a7e238ae55 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -34,16 +34,14 @@ tag output_type {
     output_type_exe;
 }
 
-fn llvm_err(sess: session::session, msg: str) {
-    unsafe {
-        let buf = llvm::LLVMRustGetLastError();
-        if buf == std::ptr::null() {
-            sess.fatal(msg);
-        } else { sess.fatal(msg + ": " + str::str_from_cstr(buf)); }
-    }
+fn llvm_err(sess: session::session, msg: str) unsafe {
+    let buf = llvm::LLVMRustGetLastError();
+    if buf == std::ptr::null() {
+        sess.fatal(msg);
+    } else { sess.fatal(msg + ": " + str::str_from_cstr(buf)); }
 }
 
-fn link_intrinsics(sess: session::session, llmod: ModuleRef) unsafe {
+fn link_intrinsics(sess: session::session, llmod: ModuleRef) {
     let path = alt filesearch::search(
         sess.filesearch(),
         bind filesearch::pick_file("intrinsics.bc", _)) {
@@ -90,8 +88,7 @@ mod write {
         } else { stem = str::substr(output_path, 0u, dot_pos as uint); }
         ret stem + "." + extension;
     }
-    fn run_passes(sess: session::session, llmod: ModuleRef, output: str)
-       unsafe {
+    fn run_passes(sess: session::session, llmod: ModuleRef, output: str) {
         let opts = sess.get_opts();
         if opts.time_llvm_passes { llvm::LLVMRustEnableTimePasses(); }
         link_intrinsics(sess, llmod);
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index 46f8da829a6..43d138c9e1a 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -325,7 +325,6 @@ 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 {
@@ -397,8 +396,7 @@ fn build_session_options(match: getopts::match)
           parse_only: parse_only,
           no_trans: no_trans,
           do_gc: do_gc,
-          stack_growth: stack_growth,
-          check_unsafe: check_unsafe};
+          stack_growth: stack_growth};
     ret sopts;
 }
 
diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs
index 6ba2148e8a4..1f3f9baab8a 100644
--- a/src/comp/driver/session.rs
+++ b/src/comp/driver/session.rs
@@ -41,8 +41,7 @@ type options =
      parse_only: bool,
      no_trans: bool,
      do_gc: bool,
-     stack_growth: bool,
-     check_unsafe: bool};
+     stack_growth: bool};
 
 type crate_metadata = {name: str, data: [u8]};
 
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index c028c028e6b..9562e05bed5 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -956,7 +956,7 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
       7 {
         ret "i" + std::int::str(llvm::LLVMGetIntTypeWidth(ty) as int);
       }
-      8 unsafe {
+      8 {
         let s = "fn(";
         let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
         let n_args: uint = llvm::LLVMCountParamTypes(ty);
@@ -969,7 +969,7 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
         s += type_to_str_inner(names, outer, out_ty);
         ret s;
       }
-      9 unsafe {
+      9 {
         let s: str = "{";
         let n_elts: uint = llvm::LLVMCountStructElementTypes(ty);
         let elts: [TypeRef] = vec::init_elt::<TypeRef>(0 as TypeRef, n_elts);
diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs
index 1dd51a8b680..fe352290d2c 100644
--- a/src/comp/metadata/creader.rs
+++ b/src/comp/metadata/creader.rs
@@ -169,27 +169,25 @@ fn find_library_crate_aux(nn: {prefix: str, suffix: str}, crate_name: str,
     });
 }
 
-fn get_metadata_section(filename: str) -> option::t<@[u8]> {
-    unsafe {
-        let mb = str::as_buf(filename, {|buf|
-            llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
-                                       });
-        if mb as int == 0 { ret option::none::<@[u8]>; }
-        let of = mk_object_file(mb);
-        let si = mk_section_iter(of.llof);
-        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
-            let name_buf = llvm::LLVMGetSectionName(si.llsi);
-            let name = str::str_from_cstr(name_buf);
-            if str::eq(name, x86::get_meta_sect_name()) {
-                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
-                let csz = llvm::LLVMGetSectionSize(si.llsi);
-                let cvbuf: *u8 = std::unsafe::reinterpret_cast(cbuf);
-                ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz));
-            }
-            llvm::LLVMMoveToNextSection(si.llsi);
+fn get_metadata_section(filename: str) -> option::t<@[u8]> unsafe {
+    let mb = str::as_buf(filename, {|buf|
+        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
+                                   });
+    if mb as int == 0 { ret option::none::<@[u8]>; }
+    let of = mk_object_file(mb);
+    let si = mk_section_iter(of.llof);
+    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
+        let name_buf = llvm::LLVMGetSectionName(si.llsi);
+        let name = str::str_from_cstr(name_buf);
+        if str::eq(name, x86::get_meta_sect_name()) {
+            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
+            let csz = llvm::LLVMGetSectionSize(si.llsi);
+            let cvbuf: *u8 = std::unsafe::reinterpret_cast(cbuf);
+            ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz));
         }
-        ret option::none::<@[u8]>;
+        llvm::LLVMMoveToNextSection(si.llsi);
     }
+    ret option::none::<@[u8]>;
 }
 
 fn load_library_crate(sess: session::session, span: span, ident: ast::ident,
diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs
index 4a103d35755..8d3f8f5d824 100644
--- a/src/comp/metadata/decoder.rs
+++ b/src/comp/metadata/decoder.rs
@@ -256,6 +256,8 @@ fn family_has_type_params(fam_ch: u8) -> bool {
           'u' { true }
           'p' { true }
           'F' { true }
+          'U' { true }
+          'P' { true }
           'y' { true }
           't' { true }
           'T' { false }
@@ -285,6 +287,8 @@ fn item_family_to_str(fam: u8) -> str {
       'u' { ret "unsafe fn"; }
       'p' { ret "pure fn"; }
       'F' { ret "native fn"; }
+      'U' { ret "unsafe native fn"; }
+      'P' { ret "pure native fn"; }
       'y' { ret "type"; }
       'T' { ret "native type"; }
       't' { ret "type"; }
diff --git a/src/comp/middle/gc.rs b/src/comp/middle/gc.rs
index 7de07b55e3b..be5376bc2b6 100644
--- a/src/comp/middle/gc.rs
+++ b/src/comp/middle/gc.rs
@@ -16,8 +16,7 @@ type ctxt = @{mutable next_tydesc_num: uint};
 
 fn mk_ctxt() -> ctxt { ret @{mutable next_tydesc_num: 0u}; }
 
-fn add_global(ccx: @crate_ctxt, llval: ValueRef, name: str)
-   -> ValueRef unsafe {
+fn add_global(ccx: @crate_ctxt, llval: ValueRef, name: str) -> ValueRef {
     let llglobal =
         str::as_buf(name,
                     {|buf|
@@ -28,8 +27,7 @@ fn add_global(ccx: @crate_ctxt, llval: ValueRef, name: str)
     ret llglobal;
 }
 
-fn add_gc_root(cx: @block_ctxt, llval: ValueRef, ty: ty::t) ->
-   @block_ctxt unsafe {
+fn add_gc_root(cx: @block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt {
     let bcx = cx;
     if !type_is_gc_relevant(bcx_tcx(cx), ty) ||
            ty::type_has_dynamic_size(bcx_tcx(cx), ty) {
diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs
index 17c72d6b6c2..7c54bde66b3 100644
--- a/src/comp/middle/shape.rs
+++ b/src/comp/middle/shape.rs
@@ -72,7 +72,7 @@ fn eq_res_info(a: res_info, b: res_info) -> bool {
 }
 
 fn mk_global(ccx: @crate_ctxt, name: str, llval: ValueRef, internal: bool) ->
-   ValueRef unsafe {
+   ValueRef {
     let llglobal =
         str::as_buf(name,
                     {|buf|
@@ -245,7 +245,7 @@ fn s_float(_tcx: ty_ctxt) -> u8 {
     ret shape_f64; // TODO: x86-64
 }
 
-fn mk_ctxt(llmod: ModuleRef) -> ctxt unsafe {
+fn mk_ctxt(llmod: ModuleRef) -> ctxt {
     let llshapetablesty = trans_common::T_named_struct("shapes");
     let llshapetables =
         str::as_buf("shapes",
@@ -580,7 +580,7 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
     ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
 }
 
-fn gen_shape_tables(ccx: @crate_ctxt) unsafe {
+fn gen_shape_tables(ccx: @crate_ctxt) {
     let lltagstable = gen_tag_shapes(ccx);
     let llresourcestable = gen_resource_shapes(ccx);
     trans_common::set_struct_body(ccx.shape_cx.llshapetablesty,
diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs
index 7cf9a9c27b3..d0b0523af93 100644
--- a/src/comp/middle/trans_build.rs
+++ b/src/comp/middle/trans_build.rs
@@ -492,16 +492,16 @@ fn _UndefReturn(Fn: ValueRef) -> ValueRef {
 }
 
 fn Call(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
+    if cx.unreachable { ret _UndefReturn(Fn); }
     unsafe {
-        if cx.unreachable { ret _UndefReturn(Fn); }
         ret llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
                                 vec::len(Args), noname());
     }
 }
 
 fn FastCall(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
+    if cx.unreachable { ret _UndefReturn(Fn); }
     unsafe {
-        if cx.unreachable { ret _UndefReturn(Fn); }
         let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
                                     vec::len(Args), noname());
         llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
@@ -511,8 +511,8 @@ fn FastCall(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
 
 fn CallWithConv(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], Conv: uint)
    -> ValueRef {
+    if cx.unreachable { ret _UndefReturn(Fn); }
     unsafe {
-        if cx.unreachable { ret _UndefReturn(Fn); }
         let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
                                     vec::len(Args), noname());
         llvm::LLVMSetInstructionCallConv(v, Conv);
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index 945530d87d2..6ed895aa655 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -427,14 +427,12 @@ fn val_ty(v: ValueRef) -> TypeRef { ret llvm::LLVMTypeOf(v); }
 fn val_str(tn: type_names, v: ValueRef) -> str { ret ty_str(tn, val_ty(v)); }
 
 // Returns the nth element of the given LLVM structure type.
-fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef {
-    unsafe {
-        let elt_count = llvm::LLVMCountStructElementTypes(llstructty);
-        assert (n < elt_count);
-        let elt_tys = std::vec::init_elt(T_nil(), elt_count);
-        llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
-        ret llvm::LLVMGetElementType(elt_tys[n]);
-    }
+fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
+    let elt_count = llvm::LLVMCountStructElementTypes(llstructty);
+    assert (n < elt_count);
+    let elt_tys = std::vec::init_elt(T_nil(), elt_count);
+    llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
+    ret llvm::LLVMGetElementType(elt_tys[n]);
 }
 
 fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
@@ -541,10 +539,8 @@ fn T_named_struct(name: str) -> TypeRef {
     ret str::as_buf(name, {|buf| llvm::LLVMStructCreateNamed(c, buf) });
 }
 
-fn set_struct_body(t: TypeRef, elts: [TypeRef]) {
-    unsafe {
-        llvm::LLVMStructSetBody(t, to_ptr(elts), std::vec::len(elts), False);
-    }
+fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
+    llvm::LLVMStructSetBody(t, to_ptr(elts), std::vec::len(elts), False);
 }
 
 fn T_empty_struct() -> TypeRef { ret T_struct([]); }
@@ -581,18 +577,16 @@ fn T_task() -> TypeRef {
     ret t;
 }
 
-fn T_tydesc_field(cx: crate_ctxt, field: int) -> TypeRef {
+fn T_tydesc_field(cx: crate_ctxt, field: int) -> TypeRef unsafe {
     // Bit of a kludge: pick the fn typeref out of the tydesc..
 
-    unsafe {
-        let tydesc_elts: [TypeRef] =
-            std::vec::init_elt::<TypeRef>(T_nil(),
-                                          abi::n_tydesc_fields as uint);
-        llvm::LLVMGetStructElementTypes(cx.tydesc_type,
-                                        to_ptr::<TypeRef>(tydesc_elts));
-        let t = llvm::LLVMGetElementType(tydesc_elts[field]);
-        ret t;
-    }
+    let tydesc_elts: [TypeRef] =
+        std::vec::init_elt::<TypeRef>(T_nil(),
+                                      abi::n_tydesc_fields as uint);
+    llvm::LLVMGetStructElementTypes(cx.tydesc_type,
+                                    to_ptr::<TypeRef>(tydesc_elts));
+    let t = llvm::LLVMGetElementType(tydesc_elts[field]);
+    ret t;
 }
 
 fn T_glue_fn(cx: crate_ctxt) -> TypeRef {
@@ -798,43 +792,33 @@ fn C_postr(s: str) -> ValueRef {
                     });
 }
 
-fn C_zero_byte_arr(size: uint) -> ValueRef {
-    unsafe {
-        let i = 0u;
-        let elts: [ValueRef] = [];
-        while i < size { elts += [C_u8(0u)]; i += 1u; }
-        ret llvm::LLVMConstArray(T_i8(), std::vec::to_ptr(elts),
-                                 std::vec::len(elts));
-    }
+fn C_zero_byte_arr(size: uint) -> ValueRef unsafe {
+    let i = 0u;
+    let elts: [ValueRef] = [];
+    while i < size { elts += [C_u8(0u)]; i += 1u; }
+    ret llvm::LLVMConstArray(T_i8(), std::vec::to_ptr(elts),
+                             std::vec::len(elts));
 }
 
-fn C_struct(elts: [ValueRef]) -> ValueRef {
-    unsafe {
-        ret llvm::LLVMConstStruct(std::vec::to_ptr(elts), std::vec::len(elts),
-                                  False);
-    }
+fn C_struct(elts: [ValueRef]) -> ValueRef unsafe {
+    ret llvm::LLVMConstStruct(std::vec::to_ptr(elts), std::vec::len(elts),
+                              False);
 }
 
-fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef {
-    unsafe {
-        ret llvm::LLVMConstNamedStruct(T, std::vec::to_ptr(elts),
-                                       std::vec::len(elts));
-    }
+fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
+    ret llvm::LLVMConstNamedStruct(T, std::vec::to_ptr(elts),
+                                   std::vec::len(elts));
 }
 
-fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef {
-    unsafe {
-        ret llvm::LLVMConstArray(ty, std::vec::to_ptr(elts),
-                                 std::vec::len(elts));
-    }
+fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
+    ret llvm::LLVMConstArray(ty, std::vec::to_ptr(elts),
+                             std::vec::len(elts));
 }
 
-fn C_bytes(bytes: [u8]) -> ValueRef {
-    unsafe {
-        ret llvm::LLVMConstString(
-            unsafe::reinterpret_cast(vec::to_ptr(bytes)),
-            vec::len(bytes), False);
-    }
+fn C_bytes(bytes: [u8]) -> ValueRef unsafe {
+    ret llvm::LLVMConstString(
+        unsafe::reinterpret_cast(vec::to_ptr(bytes)),
+        vec::len(bytes), False);
 }
 
 fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs
index af5f4266b9e..a2a63d88306 100644
--- a/src/comp/middle/trans_objects.rs
+++ b/src/comp/middle/trans_objects.rs
@@ -569,7 +569,7 @@ fn create_backwarding_vtbl(cx: @local_ctxt, sp: span, inner_obj_ty: ty::t,
 // finish_vtbl: Given a vector of vtable entries, create the table in
 // read-only memory and return a pointer to it.
 fn finish_vtbl(cx: @local_ctxt, llmethods: [ValueRef], name: str) ->
-   ValueRef unsafe {
+   ValueRef {
     let vtbl = C_struct(llmethods);
     let vtbl_name = mangle_internal_name_by_path(cx.ccx, cx.path + [name]);
     let gvar =
@@ -619,7 +619,7 @@ fn begin_fn(cx: @local_ctxt, sp: span, m: @ty::method,
 // returns the value returned from that call.
 fn process_bkwding_mthd(cx: @local_ctxt, sp: span, m: @ty::method,
                         ty_params: [ast::ty_param], outer_obj_ty: ty::t,
-                        _additional_field_tys: [ty::t]) -> ValueRef unsafe {
+                        _additional_field_tys: [ty::t]) -> ValueRef {
 
     let llbackwarding_fn = begin_fn(cx, sp, m, ty_params, "backwarding_fn");
     let fcx = new_fn_ctxt(cx, sp, llbackwarding_fn);
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index aed017eeef5..4b0f4f7b1c1 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -1524,15 +1524,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) {
-    if sess.get_opts().check_unsafe {
-        alt f_purity {
-          ast::unsafe_fn. { ret; }
-          _ {
-            sess.span_err(
-                sp,
-                "unsafe operation requires unsafe function or block");
-          }
-        }
+    alt f_purity {
+      ast::unsafe_fn. { ret; }
+      _ {
+        sess.span_err(
+            sp,
+            "unsafe operation requires unsafe function or block");
+      }
     }
 }
 
@@ -1551,15 +1549,12 @@ 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.)) |
           some(ast::def_native_fn(_, ast::unsafe_fn.)) {
-            if sess.get_opts().check_unsafe {
-                ccx.tcx.sess.span_err(
-                    sp,
-                    "safe function calls function marked unsafe");
-            }
+            ccx.tcx.sess.span_err(
+                sp,
+                "safe function calls function marked unsafe");
           }
           _ {
           }
@@ -2727,13 +2722,22 @@ fn check_constraints(fcx: @fn_ctxt, cs: [@ast::constr], args: [ast::arg]) {
 
 fn check_fn(ccx: @crate_ctxt, f: ast::_fn, id: ast::node_id,
             old_fcx: option::t<@fn_ctxt>) {
+
     let decl = f.decl;
     let body = f.body;
+
+    // If old_fcx is some(...), this is a block fn { |x| ... }.
+    // In that case, the purity is inherited from the context.
+    let purity = alt old_fcx {
+      none. { decl.purity }
+      some(f) { assert decl.purity == ast::impure_fn; f.purity }
+    };
+
     let gather_result = gather_locals(ccx, f, id, old_fcx);
     let fixups: [ast::node_id] = [];
     let fcx: @fn_ctxt =
         @{ret_ty: ty::ty_fn_ret(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)),
-          purity: decl.purity,
+          purity: purity,
           proto: f.proto,
           var_bindings: gather_result.var_bindings,
           locals: gather_result.locals,
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index 467b98d8b64..1563e3112ca 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -70,7 +70,7 @@ fn run(handle: handle, lib_path: str, prog: str, args: [str],
     ret {status: status, out: output, err: errput};
 }
 
-fn writeclose(fd: int, s: option::t<str>) unsafe {
+fn writeclose(fd: int, s: option::t<str>) {
     if option::is_some(s) {
         let writer = io::new_writer(io::fd_buf_writer(fd, option::none));
         writer.write_str(option::get(s));
@@ -79,7 +79,7 @@ fn writeclose(fd: int, s: option::t<str>) unsafe {
     os::libc::close(fd);
 }
 
-fn readclose(fd: int) -> str unsafe {
+fn readclose(fd: int) -> str {
     // Copied from run::program_output
     let file = os::fd_FILE(fd);
     let reader = io::new_reader(io::FILE_buf_reader(file, option::none));
@@ -92,7 +92,7 @@ fn readclose(fd: int) -> str unsafe {
     ret buf;
 }
 
-fn worker(p: port<request>) unsafe {
+fn worker(p: port<request>) {
 
     // FIXME (787): If we declare this inside of the while loop and then
     // break out of it before it's ever initialized (i.e. we don't run
diff --git a/src/lib/aio.rs b/src/lib/aio.rs
index 5d7430a82ec..42f744ff865 100644
--- a/src/lib/aio.rs
+++ b/src/lib/aio.rs
@@ -41,7 +41,7 @@ tag request {
 
 type ctx = chan<request>;
 
-fn ip_to_sbuf(ip: net::ip_addr) -> *u8 {
+fn ip_to_sbuf(ip: net::ip_addr) -> *u8 unsafe {
 
     // FIXME: This is broken. We're creating a vector, getting a pointer
     // to its buffer, then dropping the vector. On top of that, the vector
@@ -131,7 +131,7 @@ fn request_task(c: chan<ctx>) {
           serve(ip, portnum, events, server) {
             task::spawn(bind server_task(ip, portnum, events, server));
           }
-          write(socket, v, status) {
+          write(socket, v, status) unsafe {
             rustrt::aio_writedata(socket, vec::unsafe::to_ptr::<u8>(v),
                                   vec::len::<u8>(v), status);
           }
diff --git a/src/lib/dbg.rs b/src/lib/dbg.rs
index 6371eec349b..af568ee8f0c 100644
--- a/src/lib/dbg.rs
+++ b/src/lib/dbg.rs
@@ -42,9 +42,11 @@ fn debug_obj<T>(x: T, nmethods: uint, nbytes: uint) {
 
 fn debug_fn<T>(x: T) { rustrt::debug_fn::<T>(x); }
 
-fn ptr_cast<T, U>(x: @T) -> @U { ret rustrt::debug_ptrcast::<T, U>(x); }
+unsafe fn ptr_cast<T, U>(x: @T) -> @U {
+    ret rustrt::debug_ptrcast::<T, U>(x);
+}
 
-fn refcount<T>(a: @T) -> uint {
+fn refcount<T>(a: @T) -> uint unsafe {
     let p: *uint = unsafe::reinterpret_cast(a);
     ret *p;
 }
diff --git a/src/lib/generic_os.rs b/src/lib/generic_os.rs
index e179aa1f92c..d1e39a2ea9f 100644
--- a/src/lib/generic_os.rs
+++ b/src/lib/generic_os.rs
@@ -3,7 +3,7 @@ import str::sbuf;
 
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
-fn getenv(n: str) -> option::t<str> {
+fn getenv(n: str) -> option::t<str> unsafe {
     let s = str::as_buf(n, {|buf| os::libc::getenv(buf) });
     ret if unsafe::reinterpret_cast(s) == 0 {
             option::none::<str>
diff --git a/src/lib/io.rs b/src/lib/io.rs
index c2ee7ff53ca..327e5655889 100644
--- a/src/lib/io.rs
+++ b/src/lib/io.rs
@@ -57,7 +57,7 @@ fn convert_whence(whence: seek_style) -> int {
 resource FILE_res(f: os::libc::FILE) { os::libc::fclose(f); }
 
 obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
-    fn read(len: uint) -> [u8] {
+    fn read(len: uint) -> [u8] unsafe {
         let buf = [];
         vec::reserve::<u8>(buf, len);
         let read =
@@ -239,7 +239,7 @@ type buf_writer =
     };
 
 obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
-    fn write(v: [u8]) {
+    fn write(v: [u8]) unsafe {
         let len = vec::len::<u8>(v);
         let vbuf = vec::unsafe::to_ptr::<u8>(v);
         let nout = os::libc::fwrite(vbuf, len, 1u, f);
@@ -254,7 +254,7 @@ obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
 resource fd_res(fd: int) { os::libc::close(fd); }
 
 obj fd_buf_writer(fd: int, res: option::t<@fd_res>) {
-    fn write(v: [u8]) {
+    fn write(v: [u8]) unsafe {
         let len = vec::len::<u8>(v);
         let count = 0u;
         let vbuf;
diff --git a/src/lib/run_program.rs b/src/lib/run_program.rs
index 31bccf32037..cb36179587f 100644
--- a/src/lib/run_program.rs
+++ b/src/lib/run_program.rs
@@ -21,7 +21,7 @@ fn arg_vec(prog: str, args: [@str]) -> [sbuf] {
 }
 
 fn spawn_process(prog: str, args: [str], in_fd: int, out_fd: int, err_fd: int)
-   -> int {
+   -> int unsafe {
     // Note: we have to hold on to these vector references while we hold a
     // pointer to their buffers
     let prog = prog;
diff --git a/src/lib/str.rs b/src/lib/str.rs
index a3c8a548692..7a566024422 100644
--- a/src/lib/str.rs
+++ b/src/lib/str.rs
@@ -426,16 +426,18 @@ type sbuf = *u8;
 
 // NB: This is intentionally unexported because it's easy to misuse (there's
 // no guarantee that the string is rooted). Instead, use as_buf below.
-fn buf(s: str) -> sbuf {
+unsafe fn buf(s: str) -> sbuf {
     let saddr = ptr::addr_of(s);
     let vaddr: *[u8] = unsafe::reinterpret_cast(saddr);
     let buf = vec::to_ptr(*vaddr);
     ret buf;
 }
 
-fn as_buf<T>(s: str, f: block(sbuf) -> T) -> T { let buf = buf(s); f(buf) }
+fn as_buf<T>(s: str, f: block(sbuf) -> T) -> T unsafe {
+    let buf = buf(s); f(buf)
+}
 
-fn str_from_cstr(cstr: sbuf) -> str {
+unsafe fn str_from_cstr(cstr: sbuf) -> str {
     let res = "";
     let start = cstr;
     let curr = start;
diff --git a/src/lib/sys.rs b/src/lib/sys.rs
index c366e7c4ce5..40209f9e54e 100644
--- a/src/lib/sys.rs
+++ b/src/lib/sys.rs
@@ -15,39 +15,27 @@ native "rust" mod rustrt {
 }
 
 fn last_os_error() -> str {
-    //unsafe {
-        ret rustrt::last_os_error();
-    //}
+    ret rustrt::last_os_error();
 }
 
 fn size_of<T>() -> uint {
-    //unsafe {
-        ret rustrt::size_of::<T>();
-    //}
+    ret rustrt::size_of::<T>();
 }
 
 fn align_of<T>() -> uint {
-    //unsafe {
-        ret rustrt::align_of::<T>();
-    //}
+    ret rustrt::align_of::<T>();
 }
 
 fn refcount<T>(t: @T) -> uint {
-    //unsafe {
-        ret rustrt::refcount::<T>(t);
-    //}
+    ret rustrt::refcount::<T>(t);
 }
 
 fn do_gc() -> () {
-    //unsafe {
-        ret rustrt::do_gc();
-    //}
+    ret rustrt::do_gc();
 }
 
 fn unsupervise() -> () {
-    //unsafe {
-        ret rustrt::unsupervise();
-    //}
+    ret rustrt::unsupervise();
 }
 
 // Local Variables:
diff --git a/src/lib/task.rs b/src/lib/task.rs
index 7a95ea49aaf..de1a749fee3 100644
--- a/src/lib/task.rs
+++ b/src/lib/task.rs
@@ -108,7 +108,7 @@ fn spawn_joinable(-thunk: fn()) -> joinable_task {
 
 // FIXME: make this a fn~ once those are supported.
 fn spawn_inner(-thunk: fn(), notify: option<comm::chan<task_notification>>) ->
-   task_id {
+   task_id unsafe {
     let id = rustrt::new_task();
 
     let raw_thunk: {code: u32, env: u32} = cast(thunk);
diff --git a/src/lib/vec.rs b/src/lib/vec.rs
index b2d19d9ed54..04e35e9e979 100644
--- a/src/lib/vec.rs
+++ b/src/lib/vec.rs
@@ -15,9 +15,7 @@ native "rust" mod rustrt {
 
 /// Reserves space for `n` elements in the given vector.
 fn reserve<@T>(&v: [mutable? T], n: uint) {
-    //unsafe {
-        rustrt::vec_reserve_shared(v, n);
-    //}
+    rustrt::vec_reserve_shared(v, n);
 }
 
 pure fn len<T>(v: [mutable? T]) -> uint { unchecked { rusti::vec_len(v) } }
@@ -353,22 +351,22 @@ iter iter2<@T>(v: [T]) -> (uint, T) {
 mod unsafe {
     type vec_repr = {mutable fill: uint, mutable alloc: uint, data: u8};
 
-    fn from_buf<@T>(ptr: *T, elts: uint) -> [T] {
+    unsafe fn from_buf<@T>(ptr: *T, elts: uint) -> [T] {
         ret rustrt::vec_from_buf_shared(ptr, elts);
     }
 
-    fn set_len<@T>(&v: [T], new_len: uint) {
+    unsafe fn set_len<@T>(&v: [T], new_len: uint) {
         let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
         (**repr).fill = new_len * sys::size_of::<T>();
     }
 
-    fn to_ptr<@T>(v: [T]) -> *T {
+    unsafe fn to_ptr<@T>(v: [T]) -> *T {
         let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
         ret ::unsafe::reinterpret_cast(addr_of((**repr).data));
     }
 }
 
-fn to_ptr<@T>(v: [T]) -> *T { ret unsafe::to_ptr(v); }
+unsafe fn to_ptr<@T>(v: [T]) -> *T { ret unsafe::to_ptr(v); }
 
 // Local Variables:
 // mode: rust;
diff --git a/src/test/compile-fail/unsafe-fn-used-in-bind.rs b/src/test/compile-fail/unsafe-fn-used-in-bind.rs
new file mode 100644
index 00000000000..2622afe2e39
--- /dev/null
+++ b/src/test/compile-fail/unsafe-fn-used-in-bind.rs
@@ -0,0 +1,9 @@
+// -*- rust -*-
+// error-pattern: unsafe functions can only be called
+
+unsafe fn f(x: int, y: int) -> int { ret x + y; }
+
+fn main() {
+    let x = bind f(3, _);
+    let y = x(4);
+}