关于泛型和trait对象的小白问题

S1S2分别实现了ATrait特性
trait ATrait {}

struct S1 {}

impl ATrait for S1 {}

struct S2 {}

impl ATrait for S2 {}
以下代码是能够编译通过的,返回一个Result
fn foo1(i: i32) -> Result<Box<ATrait>, ()> {
    if i < 0 {
        Ok(Box::new(S1 {}))
    } else {
        Ok(Box::new(S2 {}))
    }
}
但是以下代码就无法编译通过(实际上就是上面的foo1方法的返回值通过另一个函数返回)
fn f1() -> Result<Box<S1>, ()> {
    Ok(Box::new(S1 {}))
}

fn f2() -> Result<Box<S2>, ()> {
    Ok(Box::new(S2 {}))
}
fn foo2(i: i32) -> Result<Box<ATrait>, ()> {
    if i < 0 {
        f1()
    } else {
        f2()
    }
}
报错内容如下,是因为f1返回值的类型与foo2不匹配导致
46 | fn foo2(i: i32) -> Result<Box<ATrait>, ()> {
   |                    ----------------------- expected `std::result::Result<std::boxed::Box<(dyn ATrait + 'static)>, ()>` because of return type
47 |     if i < 0 {
48 |         f1()
   |         ^^^^ expected trait ATrait, found struct `S1`
   |
   = note: expected type `std::result::Result<std::boxed::Box<(dyn ATrait + 'static)>, _>`
              found type `std::result::Result<std::boxed::Box<S1>, _>`
但是如果返回的不是Result,而是ATrait对象指针,则编译是能通过的
fn foo3(i: i32) -> Box<ATrait> {
    if i < 0 {
        f1().unwrap()
    } else {
        f2().unwrap()
    }
}

问题

为什么foo3(返回Box的函数)就不存在类型不匹配的问题? 这种情况,有没有比较好的实现方式?(不需要在foo2方法中把f1f2函数返回的结果转换的那种)还是说只能在foo2中把f1f2Result拆开再重新包装?

丢给我几个链接或者关键词也可以的,感谢社区各位大佬!

文章来源:

Author:Rust.cc
link:https://rust.cc/article?id=2c587690-b6d5-4bfe-8446-5c5c729c802a