Fix subtle error in caching during kind computation that could cause linear

values to be copied.  Rewrite kind computation so that instead of directly
computing the kind it computes what kinds of values are present in the type,
and then derive kinds based on that. I find this easier to think about.

Fixes #4821.
This commit is contained in:
Niko Matsakis 2013-02-07 19:33:12 -08:00
parent 6647a3402b
commit a380df809c
31 changed files with 612 additions and 579 deletions

View file

@ -9,7 +9,7 @@
// except according to those terms.
fn foo<T>() {
1u.bar::<T>(); //~ ERROR: missing `copy`
1u.bar::<T>(); //~ ERROR: does not fulfill `Copy`
}
trait bar {

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
struct foo {
i: int,
}
@ -24,4 +22,9 @@ fn foo(i:int) -> foo {
}
}
fn main() { let x = move foo(10); let y = copy x; log(error, x); }
fn main() {
let x = move foo(10);
let _y = copy x;
//~^ ERROR copying a value of non-copyable type `foo`
log(error, x);
}

View file

@ -34,7 +34,7 @@ fn main() {
let mut res = foo(x);
let mut v = ~[mut];
v = move ~[mut (move res)] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `&static`, missing `copy`)
v = move ~[mut (move res)] + v; //~ ERROR does not fulfill `Copy`
assert (v.len() == 2);
}

View file

