Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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?


Do you need multiple statements if you want your type to be "Freeze if T is Freeze", "Share if T is Share", etc?


Yes, you do. But that's not arduous.


(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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: