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) {
|
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
|
||||||
let visit =
|
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()});
|
with *visit::default_simple_visitor()});
|
||||||
visit::visit_crate(*crate, (), visit);
|
visit::visit_crate(*crate, (), visit);
|
||||||
tcx.sess.abort_if_errors();
|
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);
|
let raw_thunk: {code: u32, env: u32} = cast(thunk);
|
||||||
|
|
||||||
// set up the task pointer
|
// 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);
|
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 -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 } };
|
let actual: T = alt true { true { expected } };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(~T, ~T) -> bool;
|
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 } };
|
let actual: ~T = alt true { true { expected } };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 } };
|
let actual: T = alt true { true { expected } };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 } };
|
let actual: T = alt true { true { expected } };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 };
|
let actual: T = { expected };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(~T, ~T) -> bool;
|
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 };
|
let actual: ~T = { expected };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 };
|
let actual: T = { expected };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// Tests for standalone blocks as expressions with dynamic type sizes
|
// Tests for standalone blocks as expressions with dynamic type sizes
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 };
|
let actual: T = { expected };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// -*- rust -*-
|
// -*- rust -*-
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 };
|
let actual: T = if true { expected } else { not_expected };
|
||||||
assert (eq(expected, actual));
|
assert (eq(expected, actual));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// Tests for if as expressions with dynamic type sizes
|
// Tests for if as expressions with dynamic type sizes
|
||||||
type compare<T> = fn(T, T) -> bool;
|
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 };
|
let actual: T = if true { expected } else { not_expected };
|
||||||
assert (eq(expected, actual));
|
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); }
|
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; }
|
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] = []; }
|
for each i: uint in range(0u, 256u) { let bucket: [T] = []; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ fn test1() {
|
||||||
let i = @mutable 100;
|
let i = @mutable 100;
|
||||||
let j = @mutable 200;
|
let j = @mutable 200;
|
||||||
{
|
{
|
||||||
let x = ~r(i);
|
let x <- ~r(i);
|
||||||
let y = ~r(j);
|
let y <- ~r(j);
|
||||||
x <-> y;
|
x <-> y;
|
||||||
assert ***x == 200;
|
assert ***x == 200;
|
||||||
assert ***y == 100;
|
assert ***y == 100;
|
||||||
|
@ -20,8 +20,8 @@ fn test1() {
|
||||||
fn test2() {
|
fn test2() {
|
||||||
let i = @mutable 0;
|
let i = @mutable 0;
|
||||||
{
|
{
|
||||||
let x = ~r(i);
|
let x <- ~r(i);
|
||||||
let y = ~r(i);
|
let y <- ~r(i);
|
||||||
x <-> y;
|
x <-> y;
|
||||||
}
|
}
|
||||||
assert *i == 2;
|
assert *i == 2;
|
||||||
|
|
Loading…
Reference in a new issue