提交 055158d0 编写于 作者: P Patrick Walton

Revert "Merge pull request #2516 from mozilla/incoming" due to failures

This reverts commit adb717b5, reversing
changes made to aabf84cd.
上级 adb717b5
#[doc="Interfaces used for comparison."]
iface ord {
fn lt(&&other: self) -> bool;
}
iface eq {
fn eq(&&other: self) -> bool;
}
......@@ -44,7 +44,6 @@ 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;
......@@ -153,7 +152,6 @@ mod tuple;
// Ubiquitous-utility-type modules
mod cmp;
mod either;
mod iter;
mod logging;
......
import T = inst::T;
import cmp::{eq, ord};
export min_value, max_value;
export min, max;
......@@ -11,7 +10,6 @@
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;
......@@ -110,18 +108,6 @@ fn to_str_bytes<U>(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]
......
import T = inst::T;
import cmp::{eq, ord};
export min_value, max_value;
export min, max;
......@@ -11,7 +10,6 @@
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;
......@@ -51,18 +49,6 @@ fn range(lo: T, hi: T, it: fn(T) -> bool) {
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
......
#[doc = "Sorting methods"];
import vec::len;
import int::{eq, ord};
export le;
export merge_sort;
......@@ -142,6 +141,7 @@ fn qsort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
qsort3::<T>(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,9 +152,10 @@ fn qsort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
This is an unstable sort.
"]
fn quick_sort3<T: copy ord eq>(arr: [mut T]) {
fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
arr: [mut T]) {
if len::<T>(arr) == 0u { ret; }
qsort3::<T>({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0,
qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
(len::<T>(arr) as int) - 1);
}
......@@ -162,7 +163,11 @@ fn quick_sort3<T: copy ord eq>(arr: [mut T]) {
mod test_qsort3 {
fn check_sort(v1: [mut int], v2: [mut int]) {
let len = vec::len::<int>(v1);
quick_sort3::<int>(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::<int>(f1, f2, v1);
let mut i = 0u;
while i < len {
log(debug, v2[i]);
......
......@@ -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 =
let (last_use_map, spill_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};
vtable_map: vtable_map, spill_map: spill_map};
let (llmod, link_meta) =
time(time_passes, "translation",
......
......@@ -15,8 +15,7 @@
import getopts::{opt_present};
import rustc::driver::driver::*;
import syntax::codemap;
import syntax::diagnostic;
import rustc::driver::session;
import rustc::driver::{diagnostic, session};
import rustc::middle::lint;
import io::reader_util;
......
......@@ -7,6 +7,7 @@
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;
......@@ -14,7 +15,6 @@
import util::ppaux::ty_to_str;
import ebml::deserializer;
import syntax::diagnostic::span_handler;
import common::*;
export class_dtor;
export get_class_fields;
......
......@@ -57,6 +57,7 @@
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 = @{
......@@ -838,6 +839,12 @@ 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);
......@@ -946,6 +953,8 @@ 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);
......
......@@ -57,6 +57,7 @@
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
......@@ -65,6 +66,13 @@
// list of closed over variables that can be moved into the closure.
type last_use_map = hashmap<node_id, @dvec<node_id>>;
// 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<node_id, ()>;
enum variable = uint;
enum live_node = uint;
......@@ -77,7 +85,7 @@ enum live_node_kind {
fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
crate: @crate) -> last_use_map {
crate: @crate) -> (last_use_map, spill_map) {
let visitor = visit::mk_vt(@{
visit_fn: visit_fn,
visit_local: visit_local,
......@@ -86,11 +94,12 @@ 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);
last_use_map, spill_map);
visit::visit_crate(*crate, initial_maps, visitor);
tcx.sess.abort_if_errors();
ret last_use_map;
ret (last_use_map, spill_map);
}
impl of to_str::to_str for live_node {
......@@ -153,6 +162,7 @@ fn relevant_def(def: def) -> option<relevant_def> {
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;
......@@ -164,10 +174,11 @@ fn relevant_def(def: def) -> option<relevant_def> {
let mut lnks: [live_node_kind];
new(tcx: ty::ctxt, method_map: typeck::method_map,
last_use_map: last_use_map) {
last_use_map: last_use_map, spill_map: spill_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;
......@@ -253,6 +264,17 @@ fn lnk(ln: live_node) -> live_node_kind {
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];
......@@ -286,7 +308,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.last_use_map, self.spill_map);
#debug["creating fn_maps: %x", ptr::addr_of(*fn_maps) as uint];
......@@ -1385,7 +1407,11 @@ 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 | by_ref | by_mutbl_ref{
by_val | by_copy {
vt.visit_expr(arg_expr, self, vt);
}
by_ref | by_mutbl_ref {
self.spill_expr(arg_expr);
vt.visit_expr(arg_expr, self, vt);
}
by_move {
......@@ -1395,6 +1421,10 @@ 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(*) |
......@@ -1404,7 +1434,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_addr_of(*) {
expr_block(*) | expr_swap(*) | expr_mac(*) {
visit::visit_expr(expr, self, vt);
}
}
......@@ -1471,7 +1501,10 @@ fn check_move_from_var(span: span, ln: live_node, var: variable) {
ln.to_str(), var.to_str()];
alt (*self).live_on_exit(ln, var) {
none { }
none {
// update spill map to include this variable, as it is moved:
(*self.ir).add_spill(var);
}
some(lnk) {
self.report_illegal_move(span, lnk, var);
}
......@@ -1483,10 +1516,20 @@ fn consider_last_use(expr: @expr, ln: live_node, var: variable) {
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)];
......@@ -1732,4 +1775,4 @@ fn warn_about_dead_assign(sp: span, ln: live_node, var: variable) {
}
}
}
}
}
\ No newline at end of file
......@@ -3749,8 +3749,6 @@ 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)
}
......@@ -4041,10 +4039,29 @@ 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 }
_ { bcx.tcx().sess.span_bug(local.span,
some(_) { 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;
......@@ -4324,6 +4341,17 @@ 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|
......
......@@ -13,8 +13,9 @@
set_postcondition, ts_ann,
clear_in_postcond,
clear_in_poststate_};
import tritv::*;
import bitvectors::promises_;
import driver::session::session;
import tritv::{dont_care, tfalse, tritv_get, ttrue};
import syntax::print::pprust::{constr_args_to_str, lit_to_str};
......@@ -810,7 +811,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 bitvectors::promises_(p.from, src_post) {
if promises_(p.from, src_post) {
set_in_poststate_(p.to, target_post);
}
}
......
......@@ -4,19 +4,19 @@
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;
......
......@@ -45,8 +45,7 @@
"];
import check::fn_ctxt;
import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
import rscope::{in_binding_rscope, region_scope, type_rscope};
import rscope::*;
iface ast_conv {
fn tcx() -> ty::ctxt;
......
......@@ -71,8 +71,7 @@
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::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
import rscope::{in_binding_rscope, region_scope, type_rscope};
import rscope::*;
type fn_ctxt =
// var_bindings, locals and next_var_id are shared
......@@ -387,12 +386,6 @@ 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);
}
......
import std::map::hashmap;
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 middle::ty::*;
import metadata::encoder;
import syntax::codemap;
import syntax::print::pprust;
......
class c { //! ERROR A class must have at least one field
new() { }
}
fn main() {
let a = c();
let x = [a];
let _y = x[0];
}
......@@ -26,13 +26,11 @@ enum tg { bar, }
#[cfg(bogus)]
class r {
let i: int;
new(i:int) { self.i = i; }
new(i:int) {}
}
class r {
let i: int;
new(i:int) { self.i = i; }
new(i:int) {}
}
#[cfg(bogus)]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册