Skip to content

Commit

Permalink
Refactor trans to replace lvalue and friends with Datum.
Browse files Browse the repository at this point in the history
Also:
- report illegal move/ref combos whether or not ref comes first
- commented out fix for #3387, too restrictive and causes an ICE
  • Loading branch information
nikomatsakis committed Sep 6, 2012
1 parent adc1427 commit 5e36a99
Show file tree
Hide file tree
Showing 53 changed files with 6,456 additions and 5,110 deletions.
3 changes: 3 additions & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ endif
ifdef TIME_LLVM_PASSES
CFG_RUSTC_FLAGS += -Z time-llvm-passes
endif
ifdef TRACE
CFG_RUSTC_FLAGS += -Z trace
endif

# platform-specific auto-configuration
include $(CFG_SRC_DIR)mk/platform.mk
Expand Down
4 changes: 3 additions & 1 deletion src/libcore/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ mod tests {
fn identity_crisis() {
// Writing a test for the identity function. How did it come to this?
let x = ~[(5, false)];
assert x.eq(id(copy x));
//FIXME #3387 assert x.eq(id(copy x));
let y = copy x;
assert x.eq(id(y));
}
#[test]
fn test_swap() {
Expand Down
24 changes: 14 additions & 10 deletions src/libstd/getopts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,10 +800,11 @@ mod tests {
let rs = getopts(args, opts);
match rs {
Ok(m) => {
assert (opt_present(m, ~"test"));
assert (opt_str(m, ~"test") == ~"20");
assert (opt_strs(m, ~"test")[0] == ~"20");
assert (opt_strs(m, ~"test")[1] == ~"30");
assert (opt_present(m, ~"test"));
assert (opt_str(m, ~"test") == ~"20");
let pair = opt_strs(m, ~"test");
assert (pair[0] == ~"20");
assert (pair[1] == ~"30");
}
_ => fail
}
Expand Down Expand Up @@ -854,8 +855,9 @@ mod tests {
Ok(m) => {
assert (opt_present(m, ~"t"));
assert (opt_str(m, ~"t") == ~"20");
assert (opt_strs(m, ~"t")[0] == ~"20");
assert (opt_strs(m, ~"t")[1] == ~"30");
let pair = opt_strs(m, ~"t");
assert (pair[0] == ~"20");
assert (pair[1] == ~"30");
}
_ => fail
}
Expand Down Expand Up @@ -903,10 +905,12 @@ mod tests {
assert (opt_present(m, ~"flag"));
assert (opt_str(m, ~"long") == ~"30");
assert (opt_present(m, ~"f"));
assert (opt_strs(m, ~"m")[0] == ~"40");
assert (opt_strs(m, ~"m")[1] == ~"50");
assert (opt_strs(m, ~"n")[0] == ~"-A B");
assert (opt_strs(m, ~"n")[1] == ~"-60 70");
let pair = opt_strs(m, ~"m");
assert (pair[0] == ~"40");
assert (pair[1] == ~"50");
let pair = opt_strs(m, ~"n");
assert (pair[0] == ~"-A B");
assert (pair[1] == ~"-60 70");
assert (!opt_present(m, ~"notpresent"));
}
_ => fail
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/par.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const min_granularity : uint = 1024u;
* like map or alli.
*/
fn map_slices<A: copy send, B: copy send>(
xs: ~[A],
xs: &[A],
f: fn() -> fn~(uint, v: &[A]) -> B)
-> ~[B] {

Expand Down Expand Up @@ -104,7 +104,7 @@ fn mapi<A: copy send, B: copy send>(xs: ~[A],
* inner elements. This is to skirt the need for copy constructors.
*/
fn mapi_factory<A: copy send, B: copy send>(
xs: ~[A], f: fn() -> fn~(uint, A) -> B) -> ~[B] {
xs: &[A], f: fn() -> fn~(uint, A) -> B) -> ~[B] {
let slices = map_slices(xs, || {
let f = f();
fn~(base: uint, slice : &[A], move f) -> ~[B] {
Expand Down
51 changes: 30 additions & 21 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,29 +1169,38 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
None => ()
}
word_space(s, ~"=>");

// Extract the expression from the extra block the parser adds
assert arm.body.node.view_items.is_empty();
assert arm.body.node.stmts.is_empty();
assert arm.body.node.rules == ast::default_blk;
match arm.body.node.expr {
Some(expr) => {
match expr.node {
ast::expr_block(blk) => {
// the block will close the pattern's ibox
print_block_unclosed_indent(s, blk, alt_indent_unit);
}
_ => {
end(s); // close the ibox for the pattern
print_expr(s, expr);
}
}
if !expr_is_simple_block(expr)
&& i < len - 1 {
word(s.s, ~",");
// in the case of foo => expr
if arm.body.node.view_items.is_empty() &&
arm.body.node.stmts.is_empty() &&
arm.body.node.rules == ast::default_blk &&
arm.body.node.expr.is_some()
{
match arm.body.node.expr {
Some(expr) => {
match expr.node {
ast::expr_block(blk) => {
// the block will close the pattern's ibox
print_block_unclosed_indent(
s, blk, alt_indent_unit);
}
_ => {
end(s); // close the ibox for the pattern
print_expr(s, expr);
}
}
if !expr_is_simple_block(expr)
&& i < len - 1 {
word(s.s, ~",");
}
end(s); // close enclosing cbox
}
None => fail
}
end(s); // close enclosing cbox
}
None => fail
} else {
// the block will close the pattern's ibox
print_block_unclosed_indent(s, arm.body, alt_indent_unit);
}
}
bclose_(s, expr.span, alt_indent_unit);
Expand Down
5 changes: 4 additions & 1 deletion src/rt/rust_upcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ extern "C" CDECL void
upcall_s_exchange_malloc(s_exchange_malloc_args *args) {
rust_task *task = args->task;
LOG_UPCALL_ENTRY(task);
LOG(task, mem, "upcall exchange malloc(0x%" PRIxPTR ")", args->td);

size_t total_size = get_box_size(args->size, args->td->align);
// FIXME--does this have to be calloc? (Issue #2682)
Expand All @@ -159,6 +158,9 @@ upcall_s_exchange_malloc(s_exchange_malloc_args *args) {
header->prev = 0;
header->next = 0;

LOG(task, mem, "exchange malloced %p of size %" PRIuPTR,
header, args->size);

args->retval = (uintptr_t)header;
}

Expand Down Expand Up @@ -187,6 +189,7 @@ extern "C" CDECL void
upcall_s_exchange_free(s_exchange_free_args *args) {
rust_task *task = args->task;
LOG_UPCALL_ENTRY(task);
LOG(task, mem, "exchange freed %p", args->ptr);
task->kernel->free(args->ptr);
}

Expand Down
10 changes: 6 additions & 4 deletions src/rustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,11 @@ extern mod llvm {
ValueRef;
fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
ValueRef;
fn LLVMConstGEP(ConstantVal: ValueRef, ConstantIndices: *uint,
fn LLVMConstGEP(ConstantVal: ValueRef,
ConstantIndices: *ValueRef,
NumIndices: c_uint) -> ValueRef;
fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: *uint,
fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
ConstantIndices: *ValueRef,
NumIndices: c_uint) -> ValueRef;
fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
Expand Down Expand Up @@ -493,10 +495,10 @@ extern mod llvm {
fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
VectorBConstant: ValueRef,
MaskConstant: ValueRef) -> ValueRef;
fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *uint,
fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *c_uint,
NumIdx: c_uint) -> ValueRef;
fn LLVMConstInsertValue(AggConstant: ValueRef,
ElementValueConstant: ValueRef, IdxList: *uint,
ElementValueConstant: ValueRef, IdxList: *c_uint,
NumIdx: c_uint) -> ValueRef;
fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: *c_char,
Constraints: *c_char, HasSideEffects: Bool,
Expand Down
86 changes: 58 additions & 28 deletions src/rustc/middle/borrowck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ use syntax::visit;
use syntax::ast_util;
use syntax::ast_map;
use syntax::codemap::span;
use util::ppaux::{ty_to_str, region_to_str, explain_region};
use util::ppaux::{ty_to_str, region_to_str, explain_region,
note_and_explain_region};
use std::map::{int_hash, hashmap, set};
use std::list;
use std::list::{List, Cons, Nil};
Expand Down Expand Up @@ -464,6 +465,7 @@ impl borrowck_ctxt {
err.cmt.span,
fmt!("illegal borrow: %s",
self.bckerr_code_to_str(err.code)));
self.note_and_explain_bckerr(err.code);
}

fn span_err(s: span, m: ~str) {
Expand All @@ -488,37 +490,65 @@ impl borrowck_ctxt {

fn bckerr_code_to_str(code: bckerr_code) -> ~str {
match code {
err_mutbl(req, act) => {
fmt!("creating %s alias to aliasable, %s memory",
self.mut_to_str(req), self.mut_to_str(act))
}
err_mut_uniq => {
~"unique value in aliasable, mutable location"
}
err_mut_variant => {
~"enum variant in aliasable, mutable location"
}
err_root_not_permitted => {
// note: I don't expect users to ever see this error
// message, reasons are discussed in attempt_root() in
// preserve.rs.
~"rooting is not permitted"
}
err_out_of_root_scope(super_scope, sub_scope) => {
fmt!("managed value would have to be rooted for %s, \
but can only be rooted for %s",
explain_region(self.tcx, sub_scope),
explain_region(self.tcx, super_scope))
}
err_out_of_scope(super_scope, sub_scope) => {
fmt!("borrowed pointer must be valid for %s, \
but the borrowed value is only valid for %s",
explain_region(self.tcx, sub_scope),
explain_region(self.tcx, super_scope))
err_mutbl(req, act) => {
fmt!("creating %s alias to aliasable, %s memory",
self.mut_to_str(req), self.mut_to_str(act))
}
err_mut_uniq => {
~"unique value in aliasable, mutable location"
}
err_mut_variant => {
~"enum variant in aliasable, mutable location"
}
err_root_not_permitted => {
// note: I don't expect users to ever see this error
// message, reasons are discussed in attempt_root() in
// preserve.rs.
~"rooting is not permitted"
}
err_out_of_root_scope(*) => {
~"cannot root managed value long enough"
}
err_out_of_scope(*) => {
~"borrowed value does not live long enough"
}
}
}

fn note_and_explain_bckerr(code: bckerr_code) {
match code {
err_mutbl(*) | err_mut_uniq | err_mut_variant |
err_root_not_permitted => {}

err_out_of_root_scope(super_scope, sub_scope) => {
note_and_explain_region(
self.tcx,
~"managed value would have to be rooted for ",
sub_scope,
~"...");
note_and_explain_region(
self.tcx,
~"...but can only be rooted for ",
super_scope,
~"");
}

err_out_of_scope(super_scope, sub_scope) => {
note_and_explain_region(
self.tcx,
~"borrowed pointer must be valid for ",
sub_scope,
~"...");
note_and_explain_region(
self.tcx,
~"...but borrowed value is only valid for ",
super_scope,
~"");
}
}
}


fn cmt_to_str(cmt: cmt) -> ~str {
let mc = &mem_categorization_ctxt {tcx: self.tcx,
method_map: self.method_map};
Expand Down
12 changes: 10 additions & 2 deletions src/rustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ impl check_loan_ctxt {
e.cmt.span,
fmt!("illegal borrow unless pure: %s",
self.bccx.bckerr_code_to_str(e.code)));
self.bccx.note_and_explain_bckerr(e.code);
self.tcx().sess.span_note(
sp,
fmt!("impure due to %s", msg));
Expand Down Expand Up @@ -484,10 +485,14 @@ impl check_loan_ctxt {
// when there is an outstanding loan. In that case, it is not
// safe to consider the use a last_use.
fn check_last_use(expr: @ast::expr) {
debug!("Checking last use of expr %?", expr.id);
let cmt = self.bccx.cat_expr(expr);
let lp = match cmt.lp {
None => return,
Some(lp) => lp
None => {
debug!("Not a loanable expression");
return;
}
Some(lp) => lp
};
for self.walk_loans_of(cmt.id, lp) |_loan| {
debug!("Removing last use entry %? due to outstanding loan",
Expand Down Expand Up @@ -592,6 +597,9 @@ fn check_loans_in_local(local: @ast::local,
fn check_loans_in_expr(expr: @ast::expr,
&&self: check_loan_ctxt,
vt: visit::vt<check_loan_ctxt>) {
debug!("check_loans_in_expr(expr=%?/%s)",
expr.id, pprust::expr_to_str(expr, self.tcx().sess.intr()));

self.check_for_conflicting_loans(expr.id);

match expr.node {
Expand Down
34 changes: 25 additions & 9 deletions src/rustc/middle/borrowck/gather_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ fn req_loans_in_expr(ex: @ast::expr,
let tcx = bccx.tcx;
let old_root_ub = self.root_ub;

debug!("req_loans_in_expr(ex=%s)",
pprust::expr_to_str(ex, tcx.sess.intr()));
debug!("req_loans_in_expr(expr=%?/%s)",
ex.id, pprust::expr_to_str(ex, tcx.sess.intr()));

// If this expression is borrowed, have to ensure it remains valid:
for tcx.borrowings.find(ex.id).each |borrow| {
Expand Down Expand Up @@ -200,6 +200,21 @@ fn req_loans_in_expr(ex: @ast::expr,
visit::visit_expr(ex, self, vt);
}

// FIXME--#3387
// ast::expr_binary(_, lhs, rhs) => {
// // Universal comparison operators like ==, >=, etc
// // take their arguments by reference.
// let lhs_ty = ty::expr_ty(self.tcx(), lhs);
// if !ty::type_is_scalar(lhs_ty) {
// let scope_r = ty::re_scope(ex.id);
// let lhs_cmt = self.bccx.cat_expr(lhs);
// self.guarantee_valid(lhs_cmt, m_imm, scope_r);
// let rhs_cmt = self.bccx.cat_expr(rhs);
// self.guarantee_valid(rhs_cmt, m_imm, scope_r);
// }
// visit::visit_expr(ex, self, vt);
// }

ast::expr_field(rcvr, _, _)
if self.bccx.method_map.contains_key(ex.id) => {
// Receivers in method calls are always passed by ref.
Expand Down Expand Up @@ -395,14 +410,15 @@ impl gather_loan_ctxt {
}

fn add_loans(scope_id: ast::node_id, loans: @DVec<loan>) {
debug!("adding %u loans to scope_id %?", loans.len(), scope_id);
match self.req_maps.req_loan_map.find(scope_id) {
Some(l) => {
(*l).push(loans);
}
None => {
self.req_maps.req_loan_map.insert(
scope_id, @dvec::from_vec(~[mut loans]));
}
Some(l) => {
l.push(loans);
}
None => {
self.req_maps.req_loan_map.insert(
scope_id, @dvec::from_vec(~[mut loans]));
}
}
}

Expand Down
Loading

1 comment on commit 5e36a99

@graydon
Copy link
Contributor

@graydon graydon commented on 5e36a99 Sep 6, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my. That's ... quite something!

Congratulations!

Please sign in to comment.