@ -20,6 +20,6 @@ impl C : Drop {
fn main() {
let c = C{ x: 2};
let d = copy c; //~ ERROR copying a noncopyable value
let d = copy c; //~ ERROR copying a value of non-copyable type `C`
error!("%?", d.x);
}

View file

@ -12,7 +12,7 @@ fn foo(_x: @uint) {}
fn main() {
let x = @3u;
let _ = fn~() { foo(x); }; //~ ERROR not a sendable value
let _ = fn~(copy x) { foo(x); }; //~ ERROR not a sendable value
let _ = fn~(move x) { foo(x); }; //~ ERROR not a sendable value
let _ = fn~() { foo(x); }; //~ ERROR value has non-owned type `@uint`
let _ = fn~(copy x) { foo(x); }; //~ ERROR value has non-owned type `@uint`
let _ = fn~(move x) { foo(x); }; //~ ERROR value has non-owned type `@uint`
}

View file

@ -18,12 +18,12 @@ fn copy2<T: Copy &static>(t: T) -> fn@() -> T {
fn main() {
let x = &3;
copy2(&x); //~ ERROR missing `&static`
copy2(&x); //~ ERROR does not fulfill `&static`
copy2(@3);
copy2(@&x); //~ ERROR missing `&static`
copy2(@&x); //~ ERROR does not fulfill `&static`
copy2(fn@() {});
copy2(fn~() {}); //~ ERROR missing `copy`
copy2(fn&() {}); //~ ERROR missing `&static`
copy2(fn~() {}); //~ ERROR does not fulfill `Copy`
copy2(fn&() {}); //~ ERROR does not fulfill `&static`
}

View file

@ -68,5 +68,5 @@ impl r : Drop {
fn main() {
let x = r { x: () };
fn@(move x) { copy x; }; //~ ERROR copying a noncopyable value
fn@(move x) { copy x; }; //~ ERROR copying a value of non-copyable type
}

View file

@ -0,0 +1,34 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test for a subtle failure computing kinds of cyclic types, in which
// temporary kinds wound up being stored in a cache and used later.
// See middle::ty::type_contents() for more information.
extern mod std;
use core::cmp::Ord;
use core::option::swap_unwrap;
struct List { key: int, next: Option<~List> }
fn foo(node: ~List) -> int {
let r = match node.next {
Some(right) => consume(right),
None => 0
};
consume(node) + r //~ ERROR use of partially moved value: `node`
}
fn consume(v: ~List) -> int {
v.key
}
fn main() {}

View file

@ -29,7 +29,7 @@ fn main() {
do task::spawn {
let mut y = None;
*x <-> y; //~ ERROR not a sendable value
*x <-> y; //~ ERROR value has non-owned type
log(error, y);
}
}

View file

@ -42,14 +42,14 @@ fn r2(x:@mut int) -> r2 {
fn main() {
foo({f: 3});
foo({mut f: 3}); //~ ERROR missing `const`
foo({mut f: 3}); //~ ERROR does not fulfill `Const`
foo(~[1]);
foo(~[mut 1]); //~ ERROR missing `const`
foo(~[mut 1]); //~ ERROR does not fulfill `Const`
foo(~1);
foo(~mut 1); //~ ERROR missing `const`
foo(~mut 1); //~ ERROR does not fulfill `Const`
foo(@1);
foo(@mut 1); //~ ERROR missing `const`
foo(@mut 1); //~ ERROR does not fulfill `Const`
foo(r(1)); // this is okay now.
foo(r2(@mut 1)); //~ ERROR missing `const`
foo({f: {mut f: 1}}); //~ ERROR missing `const`
foo(r2(@mut 1)); //~ ERROR does not fulfill `Const`
foo({f: {mut f: 1}}); //~ ERROR does not fulfill `Const`
}

View file

@ -13,6 +13,6 @@ fn main() {
let y : *libc::c_void = x as *libc::c_void;
unsafe {
let _z = copy *y;
//~^ ERROR copying a noncopyable value
//~^ ERROR copying a value of non-copyable type
}
}

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
// Test that a class with a non-copyable field can't be
// copied
struct bar {
@ -38,4 +36,8 @@ fn foo(i:int) -> foo {
}
}
fn main() { let x = move foo(10); let y = copy x; log(error, x); }
fn main() {
let x = move foo(10);
let _y = copy x; //~ ERROR copying a value of non-copyable type
log(error, x);
}

View file

@ -11,7 +11,7 @@
fn main() {
let x = Some(private::exclusive(false));
match x {
Some(copy z) => { //~ ERROR copying a noncopyable value
Some(copy z) => { //~ ERROR copying a value of non-copyable type
do z.with |b| { assert !*b; }
}
None => die!()

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
struct r {
i: @mut int,
}
@ -31,7 +29,7 @@ fn main() {
{
// Can't do this copy
let x = ~~~{y: r(i)};
let z = copy x;
let _z = copy x; //~ ERROR copying a value of non-copyable type
log(debug, x);
}
log(error, *i);

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
struct my_resource {
x: int,
}
@ -29,7 +27,7 @@ fn my_resource(x: int) -> my_resource {
fn main() {
{
let a = {x: 0, y: my_resource(20)};
let b = {x: 2,.. copy a};
let b = {x: 2,.. copy a}; //~ ERROR copying a value of non-copyable type
log(error, (a, b));
}
}

View file

@ -24,6 +24,6 @@ impl Foo : Drop {
fn main() {
let a = Foo { x: 3 };
let _ = [ a, ..5 ]; //~ ERROR copying a noncopyable value
let _ = [ a, ..5 ]; //~ ERROR copying a value of non-copyable type
}

View file

@ -9,7 +9,7 @@
// except according to those terms.
trait Foo {
fn f();
fn f(&self);
}
struct Bar {
@ -21,14 +21,14 @@ impl Bar : Drop {
}
impl Bar : Foo {
fn f() {
fn f(&self) {
io::println("hi");
}
}
fn main() {
let x = ~Bar { x: 10 };
let y = (move x) as ~Foo; //~ ERROR uniquely-owned trait objects must be copyable
let _z = copy y;
let y: ~Foo = x as ~Foo;
let _z = copy y; //~ ERROR copying a value of non-copyable type
}

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
struct r {
b:bool,
}
@ -20,6 +18,6 @@ impl r : Drop {
fn main() {
let i = move ~r { b: true };
let j = copy i;
let _j = copy i; //~ ERROR copying a value of non-copyable type
log(debug, i);
}

View file

@ -13,5 +13,5 @@ fn f<T: Owned>(_i: T) {
fn main() {
let i = ~@100;
f(move i); //~ ERROR missing `owned`
f(move i); //~ ERROR does not fulfill `Owned`
}

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: copying a noncopyable value
struct r {
i: @mut int,
}
@ -20,7 +18,7 @@ impl r : Drop {
}
}
fn f<T>(+i: ~[T], +j: ~[T]) {
fn f<T>(+_i: ~[T], +_j: ~[T]) {
}
fn main() {
@ -29,6 +27,8 @@ fn main() {
let r1 = move ~[~r { i: i1 }];
let r2 = move ~[~r { i: i2 }];
f(copy r1, copy r2);
//~^ ERROR copying a value of non-copyable type
//~^^ ERROR copying a value of non-copyable type
log(debug, (r2, *i1));
log(debug, (r1, *i2));
}

View file

@ -25,6 +25,6 @@ fn foo(i:int, j: @~str) -> foo {
fn main() {
let cat = ~"kitty";
let (_, ch) = pipes::stream(); //~ ERROR missing `owned`
ch.send(foo(42, @(move cat))); //~ ERROR missing `owned`
let (_, ch) = pipes::stream(); //~ ERROR does not fulfill `Owned`
ch.send(foo(42, @(move cat))); //~ ERROR does not fulfill `Owned`
}

View file

@ -26,8 +26,6 @@ pub fn main() {
let x = ~S { x: 3 };
let y = x as ~Foo;
y.f();
y.f();
y.f();
}

View file

@ -9,7 +9,7 @@
// except according to those terms.
trait Foo {
fn f();
fn f(&self) -> int;
}
struct Bar {
@ -17,16 +17,14 @@ struct Bar {
}
impl Bar : Foo {
fn f() {
io::println("hi");
fn f(&self) -> int {
self.x
}
}
pub fn main() {
let x = ~Bar { x: 10 };
let y = x as ~Foo;
let z = copy y;
y.f();
z.f();
assert y.f() == 10;
}