Add blanket impls to allow the various Fn
traits to be interconverted.
Fixes #18387.
This commit is contained in:
parent
63c4f22f2b
commit
680d579ff0
@ -866,13 +866,45 @@ pub trait FnOnce<Args,Result> {
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Result;
|
||||
}
|
||||
|
||||
macro_rules! def_fn_mut(
|
||||
impl<F,A,R> FnMut<A,R> for F
|
||||
where F : Fn<A,R>
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: A) -> R {
|
||||
self.call(args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F,A,R> FnOnce<A,R> for F
|
||||
where F : FnMut<A,R>
|
||||
{
|
||||
extern "rust-call" fn call_once(mut self, args: A) -> R {
|
||||
self.call_mut(args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<Result> Fn<(),Result> for extern "Rust" fn() -> Result {
|
||||
#[allow(non_snake_case)]
|
||||
extern "rust-call" fn call(&self, _args: ()) -> Result {
|
||||
(*self)()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Result,A0> Fn<(A0,),Result> for extern "Rust" fn(A0) -> Result {
|
||||
#[allow(non_snake_case)]
|
||||
extern "rust-call" fn call(&self, args: (A0,)) -> Result {
|
||||
let (a0,) = args;
|
||||
(*self)(a0)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! def_fn(
|
||||
($($args:ident)*) => (
|
||||
impl<Result$(,$args)*>
|
||||
FnMut<($($args,)*),Result>
|
||||
Fn<($($args,)*),Result>
|
||||
for extern "Rust" fn($($args: $args,)*) -> Result {
|
||||
#[allow(non_snake_case)]
|
||||
extern "rust-call" fn call_mut(&mut self, args: ($($args,)*)) -> Result {
|
||||
extern "rust-call" fn call(&self, args: ($($args,)*)) -> Result {
|
||||
let ($($args,)*) = args;
|
||||
(*self)($($args,)*)
|
||||
}
|
||||
@ -880,20 +912,18 @@ macro_rules! def_fn_mut(
|
||||
)
|
||||
)
|
||||
|
||||
def_fn_mut!()
|
||||
def_fn_mut!(A0)
|
||||
def_fn_mut!(A0 A1)
|
||||
def_fn_mut!(A0 A1 A2)
|
||||
def_fn_mut!(A0 A1 A2 A3)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
|
||||
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
|
||||
def_fn!(A0 A1)
|
||||
def_fn!(A0 A1 A2)
|
||||
def_fn!(A0 A1 A2 A3)
|
||||
def_fn!(A0 A1 A2 A3 A4)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
|
||||
def_fn!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
|
||||
|
@ -804,12 +804,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
&candidates[i],
|
||||
&candidates[j]));
|
||||
if is_dup {
|
||||
debug!("Dropping candidate #{}/#{}: {}",
|
||||
debug!("Dropping candidate #{}/{}: {}",
|
||||
i, candidates.len(), candidates[i].repr(self.tcx()));
|
||||
candidates.swap_remove(i);
|
||||
} else {
|
||||
debug!("Retaining candidate #{}/#{}",
|
||||
i, candidates.len());
|
||||
debug!("Retaining candidate #{}/{}: {}",
|
||||
i, candidates.len(), candidates[i].repr(self.tcx()));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
@ -3493,6 +3493,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
|
||||
};
|
||||
|
||||
debug!("unboxed_closure for {} --> sig={} kind={}",
|
||||
local_def(expr.id).repr(fcx.tcx()),
|
||||
fn_ty.sig.repr(fcx.tcx()),
|
||||
kind);
|
||||
|
||||
let unboxed_closure = ty::UnboxedClosure {
|
||||
closure_type: fn_ty,
|
||||
kind: kind,
|
||||
|
34
src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
Normal file
34
src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
Normal 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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
40
src/test/run-pass/unboxed-closures-extern-fn.rs
Normal file
40
src/test/run-pass/unboxed-closures-extern-fn.rs
Normal 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));
|
||||
}
|
||||
|
46
src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
Normal file
46
src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
Normal 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);
|
||||
}
|
||||
|
40
src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
Normal file
40
src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
Normal 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);
|
||||
}
|
||||
|
@ -12,6 +12,6 @@
|
||||
|
||||
fn main() {
|
||||
let mut zero = |&mut:| {};
|
||||
zero.call_mut(());
|
||||
let () = zero.call_mut(());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user