impl trait 参数和泛型函数参数之间有什么区别?

impl trait 参数和泛型函数参数之间有什么区别?

问题描述:

impl Traits 可以用作函数参数.这与具有 trait 约束的泛型函数有区别吗?

impl Traits can be used as function arguments. Are there differences between this and a generic function with a trait constraint?

trait Foo {}

fn func1(_: impl Foo) {}

fn func2<T: Foo>(_: T) {}

impl Traits 作为函数参数被脱糖为匿名泛型参数.参见 RFC,其中说:

impl Traits as function arguments are desugared to an anonymous generic parameter. See the RFC, which says:

扩展 impl Trait 以允许在参数中使用,它的行为类似于匿名泛型参数.

Expand impl Trait to allow use in arguments, where it behaves like an anonymous generic parameter.

RFC 中还有一个例子:

There's also an example in the RFC:

// These two are equivalent
fn map<U>(self, f: impl FnOnce(T) -> U) -> Option<U>
fn map<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> U

然而,一个区别是 impl Trait 参数不能明确指定它们的类型:

However, one difference is that impl Trait arguments cannot have their types explicitly specified:

fn foo<T: Trait>(t: T)
fn bar(t: impl Trait)

foo::<u32>(0) // this is allowed
bar::<u32>(0) // this is not

扩展到参数位置的动机 部分解释了为什么要为现有功能添加额外的语法.简而言之,它是为了在函数返回位置具有与 impl 特征相似的语法,从而提高可学习性,并改善人体工程学.

The Motivation for expanding to argument position section explains why additional syntax was added for an existing feature. In short, it's for having similar syntax as impl traits in function return position, which improves learnability, and to improve ergonomics.