diff --git a/Makefile.in b/Makefile.in index b657ad6a688..df9cb78ef8f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -421,9 +421,9 @@ else TSREQS := \ $(foreach target,$(CFG_TARGET_TRIPLES), \ $(SREQ3_T_$(target)_H_$(CFG_HOST_TRIPLE))) -FUZZ := $(HBIN3_H_$(CFG_HOST_TRIPLE))/fuzzer$(X) -CARGO := $(HBIN3_H_$(CFG_HOST_TRIPLE))/cargo$(X) -RUSTDOC := $(HBIN3_H_$(CFG_HOST_TRIPLE))/rustdoc$(X) +FUZZ := $(HBIN2_H_$(CFG_HOST_TRIPLE))/fuzzer$(X) +CARGO := $(HBIN2_H_$(CFG_HOST_TRIPLE))/cargo$(X) +RUSTDOC := $(HBIN2_H_$(CFG_HOST_TRIPLE))/rustdoc$(X) all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs new file mode 100644 index 00000000000..aea97cf1649 --- /dev/null +++ b/src/libcore/cmp.rs @@ -0,0 +1,10 @@ +#[doc="Interfaces used for comparison."] + +iface ord { + fn lt(&&other: self) -> bool; +} + +iface eq { + fn eq(&&other: self) -> bool; +} + diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 6b4c7ad7d3c..efcd424024a 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -44,6 +44,7 @@ export extfmt; export tuple; export to_str; export dvec, dvec_iter; +export cmp; // NDM seems to be necessary for resolve to work export option_iter; @@ -152,6 +153,7 @@ mod tuple; // Ubiquitous-utility-type modules +mod cmp; mod either; mod iter; mod logging; diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 156724cb061..4011ac1a18a 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -1,4 +1,5 @@ import T = inst::T; +import cmp::{eq, ord}; export min_value, max_value; export min, max; @@ -10,6 +11,7 @@ export range; export compl; export abs; export parse_buf, from_str, to_str, to_str_bytes, str; +export ord, eq; const min_value: T = -1 as T << (inst::bits - 1 as T); const max_value: T = min_value - 1 as T; @@ -108,6 +110,18 @@ fn to_str_bytes(n: T, radix: uint, f: fn([u8]/&) -> U) -> U { #[doc = "Convert to a string"] fn str(i: T) -> str { ret to_str(i, 10u); } +impl ord of ord for T { + fn lt(&&other: T) -> bool { + ret self < other; + } +} + +impl eq of eq for T { + fn eq(&&other: T) -> bool { + ret self == other; + } +} + // FIXME: Has alignment issues on windows and 32-bit linux #[test] diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index a63d01e6e8e..7126fb3d007 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -1,4 +1,5 @@ import T = inst::T; +import cmp::{eq, ord}; export min_value, max_value; export min, max; @@ -10,6 +11,7 @@ export range; export compl; export to_str, to_str_bytes; export from_str, from_str_radix, str, parse_buf; +export ord, eq; const min_value: T = 0 as T; const max_value: T = 0 as T - 1 as T; @@ -49,6 +51,18 @@ pure fn compl(i: T) -> T { max_value ^ i } +impl ord of ord for T { + fn lt(&&other: T) -> bool { + ret self < other; + } +} + +impl eq of eq for T { + fn eq(&&other: T) -> bool { + ret self == other; + } +} + #[doc = " Parse a buffer of bytes diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 7e16578fd9c..76c71d7ed2a 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1,5 +1,6 @@ #[doc = "Sorting methods"]; import vec::len; +import int::{eq, ord}; export le; export merge_sort; @@ -141,7 +142,6 @@ fn qsort3(compare_func_lt: le, compare_func_eq: le, qsort3::(compare_func_lt, compare_func_eq, arr, i, right); } -// FIXME: This should take lt and eq types (#2348) #[doc = " Fancy quicksort. Sorts a mut vector in place. @@ -152,10 +152,9 @@ According to these slides this is the algorithm of choice for This is an unstable sort. "] -fn quick_sort3(compare_func_lt: le, compare_func_eq: le, - arr: [mut T]) { +fn quick_sort3(arr: [mut T]) { if len::(arr) == 0u { ret; } - qsort3::(compare_func_lt, compare_func_eq, arr, 0, + qsort3::({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0, (len::(arr) as int) - 1); } @@ -163,11 +162,7 @@ fn quick_sort3(compare_func_lt: le, compare_func_eq: le, mod test_qsort3 { fn check_sort(v1: [mut int], v2: [mut int]) { let len = vec::len::(v1); - fn lt(&&a: int, &&b: int) -> bool { ret a < b; } - fn equal(&&a: int, &&b: int) -> bool { ret a == b; } - let f1 = lt; - let f2 = equal; - quick_sort3::(f1, f2, v1); + quick_sort3::(v1); let mut i = 0u; while i < len { log(debug, v2[i]); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 6d54615e827..f58333c5599 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -86,11 +86,14 @@ impl codemap_handler of handler for handler_t { } fn has_errors() -> bool { self.err_count > 0u } fn abort_if_errors() { - if self.err_count > 0u { - let s = #fmt["aborting due to %u previous errors", - self.err_count]; - self.fatal(s); + let s; + alt self.err_count { + 0u { ret; } + 1u { s = "aborting due to previous error"; } + _ { s = #fmt["aborting due to %u previous errors", + self.err_count]; } } + self.fatal(s); } fn warn(msg: str) { self.emit(none, msg, warning); diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 6d4f48595d2..e769455376a 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -194,7 +194,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, bind middle::check_loop::check_crate(ty_cx, crate)); time(time_passes, "alt checking", bind middle::check_alt::check_crate(ty_cx, crate)); - let (last_use_map, spill_map) = + let last_use_map = time(time_passes, "liveness checking", bind middle::liveness::check_crate(ty_cx, method_map, crate)); time(time_passes, "typestate checking", @@ -216,7 +216,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let maps = {mutbl_map: mutbl_map, root_map: root_map, copy_map: copy_map, last_use_map: last_use_map, impl_map: impl_map, method_map: method_map, - vtable_map: vtable_map, spill_map: spill_map}; + vtable_map: vtable_map}; let (llmod, link_meta) = time(time_passes, "translation", diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs index db185215bea..5e88df1de5e 100644 --- a/src/rustc/driver/rustc.rs +++ b/src/rustc/driver/rustc.rs @@ -15,7 +15,8 @@ import std::map::hashmap; import getopts::{opt_present}; import rustc::driver::driver::*; import syntax::codemap; -import rustc::driver::{diagnostic, session}; +import syntax::diagnostic; +import rustc::driver::session; import rustc::middle::lint; import io::reader_util; diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 644d519fc0f..4df45033a77 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -7,7 +7,6 @@ import syntax::{ast, ast_util}; import syntax::attr; import middle::ty; import syntax::ast_map; -import common::*; import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, parse_ident}; import syntax::print::pprust; @@ -15,6 +14,7 @@ import cmd=cstore::crate_metadata; import util::ppaux::ty_to_str; import ebml::deserializer; import syntax::diagnostic::span_handler; +import common::*; export class_dtor; export get_class_fields; diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 2fd59cb2166..6ebf0ed9ec6 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -57,7 +57,6 @@ type maps = { impl_map: middle::resolve::impl_map, method_map: middle::typeck::method_map, vtable_map: middle::typeck::vtable_map, - spill_map: middle::liveness::spill_map }; type decode_ctxt = @{ @@ -839,12 +838,6 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, } } - option::iter(maps.spill_map.find(id)) {|_m| - ebml_w.tag(c::tag_table_spill) {|| - ebml_w.id(id); - } - } - option::iter(maps.last_use_map.find(id)) {|m| ebml_w.tag(c::tag_table_last_use) {|| ebml_w.id(id); @@ -953,8 +946,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt, dcx.maps.mutbl_map.insert(id, ()); } else if tag == (c::tag_table_copy as uint) { dcx.maps.copy_map.insert(id, ()); - } else if tag == (c::tag_table_spill as uint) { - dcx.maps.spill_map.insert(id, ()); } else { let val_doc = entry_doc[c::tag_table_val]; let val_dsr = ebml::ebml_deserializer(val_doc); diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 729ffa0bb93..0f1edb0c415 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -57,7 +57,6 @@ import capture::{cap_move, cap_drop, cap_copy, cap_ref}; export check_crate; export last_use_map; -export spill_map; // Maps from an expr id to a list of variable ids for which this expr // is the last use. Typically, the expr is a path and the node id is @@ -66,13 +65,6 @@ export spill_map; // list of closed over variables that can be moved into the closure. type last_use_map = hashmap>; -// A set of variable ids which must be spilled (stored on the stack). -// We add in any variables or arguments where: -// (1) the variables are moved; -// (2) the address of the variable/argument is taken; -// or (3) we find a last use (as they may be moved). -type spill_map = hashmap; - enum variable = uint; enum live_node = uint; @@ -85,7 +77,7 @@ enum live_node_kind { fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, - crate: @crate) -> (last_use_map, spill_map) { + crate: @crate) -> last_use_map { let visitor = visit::mk_vt(@{ visit_fn: visit_fn, visit_local: visit_local, @@ -94,12 +86,11 @@ fn check_crate(tcx: ty::ctxt, }); let last_use_map = int_hash(); - let spill_map = int_hash(); let initial_maps = @ir_maps(tcx, method_map, - last_use_map, spill_map); + last_use_map); visit::visit_crate(*crate, initial_maps, visitor); tcx.sess.abort_if_errors(); - ret (last_use_map, spill_map); + ret last_use_map; } impl of to_str::to_str for live_node { @@ -162,7 +153,6 @@ class ir_maps { let tcx: ty::ctxt; let method_map: typeck::method_map; let last_use_map: last_use_map; - let spill_map: spill_map; let mut num_live_nodes: uint; let mut num_vars: uint; @@ -174,11 +164,10 @@ class ir_maps { let mut lnks: [live_node_kind]; new(tcx: ty::ctxt, method_map: typeck::method_map, - last_use_map: last_use_map, spill_map: spill_map) { + last_use_map: last_use_map) { self.tcx = tcx; self.method_map = method_map; self.last_use_map = last_use_map; - self.spill_map = spill_map; self.num_live_nodes = 0u; self.num_vars = 0u; @@ -264,17 +253,6 @@ class ir_maps { self.lnks[*ln] } - fn add_spill(var: variable) { - let vk = self.var_kinds[*var]; - alt vk { - vk_local(id, _) | vk_arg(id, _, by_val) { - #debug["adding spill for %?", vk]; - self.spill_map.insert(id, ()); - } - vk_arg(*) | vk_field(_) | vk_self | vk_implicit_ret {} - } - } - fn add_last_use(expr_id: node_id, var: variable) { let vk = self.var_kinds[*var]; #debug["Node %d is a last use of variable %?", expr_id, vk]; @@ -308,7 +286,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, // swap in a new set of IR maps for this function body: let fn_maps = @ir_maps(self.tcx, self.method_map, - self.last_use_map, self.spill_map); + self.last_use_map); #debug["creating fn_maps: %x", ptr::addr_of(*fn_maps) as uint]; @@ -1407,11 +1385,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { vt.visit_expr(f, self, vt); vec::iter2(args, targs) { |arg_expr, arg_ty| alt ty::resolved_mode(self.tcx, arg_ty.mode) { - by_val | by_copy { - vt.visit_expr(arg_expr, self, vt); - } - by_ref | by_mutbl_ref { - self.spill_expr(arg_expr); + by_val | by_copy | by_ref | by_mutbl_ref{ vt.visit_expr(arg_expr, self, vt); } by_move { @@ -1421,10 +1395,6 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { } } - expr_addr_of(_, arg_expr) { - self.spill_expr(arg_expr); - } - // no correctness conditions related to liveness expr_if_check(*) | expr_if(*) | expr_alt(*) | expr_while(*) | expr_loop(*) | @@ -1434,7 +1404,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { expr_assert(*) | expr_check(*) | expr_copy(*) | expr_loop_body(*) | expr_cast(*) | expr_unary(*) | expr_fail(*) | expr_ret(*) | expr_break | expr_cont | expr_lit(_) | - expr_block(*) | expr_swap(*) | expr_mac(*) { + expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) { visit::visit_expr(expr, self, vt); } } @@ -1501,10 +1471,7 @@ impl check_methods for @liveness { ln.to_str(), var.to_str()]; alt (*self).live_on_exit(ln, var) { - none { - // update spill map to include this variable, as it is moved: - (*self.ir).add_spill(var); - } + none { } some(lnk) { self.report_illegal_move(span, lnk, var); } @@ -1516,20 +1483,10 @@ impl check_methods for @liveness { some(_) {} none { (*self.ir).add_last_use(expr.id, var); - - // update spill map to include this variable, as it may be moved: - (*self.ir).add_spill(var); } } } - fn spill_expr(expr: @expr) { - alt (*self).variable_from_path(expr) { - some(var) {(*self.ir).add_spill(var)} - none {} - } - } - fn check_move_from_expr(expr: @expr, vt: vt<@liveness>) { #debug["check_move_from_expr(node %d: %s)", expr.id, expr_to_str(expr)]; @@ -1775,4 +1732,4 @@ impl check_methods for @liveness { } } } - } \ No newline at end of file + } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 62c3134e9ab..ff297c5dcd4 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -62,6 +62,12 @@ enum dest { ignore, } +// Heap selectors. Indicate which heap something should go on. +enum heap { + heap_shared, + heap_exchange, +} + fn dest_str(ccx: @crate_ctxt, d: dest) -> str { alt d { by_val(v) { #fmt["by_val(%s)", val_str(ccx.tn, *v)] } @@ -341,75 +347,61 @@ fn opaque_box_body(bcx: block, PointerCast(bcx, bodyptr, T_ptr(type_of(ccx, body_t))) } -// trans_malloc_boxed_raw: expects an unboxed type and returns a pointer to +// malloc_raw: expects an unboxed type and returns a pointer to // enough space for a box of that type. This includes a rust_opaque_box // header. -fn malloc_boxed_raw(bcx: block, t: ty::t, - &static_ti: option<@tydesc_info>) -> ValueRef { - let _icx = bcx.insn_ctxt("trans_malloc_boxed_raw"); +fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> ValueRef { + let _icx = bcx.insn_ctxt("malloc_raw"); let ccx = bcx.ccx(); - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_box(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + let (mk_fn, upcall) = alt heap { + heap_shared { (ty::mk_imm_box, ccx.upcalls.malloc) } + heap_exchange { + (ty::mk_imm_uniq, ccx.upcalls.exchange_malloc ) + } + }; - // Get the tydesc for the body: - let lltydesc = get_tydesc(ccx, t, static_ti); - lazily_emit_all_tydesc_glue(ccx, copy static_ti); - - // Allocate space: - let rval = Call(bcx, ccx.upcalls.malloc, [lltydesc]); - ret PointerCast(bcx, rval, llty); -} - -// trans_malloc_boxed: usefully wraps trans_malloc_box_raw; allocates a box, -// initializes the reference count to 1, and pulls out the body and rc -fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("trans_malloc_boxed"); - let mut ti = none; - let box = malloc_boxed_raw(bcx, t, ti); - let box_no_addrspace = non_gc_box_cast( - bcx, box, ty::mk_imm_box(bcx.tcx(), t)); - let body = GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]); - ret {box: box, body: body}; -} - -fn malloc_unique_raw(bcx: block, t: ty::t) -> ValueRef { - let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); - let ccx = bcx.ccx(); - - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = mk_fn(bcx.tcx(), t); + let llty = type_of(ccx, box_ptr_ty); // Get the tydesc for the body: let mut static_ti = none; let lltydesc = get_tydesc(ccx, t, static_ti); - lazily_emit_all_tydesc_glue(ccx, static_ti); + lazily_emit_all_tydesc_glue(ccx, copy static_ti); // Allocate space: - let rval = Call(bcx, ccx.upcalls.exchange_malloc, [lltydesc]); + let rval = Call(bcx, upcall, [lltydesc]); ret PointerCast(bcx, rval, llty); } -fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("malloc_unique_box"); - let box = malloc_unique_raw(bcx, t); - let non_gc_box = non_gc_box_cast(bcx, box, ty::mk_imm_uniq(bcx.tcx(), t)); +// malloc_general: usefully wraps malloc_raw; allocates a box, +// and pulls out the body +fn malloc_general(bcx: block, t: ty::t, heap: heap) -> + {box: ValueRef, body: ValueRef} { + let _icx = bcx.insn_ctxt("malloc_general"); + let mk_ty = alt heap { heap_shared { ty::mk_imm_box } + heap_exchange { ty::mk_imm_uniq } }; + let box = malloc_raw(bcx, t, heap); + let non_gc_box = non_gc_box_cast(bcx, box, mk_ty(bcx.tcx(), t)); let body = GEPi(bcx, non_gc_box, [0u, abi::box_field_body]); ret {box: box, body: body}; } +fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { + malloc_general(bcx, t, heap_shared) +} +fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { + malloc_general(bcx, t, heap_exchange) +} + fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef { - let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); + let _icx = bcx.insn_ctxt("malloc_unique_dyn_raw"); let ccx = bcx.ccx(); - // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc - // wants. - let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); - let llty = type_of(ccx, box_ptr); + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = ty::mk_imm_uniq(ccx.tcx, t); + let llty = type_of(ccx, box_ptr_ty); // Get the tydesc for the body: let mut static_ti = none; @@ -423,7 +415,7 @@ fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef { fn malloc_unique_dyn(bcx: block, t: ty::t, size: ValueRef ) -> {box: ValueRef, body: ValueRef} { - let _icx = bcx.insn_ctxt("malloc_unique_box"); + let _icx = bcx.insn_ctxt("malloc_unique_dyn"); let box = malloc_unique_dyn_raw(bcx, t, size); let body = GEPi(bcx, box, [0u, abi::box_field_body]); ret {box: box, body: body}; @@ -3749,6 +3741,8 @@ fn lval_to_dps(bcx: block, e: @ast::expr, dest: dest) -> block { let ty = expr_ty(bcx, e); let lv = trans_lval(bcx, e); let last_use = (lv.kind == owned && last_use_map.contains_key(e.id)); + #debug["is last use (%s) = %b, %d", expr_to_str(e), last_use, + lv.kind as int]; lval_result_to_dps(lv, ty, last_use, dest) } @@ -4039,29 +4033,10 @@ fn init_local(bcx: block, local: @ast::local) -> block { let ty = node_id_type(bcx, local.node.id); let llptr = alt bcx.fcx.lllocals.find(local.node.id) { some(local_mem(v)) { v } - some(_) { bcx.tcx().sess.span_bug(local.span, + _ { bcx.tcx().sess.span_bug(local.span, "init_local: Someone forgot to document why it's\ safe to assume local.node.init must be local_mem!"); - } - // This is a local that is kept immediate - none { - let initexpr = alt local.node.init { - some({expr, _}) { expr } - none { bcx.tcx().sess.span_bug(local.span, - "init_local: late-initialized var appears to \ - be an immediate -- possibly init_local was called \ - without calling alloc_local"); } - }; - let mut {bcx, val, kind} = trans_temp_lval(bcx, initexpr); - if kind != temporary { - if kind == owned { val = Load(bcx, val); } - let rs = take_ty_immediate(bcx, val, ty); - bcx = rs.bcx; val = rs.val; - add_clean_temp(bcx, val, ty); } - bcx.fcx.lllocals.insert(local.node.pat.id, local_imm(val)); - ret bcx; - } }; let mut bcx = bcx; @@ -4341,17 +4316,6 @@ fn alloc_local(cx: block, local: @ast::local) -> block { ast::pat_ident(pth, none) { some(path_to_ident(pth)) } _ { none } }; - // Do not allocate space for locals that can be kept immediate. - let ccx = cx.ccx(); - if option::is_some(simple_name) && - !ccx.maps.mutbl_map.contains_key(local.node.pat.id) && - !ccx.maps.spill_map.contains_key(local.node.pat.id) && - ty::type_is_immediate(t) { - alt local.node.init { - some({op: ast::init_assign, _}) { ret cx; } - _ {} - } - } let val = alloc_ty(cx, t); if cx.sess().opts.debuginfo { option::iter(simple_name) {|name| diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 9057c9ef630..88cd126b1e4 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -175,11 +175,12 @@ fn allocate_cbox(bcx: block, let mut temp_cleanups = []; let (bcx, box) = alt ck { ty::ck_box { - let box = malloc_boxed_raw(bcx, cdata_ty, ti); + get_tydesc(ccx, cdata_ty, ti); + let box = malloc_raw(bcx, cdata_ty, heap_shared); (bcx, box) } ty::ck_uniq { - let box = malloc_unique_raw(bcx, cdata_ty); + let box = malloc_raw(bcx, cdata_ty, heap_exchange); (bcx, box) } ty::ck_block { diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs index 2844aa68595..6d6848336d4 100644 --- a/src/rustc/middle/tstate/auxiliary.rs +++ b/src/rustc/middle/tstate/auxiliary.rs @@ -13,10 +13,9 @@ import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate, set_postcondition, ts_ann, clear_in_postcond, clear_in_poststate_}; -import tritv::*; -import bitvectors::promises_; import driver::session::session; import dvec::{dvec, extensions}; +import tritv::{dont_care, tfalse, tritv_get, ttrue}; import syntax::print::pprust::{constr_args_to_str, lit_to_str}; @@ -817,7 +816,7 @@ fn copy_in_poststate_two(fcx: fn_ctxt, src_post: poststate, // dest def_id let insts = find_instances(fcx, subst, val); for insts.each {|p| - if promises_(p.from, src_post) { + if bitvectors::promises_(p.from, src_post) { set_in_poststate_(p.to, target_post); } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 3b32bca1e5f..a426ded68f8 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -4,19 +4,19 @@ import std::map::hashmap; import driver::session; import session::session; import syntax::{ast, ast_map}; -import syntax::ast::*; import syntax::ast_util; import syntax::ast_util::{is_local, local_def, split_class_items, new_def_hash}; import syntax::codemap::span; import metadata::csearch; -import util::common::*; import util::ppaux::region_to_str; import util::ppaux::vstore_to_str; import util::ppaux::{ty_to_str, tys_to_str, ty_constr_to_str}; -import syntax::print::pprust::*; import middle::lint::{get_warning_level, vecs_not_implicitly_copyable, ignore}; +import syntax::ast::*; +import syntax::print::pprust::*; + export ty_vid, region_vid, vid; export br_hashmap; export is_instantiable; @@ -1678,11 +1678,8 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { ty_class(did, substs) { vec::push(*seen, did); - let r = vec::any(lookup_class_fields(cx, did)) {|f| - let fty = ty::lookup_item_type(cx, f.id); - let sty = subst(cx, substs, fty.ty); - type_requires(cx, seen, r_ty, sty) - }; + let r = vec::any(class_items_as_fields(cx, did, substs)) {|f| + type_requires(cx, seen, r_ty, f.mt.ty)}; vec::pop(*seen); r } diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index d8ce3d83a60..476ef9d3ba5 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -45,7 +45,8 @@ an rptr (`&r.T`) use the region `r` that appears in the rptr. "]; import check::fn_ctxt; -import rscope::*; +import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; +import rscope::{in_binding_rscope, region_scope, type_rscope}; iface ast_conv { fn tcx() -> ty::ctxt; diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 2649dc6c675..b3f7c5a9388 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -71,7 +71,8 @@ import collect::{methods}; // ccx.to_ty() import method::{methods}; // methods for method::lookup import middle::ty::tys_in_fn_ty; import regionmanip::{replace_bound_regions_in_fn_ty, region_of}; -import rscope::*; +import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; +import rscope::{in_binding_rscope, region_scope, type_rscope}; type fn_ctxt = // var_bindings, locals and next_var_id are shared @@ -386,6 +387,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { }; // typecheck the members for members.each {|m| check_class_member(class_ccx, class_t, m); } + // Check that there's at least one field + let (fields,_) = split_class_items(members); + if fields.len() < 1u { + ccx.tcx.sess.span_err(it.span, "A class must have at least one \ + field"); + } // Check that the class is instantiable check_instantiable(ccx.tcx, it.span, it.id); } diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index 60f4ea8dabf..c5c445702d5 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -1,6 +1,14 @@ import std::map::hashmap; import middle::ty; -import middle::ty::*; +import middle::ty::{arg, bound_region, br_anon, br_named, canon_mode}; +import middle::ty::{ck_block, ck_box, ck_uniq, constr, ctxt, field, method}; +import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t}; +import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_constr, ty_enum}; +import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_iface, ty_int}; +import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param}; +import middle::ty::{ty_ptr, ty_rec, ty_res, ty_rptr, ty_self, ty_str, ty_tup}; +import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral}; +import middle::ty::{ty_vec, vid}; import metadata::encoder; import syntax::codemap; import syntax::print::pprust; diff --git a/src/test/compile-fail/issue-2509-a.rs b/src/test/compile-fail/issue-2509-a.rs new file mode 100644 index 00000000000..a500d249c07 --- /dev/null +++ b/src/test/compile-fail/issue-2509-a.rs @@ -0,0 +1,9 @@ +class c { //! ERROR A class must have at least one field + new() { } +} + +fn main() { + let a = c(); + let x = [a]; + let _y = x[0]; +} diff --git a/src/test/compile-fail/noncopyable-class.rs b/src/test/compile-fail/noncopyable-class.rs index da0a0a488f5..736fee0f66c 100644 --- a/src/test/compile-fail/noncopyable-class.rs +++ b/src/test/compile-fail/noncopyable-class.rs @@ -3,14 +3,15 @@ // Test that a class with a non-copyable field can't be // copied class bar { - new() {} + let x: int; + new(x:int) {self.x = x;} drop {} } class foo { let i: int; let j: bar; - new(i:int) { self.i = i; self.j = bar(); } + new(i:int) { self.i = i; self.j = bar(5); } } fn main() { let x <- foo(10); let y = x; log(error, x); } diff --git a/src/test/compile-fail/regions-bounds.rs b/src/test/compile-fail/regions-bounds.rs index 1582c8a049f..c62db9b8fff 100644 --- a/src/test/compile-fail/regions-bounds.rs +++ b/src/test/compile-fail/regions-bounds.rs @@ -4,7 +4,7 @@ enum an_enum/& { } iface an_iface/& { } -class a_class/& { new() { } } +class a_class/& { let x:int; new(x:int) { self.x = x; } } fn a_fn1(e: an_enum/&a) -> an_enum/&b { ret e; //! ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a` diff --git a/src/test/compile-fail/vec-res-add.rs b/src/test/compile-fail/vec-res-add.rs index ea411ca27a2..f6388b19798 100644 --- a/src/test/compile-fail/vec-res-add.rs +++ b/src/test/compile-fail/vec-res-add.rs @@ -1,7 +1,8 @@ // error-pattern: copying a noncopyable value class r { - new(_i:int) {} + let i:int; + new(i:int) {self.i = i;} drop {} } diff --git a/src/test/run-fail/morestack2.rs b/src/test/run-fail/morestack2.rs index 736d0d81a5d..d68e9c49789 100644 --- a/src/test/run-fail/morestack2.rs +++ b/src/test/run-fail/morestack2.rs @@ -21,7 +21,8 @@ fn getbig_call_c_and_fail(i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop { fn getbig(i: int) { if i != 0 { @@ -34,7 +35,7 @@ class and_then_get_big_again { fn main() { task::spawn {|| - let r = and_then_get_big_again(); + let r = and_then_get_big_again(4); getbig_call_c_and_fail(10000); }; } \ No newline at end of file diff --git a/src/test/run-fail/morestack3.rs b/src/test/run-fail/morestack3.rs index 61b0b824d25..0f0aea5ccd1 100644 --- a/src/test/run-fail/morestack3.rs +++ b/src/test/run-fail/morestack3.rs @@ -5,7 +5,7 @@ use std; fn getbig_and_fail(&&i: int) { - let _r = and_then_get_big_again(); + let _r = and_then_get_big_again(5); if i != 0 { getbig_and_fail(i - 1); } else { @@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop { fn getbig(i: int) { if i != 0 { diff --git a/src/test/run-fail/morestack4.rs b/src/test/run-fail/morestack4.rs index 63155b50de1..b1c86d5110a 100644 --- a/src/test/run-fail/morestack4.rs +++ b/src/test/run-fail/morestack4.rs @@ -5,7 +5,7 @@ use std; fn getbig_and_fail(&&i: int) { - let r = and_then_get_big_again(); + let r = and_then_get_big_again(5); if i != 0 { getbig_and_fail(i - 1); } else { @@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) { } class and_then_get_big_again { - new() {} + let x:int; + new(x:int) {self.x = x;} drop {} } diff --git a/src/test/run-fail/rt-set-exit-status-fail2.rs b/src/test/run-fail/rt-set-exit-status-fail2.rs index 680df73d62e..2c2665446cd 100644 --- a/src/test/run-fail/rt-set-exit-status-fail2.rs +++ b/src/test/run-fail/rt-set-exit-status-fail2.rs @@ -1,19 +1,20 @@ // error-pattern:whatever class r { + let x:int; // Setting the exit status after the runtime has already // failed has no effect and the process exits with the // runtime's exit code drop { os::set_exit_status(50); } - new() {} + new(x:int) {self.x = x;} } fn main() { log(error, "whatever"); task::spawn {|| - let i = r(); + let i = r(5); }; fail; } \ No newline at end of file diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index 8f4bd22f75d..2b64840d830 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -26,11 +26,13 @@ enum tg { bar, } #[cfg(bogus)] class r { - new(i:int) {} + let i: int; + new(i:int) { self.i = i; } } class r { - new(i:int) {} + let i: int; + new(i:int) { self.i = i; } } #[cfg(bogus)]