如何存根返回impl Trait类型的函数?
这个坑我之前踩过!平时用panic!给普通函数打桩超顺手,比如返回u64的函数直接写panic!("TODO")就行,编译器会自动把发散类型!转换成需要的返回类型。但碰到返回impl Trait(比如impl Future)的情况,直接用panic!就会报错,说!不是Future,确实挺让人摸不着头脑的。
其实核心原因是:impl Trait要求返回的类型必须严格实现对应的trait,而panic!的返回类型!本身并没有实现Future(或者你要返回的其他trait),所以编译器不认。下面给你几个简单的解决办法:
最推荐:用
async块包裹panic!
这是最直观的写法,和普通打桩的思路几乎一致,代码长这样:use std::future::Future; fn foo() -> impl Future<Output = u64> { async { panic!("TODO") } }async块会自动生成一个实现了Future的匿名类型,完全符合impl Future的要求。而且这里的panic!会在future被实际执行(poll)的时候触发,和你用普通打桩的预期行为一致。快速触发panic:用
ready包裹panic!
如果希望调用函数的瞬间就触发panic(而不是等future被执行时),可以用std::future::ready:use std::future::{Future, ready}; fn foo() -> impl Future<Output = u64> { ready(panic!("TODO")) }这里
ready会返回一个Ready<T>类型,它实现了Future,而panic!的发散类型!会被编译器自动转换成u64(虽然永远不会真的返回这个值)。通用方案:手动实现目标trait
如果你要存根的函数返回的是其他自定义trait,而不是Future,可以手动写一个空类型实现该trait,在方法里panic:use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; // 定义一个空类型 struct PanicMarker; // 实现需要的trait impl Future for PanicMarker { type Output = u64; fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { panic!("TODO"); } } fn foo() -> impl Future<Output = u64> { PanicMarker }这个写法稍微繁琐,但胜在通用,任何
impl Trait的场景都能套用。
总之,日常打桩用第一种方法就足够了,简单又符合预期。
内容来源于stack exchange

