Update compile-fail tests to use the expected type to force the

closure kind, thereby detecting what happens if there are
mismatches. Simply removing the `:` annotations caused most of these
tests to pass or produce other errors, because the inference would
convert the closure into a more appropriate kind. (The ability to
override the inference by using the expected type is an important
backdoor partly for this reason.)
This commit is contained in:
Niko Matsakis 2015-02-03 11:32:26 -05:00
parent 498595a3dc
commit 47f18659ff
12 changed files with 72 additions and 64 deletions

View file

@ -8,34 +8,38 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(unboxed_closures, overloaded_calls)]
#![feature(unboxed_closures)]
// Tests that we can't assign to or mutably borrow upvars from `Fn`
// closures (issue #17780)
fn set(x: &mut usize) { *x = 5; }
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn main() {
// By-ref captures
{
let mut x = 0us;
let _f = |&:| x = 42; //~ ERROR cannot assign
let _f = to_fn(|| x = 42); //~ ERROR cannot assign
let mut y = 0us;
let _g = |&:| set(&mut y); //~ ERROR cannot borrow
let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow
let mut z = 0us;
let _h = |&mut:| { set(&mut z); |&:| z = 42; }; //~ ERROR cannot assign
let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); //~ ERROR cannot assign
}
// By-value captures
{
let mut x = 0us;
let _f = move |&:| x = 42; //~ ERROR cannot assign
let _f = to_fn(move || x = 42); //~ ERROR cannot assign
let mut y = 0us;
let _g = move |&:| set(&mut y); //~ ERROR cannot borrow
let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow
let mut z = 0us;
let _h = move |&mut:| { set(&mut z); move |&:| z = 42; }; //~ ERROR cannot assign
let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign
}
}

View file

@ -8,11 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax)]
#![feature(box_syntax,unboxed_closures)]
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
pub fn main() {
let bar = box 3;
let _g = |&mut:| {
let _h = move |:| -> isize { *bar }; //~ ERROR cannot move out of captured outer variable
};
let _g = to_fn_mut(|| {
let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of
});
}

View file

@ -8,12 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
let x = 1;
move|:| { x = 2; };
to_fn_once(move|:| { x = 2; });
//~^ ERROR: cannot assign to immutable captured outer variable
let s = std::old_io::stdin();
move|:| { s.read_to_end(); };
to_fn_once(move|:| { s.read_to_end(); });
//~^ ERROR: cannot borrow immutable captured outer variable
}

View file

@ -8,12 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax)]
#![feature(box_syntax, unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
let r = {
let x = box 42;
let f = move|:| &x; //~ ERROR: `x` does not live long enough
let f = to_fn_once(move|| &x); //~ ERROR: `x` does not live long enough
f()
};

View file

@ -8,14 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax)]
#![feature(box_syntax, unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn do_it(x: &isize) { }
fn main() {
let x = box 22;
let f = move|:| do_it(&*x);
(move|:| {
let f = to_fn_once(move|| do_it(&*x));
to_fn_once(move|| {
f();
f();
//~^ ERROR: use of moved value: `f`

View file

@ -8,13 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax)]
#![feature(box_syntax, unboxed_closures)]
use std::usize;
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
fn test(_x: Box<usize>) {}
fn main() {
let i = box 3;
let _f = |&:| test(i); //~ ERROR cannot move out
let _f = to_fn(|| test(i)); //~ ERROR cannot move out
}

View file

@ -10,8 +10,10 @@
#![feature(unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
let f = move|:| ();
let f = to_fn_once(move|| ());
f();
f(); //~ ERROR use of moved value
}

View file

@ -15,31 +15,35 @@
// if the upvar is captured by ref or the closure takes self by
// reference.
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
// By-ref cases
{
let x = box 0us;
let f = |&:| drop(x); //~ ERROR cannot move
let f = to_fn(|| drop(x)); //~ ERROR cannot move
}
{
let x = box 0us;
let f = |&mut:| drop(x); //~ ERROR cannot move
let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move
}
{
let x = box 0us;
let f = |:| drop(x); // OK -- FnOnce
let f = to_fn_once(|| drop(x)); // OK -- FnOnce
}
// By-value cases
{
let x = box 0us;
let f = move |&:| drop(x); //~ ERROR cannot move
let f = to_fn(move || drop(x)); //~ ERROR cannot move
}
{
let x = box 0us;
let f = move |&mut:| drop(x); //~ ERROR cannot move
let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move
}
{
let x = box 0us;
let f = move |:| drop(x); // this one is ok
let f = to_fn_once(move || drop(x)); // this one is ok
}
}

View file

@ -12,51 +12,56 @@
// as `mut` through a closure. Also test that we CAN mutate a moved copy,
// unless this is a `Fn` closure. Issue #16749.
#![feature(unboxed_closures)]
use std::mem;
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn a() {
let n = 0u8;
let mut f = |&mut:| { //~ ERROR closure cannot assign
let mut f = to_fn_mut(|| { //~ ERROR closure cannot assign
n += 1;
};
});
}
fn b() {
let mut n = 0u8;
let mut f = |&mut:| {
let mut f = to_fn_mut(|| {
n += 1; // OK
};
});
}
fn c() {
let n = 0u8;
let mut f = move |&mut:| {
let mut f = to_fn_mut(move || {
// If we just did a straight-forward desugaring, this would
// compile, but we do something a bit more subtle, and hence
// we get an error.
n += 1; //~ ERROR cannot assign
};
});
}
fn d() {
let mut n = 0u8;
let mut f = move |&mut:| {
let mut f = to_fn_mut(move || {
n += 1; // OK
};
});
}
fn e() {
let n = 0u8;
let mut f = move |&:| {
let mut f = to_fn(move || {
n += 1; //~ ERROR cannot assign
};
});
}
fn f() {
let mut n = 0u8;
let mut f = move |&:| {
let mut f = to_fn(move || {
n += 1; //~ ERROR cannot assign
};
});
}
fn main() { }

View file

@ -10,8 +10,10 @@
#![feature(unboxed_closures)]
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn main() {
let mut_ = |&mut: x| x;
let mut_ = to_fn_mut(|x| x);
mut_.call((0, )); //~ ERROR does not implement any method in scope named `call`
}

View file

@ -12,12 +12,14 @@
use std::ops::FnMut;
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
f(2, y)
}
pub fn main() {
let f = |&mut: x: usize, y: isize| -> isize { (x as isize) + y };
let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
let z = call_it(3, f);
//~^ ERROR type mismatch
//~| ERROR type mismatch

View file

@ -1,23 +0,0 @@
// Copyright 2014 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.
#![feature(lang_items, overloaded_calls, unboxed_closures)]
fn c<F:Fn(isize, isize) -> isize>(f: F) -> isize {
f(5, 6)
}
fn main() {
let z: isize = 7;
assert_eq!(c(|&mut: x: isize, y| x + y + z), 10);
//~^ ERROR not implemented
//~| ERROR not implemented
}