Closing signature strength / enforcement assessment

Here is a far-fetched example of what I'm trying to do:

use std::boxed::Box;

#[derive(Debug)]
pub struct Foo<'a>(pub &'a str);

pub trait IntoBox {
    fn into_box<'a>(self) -> Box<Fn(Foo) -> String>;
}

impl<B> IntoBox for B where B: Fn(Foo) -> String + 'static {
    fn into_box(self) -> Box<Fn(Foo) -> String> { Box::new(self) }
}

fn direct_into_box<B: Fn(Foo) -> String + 'static>(b: B) -> Box<Fn(Foo) -> String> {
    Box::new(b)
}

fn main() {
    // Doesn't work
    let x = IntoBox::into_box(|i| format!("{:?}", i) );

    // Works
    let y = IntoBox::into_box(|i: Foo| format!("{:?}", i) );

    // Also works
    let z = direct_into_box(|i| format!("{:?}", i) );
}

How can I get my trait impl to perform the same closure assessment as mine direct_into_box? I would expect direct_into_boxmy trait to behave the same.

Error in x:

error[E0271]: type mismatch resolving `for<'r> <[closure@<anon>:20:31: 20:53] as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
  --> <anon>:20:13
   |
20 |     let x = IntoBox::into_box(|i| format!("{:?}", i) );
   |             ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
   |
   = note: concrete lifetime that was found is lifetime '_#29r
   = note: required because of the requirements on the impl of `IntoBox` for `[closure@<anon>:20:31: 20:53]`
   = note: required by `IntoBox::into_box`

error[E0281]: type mismatch: the type `[closure@<anon>:20:31: 20:53]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is required (expected concrete lifetime, found bound lifetime parameter )
  --> <anon>:20:13
   |
20 |     let x = IntoBox::into_box(|i| format!("{:?}", i) );
   |             ^^^^^^^^^^^^^^^^^
   |
   = note: required because of the requirements on the impl of `IntoBox` for `[closure@<anon>:20:31: 20:53]`
   = note: required by `IntoBox::into_box`
+4
source share
1 answer

Sounds like an output error in the compiler . It seems that the compiler implements Fn(Foo<'x>)for one specific lifetime, 'xinstead of Fn(Foo<'a>)for any lifetime 'aat your close.

, , ( ), , . :

#![feature(fn_traits)]
#![feature(unboxed_closures)]

// Foo and IntoBox unchanged

struct Func;

impl<'a> FnOnce<(Foo<'a>,)> for Func {
    type Output = String;

    extern "rust-call" fn call_once(self, args: (Foo<'a>,)) -> String {
        self.call(args)
    }
}

impl<'a> FnMut<(Foo<'a>,)> for Func {
    extern "rust-call" fn call_mut(&mut self, args: (Foo<'a>,)) -> String {
        self.call(args)
    }
}

impl<'a> Fn<(Foo<'a>,)> for Func {
    extern "rust-call" fn call(&self, (i,): (Foo<'a>,)) -> String {
        format!("{:?}", i)
    }
}

fn main() {
    let x = IntoBox::into_box(Func);
}

Func struct , .

:

impl FnOnce<(Foo<'static>,)> for Func {
    type Output = String;

    extern "rust-call" fn call_once(self, args: (Foo<'static>,)) -> String {
        self.call(args)
    }
}

impl FnMut<(Foo<'static>,)> for Func {
    extern "rust-call" fn call_mut(&mut self, args: (Foo<'static>,)) -> String {
        self.call(args)
    }
}

impl Fn<(Foo<'static>,)> for Func {
    extern "rust-call" fn call(&self, (i,): (Foo<'static>,)) -> String {
        format!("{:?}", i)
    }
}

, , <'a> impl, , Foo<'a> Foo<'static>. , , "" Foo<'static>.

:

error[E0271]: type mismatch resolving `for<'r> <Func as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
  --> <anon>:51:13
   |
51 |     let x = IntoBox::into_box(Func);
   |             ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
   |
   = note: concrete lifetime that was found is the static lifetime
   = note: required because of the requirements on the impl of `IntoBox` for `Func`
   = note: required by `IntoBox::into_box`

error[E0277]: the trait bound `for<'r> Func: std::ops::Fn<(Foo<'r>,)>` is not satisfied
  --> <anon>:51:13
   |
51 |     let x = IntoBox::into_box(Func);
   |             ^^^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is not implemented for `Func`
   |
   = help: the following implementations were found:
   = help:   <Func as std::ops::Fn<(Foo<'static>,)>>
   = note: required because of the requirements on the impl of `IntoBox` for `Func`
   = note: required by `IntoBox::into_box`

, , '_#29r, , , . , , , , , 'static, , Rust. , .

+3

Source: https://habr.com/ru/post/1660432/


All Articles