Description
UPDATE: Mentoring instructions below.
Here's a minimal example program showing the issue:
#![feature(fn_traits)]
#![feature(unboxed_closures)]
struct Ishmael;
struct Maybe;
struct CallMe;
impl FnOnce<(Ishmael,)> for CallMe {
type Output = ();
extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> () {
println!("Split your lungs with blood and thunder!");
}
}
impl FnOnce<(Maybe,)> for CallMe {
type Output = ();
extern "rust-call" fn call_once(self, _args: (Maybe,)) -> () {
println!("So we just met, and this is crazy");
}
}
fn main() {
CallMe(Ishmael);
CallMe(Maybe);
}
This works perfectly if you comment out either the Ishmael
or Maybe
implementations, and the corresponding call. I've wanted this behavior at various times - if nothing else, it'd be useful for binding to certain parts of C++ - and at least in theory it's the same exact mechanism Add::add
uses.
In addition, the error message is (to steal lovingly borrow a term from the Perl 6 community) "less than awesome" - it informs the user error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
when it clearly is (as it succeeds in the single-impl case).
It also claims error[E0619]: the type of this value must be known in this context
, but only for the argument of the first call - reversing the order also exchanges the subject of the error message.
Should this be supported? If so, what needs done? If not, how can we make the error messages more helpful? Not supporting it now and adding support later is forwards-compatible, but at very least the error message should probably be improved before stabilization (cc #29625)
EDIT: Ah, seems this may be covered by #18952