-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce dyn
keyword
#1603
Introduce dyn
keyword
#1603
Conversation
@ticki Rendered link is invalid. |
Fixed. |
Is dyn keyword is reserved? |
No, it's not. It need to be context dependent. I added a new commit explaining that. |
Why can't we make warning about dyn will become reserved keyword in two release loops? |
Why should we? Adding it as context-dependent keyword won't cause breakage. |
@ticki Is it any harder to make it context-dependent? |
Yes, but it is inevitable. At least two RFCs introducing context dependent keywords have been accepted. Adding a third one won't increase the complexity. |
I’m theoretically in favour of this, but it seems kinda late to be doing this. I agree that the trait object syntax is too easy and implicit, and I’ve seen a fair few newcomers make the understandable mistake that trait objects are the way of writing functions that accept any value that implements a trait (rather than using generics, which is much more common), but this would cause an enormous amount of breakage (in Rust 2.0, when presumably the deprecation warning would be promoted to an error). |
Deprecation doesn't require breakage. |
I see way too many people doing e.g. I agree, that ideally this should have been done originally, but I don't think it is too late. I think that this is worth the turbulence, it will entail. |
Although, ideally it shall be made into an error after several release cycle, but this RFC has no such requirement. It is also worth noting that the "private in public" RFC caused severe breakage, but the ecosystem seemed to handle it well, by simply keeping it a warning in several release cycles. |
As I said, I want to be that error in several release cycle. |
I don't disagree with that, but as an initial point, this RFC suggest no such action. We can amend it later, if the consensus is positive to that. |
@kennytm @jonas-schievink, you -1'd this. Could you elaborate on why? I guess it is the stability issues? |
+ to @P1start |
Yes, I'm not in favor of adding another way to express the same thing we already can, with no chance of removing the "old" way (since it's used so heavily). Pre-1.0, sure. I don't think the idea of making the dynamic dispatch cost explicit is bad in itself, but I don't think the current way is too implicit (for example, when seeing traits as generic parameters you know there's dynamic dispatch involved - or are there exceptions to this?). |
I disagree. I see newcommers make the mistake all the time. There is a quite severe It is certainly not obvious that wrapping a trait in some pointer will allow values tos That a trait (which isn't even a type) can coerce into a trait object (an usized type) can |
@ticki Fair enough. It's been a while since I learned Rust, and now it seems obvious to me how it works, but you're right that it might be hard to learn at first. What's interesting, though, is that I've lately been actively avoiding generics in order to keep compile times low, so maybe using trait objects by default isn't too bad. Certainly, benchmarking is required before making this decision (which I admittedly didn't do, but I do think Breeze's <10 second compile time on core changes speaks for itself). |
Agreed. It is obvious to me as well, but I fairly often recieve PRs containing these kind of mistakes. The IRC contains lots of people asking about trait objects.
I find this rather strange. A system languages ought to focus on the runtime performance, more than the compile time performance. |
Wouldn't it be better/more appropriate to provide better material in the book and other tutorials to ensure that newcomers to Rust are aware of the cost of specific activities? For a new user, I don't know that a Further, wouldn't it also be more appropriate to add a lint to clippy and inform users what they're doing and why it's (potentially) a badness? |
Changing the syntax would be far more effective.
These simply looks like normal pointers, but they're not.
Such a clippy lint wouldn't make much sense. You want it to show up on every case of trait objects? |
You could lint functions that take a trait object when the implementation could be written generically. |
This is how Rust is today: “Every object compatible trait It sounds so confusing. From the pedagogical point of view, I very much agree that naming those two differently is a big win! |
You know, thinking about it, the whole point of including this feature as a minor version bump, is to prepare Rust programmers for when Rust 2.0 eventually exists in the long run. As an example, that's why when you guys deprecate calls or items and introduce new stuff in the All @ticki is advocating for is to have it there, while not absolutely mandatory to use in Rust 1. With enough compiler warnings to help further drill the awareness of The problem I see here is and what concerns me the most, is that with enough breaking changes only isolated to be introduced for Rust 2.0 only, that it will create a community split and divide between two versions of the compiler. I don't want Rust to repeat the same mistakes that Python and D did. The reason to close this RFC based on the thought "it definitely doesn't feel to me like a minor version bump" seems like an unusual reason to decline this. |
The problem, or one of the problems, as I see it, is that |
Use a keyword is not a good idea, I support the alternate |
@J-F-Liu I'm against |
@ticki Yes, unless
Thus to allow trait name to appear in all type positions. Benefits are:
This is a great breaking change of Rust 1.x, hopefully can be adopted in Rust 2.0. |
I thought this issue was already closed. IIRC the consensus was that:
This particular issue can be solved mechanically, and for this reason it might encourage people to discuss a future Rust 2.x in which we can just break the world (and fix it mechanically). But this is not the only "imperfect language decision" in Rust 1.x, not all of them can be solved mechanically, and arguably we would like to solve most of them in Rust 2.x. So while it is interesting to consider how to break the language, it doesn't really move this discussion forward. Those wanting to move this feature forward should attempt to do so in a backwards compatible way. I think that the fundamentals issues that this RFC raises (that the dynamic costs of trait objects are "too implicit") can be mostly solved in a backwards compatible way by two small incremental backwards additions to the Rust 1.x language:
These can be pursued in 2 small RFCs or combined into one small RFC, and will result in:
Whether consensus can be gathered about this changes being worth it or not, that's a different issue. But for those RFCs to be successful they should probably stay as far away from Rust 2.0 as possible. |
We knew, but nobody listened 😄 |
@gnzlbg Thank god for semver. In 2.0.0, we can break all the shit we want to. |
My guess is that a significant portion of the 👎s given are not disagreements in syntax, but rather concerns about stability. |
@ticki |
My point in a nutshell was that there won't be a rust 2.0. I am not saying
it is not worth it to discuss about "what it could have been" but rather
that if we want to get things done we should focus more on "this is how
things actually are and how do we incrementally improve them" :/ it's
extremely unsatisfying to not be able to make it perfect, worse is better I
guess.
…On Sat, 11 Feb 2017 at 22:00, Vadim Petrochenkov ***@***.***> wrote:
@ticki <https://github.com/ticki>
No large scale breakage (like this one) will be possible regardless of
semver if Rust actually becomes a widely used language.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1603 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA3NpgAoJKo4739FQYYh-UsQ1oZAhlf4ks5rbiF4gaJpZM4IUAR3>
.
|
I'd love to see the ideas from this RFC to go forward in a similar vein to the path RFC #1685 (comment) is now moving along. Yes, this is a bigger change, but I and many others think that the lack of syntactic difference between types and traits (in the context of trait objects) is a wart. It's possible to improve the situation without breaking compatibility by introducing a new more explicit syntax, utilizing rustfmt and the official documentation in the future to slowly change the the perceived "standard" and then in a long timescale, softly depreciate the old syntax with a lint. No need to break stuff. Basically I just restated what @gnzlbg said :D Just butted in to show my support. |
One comment on the comparison with the Python 3 fiasco. By the time Python 3 came out, Python 2 was widely used in production. This is currently not true for Rust 1.x. In fact (assuming things go well), a vast majority of Rust's users are yet to come. Therefore, any fears of users shunning Rust 2.x should be tempered by this fact. |
@gurry Very few were using D when they switched standard library breaking backwards compatibility. 10 years later you can still see people asking around whether D is stable yet. |
@gnzlbd Hmm. I didn't know about that. Thanks. So you imply that D's breaking change was early enough and yet they don't have much traction today. But are we sure the said breaking change is to blame? It's also possible D didn't catch on for other reasons. |
I still see people asking if Rust is stable enough for production use, or saying that they heard we "recently reworked our entire threading model" or some other thing from pre-1.0, so I'm not sure how much that sort of anecdata really applies. And there are definitely other reasons D didn't catch on. I'd also like to see this keyword introduced even though we probably can't ever get rid of the keyword-less option, but until Rust 2.0 is actually likely to happen I don't feel that strongly about it. |
@gurry A different way to put it is like this. Rust has many language features: memory safety, data-race freedom, generics, ... Notice that memory safety and data-race freedom are promises: we do not have a formal proof of this. Rust 1.0 added a new feature: "from now on, if your code compiles, it will compile with the latest compiler forever". This feature is also just a promise from everybody evolving Rust to everybody using it. It only works if those that use Rust trust those that evolve it. The moment you loose that trust, that feature is gone forever and it will never come back. Does this mean that we cannot ever break this promise? No. Imagine we find out that some other promise Rust makes does not hold, like for example, we discover that safe rust is not memory safe. That is also a promise our users rely on. If we need to break the language to fix it, we probably will. But that is a damn good reason to break the language, since otherwise our users cannot trust Rust anyways. We are trading one promise for another here, but our intention is to keep the promises we made. We would probably retain some of our users trust after doing something like this. Now think about breaking the language to fix a minor stylistic change (like this one). We can either have this breaking change, or we can keep our users trust on stability, but we cannot have both. Do you think it is worth it to sacrifice "stability" for this minor stylistic change? Most people think it is not worth it. Some people think it is. We are a diverse group of people, and not everybody can always get exactly what they want; we must compromise on consensus, that's just how big groups work. I actually would like something like this to eventually happen in some form, but I can empathize with the majority here, and even though I want this, I know that they are right: for the Rust language community as a whole, stability is a way more important feature to have than "more clear syntax" for feature X, in particular when even though the syntax is not the clearest that one could have, it is still clear enough in practice. |
@gnzlbg I fully appreciate what you say and do not take lightly the costs associated. I'm just trying to understand how high those costs truly are, especially at the present point of time.
I feel it's not a minor change. It itself and all the changes it enables further down make the language a lot easier to use and teach. Generics are everywhere in Rust. So anything that simplifies them has a major impact on the whole language. The number one complaint about Rust today is it's hard to learn. Therefore, anything that addresses that has somewhat of a disproportionate importance at this particular juncture in time IMHO. |
Another vague idea for soft-deprecating "plain" trait object syntax gracefully: Have At some point, Especially now with the discussion about having unsized rvalues and passing unsized values to functions, a new syntax would be important to have, as pointed out in #1909 (comment) |
Shall |
Anyway such label would be here even more on-topic compared to |
Maybe someone should edit "#2113" into the opening comment, so one can find the "take two" RFC more easily? (Google search of "rust dyn keyword" ends up here) |
@vi Done. |
Introduce a keyword,
dyn
, for denoting dynamic dispatch, with the motivationof avoid "accidental overhead" and making the costs more explicit, along with
deprecation of the old syntax.
Rendered.
@cramertj Edit: A variation on this RFC was merged in #2113.