Repository navigation
Description
This is a sub-issue of #44662 proposing the Rust 2015 stabilization of dyn Trait.
Status
The decision is made, we just need a stabilization PR!
Details
The new syntactic form dyn <relative-path> is added. It is an error to use dyn <relative-path> if path does not name a trait. The result is a so-called dynamic trait type.
For backwards compatibility, dyn can still be used as an identifier -- in other words, it is a contextual keyword. Note also that dyn :: foo parses as a path dyn::foo and not a use of the dyn keyword. You can however write dyn (::foo) to clarify your meaning.
There is a "allow by default" lint that suggests uses of Trait be rewritten to dyn Trait. Much code in rustc was converted using rustfix in conjunction with this lint. I believe the current plan is to keep this lint as "allow by default" for the time being, but make it as part of the "idiom shift" lints for Rust 2018.
Tests
Here are some tests documenting the current behavior:
- Positive uses of
dyn Trait, including a use ofdyn (::Path). dynby itself is an identifierdyn::foois a path
Other details
Once this is stable, we should adjust the output from ppaux to use it! (#49277)
Activity
nikomatsakis commentedon Mar 20, 2018
cc @petrochenkov, who implemented, and @Manishearth, who has been working on lint etc
nikomatsakis commentedon Mar 20, 2018
@rfcbot fcp merge
I propose that we stabilize the Rust 2015 behavior of
dyn Trait. Details found in the issue header.rfcbot commentedon Mar 20, 2018
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged teams:
No concerns currently listed.
Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
nikomatsakis commentedon Mar 21, 2018
(Here is a question to ponder, that does not I think block stabilization: for Rust 2018, is it working making
dyna true keyword? If we opt towardscrate::foopaths, as I currently prefer, then I am leaning towards "no", since the only weird behavior is arounddyn :: foo, and::foopaths are likely deprecated, so there is then only one reasonable interpretation of such a path. This allows for a gentler transition into Rust 2018.)Manishearth commentedon Mar 22, 2018
This isn't consistent --
crate::foois an idiom and not a reqirement; however makingdyn::fooparse differently is a breaking change; we can't rely on an idiom change to make a breakage "non breaking".Though it seems like you're suggesting that we could scope the epoch breakage so that
dynstays a contextual keyword, but nowdyn::fooparses asdyn Trait-- i.e. instead of breaking all dyn idents we only break it in this one case. That could work, I think.I do think that contextual keywords should eventually become true keywords and we're well poised to just make it a keyword with the epoch, so idk.
nikomatsakis commentedon Mar 22, 2018
@Manishearth
I am proposing not making it parse differently. It currently parses as a path
dyn::foo, and I am claiming that that is the only sensible interpretation in Rust 2018, since::foowould not be a path on its own (well, it's a deprecated form of path). Though we might want to lint against it.As I wrote above, I am proposing that
dyn::foocontinues to parse as a path, not as a usage ofdyn Trait(though perhaps it would be linted against).This is an interesting policy question. Some cases, like
catch, really must change. But other cases, likeunionand -- I think --dyn, don't necessarily have to. So should we change them to keywords in Rust 2018? I feel divided. I sort of like the idea of 'cleaning up' and being consistent, but I also sort of like the idea of 'make it a lint error and maybe make it a hard error in the next epoch'.nikomatsakis commentedon Mar 22, 2018
I noticed something: in our error messages, we don't use
dyn(of course). Once it's stable, we should fix that! (Filed #49277)rfcbot commentedon Mar 22, 2018
🔔 This is now entering its final comment period, as per the review above. 🔔
leoyvens commentedon Mar 23, 2018
I wonder if by stabilizing the new syntax with the exact same semantics as the old one we are not missing an opportunity to make small semantic changes without breaking existing code? I don't have any such changes in mind, it's just a thought.
rfcbot commentedon Apr 1, 2018
The final comment period is now complete.
18 remaining items
nikomatsakis commentedon Jul 5, 2018
Closed by #49968
dhardy commentedon Aug 8, 2019
I realise this decision was made a long time ago, but do me
&Trait(withoutdyn) is perfectly valid Edition 2015 code, and I don't appreciate being nagged about it (especially since I often see the warning in other people's code and in old code not receiving updates excepting for bug fixes).In the future could we please be more cautious about deprecating previously-valid code in an existing epoch?
cramertj commentedon Aug 8, 2019
It's just as valid of code in 2018 as it is in 2018-- the warning and the new syntax aren't edition-related.
dhardy commentedon Aug 8, 2019
The syntax is valid, but the deprecation is another matter. If
&Traitis to become illegal in future Edition 2015 code, then this will be a breaking change (defeating the point of editions). But if not, then I see no use to the deprecation warning — it is only of use when migrating to Edition 2018 (because lets face it, there is little reason to continue using E2015 with in code being actively maintained).cramertj commentedon Aug 8, 2019
I don't agree with this. The syntax is not a hard error in either edition. It is a warning in both editions. It is not an edition-related feature or change.
dhardy commentedon Aug 9, 2019
It is edition-related since only E2018 implemented this properly (with a new keyword). Since this discussion was already happening way before E2018 was a thing, I don't understand why
&Traitisn't a hard error there, but that's a different topic.But my point is more that breaking changes are not expected in an existing edition, and the purpose of default lints is to point out real issues (e.g.
unusedcode is often the result of an unfinished job). Breaking changes to the standard library API have been accepted within E2015 in a few cases, but this change affects far more code.So I ask again: is there any plan to make this a hard error within Edition 2015 (bearing in mind that any code still using E2015 is obviously not being updated for some reason)? Because if not, this deprecation warning has no raison d'être (though it would not be out of place in Clippy, phrased as a "recommended style" or some such).
petrochenkov commentedon Aug 9, 2019
This warning seems to affect the majority of 2015 crates, e.g. when looking through crater logs the walls of
dyn Traitwarnings is the primary thing I see.Enabling warnings of this scale is not reasonable, so would be better to make it edition-dependent even if it's not right now.
Manishearth commentedon Aug 9, 2019
I don't agree with the reasoning that we should never add new lints unless things are being deprecated to the point of being removed.
This is a form of deprecation, just one where we don't intend to remove support for the syntax.
I don't see an issue with the scale of the warnings. These are easy to fix with rustfix. If lots of people see them it's no big deal, this happens with other kinds of new warnings reasonably often as well (we had a bunch with
..=, and some more with the float match changes)dhardy commentedon Aug 9, 2019
This assumes one intends to modify the code in question, and do so immediately.
At the end of the day we can live with this, but from my POV the nuisance out-weighs the benefit.
Manishearth commentedon Aug 9, 2019
No, it doesn't, it's a warning, you can also choose to not fix it.
whitequark commentedon Aug 9, 2019
This is technically true but does not account for the fact that deprecation warnings carry a lot of psychological pressure to fix them (which is also why they work in the first place).
cramertj commentedon Aug 9, 2019
If someone is the type of programmer who feels compelled to fix all warnings, then I believe they should also want new warnings to be enabled that would help improve their code. If they don't believe following the warning improves their code, it's easy to disable the warning.
whitequark commentedon Aug 9, 2019
Indeed, and the key part is "their code". To quote @dhardy:
Ixrec commentedon Aug 10, 2019
I think most of this was already settled by the Editions RFC and the dyn Trait RFCs, and we're almost reiterating discussions that have already happened, but I also think there's a valid point buried under the confusion.
First, the relevant part of the Editions RFC:
The relevant part of the dyn Trait RFC:
In particular, some of the comments above seem to be simply confused about these points:
dynas a keyword does depend on the edition, the&dyn Traitsyntax is available on both editions and is strongly preferred to the&Traitsyntax on both editions, so debating whether the lint is "edition-related" is at best completely ambiguous and unhelpfulNon-obvious historical context: I wrote the dyn Trait RFC before the big discussion surrounding the
EpochsEditions RFC. The text I just quoted from it is the part which I had to update after the Editions RFC achieved consensus. That's why my arguments in the Motivation section are talking about the then-upcoming impl Trait stabilization as a source of impending churn rather than the then-upcoming 2018 edition, yet this one part quotes the Editions RFC verbatim.Now, with all that out of the way, the semi-buried but valid novel point I see in this discussion is:
When I updated the dyn Trait RFC, I did not notice that the argument for a warn-by-default lint against bare trait syntax on Rust 2015 becomes much weaker when you realize dyn Trait came out around the same time as a new Edition, and I don't think anybody else noticed this either. In all fairness, it is pretty minor compared to the "wait, can we actually get away with this?" question that correctly dominated the discussion.
So even though the explicit consensus of that RFC was to warn against it on 2015, in hindsight I have no objection to softening that now. Especially since we're also considering making the 2015 edition be a warning unto itself, it does seem a bit silly to have more than one warning that effectively says "this is 2015 code" on by default.