> Making opt-in explicit effectively solves this problem. It is clearly written out which traits a type is expected to fulfill, and if the type is changed in such a way as to violate one of these traits, an error will be reported at the impl site (or #[deriving] declaration).
Please implement this RFC. I really hope this gets in before Rust 1.0. I'm extremely excited and looking forward to using Rust in all my hobby projects once it stabilizes, but honestly when going through the tutorial this stood out as the only ugly wart in an otherwise amazingly beautiful language.
I'm not greatly familiar with Rust (and have never written it), and I think I was able to follow. If I'm reading correctly, there are certain traits that objects get automatically if the compiler finds they qualify, which in my mind would be something like Java automatically adding the Serializable interface to classes that it concluded were in fact Serializable, and then removing it when you did something that made it no longer automatically Serializable. The proposal seems to be to make it more like Java: you have to explicitly write "implements Serializable", and it doesn't by default. Then presumably some logic would still apply to ensure that it really can be given the trait you ask for. In particular the move/copy/clone semantics would (under this proposal) no longer be chosen automatically. It seems (again, to someone who hasn't used Rust) like a tradeoff between compilers that make smart choices automatically by default when possible (e.g. about representational strategy), vs. compilers that avoid doing surprising things.
Thanks for the feedback, it seems like you did follow it correctly
> In particular the move/copy/clone semantics would (under this proposal) no longer be chosen automatically
(Technically, it's just the move semantics: i.e. if passing a value around by-value (i.e. `a = b` like C, shallow-copying the bytes of the values) makes the compiler consider the source unreadable (a move, non-Pod types) or just duplicates the data, leaving the source still readable (an "implicit copy", Pod types).)
I know little about Rust (other than some general idea of its goals and approaches, e.g. the explicit attention paid to ownership), but the this article seemed pretty clear to me. It was well-written and made good use of examples, and the underlying issues are found in many programming languages, even if the details here are Rust-specific.
I can't tell what your point is. If it's that this is not appropriate for HN, I disagree strongly. If posts relating to a specific technology were not allowed, HN could hardly live up to its name. For myself, this was one of the few immediately interesting things on the front page, despite having little more than passing knowledge of Rust.
I was just interested to know if it was interesting to people unfamiliar with Rust; no particular point about it being inappropriate to HN or anything like that.
Having contributed a small amount to Rust, I wouldn't have naturally posted this one to HN because I though it would be of little interest to folks outside the community, but I'm glad it has interested some people! If you are interested in reading more posts like this, they pop up sometimes on our subreddit: http://www.reddit.com/r/rust/
My point is, no one bats an eye when someone posts something that's only relevant to, say, the Python or Haskell community. Further, I bet there are a lot of people like me who aren't really rustites, but are interested enough to want to keep tabs on Rust's progress. Anyway, I mean no offense, only to encourage people to be bolder in posting. :) I'll go subscribe to /r/rust now.
So I really want to work with Rust on something and get to know it better, but as a layman of it this struck me as the wrong direction. As a potential but not current user of the language I'd rather see these kinds of traits always be implicit, because that allows for more interaction potential between independent libraries.
But more specifically, this part of the post struck me:
> struct Cell<T> {
> priv value: T
> }
> This is a perfectly ordinary struct, and hence the
> compiler would conclude that cells are freezable
> (if T is freezable) and so forth.
So how does it work, in the opt-in case, if Cell should be freezable only if T is freezable? Can you declare this kind of expectation and how complex does it get (particularly when considering several different traits)?
> So how does it work, in the opt-in case, if Cell should be freezable only if T is freezable?
impl<T: Freeze> Freeze for Cell<T> { }
> I'd rather see these kinds of traits always be implicit, because that allows for more interaction potential between independent libraries.
Quite the opposite: them being implicit causes trouble with interaction between independent libraries. Because at present, a seemingly innocuous change deep in the internals of one library can prevent its being used in another library—for example, a POD type can have an owned type added to it, and all of a sudden utterly independent code that depended upon its POD behaviour will fail due to move semantics on the linear types.
I'm not clear on how it being implicit or explicit changes this issue. Sure, it is a benefit for the library writer that they can be told that their library is breaking a contract that it previously held to, but if they change it anyway the downstream user is still shit outta luck either way.
If it's just about making sure library writers don't accidentally fail a changed contract just make it so that they can declare an explicit contract that will cause an error if they don't meet and thus make clear the contracts they intend to continue honoring.
This makes the error explicit for exactly the right person in the event of a contract change: the library writer if they break without intending to and the user of the library if they are using the library in a way that they expect to work but were not guaranteed to by the library writer.
> impl<T: Freeze> Freeze for Cell<T> { }
I see. Is it multiple statements for multiple traits or can theybe combined into one statement? Forgive the newbish question.
It makes it clear that a contract is being broken, which, if one is following semver, would necessitate a new major version number. As it is, an expert could easily miss the change; making this explicit is a Very Good Thing™.
On the Cell Freeze matter: I don't understand your question. Can you clarify what you mean?
(The problems would be dramatically helped by better diagnostics about the kinds (e.g. showing which field of struct is causing non-Pod-ness) and better documentation of them (e.g. the kinds are not listed on documentation pages for types). But that still doesn't completely help with library interaction.)
In general you'd just write `#[deriving(Freeze)]`, and you can write things like `#[deriving(Freeze, Send)]` to derive multiple traits. Part of the proposal is to add a warning if you don't derive all the traits you were allowed to, unless you opt out. That way you always have to write in the code what you're allowed to do with a type, and the compiler checks that.
Please implement this RFC. I really hope this gets in before Rust 1.0. I'm extremely excited and looking forward to using Rust in all my hobby projects once it stabilizes, but honestly when going through the tutorial this stood out as the only ugly wart in an otherwise amazingly beautiful language.