Rust中已约束泛型却触发‘generic not constrained error’问题求助
Rust编译错误E0207:未约束的泛型参数FUT解答
精简代码
#[async_trait] impl <'a, FUNC, CONTEXT, PARAM, RETURN, FUT> StepWithParams<CONTEXT, PARAM, RETURN> for FUNC where FUNC: FnOnce(&'a PARAM) -> FUT + Send + Sync, FUT: Future<Output = Result<RETURN, ErrTypes>> + Send + Sync, PARAM: Send + Sync, CONTEXT: Send + Sync, RETURN: Send + Sync, { async fn run_user_step (self, request_context: &'a CONTEXT) -> Result<RETURN, ErrTypes> { let param = PARAM::from_context(request_context); self(param).await } }
编译错误信息
error[E0207]: the type parameter `FUT` is not constrained by the impl trait, self type, or predicates --> src/main.rs:22:41 | 22 | impl <'a, FUNC, CONTEXT, PARAM, RETURN, FUT> StepWithParams<CONTEXT, PARAM, RETURN> for FUNC | ^^^ unconstrained type parameter For more information about this error, try `rustc --explain E0207`.
问题原因与解决方案
错误原因
Rust的类型系统要求,impl块中的所有泛型参数必须被self类型(此处为FUNC)、trait参数(CONTEXT、PARAM、RETURN)或where子句中的约束唯一确定。虽然你通过FUNC: FnOnce(&'a PARAM) -> FUT关联了FUNC和FUT,但编译器不会自动将FUT识别为“FUNC作为FnOnce的返回类型”——它会把FUT视为独立的泛型参数,而这个参数没有被任何条件唯一限定(编译器不会假设一个FUNC类型只能对应一个FUT返回类型),因此触发E0207错误。
解决方案
有两种可行的修改方式:
方案1:移除FUT泛型参数(推荐)
直接在where子句中约束FUNC的返回值为符合要求的Future类型,不需要单独声明FUT参数:
#[async_trait] impl<'a, FUNC, CONTEXT, PARAM, RETURN> StepWithParams<CONTEXT, PARAM, RETURN> for FUNC where FUNC: FnOnce(&'a PARAM) -> impl Future<Output = Result<RETURN, ErrTypes>> + Send + Sync, PARAM: Send + Sync, CONTEXT: Send + Sync, RETURN: Send + Sync, { async fn run_user_step(self, request_context: &'a CONTEXT) -> Result<RETURN, ErrTypes> { let param = PARAM::from_context(request_context); self(param).await } }
方案2:显式约束FUT为FnOnce的返回类型
如果需要在代码中显式引用FUT类型,可以添加约束明确FUT是FUNC作为FnOnce的输出类型:
#[async_trait] impl<'a, FUNC, CONTEXT, PARAM, RETURN, FUT> StepWithParams<CONTEXT, PARAM, RETURN> for FUNC where FUNC: FnOnce(&'a PARAM) -> FUT + Send + Sync, FUT: Future<Output = Result<RETURN, ErrTypes>> + Send + Sync, PARAM: Send + Sync, CONTEXT: Send + Sync, RETURN: Send + Sync, // 明确FUT是FUNC调用FnOnce的返回类型 FUT = <FUNC as FnOnce(&'a PARAM)>::Output, { async fn run_user_step(self, request_context: &'a CONTEXT) -> Result<RETURN, ErrTypes> { let param = PARAM::from_context(request_context); self(param).await } }
内容的提问来源于stack exchange,提问作者Kellen Cataldo
相关产品推荐
相关产品推荐

