Enforce copy restrictions on let initializers

This commit is contained in:
Brian Anderson 2011-09-26 21:57:42 -07:00
parent 07e13fe447
commit 6b42ad5ea0
18 changed files with 67 additions and 18 deletions

View file

@ -212,9 +212,29 @@ fn check_expr(tcx: ty::ctxt, e: @ast::expr) {
}
}
fn check_stmt(tcx: ty::ctxt, stmt: @ast::stmt) {
alt stmt.node {
ast::stmt_decl(@{node: ast::decl_local(locals), _}, _) {
for (let_style, local) in locals {
alt local.node.init {
option::some({op: ast::init_assign., expr}) {
need_expr_kind(tcx, expr,
ast::kind_shared,
"local initializer");
check_copy(tcx, expr);
}
_ { /* fall through */ }
}
}
}
_ { /* fall through */ }
}
}
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
let visit =
visit::mk_simple_visitor(@{visit_expr: bind check_expr(tcx, _)
visit::mk_simple_visitor(@{visit_expr: bind check_expr(tcx, _),
visit_stmt: bind check_stmt(tcx, _)
with *visit::default_simple_visitor()});
visit::visit_crate(*crate, (), visit);
tcx.sess.abort_if_errors();

View file

@ -114,7 +114,7 @@ fn spawn_inner(-thunk: fn(), notify: option<comm::chan<task_notification>>) ->
let raw_thunk: {code: u32, env: u32} = cast(thunk);
// set up the task pointer
let task_ptr = rust_task_ptr(rustrt::get_task_pointer(id));
let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));
assert (ptr::null() != (**task_ptr).stack_ptr);

View file

@ -0,0 +1,12 @@
// error-pattern: mismatched kind
resource r(b: bool) {
}
fn main() {
// Kind analysis considers this a copy, which isn't strictly true,
// but for many assignment initializers could be. To actually
// assign a resource to a local we can still use a move
// initializer.
let i = r(true);
}

View file

@ -0,0 +1,9 @@
// error-pattern: mismatched kind
resource r(b: bool) {
}
fn main() {
let i <- r(true);
let j = i;
}

View file

@ -0,0 +1,8 @@
// error-pattern: mismatched kind
resource r(b: bool) {
}
fn main() {
let i = ~r(true);
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = alt true { true { expected } };
assert (eq(expected, actual));
}

View file

@ -3,7 +3,7 @@
// -*- rust -*-
type compare<T> = fn(~T, ~T) -> bool;
fn test_generic<T>(expected: ~T, eq: compare<T>) {
fn test_generic<@T>(expected: ~T, eq: compare<T>) {
let actual: ~T = alt true { true { expected } };
assert (eq(expected, actual));
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = alt true { true { expected } };
assert (eq(expected, actual));
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = alt true { true { expected } };
assert (eq(expected, actual));
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View file

@ -3,7 +3,7 @@
// -*- rust -*-
type compare<T> = fn(~T, ~T) -> bool;
fn test_generic<T>(expected: ~T, eq: compare<T>) {
fn test_generic<@T>(expected: ~T, eq: compare<T>) {
let actual: ~T = { expected };
assert (eq(expected, actual));
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View file

@ -6,7 +6,7 @@
// Tests for standalone blocks as expressions with dynamic type sizes
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View file

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, not_expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, not_expected: T, eq: compare<T>) {
let actual: T = if true { expected } else { not_expected };
assert (eq(expected, actual));
}

View file

@ -6,7 +6,7 @@
// Tests for if as expressions with dynamic type sizes
type compare<T> = fn(T, T) -> bool;
fn test_generic<T>(expected: T, not_expected: T, eq: compare<T>) {
fn test_generic<@T>(expected: T, not_expected: T, eq: compare<T>) {
let actual: T = if true { expected } else { not_expected };
assert (eq(expected, actual));
}

View file

@ -1,5 +1,5 @@
fn f<T>(t: T) { let t1: T = t; }
fn f<@T>(t: T) { let t1: T = t; }
fn main() { let x = {x: @10, y: @12}; f(x); }

View file

@ -5,7 +5,7 @@ iter range(lo: uint, hi: uint) -> uint {
while lo_ < hi { put lo_; lo_ += 1u; }
}
fn create_index<T>(index: [{a: T, b: uint}], hash_fn: fn(T) -> uint) {
fn create_index<@T>(index: [{a: T, b: uint}], hash_fn: fn(T) -> uint) {
for each i: uint in range(0u, 256u) { let bucket: [T] = []; }
}

View file

@ -7,8 +7,8 @@ fn test1() {
let i = @mutable 100;
let j = @mutable 200;
{
let x = ~r(i);
let y = ~r(j);
let x <- ~r(i);
let y <- ~r(j);
x <-> y;
assert ***x == 200;
assert ***y == 100;
@ -20,8 +20,8 @@ fn test1() {
fn test2() {
let i = @mutable 0;
{
let x = ~r(i);
let y = ~r(i);
let x <- ~r(i);
let y <- ~r(i);
x <-> y;
}
assert *i == 2;