mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-23 13:13:17 +00:00
new liveness pass to supercede last_use / initedness
This commit is contained in:
parent
a3be0b1054
commit
30b47649ea
@ -351,7 +351,7 @@ enum expr_ {
|
||||
}
|
||||
|
||||
#[auto_serialize]
|
||||
type capture_item = {
|
||||
type capture_item = @{
|
||||
id: int,
|
||||
is_move: bool,
|
||||
name: ident, // Currently, can only capture a local var.
|
||||
|
@ -434,7 +434,7 @@ class parser {
|
||||
fn parse_capture_item(p:parser, is_move: bool) -> capture_item {
|
||||
let sp = mk_sp(p.span.lo, p.span.hi);
|
||||
let ident = parse_ident(p);
|
||||
{id: p.get_id(), is_move: is_move, name: ident, span: sp}
|
||||
@{id: p.get_id(), is_move: is_move, name: ident, span: sp}
|
||||
}
|
||||
|
||||
if eat_keyword(self, "move") {
|
||||
@ -1710,7 +1710,7 @@ class parser {
|
||||
let id = p.get_id();
|
||||
let sp = mk_sp(p.span.lo, p.span.hi);
|
||||
let ident = parse_ident(p);
|
||||
res += [{id:id, is_move: is_move, name:ident, span:sp}];
|
||||
res += [@{id:id, is_move: is_move, name:ident, span:sp}];
|
||||
if !eat(p, token::COMMA) {
|
||||
ret res;
|
||||
}
|
||||
|
@ -192,6 +192,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||
bind middle::check_loop::check_crate(ty_cx, crate));
|
||||
time(time_passes, "alt checking",
|
||||
bind middle::check_alt::check_crate(ty_cx, crate));
|
||||
let _last_use_map =
|
||||
time(time_passes, "liveness checking",
|
||||
bind middle::liveness::check_crate(ty_cx, method_map, crate));
|
||||
time(time_passes, "typestate checking",
|
||||
bind middle::tstate::ck::check_crate(ty_cx, crate));
|
||||
let (root_map, mutbl_map) = time(
|
||||
|
@ -541,6 +541,15 @@ enum assignment_type {
|
||||
}
|
||||
|
||||
impl methods for assignment_type {
|
||||
fn checked_by_liveness() -> bool {
|
||||
// the liveness pass guarantees that immutable local variables
|
||||
// are only assigned once; but it doesn't consider &mut
|
||||
alt self {
|
||||
at_straight_up {true}
|
||||
at_swap {true}
|
||||
at_mutbl_ref {false}
|
||||
}
|
||||
}
|
||||
fn ing_form(desc: str) -> str {
|
||||
alt self {
|
||||
at_straight_up { "assigning to " + desc }
|
||||
@ -717,6 +726,13 @@ impl methods for check_loan_ctxt {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_local_variable(cmt: cmt) -> bool {
|
||||
alt cmt.cat {
|
||||
cat_local(_) {true}
|
||||
_ {false}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_self_field(cmt: cmt) -> bool {
|
||||
alt cmt.cat {
|
||||
cat_comp(cmt_base, comp_field(_)) {
|
||||
@ -735,9 +751,13 @@ impl methods for check_loan_ctxt {
|
||||
#debug["check_assignment(cmt=%s)",
|
||||
self.bccx.cmt_to_repr(cmt)];
|
||||
|
||||
// check that the lvalue `ex` is assignable, but be careful
|
||||
// because assigning to self.foo in a ctor is always allowed.
|
||||
if !self.in_ctor || !self.is_self_field(cmt) {
|
||||
if self.in_ctor && self.is_self_field(cmt)
|
||||
&& at.checked_by_liveness() {
|
||||
// assigning to self.foo in a ctor is always allowed.
|
||||
} else if self.is_local_variable(cmt) && at.checked_by_liveness() {
|
||||
// liveness guarantees that immutable local variables
|
||||
// are only assigned once
|
||||
} else {
|
||||
alt cmt.mutbl {
|
||||
m_mutbl { /*ok*/ }
|
||||
m_const | m_imm {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import syntax::{ast, ast_util};
|
||||
import driver::session::session;
|
||||
import syntax::codemap::span;
|
||||
import std::map;
|
||||
import std::map::hashmap;
|
||||
|
||||
@ -14,15 +15,17 @@ export cap_drop;
|
||||
export cap_ref;
|
||||
|
||||
enum capture_mode {
|
||||
cap_copy, //< Copy the value into the closure.
|
||||
cap_move, //< Move the value into the closure.
|
||||
cap_drop, //< Drop value after creating closure.
|
||||
cap_ref, //< Reference directly from parent stack frame (block fn).
|
||||
cap_copy, // Copy the value into the closure.
|
||||
cap_move, // Move the value into the closure.
|
||||
cap_drop, // Drop value after creating closure.
|
||||
cap_ref, // Reference directly from parent stack frame (block fn).
|
||||
}
|
||||
|
||||
type capture_var = {
|
||||
def: ast::def, //< The variable being accessed free.
|
||||
mode: capture_mode //< How is the variable being accessed.
|
||||
def: ast::def, // Variable being accessed free
|
||||
span: span, // Location of access or cap item
|
||||
cap_item: option<ast::capture_item>, // Capture item, if any
|
||||
mode: capture_mode // How variable is being accessed
|
||||
};
|
||||
|
||||
type capture_map = map::hashmap<ast::def_id, capture_var>;
|
||||
@ -70,15 +73,24 @@ fn compute_capture_vars(tcx: ty::ctxt,
|
||||
// if we are moving the value in, but it's not actually used,
|
||||
// must drop it.
|
||||
if vec::any(*freevars, {|fv| fv.def == cap_def}) {
|
||||
cap_map.insert(cap_def_id, { def:cap_def, mode:cap_move });
|
||||
cap_map.insert(cap_def_id, {def:cap_def,
|
||||
span: cap_item.span,
|
||||
cap_item: some(cap_item),
|
||||
mode:cap_move});
|
||||
} else {
|
||||
cap_map.insert(cap_def_id, { def:cap_def, mode:cap_drop });
|
||||
cap_map.insert(cap_def_id, {def:cap_def,
|
||||
span: cap_item.span,
|
||||
cap_item: some(cap_item),
|
||||
mode:cap_drop});
|
||||
}
|
||||
} else {
|
||||
// if we are copying the value in, but it's not actually used,
|
||||
// just ignore it.
|
||||
if vec::any(*freevars, {|fv| fv.def == cap_def}) {
|
||||
cap_map.insert(cap_def_id, { def:cap_def, mode:cap_copy });
|
||||
cap_map.insert(cap_def_id, {def:cap_def,
|
||||
span: cap_item.span,
|
||||
cap_item: some(cap_item),
|
||||
mode:cap_copy});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,7 +108,10 @@ fn compute_capture_vars(tcx: ty::ctxt,
|
||||
alt cap_map.find(fvar_def_id) {
|
||||
option::some(_) { /* was explicitly named, do nothing */ }
|
||||
option::none {
|
||||
cap_map.insert(fvar_def_id, {def:fvar.def, mode:implicit_mode});
|
||||
cap_map.insert(fvar_def_id, {def:fvar.def,
|
||||
span: fvar.span,
|
||||
cap_item: none,
|
||||
mode:implicit_mode});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1502
src/rustc/middle/liveness.rs
Normal file
1502
src/rustc/middle/liveness.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -72,6 +72,7 @@ mod middle {
|
||||
mod borrowck;
|
||||
mod alias;
|
||||
mod last_use;
|
||||
mod liveness;
|
||||
mod block_use;
|
||||
mod kind;
|
||||
mod freevars;
|
||||
|
@ -1,8 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(i
|
||||
|
||||
fn main() {
|
||||
let i: int;
|
||||
|
||||
log(debug, false && { i = 5; true });
|
||||
log(debug, i);
|
||||
}
|
9
src/test/compile-fail/assign-imm-local-twice.rs
Normal file
9
src/test/compile-fail/assign-imm-local-twice.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn test(cond: bool) {
|
||||
let v: int;
|
||||
v = 1; //! NOTE prior assignment occurs here
|
||||
v = 2; //! ERROR re-assignment of immutable variable
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint
|
||||
|
||||
fn force(f: fn()) { f(); }
|
||||
fn main() { let x: int; force(fn&() { log(error, x); }); }
|
@ -1,14 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn foo() -> int {
|
||||
let x: int;
|
||||
let i: int;
|
||||
|
||||
loop { i = 0; break; x = 0; }
|
||||
|
||||
log(debug, x);
|
||||
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
@ -1,14 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn foo() -> int {
|
||||
let x: int;
|
||||
let i: int;
|
||||
|
||||
while 1 != 2 { i = 0; break; x = 0; }
|
||||
|
||||
log(debug, x);
|
||||
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
@ -1,7 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn main() {
|
||||
// Typestate should work even in a fn@. we should reject this program.
|
||||
let f = fn@() -> int { let i: int; ret i; };
|
||||
log(error, f());
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn main() {
|
||||
let j = fn@() -> int { let i: int; ret i; }();
|
||||
log(error, j);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// -*- rust -*-
|
||||
|
||||
// error-pattern: precondition
|
||||
|
||||
type point = {x: int, y: int};
|
||||
|
||||
fn main() {
|
||||
let origin: point;
|
||||
|
||||
let right: point = {x: 10 with origin};
|
||||
origin = {x: 0, y: 0};
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
fn main(s: [str]) {
|
||||
let a: [int] = [];
|
||||
vec::each(a) { |x| //! ERROR in function `anon`, not all control paths
|
||||
} //! ERROR see function return type of `bool`
|
||||
}
|
6
src/test/compile-fail/liveness-and-init.rs
Normal file
6
src/test/compile-fail/liveness-and-init.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
let i: int;
|
||||
|
||||
log(debug, false && { i = 5; true });
|
||||
log(debug, i); //! ERROR use of possibly uninitialized variable: `i`
|
||||
}
|
11
src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
Normal file
11
src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
Normal file
@ -0,0 +1,11 @@
|
||||
fn test(cond: bool) {
|
||||
let v: int;
|
||||
loop {
|
||||
v = 1; //! ERROR re-assignment of immutable variable
|
||||
//!^ NOTE prior assignment occurs here
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
fn test(cond: bool) {
|
||||
let v: int;
|
||||
v = 2; //! NOTE prior assignment occurs here
|
||||
v += 1; //! ERROR re-assignment of immutable variable
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
18
src/test/compile-fail/liveness-assign-imm-local-in-swap.rs
Normal file
18
src/test/compile-fail/liveness-assign-imm-local-in-swap.rs
Normal file
@ -0,0 +1,18 @@
|
||||
fn test1() {
|
||||
let v: int;
|
||||
let mut w: int;
|
||||
v = 1; //! NOTE prior assignment occurs here
|
||||
w = 2;
|
||||
v <-> w; //! ERROR re-assignment of immutable variable
|
||||
}
|
||||
|
||||
fn test2() {
|
||||
let v: int;
|
||||
let mut w: int;
|
||||
v = 1; //! NOTE prior assignment occurs here
|
||||
w = 2;
|
||||
w <-> v; //! ERROR re-assignment of immutable variable
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
7
src/test/compile-fail/liveness-block-unint.rs
Normal file
7
src/test/compile-fail/liveness-block-unint.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn force(f: fn()) { f(); }
|
||||
fn main() {
|
||||
let x: int;
|
||||
force(fn&() {
|
||||
log(debug, x); //! ERROR capture of possibly uninitialized variable: `x`
|
||||
});
|
||||
}
|
16
src/test/compile-fail/liveness-break-uninit-2.rs
Normal file
16
src/test/compile-fail/liveness-break-uninit-2.rs
Normal file
@ -0,0 +1,16 @@
|
||||
fn foo() -> int {
|
||||
let x: int;
|
||||
let i: int;
|
||||
|
||||
while 1 != 2 {
|
||||
i = 0;
|
||||
break;
|
||||
x = 0; //! WARNING unreachable statement
|
||||
}
|
||||
|
||||
log(debug, x); //! ERROR use of possibly uninitialized variable: `x`
|
||||
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
16
src/test/compile-fail/liveness-break-uninit.rs
Normal file
16
src/test/compile-fail/liveness-break-uninit.rs
Normal file
@ -0,0 +1,16 @@
|
||||
fn foo() -> int {
|
||||
let x: int;
|
||||
let i: int;
|
||||
|
||||
loop {
|
||||
i = 0;
|
||||
break;
|
||||
x = 0; //! WARNING unreachable statement
|
||||
}
|
||||
|
||||
log(debug, x); //! ERROR use of possibly uninitialized variable: `x`
|
||||
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
@ -0,0 +1,11 @@
|
||||
class cat {
|
||||
let how_hungry : int;
|
||||
fn meow() {}
|
||||
new() {
|
||||
self.meow();
|
||||
//!^ ERROR use of possibly uninitialized field: `self.how_hungry`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
7
src/test/compile-fail/liveness-ctor-field-never-init.rs
Normal file
7
src/test/compile-fail/liveness-ctor-field-never-init.rs
Normal file
@ -0,0 +1,7 @@
|
||||
class cat {
|
||||
let how_hungry : int;
|
||||
new() {} //! ERROR field `self.how_hungry` is never initialized
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
14
src/test/compile-fail/liveness-ctor-uninit-field.rs
Normal file
14
src/test/compile-fail/liveness-ctor-uninit-field.rs
Normal file
@ -0,0 +1,14 @@
|
||||
class cat {
|
||||
let mut a: int;
|
||||
let mut b: int;
|
||||
let mut c: int;
|
||||
|
||||
new() {
|
||||
self.a = 3;
|
||||
self.b = self.a;
|
||||
self.a += self.c; //! ERROR use of possibly uninitialized field: `self.c`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
class cat {
|
||||
priv {
|
||||
let mut meows : uint;
|
||||
@ -13,7 +12,7 @@ class cat {
|
||||
new(in_x : uint, in_y : int) {
|
||||
let foo;
|
||||
self.meows = in_x + (in_y as uint);
|
||||
self.how_hungry = foo;
|
||||
self.how_hungry = foo; //! ERROR use of possibly uninitialized variable: `foo`
|
||||
}
|
||||
}
|
||||
|
6
src/test/compile-fail/liveness-if-no-else.rs
Normal file
6
src/test/compile-fail/liveness-if-no-else.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() {
|
||||
let x: int; if 1 > 2 { x = 10; }
|
||||
foo(x); //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() {
|
||||
@ -9,5 +7,5 @@ fn main() {
|
||||
} else {
|
||||
x = 10;
|
||||
}
|
||||
foo(x);
|
||||
foo(x); //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
7
src/test/compile-fail/liveness-init-in-called-fn-expr.rs
Normal file
7
src/test/compile-fail/liveness-init-in-called-fn-expr.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
let j = fn@() -> int {
|
||||
let i: int;
|
||||
ret i; //! ERROR use of possibly uninitialized variable: `i`
|
||||
};
|
||||
j();
|
||||
}
|
7
src/test/compile-fail/liveness-init-in-fn-expr.rs
Normal file
7
src/test/compile-fail/liveness-init-in-fn-expr.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
let f = fn@() -> int {
|
||||
let i: int;
|
||||
ret i; //! ERROR use of possibly uninitialized variable: `i`
|
||||
};
|
||||
log(error, f());
|
||||
}
|
8
src/test/compile-fail/liveness-init-in-fru.rs
Normal file
8
src/test/compile-fail/liveness-init-in-fru.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// -*- rust -*-
|
||||
|
||||
type point = {x: int, y: int};
|
||||
|
||||
fn main() {
|
||||
let mut origin: point;
|
||||
origin = {x: 10 with origin}; //! ERROR use of possibly uninitialized variable: `origin`
|
||||
}
|
8
src/test/compile-fail/liveness-init-op-equal.rs
Normal file
8
src/test/compile-fail/liveness-init-op-equal.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn test(cond: bool) {
|
||||
let v: int;
|
||||
v += 1; //! ERROR use of possibly uninitialized variable: `v`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
8
src/test/compile-fail/liveness-init-plus-equal.rs
Normal file
8
src/test/compile-fail/liveness-init-plus-equal.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn test(cond: bool) {
|
||||
let mut v: int;
|
||||
v = v + 1; //! ERROR use of possibly uninitialized variable: `v`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
5
src/test/compile-fail/liveness-issue-2163.rs
Normal file
5
src/test/compile-fail/liveness-issue-2163.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main(s: [str]) {
|
||||
let a: [int] = [];
|
||||
vec::each(a) { |x| //! ERROR not all control paths return a value
|
||||
}
|
||||
}
|
10
src/test/compile-fail/liveness-move-from-mode.rs
Normal file
10
src/test/compile-fail/liveness-move-from-mode.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn take(-x: int) {}
|
||||
|
||||
fn main() {
|
||||
|
||||
let x: int = 25;
|
||||
loop {
|
||||
take(x); //! ERROR use of moved variable: `x`
|
||||
//!^ NOTE move of variable occurred here
|
||||
}
|
||||
}
|
16
src/test/compile-fail/liveness-move-in-loop.rs
Normal file
16
src/test/compile-fail/liveness-move-in-loop.rs
Normal file
@ -0,0 +1,16 @@
|
||||
fn main() {
|
||||
|
||||
let y: int = 42;
|
||||
let mut x: int;
|
||||
loop {
|
||||
log(debug, y);
|
||||
loop {
|
||||
loop {
|
||||
loop {
|
||||
x <- y; //! ERROR use of moved variable
|
||||
//!^ NOTE move of variable occurred here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(y
|
||||
fn main() {
|
||||
|
||||
let y: int = 42;
|
||||
let x: int;
|
||||
let mut x: int;
|
||||
loop {
|
||||
log(debug, y);
|
||||
while true { while true { while true { x <- y; } } }
|
||||
//!^ ERROR use of moved variable: `y`
|
||||
//!^^ NOTE move of variable occurred here
|
||||
}
|
||||
}
|
6
src/test/compile-fail/liveness-or-init.rs
Normal file
6
src/test/compile-fail/liveness-or-init.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
let i: int;
|
||||
|
||||
log(debug, false || { i = 5; true });
|
||||
log(debug, i); //! ERROR use of possibly uninitialized variable: `i`
|
||||
}
|
6
src/test/compile-fail/liveness-return.rs
Normal file
6
src/test/compile-fail/liveness-return.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn f() -> int {
|
||||
let x: int;
|
||||
ret x; //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
||||
|
||||
fn main() { f(); }
|
5
src/test/compile-fail/liveness-swap-uninit.rs
Normal file
5
src/test/compile-fail/liveness-swap-uninit.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let x = 3;
|
||||
let y;
|
||||
x <-> y; //! ERROR use of possibly uninitialized variable: `y`
|
||||
}
|
6
src/test/compile-fail/liveness-uninit-after-item.rs
Normal file
6
src/test/compile-fail/liveness-uninit-after-item.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
let bar;
|
||||
fn baz(x: int) { }
|
||||
bind baz(bar); //! ERROR use of possibly uninitialized variable: `bar`
|
||||
}
|
||||
|
6
src/test/compile-fail/liveness-uninit.rs
Normal file
6
src/test/compile-fail/liveness-uninit.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() {
|
||||
let x: int;
|
||||
foo(x); //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
5
src/test/compile-fail/liveness-use-after-move.rs
Normal file
5
src/test/compile-fail/liveness-use-after-move.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let x = @5;
|
||||
let y <- x; //! NOTE move of variable occurred here
|
||||
log(debug, *x); //! ERROR use of moved variable: `x`
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
// error-pattern:unsatisfied precondition constraint
|
||||
fn send<T: send>(ch: _chan<T>, -data: T) {
|
||||
log(debug, ch);
|
||||
log(debug, data);
|
||||
@ -10,8 +9,8 @@ enum _chan<T> = int;
|
||||
// Tests that "log(debug, message);" is flagged as using
|
||||
// message after the send deinitializes it
|
||||
fn test00_start(ch: _chan<int>, message: int, count: int) {
|
||||
send(ch, message);
|
||||
log(debug, message);
|
||||
send(ch, message); //! NOTE move of variable occurred here
|
||||
log(debug, message); //! ERROR use of moved variable: `message`
|
||||
}
|
||||
|
||||
fn main() { fail; }
|
6
src/test/compile-fail/liveness-use-in-index-lvalue.rs
Normal file
6
src/test/compile-fail/liveness-use-in-index-lvalue.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn test() {
|
||||
let w: [int];
|
||||
w[5] = 0; //! ERROR use of possibly uninitialized variable: `w`
|
||||
}
|
||||
|
||||
fn main() { test(); }
|
12
src/test/compile-fail/liveness-while-break.rs
Normal file
12
src/test/compile-fail/liveness-while-break.rs
Normal file
@ -0,0 +1,12 @@
|
||||
fn test(cond: bool) {
|
||||
let v;
|
||||
while cond {
|
||||
v = 3;
|
||||
break;
|
||||
}
|
||||
#debug["%d", v]; //! ERROR use of possibly uninitialized variable: `v`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
4
src/test/compile-fail/liveness-while-cond.rs
Normal file
4
src/test/compile-fail/liveness-while-cond.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
let x: bool;
|
||||
while x { } //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
7
src/test/compile-fail/liveness-while.rs
Normal file
7
src/test/compile-fail/liveness-while.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn f() -> int {
|
||||
let mut x: int;
|
||||
while 1 == 1 { x = 10; }
|
||||
ret x; //! ERROR use of possibly uninitialized variable: `x`
|
||||
}
|
||||
|
||||
fn main() { f(); }
|
@ -1,4 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint
|
||||
fn test(-foo: int) { assert (foo == 10); }
|
||||
|
||||
fn main() { let x = 10; test(x); log(debug, x); }
|
@ -1,8 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(i
|
||||
|
||||
fn main() {
|
||||
let i: int;
|
||||
|
||||
log(debug, false || { i = 5; true });
|
||||
log(debug, i);
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
// error-pattern: precondition constraint
|
||||
|
||||
fn f() -> int { let x: int; ret x; }
|
||||
|
||||
fn main() { f(); }
|
@ -1,3 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn main() { let x = 3; let y; x <-> y; }
|
7
src/test/compile-fail/tstate-and-init.rs
Normal file
7
src/test/compile-fail/tstate-and-init.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
fn main() {
|
||||
let i: int = 4;
|
||||
log(debug, false && { check is_even(i); true });
|
||||
even(i); //! ERROR unsatisfied precondition
|
||||
}
|
11
src/test/compile-fail/tstate-block-uninit.rs
Normal file
11
src/test/compile-fail/tstate-block-uninit.rs
Normal file
@ -0,0 +1,11 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn force(f: fn()) { f(); }
|
||||
|
||||
fn main() {
|
||||
let x: int = 4;
|
||||
force(fn&() {
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
});
|
||||
}
|
16
src/test/compile-fail/tstate-break-uninit-2.rs
Normal file
16
src/test/compile-fail/tstate-break-uninit-2.rs
Normal file
@ -0,0 +1,16 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn foo() -> int {
|
||||
let x: int = 4;
|
||||
|
||||
while 1 != 2 {
|
||||
break;
|
||||
check is_even(x); //! WARNING unreachable statement
|
||||
}
|
||||
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
16
src/test/compile-fail/tstate-break-uninit.rs
Normal file
16
src/test/compile-fail/tstate-break-uninit.rs
Normal file
@ -0,0 +1,16 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn foo() -> int {
|
||||
let x: int = 4;
|
||||
|
||||
loop {
|
||||
break;
|
||||
check is_even(x); //! WARNING unreachable statement
|
||||
}
|
||||
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
ret 17;
|
||||
}
|
||||
|
||||
fn main() { log(debug, foo()); }
|
25
src/test/compile-fail/tstate-ctor-unsat.rs
Normal file
25
src/test/compile-fail/tstate-ctor-unsat.rs
Normal file
@ -0,0 +1,25 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
class cat {
|
||||
priv {
|
||||
let mut meows : uint;
|
||||
}
|
||||
|
||||
let how_hungry : int;
|
||||
|
||||
fn eat() {
|
||||
self.how_hungry -= 5;
|
||||
}
|
||||
|
||||
new(in_x : uint, in_y : int) {
|
||||
let foo = 3;
|
||||
self.meows = in_x + (in_y as uint);
|
||||
self.how_hungry = even(foo); //! ERROR unsatisfied precondition
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let nyan : cat = cat(52u, 99);
|
||||
nyan.eat();
|
||||
}
|
13
src/test/compile-fail/tstate-fru.rs
Normal file
13
src/test/compile-fail/tstate-fru.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// -*- rust -*-
|
||||
|
||||
type point = {x: int, y: int};
|
||||
|
||||
pure fn test(_p: point) -> bool { true }
|
||||
fn tested(p: point) : test(p) -> point { p }
|
||||
|
||||
fn main() {
|
||||
let origin: point;
|
||||
origin = {x: 0, y: 0};
|
||||
let right: point = {x: 10 with tested(origin)};
|
||||
//!^ ERROR precondition
|
||||
}
|
10
src/test/compile-fail/tstate-if-no-else.rs
Normal file
10
src/test/compile-fail/tstate-if-no-else.rs
Normal file
@ -0,0 +1,10 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() {
|
||||
let x: int = 10;
|
||||
if 1 > 2 { check is_even(x); }
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
}
|
14
src/test/compile-fail/tstate-if-with-else.rs
Normal file
14
src/test/compile-fail/tstate-if-with-else.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() {
|
||||
let x: int = 10;
|
||||
if 1 > 2 {
|
||||
#debug("whoops");
|
||||
} else {
|
||||
check is_even(x);
|
||||
}
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
}
|
19
src/test/compile-fail/tstate-loop-constraints.rs
Normal file
19
src/test/compile-fail/tstate-loop-constraints.rs
Normal file
@ -0,0 +1,19 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn main() {
|
||||
|
||||
let mut x: int = 42;
|
||||
loop {
|
||||
loop {
|
||||
loop {
|
||||
check is_even(x);
|
||||
even(x); // OK
|
||||
loop {
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
x = 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
src/test/compile-fail/tstate-or-init.rs
Normal file
7
src/test/compile-fail/tstate-or-init.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
fn main() {
|
||||
let i: int = 4;
|
||||
log(debug, false || { check is_even(i); true });
|
||||
even(i); //! ERROR unsatisfied precondition
|
||||
}
|
9
src/test/compile-fail/tstate-return.rs
Normal file
9
src/test/compile-fail/tstate-return.rs
Normal file
@ -0,0 +1,9 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn f() -> int {
|
||||
let x: int = 4;
|
||||
ret even(x); //! ERROR unsatisfied precondition
|
||||
}
|
||||
|
||||
fn main() { f(); }
|
9
src/test/compile-fail/tstate-unsat-after-item.rs
Normal file
9
src/test/compile-fail/tstate-unsat-after-item.rs
Normal file
@ -0,0 +1,9 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn main() {
|
||||
let x = 4;
|
||||
fn baz(_x: int) { }
|
||||
bind baz(even(x)); //! ERROR unsatisfied precondition
|
||||
}
|
||||
|
9
src/test/compile-fail/tstate-unsat-in-called-fn-expr.rs
Normal file
9
src/test/compile-fail/tstate-unsat-in-called-fn-expr.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn foo(v: [int]) : vec::is_empty(v) { #debug("%d", v[0]); }
|
||||
|
||||
fn main() {
|
||||
let f = fn@() {
|
||||
let v = [1];
|
||||
foo(v); //! ERROR unsatisfied precondition constraint
|
||||
}();
|
||||
log(error, f);
|
||||
}
|
9
src/test/compile-fail/tstate-unsat-in-fn-expr.rs
Normal file
9
src/test/compile-fail/tstate-unsat-in-fn-expr.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn foo(v: [int]) : vec::is_empty(v) { #debug("%d", v[0]); }
|
||||
|
||||
fn main() {
|
||||
let f = fn@() {
|
||||
let v = [1];
|
||||
foo(v); //! ERROR unsatisfied precondition constraint
|
||||
};
|
||||
log(error, f());
|
||||
}
|
7
src/test/compile-fail/tstate-unsat.rs
Normal file
7
src/test/compile-fail/tstate-unsat.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn main() {
|
||||
let x: int = 4;
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
}
|
15
src/test/compile-fail/tstate-while-break.rs
Normal file
15
src/test/compile-fail/tstate-while-break.rs
Normal file
@ -0,0 +1,15 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn test(cond: bool) {
|
||||
let v = 4;
|
||||
while cond {
|
||||
check is_even(v);
|
||||
break;
|
||||
}
|
||||
even(v); //! ERROR unsatisfied precondition
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test(true);
|
||||
}
|
7
src/test/compile-fail/tstate-while-cond.rs
Normal file
7
src/test/compile-fail/tstate-while-cond.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn main() {
|
||||
let x: int = 4;
|
||||
while even(x) != 0 { } //! ERROR unsatisfied precondition
|
||||
}
|
10
src/test/compile-fail/tstate-while.rs
Normal file
10
src/test/compile-fail/tstate-while.rs
Normal file
@ -0,0 +1,10 @@
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn f() {
|
||||
let mut x: int = 10;
|
||||
while 1 == 1 { x = 10; }
|
||||
even(x); //! ERROR unsatisfied precondition
|
||||
}
|
||||
|
||||
fn main() { f(); }
|
@ -1,7 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(bar
|
||||
fn main() {
|
||||
let bar;
|
||||
fn baz(x: int) { }
|
||||
bind baz(bar);
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(x
|
||||
fn main() { let x = @5; let y <- x; log(debug, *x); }
|
@ -1,5 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() { let x: int; if 1 > 2 { x = 10; } foo(x); }
|
@ -1,5 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition
|
||||
|
||||
fn foo(x: int) { log(debug, x); }
|
||||
|
||||
fn main() { let x: int; foo(x); }
|
@ -1,5 +0,0 @@
|
||||
// error-pattern: precondition constraint
|
||||
|
||||
fn f() -> int { let x: int; while 1 == 1 { x = 10; } ret x; }
|
||||
|
||||
fn main() { f(); }
|
@ -1,3 +0,0 @@
|
||||
// error-pattern: precondition constraint
|
||||
|
||||
fn main() { let x: bool; while x { } }
|
@ -1,14 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint (for example, init(y
|
||||
fn main() {
|
||||
|
||||
let y: int = 42;
|
||||
let x: int;
|
||||
loop {
|
||||
log(debug, y);
|
||||
loop {
|
||||
loop {
|
||||
loop { x <- y; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
// error-pattern:unsatisfied precondition constraint
|
||||
|
||||
fn test() { let w: [int]; w[5] = 0; }
|
||||
|
||||
fn main() { test(); }
|
10
src/test/run-pass/liveness-assign-imm-local-after-loop.rs
Normal file
10
src/test/run-pass/liveness-assign-imm-local-after-loop.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn test(cond: bool) {
|
||||
let v: int;
|
||||
v = 1;
|
||||
loop { } // loop never terminates, so no error is reported
|
||||
v = 2;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// note: don't call test()... :)
|
||||
}
|
9
src/test/run-pass/liveness-assign-imm-local-after-ret.rs
Normal file
9
src/test/run-pass/liveness-assign-imm-local-after-ret.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn test() {
|
||||
let _v: int;
|
||||
_v = 1;
|
||||
ret;
|
||||
_v = 2; //! WARNING: unreachable statement
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
14
src/test/run-pass/liveness-loop-break.rs
Normal file
14
src/test/run-pass/liveness-loop-break.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// xfail-test --- tstate incorrectly fails this
|
||||
|
||||
fn test() {
|
||||
let v;
|
||||
loop {
|
||||
v = 3;
|
||||
break;
|
||||
}
|
||||
#debug["%d", v];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test();
|
||||
}
|
15
src/test/run-pass/liveness-move-in-loop.rs
Normal file
15
src/test/run-pass/liveness-move-in-loop.rs
Normal file
@ -0,0 +1,15 @@
|
||||
fn take(-x: int) -> int {x}
|
||||
|
||||
fn the_loop() {
|
||||
let mut list = [];
|
||||
loop {
|
||||
let x = 5;
|
||||
if x > 3 {
|
||||
list += [take(x)];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/run-pass/tstate-loop-break.rs
Normal file
17
src/test/run-pass/tstate-loop-break.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// xfail-test
|
||||
|
||||
pure fn is_even(i: int) -> bool { (i%2) == 0 }
|
||||
fn even(i: int) : is_even(i) -> int { i }
|
||||
|
||||
fn test() {
|
||||
let v = 4;
|
||||
loop {
|
||||
check is_even(v);
|
||||
break;
|
||||
}
|
||||
even(v);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test();
|
||||
}
|
Loading…
Reference in New Issue
Block a user