about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-06-21 08:47:48 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-06-21 08:47:48 -0700
commit4396ad488f28f52bfbf4fe86cbba989761a21992 (patch)
tree7737fc921af97dc67d6b63fa8b692ab8e66c3c00
parent0a6943dd31e8002b2e0267b7539b55ba9da7490b (diff)
parent60603703eaec6944341608f54f46661099a2423b (diff)
downloadrust-4396ad488f28f52bfbf4fe86cbba989761a21992.tar.gz
rust-4396ad488f28f52bfbf4fe86cbba989761a21992.zip
Merge remote-tracking branch 'mozilla/incoming' into incoming
-rw-r--r--src/libcore/comm.rs51
-rw-r--r--src/libcore/stackwalk.rs10
-rw-r--r--src/libcore/str.rs2
-rw-r--r--src/libstd/par.rs2
-rw-r--r--src/rustc/middle/borrowck/check_loans.rs16
-rw-r--r--src/rustc/middle/resolve.rs33
-rw-r--r--src/rustc/middle/trans/base.rs94
-rw-r--r--src/rustc/middle/trans/shape.rs15
-rw-r--r--src/rustc/middle/trans/type_of.rs7
-rw-r--r--src/rustc/util/ppaux.rs6
-rw-r--r--src/snapshots.txt8
-rw-r--r--src/test/bench/graph500-bfs.rs2
-rw-r--r--src/test/compile-fail/borrowck-issue-2657-1.rs9
-rw-r--r--src/test/compile-fail/borrowck-issue-2657-2.rs14
-rw-r--r--src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs7
-rw-r--r--src/test/run-pass/borrowck-move-from-unsafe-ptr-ok.rs11
-rw-r--r--src/test/run-pass/nested-class.rs15
17 files changed, 219 insertions, 83 deletions
diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs
index 7c2a9737f04..7f43f6f308c 100644
--- a/src/libcore/comm.rs
+++ b/src/libcore/comm.rs
@@ -94,27 +94,31 @@ fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
     f(po.chan())
 }
 
-resource port_ptr<T: send>(po: *rust_port) unsafe {
+class port_ptr<T:send> {
+  let po: *rust_port;
+  new(po: *rust_port) { self.po = po; }
+  drop unsafe {
     task::unkillable {||
         // Once the port is detached it's guaranteed not to receive further
         // messages
         let yield = 0u;
         let yieldp = ptr::addr_of(yield);
-        rustrt::rust_port_begin_detach(po, yieldp);
+        rustrt::rust_port_begin_detach(self.po, yieldp);
         if yield != 0u {
             // Need to wait for the port to be detached
             // FIXME: If this fails then we're going to leave our port
             // in a bogus state. (Issue #1988)
             task::yield();
         }
-        rustrt::rust_port_end_detach(po);
+        rustrt::rust_port_end_detach(self.po);
 
         // Drain the port so that all the still-enqueued items get dropped
-        while rustrt::rust_port_size(po) > 0u as size_t {
-            recv_::<T>(po);
+        while rustrt::rust_port_size(self.po) > 0u as size_t {
+            recv_::<T>(self.po);
         }
-        rustrt::del_port(po);
+        rustrt::del_port(self.po);
     }
+  }
 }
 
 #[doc = "
@@ -126,21 +130,26 @@ Fails if the port is detached or dead. Fails if the port
 is owned by a different task.
 "]
 fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {
-    resource portref(p: *rust_port) {
-        if !ptr::is_null(p) {
-            rustrt::rust_port_drop(p);
-        }
+
+    class portref {
+       let p: *rust_port;
+       new(p: *rust_port) { self.p = p; }
+       drop {
+         if !ptr::is_null(self.p) {
+           rustrt::rust_port_drop(self.p);
+         }
+       }
     }
 
     let p = portref(rustrt::rust_port_take(*ch));
 
-    if ptr::is_null(*p) {
+    if ptr::is_null(p.p) {
         fail "unable to locate port for channel"
-    } else if rustrt::get_task_id() != rustrt::rust_port_task(*p) {
+    } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
         fail "unable to access unowned port"
     }
 
-    f(*p)
+    f(p.p)
 }
 
 #[doc = "
@@ -148,7 +157,7 @@ Constructs a channel. The channel is bound to the port used to
 construct it.
 "]
 fn chan<T: send>(p: port<T>) -> chan<T> {
-    chan_t(rustrt::get_port_id(***p))
+    chan_t(rustrt::get_port_id((**p).po))
 }
 
 #[doc = "
@@ -170,10 +179,10 @@ fn send<T: send>(ch: chan<T>, -data: T) {
 Receive from a port.  If no data is available on the port then the
 task will block until data becomes available.
 "]
-fn recv<T: send>(p: port<T>) -> T { recv_(***p) }
+fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }
 
 #[doc = "Returns true if there are messages available"]
-fn peek<T: send>(p: port<T>) -> bool { peek_(***p) }
+fn peek<T: send>(p: port<T>) -> bool { peek_((**p).po) }
 
 #[doc(hidden)]
 fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
@@ -196,7 +205,7 @@ fn recv_<T: send>(p: *rust_port) -> T {
         // Data isn't available yet, so res has not been initialized.
         task::yield();
     } else {
-        // In the absense of compiler-generated preemption points
+        // In the absence of compiler-generated preemption points
         // this is a good place to yield
         task::yield();
     }
@@ -210,7 +219,7 @@ fn peek_(p: *rust_port) -> bool unsafe {
 #[doc = "Receive on one of two ports"]
 fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
     -> either<A, B> unsafe {
-    let ports = [***p_a, ***p_b];
+    let ports = [(**p_a).po, (**p_b).po];
     let n_ports = 2 as libc::size_t;
     let yield = 0u, yieldp = ptr::addr_of(yield);
 
@@ -233,9 +242,9 @@ fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
     // Now we know the port we're supposed to receive from
     assert resport != ptr::null();
 
-    if resport == ***p_a {
+    if resport == (**p_a).po {
         either::left(recv(p_a))
-    } else if resport == ***p_b {
+    } else if resport == (**p_b).po {
         either::right(recv(p_b))
     } else {
         fail "unexpected result from rust_port_select";
@@ -482,4 +491,4 @@ fn test_port_detach_fail() {
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs
index 321fa605f48..0041dde319d 100644
--- a/src/libcore/stackwalk.rs
+++ b/src/libcore/stackwalk.rs
@@ -23,10 +23,10 @@ fn walk_stack(visit: fn(frame) -> bool) {
             reinterpret_cast(frame_pointer)
         };
         loop {
-            let frame = frame(frame_address);
+            let fr = frame(frame_address);
 
-            #debug("frame: %x", unsafe { reinterpret_cast(frame.fp) });
-            visit(frame);
+            #debug("frame: %x", unsafe { reinterpret_cast(fr.fp) });
+            visit(fr);
 
             unsafe {
                 let next_fp: **word = reinterpret_cast(frame_address);
@@ -44,7 +44,7 @@ fn walk_stack(visit: fn(frame) -> bool) {
 
 #[test]
 fn test_simple() {
-    for walk_stack { |frame|
+    for walk_stack { |_frame|
     }
 }
 
@@ -53,7 +53,7 @@ fn test_simple_deep() {
     fn run(i: int) {
         if i == 0 { ret }
 
-        for walk_stack { |frame|
+        for walk_stack { |_frame|
             unsafe {
                 breakpoint();
             }
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 8f68ff8d4da..f1136fde5e2 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -566,7 +566,7 @@ pure fn to_upper(s: str/&) -> str {
 }
 
 #[doc = "
-Replace all occurances of one string with another
+Replace all occurrences of one string with another
 
 # Arguments
 
diff --git a/src/libstd/par.rs b/src/libstd/par.rs
index ffca5989857..e621fd78724 100644
--- a/src/libstd/par.rs
+++ b/src/libstd/par.rs
@@ -7,7 +7,7 @@ import future::future;
 export map, mapi, alli, any, mapi_factory;
 
 #[doc="The maximum number of tasks this module will spawn for a single
-operationg."]
+operation."]
 const max_tasks : uint = 32u;
 
 #[doc="The minimum number of elements each task will process."]
diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs
index 572be4f2ac7..bae0f4648d2 100644
--- a/src/rustc/middle/borrowck/check_loans.rs
+++ b/src/rustc/middle/borrowck/check_loans.rs
@@ -47,6 +47,7 @@ fn check_loans(bccx: borrowck_ctxt,
                                  mut declared_purity: ast::impure_fn,
                                  mut fn_args: @[]});
     let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr,
+                            visit_local: check_loans_in_local,
                             visit_block: check_loans_in_block,
                             visit_fn: check_loans_in_fn
                             with *visit::default_visitor()});
@@ -419,6 +420,9 @@ impl methods for check_loan_ctxt {
           // rvalues, I guess.
           cat_special(sk_static_item) { }
 
+          cat_deref(_, _, unsafe_ptr) {
+          }
+
           // Nothing else.
           _ {
             self.bccx.span_err(
@@ -542,6 +546,18 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
     #debug["purity on exit=%?", copy self.declared_purity];
 }
 
+fn check_loans_in_local(local: @ast::local,
+                        &&self: check_loan_ctxt,
+                        vt: visit::vt<check_loan_ctxt>) {
+    alt local.node.init {
+      some({op: ast::init_move, expr: expr}) {
+        self.check_move_out(expr);
+      }
+      some({op: ast::init_assign, _}) | none {}
+    }
+    visit::visit_local(local, self, vt);
+}
+
 fn check_loans_in_expr(expr: @ast::expr,
                        &&self: check_loan_ctxt,
                        vt: visit::vt<check_loan_ctxt>) {
diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs
index fd0ecaa4fd5..78a0f1bfef7 100644
--- a/src/rustc/middle/resolve.rs
+++ b/src/rustc/middle/resolve.rs
@@ -573,7 +573,6 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
       }
       ast::item_class(tps, ifaces, members, ctor, m_dtor, _) {
         v.visit_ty_params(tps, sc, v);
-        // Can maybe skip this now that we require self on class fields
         let class_scope = @cons(scope_item(i), sc);
         /* visit the constructor... */
         let ctor_scope = @cons(scope_method(ctor.node.self_id, tps),
@@ -1061,7 +1060,7 @@ fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
               }
               ast::item_class(tps, _, members, ctor, _, _) {
                   if ns == ns_type {
-                    ret lookup_in_ty_params(e, name, tps);
+                      ret lookup_in_ty_params(e, name, tps);
                   }
                   if ns == ns_val && name == it.ident {
                       ret some(ast::def_fn(local_def(ctor.node.id),
@@ -1317,13 +1316,14 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
     alt i.node {
       ast::item_const(*) {
         if ns == ns_val {
-            ret some(ast::def_const(local_def(i.id))); }
+            ret some(ast::def_const(local_def(i.id)));
+        }
       }
       ast::item_fn(decl, _, _) {
-        if ns == ns_val {
+          if ns == ns_val {
             ret some(ast::def_fn(local_def(i.id), decl.purity));
-        }
-      }
+           }
+       }
       ast::item_mod(_) {
         if ns == ns_module { ret some(ast::def_mod(local_def(i.id))); }
       }
@@ -1342,9 +1342,16 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
           _ { }
         }
       }
-      ast::item_class(*) {
-          if ns == ns_type {
-            ret some(ast::def_class(local_def(i.id)));
+      ast::item_class(_, _, _members, ct, _, _) {
+          alt ns {
+             ns_type {
+               ret some(ast::def_class(local_def(i.id)));
+             }
+             ns_val {
+               ret some(ast::def_fn(local_def(ct.node.id),
+                                    ast::impure_fn));
+             }
+             ns_module { }
           }
       }
       ast::item_impl(*) { /* ??? */ }
@@ -1653,14 +1660,6 @@ fn index_mod(md: ast::_mod) -> mod_index {
           ast::item_class(tps, _, items, ctor, _, _) {
               // add the class name itself
               add_to_index(index, it.ident, mie_item(it));
-              // add the constructor decl
-              add_to_index(index, it.ident,
-                           mie_item(@{ident: it.ident, attrs: [],
-                            id: ctor.node.id,
-                            node:
-                              item_fn(ctor.node.dec, tps, ctor.node.body),
-                            vis: ast::public,
-                            span: ctor.node.body.span}));
           }
         }
     }
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 44bb515393e..47baa8aebca 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -754,7 +754,8 @@ fn trans_class_drop(bcx: block, v0: ValueRef, dtor_did: ast::def_id,
       // We have to cast v0
      let classptr = GEPi(bcx, v0, [0u, 1u]);
      // Find and call the actual destructor
-     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, substs.tps);
+     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, some(class_did),
+                                  substs.tps);
      // The second argument is the "self" argument for drop
      let params = lib::llvm::fn_ty_param_tys
          (llvm::LLVMGetElementType
@@ -829,7 +830,11 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
     build_return(bcx);
 }
 
-fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
+fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
+                // Parent ID is an option because resources don't
+                // have one. We can make this a def_id when
+                // resources get removed.
+                opt_id: option<ast::def_id>, substs: [ty::t])
    -> ValueRef {
     let _icx = ccx.insn_ctxt("trans_res_dtor");
     if (substs.len() > 0u) {
@@ -841,14 +846,27 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
     } else if did.crate == ast::local_crate {
         get_item_val(ccx, did.node)
     } else {
-        let fty = ty::mk_fn(ccx.tcx, {purity: ast::impure_fn,
-                                      proto: ast::proto_bare,
-                                      inputs: [{mode: ast::expl(ast::by_ref),
+        alt opt_id {
+           some(parent_id) {
+             let tcx = ccx.tcx;
+             let name = csearch::get_symbol(ccx.sess.cstore, did);
+             let class_ty = ty::subst_tps(tcx, substs,
+                              ty::lookup_item_type(tcx, parent_id).ty);
+             let llty = type_of_dtor(ccx, class_ty);
+             get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
+                           llty)
+           }
+           none {
+             let fty = ty::mk_fn(ccx.tcx, {purity: ast::impure_fn,
+                                       proto: ast::proto_bare,
+                                     inputs: [{mode: ast::expl(ast::by_ref),
                                                 ty: ty::mk_nil_ptr(ccx.tcx)}],
                                       output: ty::mk_nil(ccx.tcx),
                                       ret_style: ast::return_val,
                                       constraints: []});
-        trans_external_path(ccx, did, fty)
+             trans_external_path(ccx, did, fty)
+           }
+      }
     }
 }
 
@@ -862,7 +880,7 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
     with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
         let valptr = GEPi(bcx, rs, [0u, 1u]);
         // Find and call the actual destructor.
-        let dtor_addr = get_res_dtor(ccx, did, tps);
+        let dtor_addr = get_res_dtor(ccx, did, none, tps);
         let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
         // Kludge to work around the fact that we know the precise type of the
         // value here, but the dtor expects a type that might have opaque
@@ -2304,14 +2322,14 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
         }
       }
       ast_map::node_dtor(_, dtor, _, pt) {
-          let parent_id = alt ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx,
-                                     dtor.node.self_id)) {
-                  some(did) { did }
-                  none      { ccx.sess.span_bug(dtor.span, "Bad self ty in \
+        let parent_id = alt ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx,
+                                              dtor.node.self_id)) {
+                some(did) { did }
+                none      { ccx.sess.span_bug(dtor.span, "Bad self ty in \
                                dtor"); }
-          };
-          trans_class_dtor(ccx, *pt, dtor.node.body,
-                           dtor.node.id, psubsts, some(hash_id), parent_id)
+        };
+        trans_class_dtor(ccx, *pt, dtor.node.body,
+          dtor.node.id, psubsts, some(hash_id), parent_id)
       }
       // Ugh -- but this ensures any new variants won't be forgotten
       ast_map::node_expr(*) { ccx.tcx.sess.bug("Can't monomorphize an expr") }
@@ -4930,15 +4948,15 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
 }
 
 fn trans_class_dtor(ccx: @crate_ctxt, path: path,
-    body: ast::blk,
-    dtor_id: ast::node_id, substs: option<param_substs>,
-                    hash_id: option<mono_id>, parent_id: ast::def_id)
+    body: ast::blk, dtor_id: ast::node_id,
+    psubsts: option<param_substs>,
+    hash_id: option<mono_id>, parent_id: ast::def_id)
     -> ValueRef {
   let tcx = ccx.tcx;
   /* Look up the parent class's def_id */
   let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty;
   /* Substitute in the class type if necessary */
-  option::iter(substs) {|ss|
+  option::iter(psubsts) {|ss|
     class_ty = ty::subst_tps(tcx, ss.tys, class_ty);
   }
 
@@ -4947,7 +4965,9 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
   let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
                     T_ptr(type_of(ccx, class_ty))],
                    llvm::LLVMVoidType());
-  let s = get_dtor_symbol(ccx, path, dtor_id);
+
+  let s = get_dtor_symbol(ccx, path, dtor_id, psubsts);
+
   /* Register the dtor as a function. It has external linkage */
   let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
   lib::llvm::SetLinkage(lldecl, lib::llvm::ExternalLinkage);
@@ -4959,7 +4979,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
   }
   /* Translate the dtor body */
   trans_fn(ccx, path, ast_util::dtor_dec(),
-           body, lldecl, impl_self(class_ty), substs, dtor_id);
+           body, lldecl, impl_self(class_ty), psubsts, dtor_id);
   lldecl
 }
 
@@ -5196,16 +5216,34 @@ fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
     } + [path_name(i.ident)]
 }
 
-/* If there's already a symbol for the dtor with <id>, return it;
-   otherwise, create one and register it, returning it as well */
-fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id) -> str {
+/* If there's already a symbol for the dtor with <id> and substs <substs>,
+   return it; otherwise, create one and register it, returning it as well */
+fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id,
+                   substs: option<param_substs>) -> str {
+  let t = ty::node_id_to_type(ccx.tcx, id);
   alt ccx.item_symbols.find(id) {
      some(s) { s }
+     none if is_none(substs) {
+       let s = mangle_exported_name(ccx,
+                               path + [path_name(@ccx.names("dtor"))],
+                               t);
+       ccx.item_symbols.insert(id, s);
+       s
+     }
      none    {
-         let s = mangle_exported_name(ccx, path +
-           [path_name(@ccx.names("dtor"))], ty::node_id_to_type(ccx.tcx, id));
-         ccx.item_symbols.insert(id, s);
-         s
+       // Monomorphizing, so just make a symbol, don't add
+       // this to item_symbols
+       alt substs {
+         some(ss) {
+           let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, t);
+           mangle_exported_name(ccx, path +
+                           [path_name(@ccx.names("dtor"))], mono_ty)
+         }
+         none {
+             ccx.sess.bug(#fmt("get_dtor_symbol: not monomorphizing and \
+               couldn't find a symbol for dtor %?", path));
+         }
+       }
      }
   }
 }
@@ -5289,7 +5327,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
             let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
                     T_ptr(type_of(ccx, class_ty))],
                                    llvm::LLVMVoidType());
-            let s = get_dtor_symbol(ccx, *pt, dt.node.id);
+            let s = get_dtor_symbol(ccx, *pt, dt.node.id, none);
 
             /* Make the declaration for the dtor */
             let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs
index 61f82997e93..f0d98da5adb 100644
--- a/src/rustc/middle/trans/shape.rs
+++ b/src/rustc/middle/trans/shape.rs
@@ -21,12 +21,14 @@ import std::map::hashmap;
 
 import ty_ctxt = middle::ty::ctxt;
 
-type nominal_id = @{did: ast::def_id, tps: [ty::t]};
+type nominal_id = @{did: ast::def_id, parent_id: option<ast::def_id>,
+                    tps: [ty::t]};
 
 fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id,
+                 parent_id: option<ast::def_id>,
                  tps: [ty::t]) -> nominal_id {
     let tps_norm = tps.map { |t| ty::normalize_ty(tcx, t) };
-    @{did: did, tps: tps_norm}
+    @{did: did, parent_id: parent_id, tps: tps_norm}
 }
 
 fn hash_nominal_id(&&ri: nominal_id) -> uint {
@@ -233,7 +235,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
           tk_enum { [s_variant_enum_t(ccx.tcx)] }
           tk_newtype | tk_complex {
             let mut s = [shape_enum], id;
-            let nom_id = mk_nominal_id(ccx.tcx, did, substs.tps);
+            let nom_id = mk_nominal_id(ccx.tcx, did, none, substs.tps);
             alt ccx.shape_cx.tag_id_to_index.find(nom_id) {
               none {
                 id = ccx.shape_cx.next_tag_id;
@@ -335,7 +337,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
           else { [shape_struct] };
         let mut sub = [];
         option::iter(m_dtor_did) {|dtor_did|
-          let ri = @{did: dtor_did, tps: tps};
+          let ri = @{did: dtor_did, parent_id: some(did), tps: tps};
           let id = interner::intern(ccx.shape_cx.resources, ri);
           add_u16(s, id as u16);
 
@@ -362,7 +364,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
         for substs.tps.each() {|t| assert !ty::type_has_params(t); }
         let subt = ty::subst(ccx.tcx, substs, raw_subt);
         let tps = substs.tps;
-        let ri = @{did: did, tps: tps};
+        let ri = @{did: did, parent_id: none, tps: tps};
         let id = interner::intern(ccx.shape_cx.resources, ri);
 
         let mut s = [shape_res];
@@ -597,7 +599,8 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
     for uint::range(0u, len) {|i|
         let ri = interner::get(ccx.shape_cx.resources, i);
         for ri.tps.each() {|s| assert !ty::type_has_params(s); }
-        dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
+        dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.parent_id,
+                                            ri.tps)];
     }
     ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
 }
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index c0f3014cf96..dc8dc1b92cf 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -8,6 +8,7 @@ import std::map::hashmap;
 import ty::*;
 
 export type_of;
+export type_of_dtor;
 export type_of_explicit_args;
 export type_of_fn_from_ty;
 export type_of_fn;
@@ -251,3 +252,9 @@ fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str {
     );
 }
 
+fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
+    T_fn([T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))),
+          T_ptr(type_of(ccx, self_ty))],
+         llvm::LLVMVoidType())
+}
+
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index 431eb8b0aea..83167597bb8 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -28,12 +28,12 @@ fn bound_region_to_str(cx: ctxt, br: bound_region) -> str {
 }
 
 fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> str {
-    alt cx.items.get(node_id) {
-      ast_map::node_block(blk) {
+    alt cx.items.find(node_id) {
+      some(ast_map::node_block(blk)) {
         #fmt("<block at %s>",
              codemap::span_to_str(blk.span, cx.sess.codemap))
       }
-      ast_map::node_expr(expr) {
+      some(ast_map::node_expr(expr)) {
         alt expr.node {
           ast::expr_call(*) {
             #fmt("<call at %s>",
diff --git a/src/snapshots.txt b/src/snapshots.txt
index e2f0c151889..169a8667316 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,11 @@
+S 2012-06-20 c891dec
+  macos-x86_64 cd7b3213a05e11dbf7440db016c9f7db16598501
+  macos-i386 eba609b4c815c415ca9485cac749c08ede5bf9ff
+  freebsd-x86_64 c93d3297bf68d12a55af04fecab5c1792394fcca
+  linux-x86_64 eb0e614c6f463fdbf3f40953ff122eb7cd829b85
+  linux-i386 6d858ef6915517135e633043115ab51d677010c5
+  winnt-i386 ffc26150a21aac3c5b023070c0e52d3c01b1881c
+
 S 2012-06-19 de491ea
   freebsd-x86_64 b5c1080df70136bb316286e1973fa2b5734c9a01
   winnt-i386 fa1c7b2295dbde00269f859b8cb637a59a8deec4
diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs
index e51cb6c98b2..6c6466017ef 100644
--- a/src/test/bench/graph500-bfs.rs
+++ b/src/test/bench/graph500-bfs.rs
@@ -1,6 +1,6 @@
 /**
 
-An implementation of the Graph500 Bread First Search problem in Rust.
+An implementation of the Graph500 Breadth First Search problem in Rust.
 
 */
 
diff --git a/src/test/compile-fail/borrowck-issue-2657-1.rs b/src/test/compile-fail/borrowck-issue-2657-1.rs
new file mode 100644
index 00000000000..00c579dc45e
--- /dev/null
+++ b/src/test/compile-fail/borrowck-issue-2657-1.rs
@@ -0,0 +1,9 @@
+fn main() {
+let x = some(~1);
+alt x { //! NOTE loan of immutable local variable granted here
+  some(y) {
+    let _a <- x; //! ERROR moving out of immutable local variable prohibited due to outstanding loan
+  }
+  _ {}
+}
+}
diff --git a/src/test/compile-fail/borrowck-issue-2657-2.rs b/src/test/compile-fail/borrowck-issue-2657-2.rs
new file mode 100644
index 00000000000..c9e94331ab0
--- /dev/null
+++ b/src/test/compile-fail/borrowck-issue-2657-2.rs
@@ -0,0 +1,14 @@
+//xfail-test
+
+// this should be illegal but borrowck is not handling 
+// pattern bindings correctly right now
+
+fn main() {
+let x = some(~1);
+alt x {
+  some(y) {
+    let b <- y;
+  }
+  _ {}
+}
+}
diff --git a/src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs b/src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs
new file mode 100644
index 00000000000..03fbb6b975c
--- /dev/null
+++ b/src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs
@@ -0,0 +1,7 @@
+fn foo(x: *~int) -> ~int {
+    let y <- *x; //! ERROR dereference of unsafe pointer requires unsafe function or block
+    ret y;
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/borrowck-move-from-unsafe-ptr-ok.rs b/src/test/run-pass/borrowck-move-from-unsafe-ptr-ok.rs
new file mode 100644
index 00000000000..ef0803c00d0
--- /dev/null
+++ b/src/test/run-pass/borrowck-move-from-unsafe-ptr-ok.rs
@@ -0,0 +1,11 @@
+// just make sure this compiles:
+
+fn bar(x: *~int) -> ~int {
+    unsafe {
+        let y <- *x;
+        ret y;
+    }
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/nested-class.rs b/src/test/run-pass/nested-class.rs
new file mode 100644
index 00000000000..b0f62cc3ea9
--- /dev/null
+++ b/src/test/run-pass/nested-class.rs
@@ -0,0 +1,15 @@
+fn main() {
+  
+  class b {
+    let i: int;
+    fn do_stuff() -> int { ret 37; }
+    new(i:int) { self.i = i; }
+  }
+
+  //  fn b(x:int) -> int { fail; }
+
+  let z = b(42);
+  assert(z.i == 42);
+  assert(z.do_stuff() == 37);
+  
+}
\ No newline at end of file