Skip to content

Instantly share code, notes, and snippets.

@little-dude
Created February 10, 2022 15:48
Show Gist options
  • Save little-dude/a10d1b1868b99304e80c524c1fece506 to your computer and use it in GitHub Desktop.
Save little-dude/a10d1b1868b99304e80c524c1fece506 to your computer and use it in GitHub Desktop.
valid code that rust fails to compile
#![allow(dead_code)]
struct Input<'a, 'b> {
a: &'a i32,
b: &'b i32,
}
struct Output<'a, 'b> {
a: &'a i32,
b: &'b i32,
}
trait MyTrait {
fn run<'a, 'b>(&self, i: Input<'a, 'b>) -> Output<'a, 'b>;
}
impl<F> MyTrait for F
where
F: for<'a, 'b> Fn(Input<'a, 'b>) -> Output<'a, 'b>,
{
fn run<'a, 'b>(&self, i: Input<'a, 'b>) -> Output<'a, 'b> {
self(i)
}
}
fn main() {
// I want to create a Box<dyn MyTrait> from a closure, but this doesn't work
//
let _doesnt_work: Box<dyn MyTrait> = Box::new(|i: Input<'_, '_>| Output { a: i.a, b: i.b });
// Therefore I tried to help the compiler infer the correct type:
// let _dyn_fn: Box<dyn for<'a, 'b> Fn(Input<'a, 'b>) -> Output<'a, 'b>> =
// Box::new(|i: Input<'_, '_>| Output { a: i.a, b: i.b });
// So now I have a Box<dyn Fn(Input) -> Output> which implements MyTrait,
// but how do I turn it into a Box<dyn MyTrait>?
}
@little-dude
Copy link
Author

Someone on Discord found how to make it compile: https://discordapp.com/channels/442252698964721669/443150878111694848/793854339113680926

#![allow(dead_code)]

struct Input<'a, 'b> {
    a: &'a i32,
    b: &'b i32,
}

struct Output<'a, 'b> {
    a: &'a i32,
    b: &'b i32,
}

trait MyTrait {
    fn run<'a, 'b>(&self, i: Input<'a, 'b>) -> Output<'a, 'b>;
}

impl<F> MyTrait for F
where
    F: for<'a, 'b> Fn(Input<'a, 'b>) -> Output<'a, 'b>,
{
    fn run<'a, 'b>(&self, i: Input<'a, 'b>) -> Output<'a, 'b> {
        self(i)
    }
}

fn new_my_trait(i:impl for<'a, 'b> Fn(Input<'a, 'b>) -> Output<'a, 'b>) -> impl MyTrait{
    i
}

fn main() {
    // I want to create a Box<dyn MyTrait> from a closure, but this doesn't work
    //
    // let _doesnt_work: Box<dyn MyTrait> = Box::new( |i: Input<'_,'_>| Output { a: i.a, b: i.b });
    let _doesnt_work: Box<dyn MyTrait> = Box::new( 
        new_my_trait(|i: Input<'_,'_>| Output { a: i.a, b: i.b })
    );
    

    // Therefore I tried to help the compiler infer the correct type:
    let _dyn_fn: Box<dyn for<'a, 'b> Fn(Input<'a, 'b>) -> Output<'a, 'b>> =
        Box::new(|i: Input<'_, '_>| Output { a: i.a, b: i.b });

    // So now I have a Box<dyn Fn(Input) -> Output> which implements MyTrait,
    // but how do I turn it into a Box<dyn MyTrait>?
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment