Auto merge of #55986 - cjgillot:issue-45510, r=nikomatsakis

Allow to dispatch fn traits depending on number of parameters

Hello,

By following @eddyb's advise on issue #45510, I managed to have the snippets of code in #45510 and #18952 passing without breaking older diagnostics.

EDIT: the codegen tests breakage I experienced is due to the poor quality of my laptop.

If any kind reviewer has any advice, you are very welcome.
This commit is contained in:
bors 2019-01-04 11:51:30 +00:00
commit a602f13f02
3 changed files with 308 additions and 144 deletions

View file

@ -0,0 +1,56 @@
// This issue tests fn_traits overloading on arity.
// run-pass
#![feature(fn_traits)]
#![feature(unboxed_closures)]
struct Foo;
impl Fn<(isize, isize)> for Foo {
extern "rust-call" fn call(&self, args: (isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 1, args.1 + 1)
}
}
impl FnMut<(isize, isize)> for Foo {
extern "rust-call" fn call_mut(&mut self, args: (isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 1, args.1 + 1)
}
}
impl FnOnce<(isize, isize)> for Foo {
type Output = (isize, isize);
extern "rust-call" fn call_once(self, args: (isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 1, args.1 + 1)
}
}
impl Fn<(isize, isize, isize)> for Foo {
extern "rust-call" fn call(&self, args: (isize, isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 3, args.1 + 3, args.2 + 3)
}
}
impl FnMut<(isize, isize, isize)> for Foo {
extern "rust-call" fn call_mut(&mut self, args: (isize, isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 3, args.1 + 3, args.2 + 3)
}
}
impl FnOnce<(isize, isize, isize)> for Foo {
type Output = (isize, isize, isize);
extern "rust-call" fn call_once(self, args: (isize, isize, isize)) -> Self::Output {
println!("{:?}", args);
(args.0 + 3, args.1 + 3, args.2 + 3)
}
}
fn main() {
let foo = Foo;
assert_eq!(foo(1, 1), (2, 2));
assert_eq!(foo(1, 1, 1), (4, 4, 4));
}

View file

@ -0,0 +1,32 @@
// Test overloaded resolution of fn_traits.
// run-pass
#![feature(fn_traits)]
#![feature(unboxed_closures)]
#[derive(Debug, PartialEq, Eq)]
struct Ishmael;
#[derive(Debug, PartialEq, Eq)]
struct Maybe;
struct CallMe;
impl FnOnce<(Ishmael,)> for CallMe {
type Output = Ishmael;
extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> Ishmael {
println!("Split your lungs with blood and thunder!");
Ishmael
}
}
impl FnOnce<(Maybe,)> for CallMe {
type Output = Maybe;
extern "rust-call" fn call_once(self, _args: (Maybe,)) -> Maybe {
println!("So we just met, and this is crazy");
Maybe
}
}
fn main() {
assert_eq!(CallMe(Ishmael), Ishmael);
assert_eq!(CallMe(Maybe), Maybe);
}