You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何将Box<dyn Fn>用作&impl Fn?

问题解决:闭包传递给外部crate的&impl Fn参数报错

错误原因

你传递的&*retv.injection_closure是指向**动态大小类型(DST)的引用,具体为&dyn Fn(&f64) -> f64。外部函数LibObj::new的参数&impl Fn(&Arg) -> Arg默认要求被引用类型必须是编译期大小可知(Sized)**的,而动态大小类型不满足该约束,因此触发编译错误。

解决方案

直接传递Box本身的引用(&retv.injection_closure),而非解引用Box后的动态类型引用。Box<dyn Fn(...)>是大小固定的类型(Sized),且它通过Deref trait自动解引用到内部闭包,完全满足Fn(&f64) -> f64的 trait 约束,符合外部函数的要求。

修改后的完整代码

use std::rc::Rc;
use std::cell::Cell;

/// 我可控制的代码

struct MyWrapper<'a> {
    obj: Option<LibObj<'a, f64>>,
    injection_closure: Box<dyn Fn(&f64) -> f64 + 'a>,
}

impl<'a> MyWrapper<'a> {
    fn new(transaction: Rc<Cell<f64>>) -> MyWrapper<'a> {
        let injection_closure = Box::new(move |_: &f64| transaction.get());
        let mut retv = MyWrapper {
            injection_closure,
            obj: None,
        };
        // 直接传递Box的引用,而非解引用后的dyn trait引用
        retv.obj = Some(LibObj::new(&retv.injection_closure));

        retv
    }
}

/// 我无法控制的外部代码

struct LibObj<'f_lifetime, Arg> {
    my_thing: ThingWrapper<'f_lifetime, Arg>,
}

impl<'f_lifetime, Arg> LibObj<'f_lifetime, Arg> {
    pub fn new(f: &'f_lifetime impl Fn(&Arg) -> Arg) -> Self {
        let thing = ThingWrapper::new(f);
        LibObj { my_thing: thing }
    }
}

pub struct ThingWrapper<'f_lifetime, Arg> {
    f: &'f_lifetime dyn Fn(&Arg) -> Arg,
}

impl<'f_lifetime, Arg> ThingWrapper<'f_lifetime, Arg> {
    pub fn new(f: &'f_lifetime impl Fn(&Arg) -> Arg) -> Self {
        ThingWrapper { f }
    }
}

补充说明

如果需要对闭包进行多所有权管理,也可以用Rc替代Box,修改方式完全一致——只需将Box替换为Rc,传递&retv.injection_closure即可。

内容的提问来源于stack exchange,提问作者deftfyodor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:45:46