From e7ce32310b90a4738452f2331e25d4815f2ab81f Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 18 Jun 2012 13:33:07 -0700 Subject: [PATCH 01/11] Change map::get to map::find in ppaux --- src/rustc/util/ppaux.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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("", 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("", From 1b4dcbecac824796bf7cd49a1fbadc20e63c99ea Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 18 Jun 2012 13:34:15 -0700 Subject: [PATCH 02/11] Comments only: typos --- src/libcore/str.rs | 2 +- src/libstd/par.rs | 2 +- src/test/bench/graph500-bfs.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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/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. */ From 6db7843f46afd5cd905b2e3a4266a23c4bb41ef1 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 18 Jun 2012 13:34:50 -0700 Subject: [PATCH 03/11] Monomorphize dtors correctly The same dtor was getting re-used for different instances, which didn't always work right. Fixed. --- src/rustc/middle/trans/base.rs | 62 ++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 44bb515393e..8eab69b1133 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2304,14 +2304,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 +4930,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, - hash_id: option, parent_id: ast::def_id) + body: ast::blk, dtor_id: ast::node_id, + psubsts: option, + hash_id: option, 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 +4947,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 +4961,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 +5198,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 , 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 and 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) -> 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 +5309,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); From 76d6120e521b6546c54722e0dabfe8e73a5d6e73 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 19 Jun 2012 12:00:09 -0700 Subject: [PATCH 04/11] Fix resolve bug that made nested classes not work It wasn't possible to refer to the constructor for a class nested inside an item from the class's outer scope. Fixed. --- src/rustc/middle/resolve.rs | 35 +++++++++++++++---------------- src/test/run-pass/nested-class.rs | 15 +++++++++++++ 2 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 src/test/run-pass/nested-class.rs 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 { alt i.node { ast::item_const(*) { if ns == ns_val { - ret some(ast::def_const(local_def(i.id))); } - } - ast::item_fn(decl, _, _) { - if ns == ns_val { - ret some(ast::def_fn(local_def(i.id), decl.purity)); + ret some(ast::def_const(local_def(i.id))); } } + ast::item_fn(decl, _, _) { + 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 { _ { } } } - 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/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 From 00171165205a1d5222563d0e2bdf7f970758b388 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 19 Jun 2012 12:01:02 -0700 Subject: [PATCH 05/11] Don't shadow a class name with a local The fix in 208621 means you now can't shadow a class name with a local, which is consistent with other behavior. But stackwalk was doing that. Fixed it. --- src/libcore/stackwalk.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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(); } From b02172971fa658f2e6d3cdb3cbf3bf663801d656 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 19 Jun 2012 14:44:38 -0700 Subject: [PATCH 06/11] Make trans give correct types to monomorphic dtors Irritatingly, class dtors have a different type from resource dtors (because class dtors have a self argument), and the monomorphic case wasn't reflecting that. Fixed. --- src/rustc/middle/trans/base.rs | 32 ++++++++++++++++++++++++------- src/rustc/middle/trans/shape.rs | 15 +++++++++------ src/rustc/middle/trans/type_of.rs | 7 +++++++ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 8eab69b1133..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, 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 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, + tps: [ty::t]}; fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id, + parent_id: option, 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()) +} + From 1b642bf02f23d48c93047ae2fca9ebd7c2bdc518 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Mon, 18 Jun 2012 13:49:20 -0700 Subject: [PATCH 07/11] Change core::comm to use classes instead of resources Ports now are represented internally as classes. --- src/libcore/comm.rs | 51 ++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 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(f: fn(chan) -> U) -> U { f(po.chan()) } -resource port_ptr(po: *rust_port) unsafe { +class port_ptr { + 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_::(po); + while rustrt::rust_port_size(self.po) > 0u as size_t { + recv_::(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(ch: comm::chan, 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(p: port) -> chan { - chan_t(rustrt::get_port_id(***p)) + chan_t(rustrt::get_port_id((**p).po)) } #[doc = " @@ -170,10 +179,10 @@ fn send(ch: chan, -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(p: port) -> T { recv_(***p) } +fn recv(p: port) -> T { recv_((**p).po) } #[doc = "Returns true if there are messages available"] -fn peek(p: port) -> bool { peek_(***p) } +fn peek(p: port) -> bool { peek_((**p).po) } #[doc(hidden)] fn recv_chan(ch: comm::chan) -> T { @@ -196,7 +205,7 @@ fn recv_(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(p_a: port, p_b: port) -> either 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(p_a: port, p_b: port) // 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 +} From 0865170f1ac0167f244617a15ec3bdeb438b9ce3 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 20 Jun 2012 19:23:02 -0700 Subject: [PATCH 08/11] Register snapshots --- src/snapshots.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/snapshots.txt b/src/snapshots.txt index e2f0c151889..1220958b80a 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 ffc26150a21aac3c5b023070c0e52d3c01b188c1 + S 2012-06-19 de491ea freebsd-x86_64 b5c1080df70136bb316286e1973fa2b5734c9a01 winnt-i386 fa1c7b2295dbde00269f859b8cb637a59a8deec4 From 419c335faaf94cd0bdc3470eff06bed7ae53e993 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 20 Jun 2012 21:25:39 -0700 Subject: [PATCH 09/11] Apparently an extra space in the snapshot file breaks Windows completely? --- src/snapshots.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snapshots.txt b/src/snapshots.txt index 1220958b80a..a6ec99f2850 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -4,7 +4,7 @@ S 2012-06-20 c891dec freebsd-x86_64 c93d3297bf68d12a55af04fecab5c1792394fcca linux-x86_64 eb0e614c6f463fdbf3f40953ff122eb7cd829b85 linux-i386 6d858ef6915517135e633043115ab51d677010c5 - winnt-i386 ffc26150a21aac3c5b023070c0e52d3c01b188c1 + winnt-i386 ffc26150a21aac3c5b023070c0e52d3c01b188c1 S 2012-06-19 de491ea freebsd-x86_64 b5c1080df70136bb316286e1973fa2b5734c9a01 From f9afce319a1df2cc5c0098ea52e13dd9a54a05c9 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Wed, 20 Jun 2012 21:42:36 -0700 Subject: [PATCH 10/11] Fix typo in Windows snapshot hash --- src/snapshots.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snapshots.txt b/src/snapshots.txt index a6ec99f2850..169a8667316 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -4,7 +4,7 @@ S 2012-06-20 c891dec freebsd-x86_64 c93d3297bf68d12a55af04fecab5c1792394fcca linux-x86_64 eb0e614c6f463fdbf3f40953ff122eb7cd829b85 linux-i386 6d858ef6915517135e633043115ab51d677010c5 - winnt-i386 ffc26150a21aac3c5b023070c0e52d3c01b188c1 + winnt-i386 ffc26150a21aac3c5b023070c0e52d3c01b1881c S 2012-06-19 de491ea freebsd-x86_64 b5c1080df70136bb316286e1973fa2b5734c9a01 From 60603703eaec6944341608f54f46661099a2423b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Jun 2012 20:08:25 -0700 Subject: [PATCH 11/11] handle moves in let initializers and allow moves from unsafe ptrs Related to issue #2657, but this is not a complete fix. --- src/rustc/middle/borrowck/check_loans.rs | 16 ++++++++++++++++ src/test/compile-fail/borrowck-issue-2657-1.rs | 9 +++++++++ src/test/compile-fail/borrowck-issue-2657-2.rs | 14 ++++++++++++++ .../borrowck-move-from-unsafe-ptr.rs | 7 +++++++ .../run-pass/borrowck-move-from-unsafe-ptr-ok.rs | 11 +++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/test/compile-fail/borrowck-issue-2657-1.rs create mode 100644 src/test/compile-fail/borrowck-issue-2657-2.rs create mode 100644 src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs create mode 100644 src/test/run-pass/borrowck-move-from-unsafe-ptr-ok.rs 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) { + 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) { 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