impl Trait
将函数参数类型从 更改为泛型是否可能是一个重大更改? Rust 参考指出:
注意:对于函数参数,泛型类型参数和
impl Trait
并不完全等价。对于泛型参数(例如)<T: Trait>
,调用者可以选择T
在调用站点使用GenericArgs明确指定 的泛型参数,例如foo::<usize>(1)
。如果impl Trait
是任何函数参数的类型,则调用者在调用该函数时永远不能提供任何泛型参数。这包括返回类型的泛型参数或任何 const 泛型。因此,将函数签名从其中一个更改为另一个可能会对函数调用者造成重大改变。
但是,如果至少有一个impl Trait
参数,则调用者不能命名任何泛型参数,这是否意味着更改impl Trait
为<T: Trait>
只能使调用者能够命名泛型参数?由于泛型已经推断出来,我们也不能破坏类型推断。
编辑:我假设每个都impl Trait
更改为不同的、唯一的泛型类型(不与其他impl Trait
s 或以前的泛型重叠)。违反这一点显然会造成破坏,感谢@啊鹿Dizzyi 指出这一点。
我在这里列出了(我认为是详尽的)impl Trait
更改为通用的案例列表。如果其中任何一个案例可能导致下游中断,请说明原因。如果我遗漏了某些案例,请解释它是否导致中断。
- 仅更改
impl Trait
// before
pub fn foo(_: impl Trait) {}
// after
pub fn foo<T: Trait>(_: T) {}
- 很多
impl Trait
,但只改变其中的一些
// before
pub fn foo(_: impl Trait1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2>(_: T1, _: T2, _: impl Trait3) {}
- 很多
impl Trait
,全部改变
// before
pub fn foo(_: impl Trait1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2, T3: Trait3>(_: T1, _: T2, _: T3) {}
- 一些通用类型,改变一些
impl Trait
,但保留至少一个
// before
pub fn foo<T1: Trait1>(_: T1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2>(_: T1, _: T2, _: impl Trait3) {}
- 一些通用类型,改变所有
impl Trait
的
// before
pub fn foo<T1: Trait1>(_: T1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2, T3: Trait3>(_: T1, _: T2, _: T3) {}
发生这种情况的一种情况是,当您想让函数接受两个参数,并且这两个参数都实现某些特征时
Trait
,但您不关心这两个参数是否是同一类型。因为当你定义一个泛型类型时
T
,所有出现的内容都会绑定到同一个类型。并且会导致错误,因此,在更改时需要小心。例子
错误信息
我最近编辑了参考资料的这部分,因为它已经过时了。您可以在夜间版本中看到更新(它应该会在明天(9 月 5 日)稳定发布)。
简而言之,1.63.0 增加了在存在泛型时指定泛型的可能性
impl Trait
。据我所知,你说得对,这不可能是一个重大变化。从 1.63.0 开始,如果至少有一个现有的泛型,它就可能是一个重大变化。长版本位于PR #1495中。