Enforce copy restrictions on let initializers
This commit is contained in:
parent
07e13fe447
commit
6b42ad5ea0
18 changed files with 67 additions and 18 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
12
src/test/compile-fail/resource-let.rs
Normal file
12
src/test/compile-fail/resource-let.rs
Normal 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);
|
||||
}
|
9
src/test/compile-fail/resource-let2.rs
Normal file
9
src/test/compile-fail/resource-let2.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
// error-pattern: mismatched kind
|
||||
|
||||
resource r(b: bool) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let i <- r(true);
|
||||
let j = i;
|
||||
}
|
8
src/test/compile-fail/unique-pinned-nocopy-2.rs
Normal file
8
src/test/compile-fail/unique-pinned-nocopy-2.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
// error-pattern: mismatched kind
|
||||
|
||||
resource r(b: bool) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let i = ~r(true);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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] = []; }
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue