Summary

This is a conventions RFC establishing a definition

定義
and naming convention for extension traits: FooExt.

Motivation

This RFC is part of the ongoing API conventions and stabilization effort.

Extension traits are a programming

プログラミング
pattern that makes it possible to add methods to an existing type outside of the crate defining that type. While they should be used sparingly, the new object safety rules have increased
増加する、昇順の
the need for this kind of trait, and hence the need for a clear convention.

Detailed design
設計(する)

What is an extension trait?

Rust currently allows

許可する、可能にする
inherent methods to be defined
定義する
on a type only in the crate where that type is defined.
定義する
But it is often the case that clients of a type would like to incorporate additional
追加の
methods to it. Extension traits are a pattern for doing so:

#![allow(unused)] fn main() { extern crate foo; use foo::Foo; trait FooExt { fn bar(&self); } impl FooExt for Foo { fn bar(&self) { .. } } }

By defining a new trait, a client of foo can add new methods to Foo.

Of course, adding

たす
methods via a new trait happens all the time. What makes it an extension trait is that the trait is not designed
設計(する)
for generic use, but only as way of adding
たす
methods to a specific
特定の
type or family of types.

This is of course a somewhat subjective distinction. Whenever designing

設計(する)
an extension trait, one should consider
考える、みなす
whether the trait could be used in some more generic way. If so, the trait should be named and exported as if it were just a "normal" trait. But traits offering groups of methods that really only make sense in the context
文脈、背景
of some particular type(s) are true extension traits.

The new object safety rules mean that a trait can only be used for trait objects if all of its methods are usable; put differently, it ensures that for "object safe traits" there is always a canonical way to implement

実装する
Trait for Box<Trait>. To deal with this new rule, it is sometimes necessary to break traits apart into an object safe trait and extension traits:

#![allow(unused)] fn main() { // The core, object-safe trait trait Iterator<A> { fn next(&mut self) -> Option<A>; } // The extension trait offering object-unsafe methods trait IteratorExt<A>: Iterator<A> { fn chain<U: Iterator<A>>(self, other: U) -> Chain<Self, U> { ... } fn zip<B, U: Iterator<B>>(self, other: U) -> Zip<Self, U> { ... } fn map<B>(self, f: |A| -> B) -> Map<'r, A, B, Self> { ... } ... } // A blanket impl impl<A, I> IteratorExt<A> for I where I: Iterator<A> { ... } }

Note that, although this split-up definition

定義
is somewhat more complex,
複素数、複文の
it is also more flexible: because Box<Iterator<A>> will implement
実装する
Iterator<A>, you can now use all of the adapter methods provided
与える
in IteratorExt on trait objects, even though they are not object safe.

The convention

The proposed convention is, first of all, to (1) prefer adding

たす
default methods to existing traits or (2) prefer generically useful traits to extension traits whenever feasible.

For true extension traits, there should be a clear type or trait that they are extending.

拡張する
The extension trait should be called
呼び出し
FooExt where Foo is that type or trait.

In some cases, the extension trait only applies

適用する
conditionally. For example, AdditiveIterator is an extension trait currently in std that applies
適用する
to iterators over numeric
数の、数値の
types. These extension traits should follow
下記の、次に続く、追従する
a similar
似ている、同様の
convention, putting together the type/trait name and the qualifications, together with the Ext suffix: IteratorAddExt.

What about Prelude?

A previous

convention used a Prelude suffix for extension traits that were also part of the std prelude; this new convention deprecates that one.

Future proofing

In the future, the need for many of these extension traits may disappear as other languages

言語
features are added.
たす
For example, method-level where clauses
句、節
will eliminate the need for AdditiveIterator. And allowing
許可する、可能にする
inherent impls like impl<T: Trait> T { .. } for the crate defining Trait would eliminate even more.

However, there will always be some use of extension traits, and we need to stabilize the 1.0 libraries prior to these language

言語
features landing. So this is the proposed convention for now, and in the future it may be possible to deprecate some of the resulting
結果、戻り値
traits.

Alternatives

It seems clear that we need some convention here. Other possible suffixes would be Util or Methods, but Ext is both shorter and connects to the name of the pattern.

Drawbacks

In general,

一般
extension traits tend to require additional
追加の
imports -- especially painful when dealing with object safety. However, this is more to do with the language
言語
as it stands today than with the conventions in this RFC.

Libraries are already starting to export their own prelude module containing

含む
extension traits among other things, which by convention is glob imported.

In the long run, we should add a general

一般
"prelude" facility
施設、設備
for external libraries that makes it possible to globally import a small set
セットする、集合
of names from the crate. Some early investigations of such a feature are already under way, but are outside the scope of this RFC.