-
-
Notifications
You must be signed in to change notification settings - Fork 690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
callback::NotRawCallback
is not implemented for <closure>
#2142
Comments
Is this a duplicate of #2041? |
Could very well be! I've done some experimenting and it seems to be caused by my reference to an let fetch_user_info = create_action(move |_| async move {
/*
Does nothing
}*/
}); Fails to compile: let on_success = move |api| {
//log::info!("Successfully logged in");
authorized_api.update(|v| *v = Some(api));
let navigate = use_navigate();
navigate(Page::MeasureList.path(), Default::default());
fetch_user_info.dispatch(());
}; Compiles (or at least generates no errors): let on_success = move |api| {
//log::info!("Successfully logged in");
authorized_api.update(|v| *v = Some(api));
let navigate = use_navigate();
navigate(Page::MeasureList.path(), Default::default());
//fetch_user_info.dispatch(());
}; |
This is fixed if I switch back to stable Rust and remove the |
I've been in the car all afternoon so haven't dug in but I assume the nightly compiler without |
The root of the problem is the use of #![feature(auto_traits)]
#![feature(negative_impls)]
auto trait Foo {}
struct Bar;
impl !Foo for Bar {}
struct BarWrapper(Bar);
fn assert_foo(_: impl Foo) {}
fn test() {
assert_foo(BarWrapper(Bar)); // <- error
let bar = Bar;
assert_foo(move || {
let _ = bar;
}); // <- also error
assert_foo(move || {}); // <- OK
} Because The only way to fix this problem is to get rid of the negative trait impl, but it's needed to avoid collision for The only other solutions are either specialization, to specialize the The other one I can think of is to use the autoderef specialization trick. Don't directly implement #![feature(fn_traits)]
#![feature(unboxed_closures)]
use leptos::{store_value, Callable, StoredValue};
pub struct InnerCallback<In: 'static, Out: 'static>(StoredValue<Box<dyn Fn(In) -> Out>>);
impl<In: 'static, Out: 'static> Callable<In, Out> for InnerCallback<In, Out> {
fn call(&self, input: In) -> Out {
self.0.with_value(|f| f(input))
}
}
impl<In, Out> Clone for InnerCallback<In, Out> {
fn clone(&self) -> Self {
*self
}
}
impl<In, Out> Copy for InnerCallback<In, Out> {}
pub struct Callback<In: 'static, Out: 'static = ()>(InnerCallback<In, Out>);
impl<In: 'static, Out: 'static> Callable<In, Out> for Callback<In, Out> {
fn call(&self, input: In) -> Out {
Callable::call(&self.0, input)
}
}
impl<In> fmt::Debug for Callback<In> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt.write_str("Callback")
}
}
impl<In, Out> Clone for Callback<In, Out> {
fn clone(&self) -> Self {
*self
}
}
impl<In, Out> Copy for Callback<In, Out> {}
impl<In, Out> Callback<In, Out> {
/// Creates a new callback from the given function.
pub fn new<F>(f: F) -> Callback<In, Out>
where
F: Fn(In) -> Out + 'static,
{
Self(InnerCallback(store_value(Box::new(f))))
}
}
impl<In, Out> FnOnce<(In,)> for InnerCallback<In, Out> {
type Output = Out;
extern "rust-call" fn call_once(self, args: (In,)) -> Self::Output {
Callable::call(&self, args.0)
}
}
impl<In, Out> FnMut<(In,)> for InnerCallback<In, Out> {
extern "rust-call" fn call_mut(&mut self, args: (In,)) -> Self::Output {
Callable::call(&*self, args.0)
}
}
impl<In, Out> Fn<(In,)> for InnerCallback<In, Out> {
extern "rust-call" fn call(&self, args: (In,)) -> Self::Output {
Callable::call(self, args.0)
}
}
impl<In, Out> Deref for Callback<In, Out> {
type Target = InnerCallback<In, Out>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<F, In, T, Out> From<F> for Callback<In, Out>
where
F: Fn(In) -> T + 'static,
T: Into<Out> + 'static,
{
fn from(f: F) -> Self {
Self::new(move |x| f(x).into())
}
} I'm not a fan of using Deref like this, it's kind of an anti-pattern, but from what I tested it does seams to fix the problem. |
Just realised, but it is still a breaking change, as functions expecting a just need to deref it but still not very convenient: fn foo() {
fn inner(_: impl Fn(())) {}
let cb: Callback<()> = Callback::new(|()| {});
inner(*cb);
} |
Describe the bug
When using
Callback
s as demonstrated in thelogin_with_token_csr_only
example I get the following error:And my build is full of messages like:
Leptos Dependencies
For example:
To Reproduce
trunk build
The text was updated successfully, but these errors were encountered: