- Feature Name: dyn-trait-syntax
- Start Date: 2017-08-17
- RFC PR: rust-lang/rfcs#2113
- Rust Issue: rust-lang/rust#44662
Summary
Introducedyn Trait
syntaxdyn
keyword, and deprecate "bare trait" syntaxdyn
will become a proper keyword and a lint against bare trait syntax
Motivation
In a nutshell
The current syntax
Motivation is the key issue for this RFC, so let's expand on some of those claims:
The current syntax文法 is often ambiguous and confusing
Because it makes traits and trait objects appear
- This author has seen multiple複数のpeople write
impl SomeTrait for AnotherTrait
when they wantedimpl<T> SomeTrait for T where T: AnotherTrait
. impl MyTrait {}
is valid有効な、正しいsyntax,文法which can easily be mistaken for addingたすdefault impls of methods or addingたすextension methods or some other useful operation演算、操作on the trait itself. In reality, it adds inherent methods to the trait object.- Function types and function traits only differ in the capitalization of one letter.文字This leads to function pointers
&fn ...
and function trait objects&Fn ...
differing only in one letter,文字making it very easy to mistake one for the other.
Making one of these mistakes typically
favors a feature that is not more frequently used than its alternatives代わりのもの、選択肢
When you want to store multiple
When you want to return a type implementing
When you want a function to accept
There are many cases where trait objects are the best solution, but they're not more common than all of the above. Usually trait objects become the best solution when you want to do two or more of the things listed
favors a feature that ... is sometimes slower
Trait objects typically
enums and impl Trait simply don't have these costs. It's strange that the more concise syntax
favors a feature that ... often cannot be used at all when its alternatives代わりのもの、選択肢 can
Many traits simply can't have trait objects at all, because they don't meet the object safety rules.
In contrast,
impl Trait is going to require a significant shift in idioms and teaching materials all on its own
Today, when you want to return a type implementingBox
a trait object and accept
The way we teach the trait system will also have to change to describe impl Trait alongside all the existing ways of using traits via generics and trait objects, and explain when impl Trait is preferable to those and other options like enums. Moreover,
Ideally, introducing dyn Trait won't create much additional
"dyn Trait vs impl Trait" is much nicer for teaching and ergonomics than "bare trait vs impl Trait"
There's a natural parallel between the impl/dyn keywords and static/dynamic dispatch that we'll likely mention in The Book. Having a keyword for both kinds of dispatch correctly implies
After impl Trait stabilizes, it will become more common to accidentally write a trait object without realizing it by forgetting the impl keyword. This often leads to unhelpful and cryptic errors about your trait not implementing
Explanation
The functionality of dyn Trait
is identical
Box<Trait>
becomes Box<dyn Trait>
.
&Trait
and &mut Trait
become &dyn Trait
and &mut dyn Trait
.
Migration
On the current edition:
- The
dyn
keyword will be added,たすand will be a contextual keyword - A lint against bare trait syntax文法will be addedたす
In the next edition:
dyn
becomes a real keyword, uses of it as an identifier識別子become hard errors- The bare trait syntax文法lint is raised to deny-by-default
This followsdyn
keyword is unlikely to affect much code, but removing bare trait syntax
Drawbacks
-
Yet another (temporarily contextual) keyword.
-
Code that uses trait objects becomes slightly more verbose.
-
&dyn Trait
might give the impression that&dyn
is a third type of reference参照alongside&
and&mut
. -
In general,
一般favoring generics over trait objects makes Rust code takeとるlonger to compile, and this change may encourage more of that.
Rationale and Alternatives代わりのもの、選択肢
We could use a different keyword such as obj
or virtual
. There wasn't very much discussion of these options on the original RFC thread, since the motivation was a far bigger concern than the proposed syntax,
This author believes that dyn
is a better choice because the notion of "dynamic"obj
is likely to incorrectly imply an "object" in the OOP sense, which is very different from a trait object. virtual
is a termvirtual
keyword or don't even expose the notion of virtual/dynamic dispatch to the programmer, and the languagesvirtual
keyword usually use it to mean "this method can be overridden", not "this value uses dynamic
We could also use a more radical syntaxObject<Trait>
was suggested on the original RFC thread but didn't gain much traction, presumably because it adds more "noise" than a keyword and is arguably misleading.
Finally, we could repurpose bare trait syntax
Unresolved questions
-
How common are trait objects in real code? There were some requests for hard data on this in the original RFC thread, but none was ever provided.
与える -
Does introducing this contextual keyword create any parsing
構文解析するambiguities? -
Should we try to write out how The Book would teach impl Trait vs dyn Trait in the future?