diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-03-24 14:50:44 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-03-24 14:50:44 -0700 |
| commit | 8f6c879d2af6834a4f7a8b41ad335e52fe714e6d (patch) | |
| tree | eb514877eac12c4a528ac58fda4a744d33ab2dc3 /src/test | |
| parent | ed810385045ab0db90303574ba3ea47dfa2a36d5 (diff) | |
| parent | 9330bae4bde720dbdf8d379bd5529a1bb7a6f1e9 (diff) | |
| download | rust-8f6c879d2af6834a4f7a8b41ad335e52fe714e6d.tar.gz rust-8f6c879d2af6834a4f7a8b41ad335e52fe714e6d.zip | |
rollup merge of #23282: nikomatsakis/fn-trait-inheritance
The primary motivation here is to sidestep #19032 -- for a time, I thought that we should improve coherence or otherwise extend the language, but I now think that any such changes will require more time to bake. In the meantime, inheritance amongst the fn traits is both logically correct *and* a simple solution to that obstacle. This change introduces inheritance and modifies the compiler so that it can properly generate impls for closures and fns. Things enabled by this PR (but not included in this PR): 1. An impl of `FnMut` for `&mut F` where `F : FnMut` (https://github.com/rust-lang/rust/issues/23015). 2. A better version of `Thunk` I've been calling `FnBox`. I did not include either of these in the PR because: 1. Adding the impls in 1 currently induces a coherence conflict with the pattern trait. This is interesting and merits some discussion. 2. `FnBox` deserves to be a PR of its own. The main downside to this design is (a) the need to write impls by hand; (b) the possibility of implementing `FnMut` with different semantics from `Fn`, etc. Point (a) is minor -- in particular, it does not affect normal closure usage -- and could be addressed in the future in many ways (better defaults; convenient macros; specialization; etc). Point (b) is unfortunate but "just a bug" from my POV, and certainly not unique to these traits (c.f. Copy/Clone, PartialEq/Eq, etc). (Until we lift the feature-gate on implementing the Fn traits, in any case, there is room to correct both of these if we find a nice way.) Note that I believe this change is reversible in the future if we decide on another course of action, due to the feature gate on implementing the `Fn` traits, though I do not (currently) think we should reverse it. Fixes #18835. r? @nrc
Diffstat (limited to 'src/test')
27 files changed, 208 insertions, 57 deletions
diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs index 673c025e863..93c37524bf5 100644 --- a/src/test/compile-fail/borrowck-overloaded-call.rs +++ b/src/test/compile-fail/borrowck-overloaded-call.rs @@ -18,26 +18,36 @@ struct SFn { } impl Fn<(isize,)> for SFn { - type Output = isize; - extern "rust-call" fn call(&self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnMut<(isize,)> for SFn { + extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) } +} + +impl FnOnce<(isize,)> for SFn { + type Output = isize; + extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) } +} + struct SFnMut { x: isize, y: isize, } impl FnMut<(isize,)> for SFnMut { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnOnce<(isize,)> for SFnMut { + type Output = isize; + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + struct SFnOnce { x: String, } diff --git a/src/test/compile-fail/coerce-unsafe-to-closure.rs b/src/test/compile-fail/coerce-unsafe-to-closure.rs index fe7635f065c..27b4a04054f 100644 --- a/src/test/compile-fail/coerce-unsafe-to-closure.rs +++ b/src/test/compile-fail/coerce-unsafe-to-closure.rs @@ -10,5 +10,6 @@ fn main() { let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); - //~^ ERROR: is not implemented for the type + //~^ ERROR E0277 + //~| ERROR E0277 } diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index db3373ea027..d1abed9b262 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -18,5 +18,5 @@ fn main() { let _x: extern "C" fn() = f; // OK is_fn(f); //~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() - //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() + //~| ERROR the trait `core::ops::FnOnce<()>` is not implemented for the type `extern "C" fn() } diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs index e5e5ddadafc..d86c5d211dc 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs +++ b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs @@ -18,28 +18,21 @@ struct Foo; impl Fn<()> for Foo { //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - - extern "rust-call" fn call(&self, args: ()) -> () {} + extern "rust-call" fn call(self, args: ()) -> () {} } struct Foo1; -impl Fn() for Foo1 { +impl FnOnce() for Foo1 { //~^ ERROR associated type bindings are not allowed here - - extern "rust-call" fn call(&self, args: ()) -> () {} + extern "rust-call" fn call_once(self, args: ()) -> () {} } struct Bar; impl FnMut<()> for Bar { //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - extern "rust-call" fn call_mut(&self, args: ()) -> () {} } struct Baz; impl FnOnce<()> for Baz { //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - extern "rust-call" fn call_once(&self, args: ()) -> () {} } diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 35c55193136..6433255bd4d 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -35,5 +35,5 @@ fn main() { needs_fn(1); //~^ ERROR `core::ops::Fn<(isize,)>` - //~| ERROR `core::ops::Fn<(isize,)>` + //~| ERROR `core::ops::FnOnce<(isize,)>` } diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs index 838e65e1d05..8e1e88a92e4 100644 --- a/src/test/compile-fail/fn-variance-1.rs +++ b/src/test/compile-fail/fn-variance-1.rs @@ -17,9 +17,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) { } fn main() { - apply(&3, takes_mut); //~ ERROR (values differ in mutability) apply(&3, takes_imm); + apply(&3, takes_mut); + //~^ ERROR (values differ in mutability) + //~| ERROR (values differ in mutability) apply(&mut 3, takes_mut); - apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability) + apply(&mut 3, takes_imm); + //~^ ERROR (values differ in mutability) + //~| ERROR (values differ in mutability) } diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs index 8f79022405e..3853434e128 100644 --- a/src/test/compile-fail/issue-15094.rs +++ b/src/test/compile-fail/issue-15094.rs @@ -16,11 +16,10 @@ struct Debuger<T> { x: T } -impl<T: fmt::Debug> ops::Fn<(),> for Debuger<T> { +impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> { type Output = (); - - fn call(&self, _args: ()) { -//~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn + fn call_once(self, _args: ()) { +//~^ ERROR `call_once` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn println!("{:?}", self.x); } } diff --git a/src/test/compile-fail/issue-20225.rs b/src/test/compile-fail/issue-20225.rs index e4bedbbb7e1..fe427e02451 100644 --- a/src/test/compile-fail/issue-20225.rs +++ b/src/test/compile-fail/issue-20225.rs @@ -13,9 +13,19 @@ struct Foo; impl<'a, T> Fn<(&'a T,)> for Foo { + extern "rust-call" fn call(&self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +impl<'a, T> FnMut<(&'a T,)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +impl<'a, T> FnOnce<(&'a T,)> for Foo { type Output = (); - extern "rust-call" fn call(&self, (_,): (T,)) {} + extern "rust-call" fn call_once(self, (_,): (T,)) {} //~^ ERROR: has an incompatible type for trait: expected &-ptr } diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs index 61752e62abd..77ac97bc8b8 100644 --- a/src/test/compile-fail/overloaded-calls-bad.rs +++ b/src/test/compile-fail/overloaded-calls-bad.rs @@ -18,13 +18,18 @@ struct S { } impl FnMut<(isize,)> for S { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnOnce<(isize,)> for S { + type Output = isize; + extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize { + self.call_mut((z,)) + } +} + fn main() { let mut s = S { x: 3, diff --git a/src/test/compile-fail/overloaded-calls-nontuple.rs b/src/test/compile-fail/overloaded-calls-nontuple.rs index c4019fa2209..ea47d676412 100644 --- a/src/test/compile-fail/overloaded-calls-nontuple.rs +++ b/src/test/compile-fail/overloaded-calls-nontuple.rs @@ -18,12 +18,16 @@ struct S { } impl FnMut<isize> for S { - type Output = isize; extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { self.x + self.y + z } } +impl FnOnce<isize> for S { + type Output = isize; + extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } +} + fn main() { let mut s = S { x: 1, diff --git a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs index 92e6affa4c2..93498ac7f83 100644 --- a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs +++ b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs @@ -19,13 +19,17 @@ use std::ops::{Fn,FnMut,FnOnce}; struct S; impl FnMut<(isize,)> for S { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize { x * x } } +impl FnOnce<(isize,)> for S { + type Output = isize; + + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize { f.call((x,)) } @@ -33,5 +37,4 @@ fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize { fn main() { let x = call_it(&S, 22); //~^ ERROR not implemented - //~| ERROR not implemented } diff --git a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs index 713b64b1349..2dcd7a97d89 100644 --- a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs +++ b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -28,14 +28,19 @@ impl<F,A,R> YCombinator<F,A,R> { } impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> { - type Output = R; - extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R { (self.func)(self, arg) //~^ ERROR cannot borrow `*self` as mutable more than once at a time } } +impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> { + type Output = R; + extern "rust-call" fn call_once(mut self, args: (A,)) -> R { + self.call_mut(args) + } +} + fn main() { let mut counter = 0; let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 { diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index 23f7ee2b010..dc7c70ba649 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -27,11 +27,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index 40655f8a3ce..cdcb435b65a 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -27,11 +27,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index ebcbdbbc006..150bf36dcc2 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -28,11 +28,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } diff --git a/src/test/run-pass/issue-13655.rs b/src/test/run-pass/issue-13655.rs index cd5da3844e1..11219b04f2b 100644 --- a/src/test/run-pass/issue-13655.rs +++ b/src/test/run-pass/issue-13655.rs @@ -14,7 +14,6 @@ use std::ops::Fn; struct Foo<T>(T); impl<T: Copy> Fn<()> for Foo<T> { - type Output = T; extern "rust-call" fn call(&self, _: ()) -> T { match *self { Foo(t) => t @@ -22,6 +21,20 @@ impl<T: Copy> Fn<()> for Foo<T> { } } +impl<T: Copy> FnMut<()> for Foo<T> { + extern "rust-call" fn call_mut(&mut self, _: ()) -> T { + self.call(()) + } +} + +impl<T: Copy> FnOnce<()> for Foo<T> { + type Output = T; + + extern "rust-call" fn call_once(self, _: ()) -> T { + self.call(()) + } +} + fn main() { let t: u8 = 1; println!("{}", Foo(t)()); diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index be13d0bc80c..ec482a776de 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -17,10 +17,18 @@ trait Foo { fn dummy(&self) { }} struct Bar; impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar { - type Output = (); extern "rust-call" fn call(&self, _: (&'a Foo,)) {} } +impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar { + extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) } +} + +impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar { + type Output = (); + extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) } +} + struct Baz; impl Foo for Baz {} diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index d6fdd9f230a..5accaf36349 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -36,9 +36,21 @@ impl Alloy { } impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile { + extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} +} + +impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile { + extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) { + self.call((_res,)) + } +} + +impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile { type Output = (); - extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} + extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) { + self.call((_res,)) + } } impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld { diff --git a/src/test/run-pass/issue-16739.rs b/src/test/run-pass/issue-16739.rs index 5270ef9268c..99ddaba4e55 100644 --- a/src/test/run-pass/issue-16739.rs +++ b/src/test/run-pass/issue-16739.rs @@ -20,20 +20,36 @@ struct Foo { foo: u32 } impl FnMut<()> for Foo { - type Output = u32; extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo } } -impl FnMut<(u32,)> for Foo { +impl FnOnce<()> for Foo { type Output = u32; + extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } +} + +///////////////////////////////////////////////////////////////////////// + +impl FnMut<(u32,)> for Foo { extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } -impl FnMut<(u32,u32)> for Foo { +impl FnOnce<(u32,)> for Foo { type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } +} + +///////////////////////////////////////////////////////////////////////// + +impl FnMut<(u32,u32)> for Foo { extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } +impl FnOnce<(u32,u32)> for Foo { + type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) } +} + fn main() { let mut f = box Foo { foo: 42 } as Box<FnMut() -> u32>; assert_eq!(f.call_mut(()), 42); diff --git a/src/test/run-pass/issue-19982.rs b/src/test/run-pass/issue-19982.rs index 41d202c4635..9442b039bc6 100644 --- a/src/test/run-pass/issue-19982.rs +++ b/src/test/run-pass/issue-19982.rs @@ -16,9 +16,17 @@ struct Foo; impl<'a> Fn<(&'a (),)> for Foo { + extern "rust-call" fn call(&self, (_,): (&(),)) {} +} + +impl<'a> FnMut<(&'a (),)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {} +} + +impl<'a> FnOnce<(&'a (),)> for Foo { type Output = (); - extern "rust-call" fn call(&self, (_,): (&(),)) {} + extern "rust-call" fn call_once(self, (_,): (&(),)) {} } fn main() {} diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index f5ccd87fd25..597075c5500 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -21,13 +21,20 @@ use std::ops::Add; struct G<A>(PhantomData<A>); impl<'a, A: Add<i32, Output=i32>> Fn<(A,)> for G<A> { - type Output = i32; - extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { arg.add(1) } } +impl<'a, A: Add<i32, Output=i32>> FnMut<(A,)> for G<A> { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) } +} + +impl<'a, A: Add<i32, Output=i32>> FnOnce<(A,)> for G<A> { + type Output = i32; + extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) } +} + fn main() { // ICE trigger (G(PhantomData))(1); diff --git a/src/test/run-pass/overloaded-calls-simple.rs b/src/test/run-pass/overloaded-calls-simple.rs index 17990bb1bd1..eeb705a2e3c 100644 --- a/src/test/run-pass/overloaded-calls-simple.rs +++ b/src/test/run-pass/overloaded-calls-simple.rs @@ -20,24 +20,38 @@ struct S1 { } impl FnMut<(i32,)> for S1 { - type Output = i32; extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 { self.x * self.y * z } } +impl FnOnce<(i32,)> for S1 { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { + self.call_mut(args) + } +} + struct S2 { x: i32, y: i32, } impl Fn<(i32,)> for S2 { - type Output = i32; extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 { self.x * self.y * z } } +impl FnMut<(i32,)> for S2 { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S2 { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + struct S3 { x: i32, y: i32, diff --git a/src/test/run-pass/overloaded-calls-zero-args.rs b/src/test/run-pass/overloaded-calls-zero-args.rs index ea78a75c0c7..110109018db 100644 --- a/src/test/run-pass/overloaded-calls-zero-args.rs +++ b/src/test/run-pass/overloaded-calls-zero-args.rs @@ -20,12 +20,16 @@ struct S { } impl FnMut<()> for S { - type Output = i32; extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 { self.x * self.y } } +impl FnOnce<()> for S { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) } +} + fn main() { let mut s = S { x: 3, diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs index 5ec280dabc9..9b71abf3653 100644 --- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -20,12 +20,20 @@ use std::ops::{Fn,FnMut,FnOnce}; struct S; impl Fn<(i32,)> for S { - type Output = i32; extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 { x * x } } +impl FnMut<(i32,)> for S { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + fn call_it<F:Fn(i32)->i32>(f: &F, x: i32) -> i32 { f(x) } diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs index 79be7dae8d7..6261058b867 100644 --- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs @@ -20,13 +20,17 @@ use std::ops::{FnMut,FnOnce}; struct S; impl FnMut<(i32,)> for S { - type Output = i32; - extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + fn call_it_mut<F:FnMut(i32)->i32>(f: &mut F, x: i32) -> i32 { f(x) } diff --git a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs index ece583e8d63..e02784f917a 100644 --- a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs +++ b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs @@ -32,13 +32,20 @@ impl<F,A,R> YCombinator<F,A,R> { } impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> Fn<(A,)> for YCombinator<F,A,R> { - type Output = R; - extern "rust-call" fn call(&self, (arg,): (A,)) -> R { (self.func)(self, arg) } } +impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) } +} + +impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> { + type Output = R; + extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) } +} + fn main() { let factorial = |recur: &Fn(u32) -> u32, arg: u32| -> u32 { if arg == 0 {1} else {arg * recur(arg-1)} diff --git a/src/test/run-pass/unboxed-closures-manual-impl.rs b/src/test/run-pass/unboxed-closures-manual-impl.rs index b505caf6dd8..38f15d6e449 100644 --- a/src/test/run-pass/unboxed-closures-manual-impl.rs +++ b/src/test/run-pass/unboxed-closures-manual-impl.rs @@ -17,13 +17,17 @@ use std::ops::FnMut; struct S; impl FnMut<(i32,)> for S { - type Output = i32; - extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + fn call_it<F:FnMut(i32)->i32>(mut f: F, x: i32) -> i32 { f(x) + 3 } |
