Add blanket impls to allow the various Fn traits to be interconverted.

Fixes #18387.
This commit is contained in:
Niko Matsakis 2014-10-28 07:24:25 -04:00
parent 63c4f22f2b
commit 680d579ff0
10 changed files with 221 additions and 26 deletions

View file

@ -0,0 +1,34 @@
// 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.
// Checks that the Fn trait hierarchy rules do not permit
// Fn to be used where FnMut is implemented.
#![feature(unboxed_closure_sugar)]
#![feature(overloaded_calls)]
use std::ops::{Fn,FnMut,FnOnce};
struct S;
impl FnMut<(int,),int> for S {
extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
x * x
}
}
fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
f.call((x,))
}
fn main() {
let x = call_it(&S, 22); //~ ERROR not implemented
}

View file

@ -20,8 +20,8 @@ impl<'a, I, O: 'a> Parser<'a, I, O> {
fn compose<K: 'a>(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> {
Parser {
parse: box move |&mut: x: I| {
match self.parse.call_mut((x,)) {
Ok(r) => rhs.parse.call_mut((r,)),
match (*self.parse).call_mut((x,)) {
Ok(r) => (*rhs.parse).call_mut((r,)),
Err(e) => Err(e)
}
}

View file

@ -0,0 +1,40 @@
// 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.
// Checks that extern fn points implement the full range of Fn traits.
#![feature(unboxed_closure_sugar)]
#![feature(overloaded_calls)]
use std::ops::{Fn,FnMut,FnOnce};
fn square(x: int) -> int { x * x }
fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
f.call((x,))
}
fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
f.call_mut((x,))
}
fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
f.call_once((x,))
}
fn main() {
let x = call_it(&square, 22);
let y = call_it_mut(&mut square, 22);
let z = call_it_once(square, 22);
assert_eq!(x, square(22));
assert_eq!(y, square(22));
assert_eq!(z, square(22));
}

View file

@ -0,0 +1,46 @@
// 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.
// Checks that the Fn trait hierarchy rules permit
// any Fn trait to be used where Fn is implemented.
#![feature(unboxed_closure_sugar)]
#![feature(overloaded_calls)]
use std::ops::{Fn,FnMut,FnOnce};
struct S;
impl Fn<(int,),int> for S {
extern "rust-call" fn call(&self, (x,): (int,)) -> int {
x * x
}
}
fn call_it<F:Fn(int)->int>(f: &F, x: int) -> int {
f.call((x,))
}
fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
f.call_mut((x,))
}
fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
f.call_once((x,))
}
fn main() {
let x = call_it(&S, 22);
let y = call_it_mut(&mut S, 22);
let z = call_it_once(S, 22);
assert_eq!(x, y);
assert_eq!(y, z);
}

View file

@ -0,0 +1,40 @@
// 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.
// Checks that the Fn trait hierarchy rules permit
// FnMut or FnOnce to be used where FnMut is implemented.
#![feature(unboxed_closure_sugar)]
#![feature(overloaded_calls)]
use std::ops::{FnMut,FnOnce};
struct S;
impl FnMut<(int,),int> for S {
extern "rust-call" fn call_mut(&mut self, (x,): (int,)) -> int {
x * x
}
}
fn call_it_mut<F:FnMut(int)->int>(f: &mut F, x: int) -> int {
f.call_mut((x,))
}
fn call_it_once<F:FnOnce(int)->int>(f: F, x: int) -> int {
f.call_once((x,))
}
fn main() {
let y = call_it_mut(&mut S, 22);
let z = call_it_once(S, 22);
assert_eq!(y, z);
}

View file

@ -12,6 +12,6 @@
fn main() {
let mut zero = |&mut:| {};
zero.call_mut(());
let () = zero.call_mut(());
}