[rust-dev] Place for discussions
Hello, I'm following rust for quite a while, but the discussions are more and more distributed between different places. The mailing list was probably first, then with more user attention reddit and StackOverflow, and now the discourse forum. I understand that StackOverflow and Reddit are more for users, not developers, but the discourse forum seems mostly redundant. What's the reason for that split? Is the mailing list deprecated? Which one is the future? I for myself prefer the mailing list because of the gmane NNTP service, I can use my usual usenet software and have all my forums in one place. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Mutable files
Patrick Walton pcwal...@mozilla.com wrote: On 7/21/14 2:22 PM, Tobias Müller wrote: We discussed this with Bartosz literally for weeks (him being a fan of auto_ptr for too long, later completely converted against it and I take credit for that :o)). With auto_ptr this was possible: auto_ptrint a(new int); auto_ptrint b = a; It would nullify a with copy syntax. That code won't compile with unique_ptr; you'd need an explicit move(a). It only got worse from there: passing into functions, member variables... MOVING WITH COPY SYNTAX DOES NOT WORK. It's cut and dried. Please don't snip the attribution, that was a quote! ... in C++. Not in Rust. That's because, unlike C++, Rust is designed from the ground up to support moves and copies in a first class way. It's just strange that you can change the semantic of an already existing operation just by adding new capabilities. Adding traits should define new operations with new semantics, not changing the semantics of existing operations. At least that's how it works for all other traits, and deviating from that is at least surprising. Hence the Opt-In Built-In Traits proposal Opt-In built-In traits makes things a bit better but my point is still valid. By adding Copy (implicitly or explicitly) you remove the possibility of move semantics from the type. Usually you don't work alone on a project and some coworker adding Copy to a type that I expected to be Move may be fatal. No other trait removed works like that. Maybe the syntax was just too heavy? Any syntax at all is too much. I am convinced of that. I'm still not convinced but maybe my fear is unjustified. Time will tell. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Mutable files
Patrick Walton pcwal...@mozilla.com wrote: On 7/21/14 8:49 AM, Tobias Müller wrote: As a rust newbie, that aspect aways makes me a bit nervous. Two quite different operations with the same syntax and and simply changing a detail in the struct can be enough to switch between the two. This is the reason for Opt-In Built-In Traits. AFAIK this also was one of the reasons (if not _the_ reason) why std::auto_ptr was deprecated in C++. No, `auto_ptr` was deprecated because it copies, not moves, making it hard to sensibly use in containers (among other things). Quoting Andrei Alexandrescu on digitalmars.d: We discussed this with Bartosz literally for weeks (him being a fan of auto_ptr for too long, later completely converted against it and I take credit for that :o)). With auto_ptr this was possible: auto_ptrint a(new int); auto_ptrint b = a; It would nullify a with copy syntax. That code won't compile with unique_ptr; you'd need an explicit move(a). It only got worse from there: passing into functions, member variables... MOVING WITH COPY SYNTAX DOES NOT WORK. It's cut and dried. Andrei - But you are right, Rust is not C++, it's actually the other way round that makes me nervous. Comparisons between C++ aren't really relevant anyway because the compiler catches any use-after-move at *compile time*, rather than at runtime. This means that mistaking the two doesn't cause any harm: * Causing a move when you thought you were copying results in a compiler error. * Causing a copy when you thought you were moving is harmless, as any implicit copy in Rust has *exactly the same runtime semantics* as a move, except that the compiler prevents you from using the value again. From a performance point of view that may be true, but you may lose desired semantics. If you want an instance of a type to be move-only, but later decide that copying that type is still useful in another place, then you lose the guarantee in the first place. It's just strange that you can change the semantic of an already existing operation just by adding new capabilities. Adding traits should define new operations with new semantics, not changing the semantics of existing operations. At least that's how it works for all other traits, and deviating from that is at least surprising. Again, we had that world before. It was extremely annoying to write move all over the place. Be careful what you wish for. Maybe the syntax was just too heavy? Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Virtual fn is a bad idea
Ziad Hatahet hata...@gmail.com wrote: Kind of off-topic, but there is a heated discussion on the D language forums about why having non-virtual base class methods by default is a bad idea: a href=http://forum.dlang.org/thread/lfqoan$5qq$1...@digitalmars.com;http://forum.dlang.org/thread/lfqoan$5qq$1...@digitalmars.com/a Also comes up here: a href=http://forum.dlang.org/thread/zkmunpiikmrezbzme...@forum.dlang.org;http://forum.dlang.org/thread/zkmunpiikmrezbzme...@forum.dlang.org/a I've just read the entire thread (~250 posts by now) and the discussion is mainly about pro/cons of breaking changes to the language, not about the feature itself. The conclusion of that thread seems to be - Almost everyone agrees that non-virtual (=final) by default is a _good_ thing. - The lead developers feel that it's not worth a breaking change. - Many users don't agree with that decision. Where did you find a point against non-virtual by default? (Except that it's a breaking change, of course) Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Alternative to Option types
Eric Reed ecr...@cs.washington.edu wrote: In general, monads require higher-kinded types because for a type to be a monad it must take a type variable. That is, OptionT and ListT could be monads, but int and TcpSocket can't be monads. So imagine we wanted to define a trait Monad in Rust. Just for my understanding. Is there an inherent reason that a monad has to be a higher kinded type (type constructor)? Couldn't it also be represented somehow as a multiparam trait/typeclass? AFAIK, higher kinded types are standard haskell, while MPTCs are not, so it's the obvious choice for haskell. Is it also for rust? Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
Lee Braiden leebr...@gmail.com wrote: On 14/01/14 01:50, Palmer Cox wrote: On Mon, Jan 13, 2014 at 12:18 PM, Tobias Müller trop...@bluewin.ch mailto:trop...@bluewin.ch wrote: Daniel Micay danielmi...@gmail.com mailto:danielmi...@gmail.com wrote: Do you know what undefined behavior is? It doesn't mean unspecified. True, but despite beeing so often cited it won't format your hard disk (even in C). Actually, it's possible, at least on systems without MMU protection --- some embedded systems, for example. Ints are often used (not just in your own code but in library code) to index a jump table. If that index is a different number than you expected it to be, you could end up executing calling random functions in memory. Said functions could (and probably would) crash within 1--2 instructions, but even then, it's not INCONCEIVABLE that those instructions could equate to 1) load hard drive device number into the first arg register; 2) call the OS format_drive function. But this is just as likely with wrapping integers. _Any_ deviation from the expected behavior is as dangerous as UB. This all leaves the realm of remote possibility and enters the realm of unacceptable risk, at least for some software on some systems, when you factor in malicious individuals trying to manipulate what address gets called and/or what code is sitting at the address called, waiting to execute. As I understand it, there are essentially three bugs that can cause a segfault: 1) write to memory you're not allowed to write to. 2) read memory you're not allowed to read from. 3) execute code in memory you're not allowed to execute code from. The third kind of bug is basically saying do anything you like computer, I don't care. It's very much undefined behaviour, very much like calling a function pointer that's NULL. Mostly, you get a segfault, thanks to the MMU, but in portable code, you can't depend on that -- either the compiler handles it, or you have to remember to check everything carefully, treating your coding environment as a hostile one, full of adversaries. And that's just why I want to help the programmer with those checks as much as possible. Lifetimes and non-nullable pointers do a great job ensuring this for memory management, int overflow is missing such a feature. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
comex com...@gmail.com wrote: On Mon, Jan 13, 2014 at 4:06 PM, Tobias Müller trop...@bluewin.ch wrote: intl1,u1 + intl2,u2 = intl1+l2,u1+u2 ... If the result does not fit into an int the compiler throws an error. To resolve an error, you can: - annotate the operands with appropriate bounds - use a bigger type for the operation and check the result. I remember wondering whether this type of solution would be feasible or too much of a hassle in practice. As I see it, many values which might be arithmetic operands are sizes or counts, and really ought to be size_t sized, and any mutable variable which is operated on in a loop can't be bounded with a lot more complexity, so it might lean toward the latter. You are right, mutations that depend on previous values of the same variable are a problem. For example it would be impossible to determine bounds for i in 'i = i + 1'. But you could shadow i like 'let i = i + 1'. However that is no more mutation but definition of a new variable. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
Daniel Micay danielmi...@gmail.com wrote: On Sun, Jan 12, 2014 at 1:23 PM, Tobias Müller trop...@bluewin.ch wrote: Isaac Dupree m...@isaac.cedarswampstudios.org wrote: In general, Rust is a systems language, so fixed-size integral types are important to have. They are better-behaved than in C and C++ in that signed types are modulo, not undefined behaviour, on overflow. It could be nice to have integral types that are task-failure on overflow as an option too. As you note, bignum integers are important too; it's good they're available. I think bignum rationals would be a fine additional choice to have (Haskell and GMP offer them, for example). Wrapping overflow is just as bad as undefined behavior IMO. Do you know what undefined behavior is? It doesn't mean unspecified. True, but despite beeing so often cited it won't format your hard disk (even in C). The result of an integer addition will always be an integer in every compiler I know so in this specific case I don't fear the UB. I cannot remember a single case of using signed integers where wrapping would make any sense. It often makes sense in codecs, hashing algorithms and cryptography. I'm sure there exist many cases where _unsigned_ int overflow makes sense. For _signed_ integers I'm a bit sceptical but I am no expert in that field. In any case it should not be the default but rather 'opt-in'. But this is not what I meant. Let me rephrase it differently: Assume that signed int overflow is UB (like in C). That means, all actual overflows at runtime have to be considered bugs. Now I cannot imagine any such case (bug) where guaranteed wrapping would actually behave nicer. If you don't have clear bounds and don't want modular arithmetic, you need big integers. Or proper input validation. The type defines the bounds. And you lose some optimization opportunities. It's treated as undefined because there are more optimization opportunities that way. That's what I wanted to say. If you guarantee wrapping overflow you lose those opportunities. So why not take the path of the rust memory management and enforce bounds statically? It would need annotations on the types, like lifetimes, but it would be very rusty. Like C but safe. Rust isn't supposed to be really hard to write. Complex dependent typing would I'm not sure that this would be so complex. At least not more than the lifetime system. Is simple arithmetics on the bounds. In reality (rust beeing a systems PL) fixed width ints _will_ be used, and I am sure that overflow will often just be neglected. So why not enforce it statically? Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
Carter Schonwald carter.schonw...@gmail.com wrote: enforce what statically? There is a very really very subtle tradeoff in how powerful a static verification scheme can be vs how easily it can be used (the sweet spot being somewhere in between nothing and complete proof based verification). Enforce that integer overflow never happens. Roughly, I was thinking of the following: Every int variable/parameter/binding has an associated range (lower and upper bound): intl,u If no bound is specified, the min and max values of the type are used. Every operation on ints specify the range of the result using the range of the operands: intl1,u1 + intl2,u2 = intl1+l2,u1+u2 ... If the result does not fit into an int the compiler throws an error. To resolve an error, you can: - annotate the operands with appropriate bounds - use a bigger type for the operation and check the result. To go from a bigger to a smaller range you use: let x : int match x { int0,255 = ... _ = fail() } Sorry for the sketchy syntax, I'm just following this list but have never actually used rust. It sounds like there are valid arguments for several different error semantics for fixed size numbers, and those should perhaps be different builtin types. Everyone is right about the tradeoffs for their own needs, and choosing one semantics over another in that context is a mixed bag / iffy proposition. Tradeoffs are real, the best a language can do is make it easy to choose the right tradeoffs for you! But also different languages choose different tradeoffs and rust aims to be a systems PL. By banning the fastest int version from the language by making overflow wrapping or failing at runtime, you actually limit the choice already. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
Carter Schonwald carter.schonw...@gmail.com wrote: indeed, hence why i was saying there should be sized int variants for each of those semantics (wrapping, trapping, overflowing, etc). This is something that many people seem to favor, and is the right choice for supporting smart engineers build reliable sophisticated software. Namely, really spell out what each alternative means, make sure they're all first class options, etc etc. staticly verifying bounded ranges in a language is really subtle. You're proposing what easily turns into a pretty tricky flow analysis (to have it have any precision!), and it'd have to happen in type checker too... I was actually trying to avoid flow analysis. With my proposal, the range would be attached to the type and cannot change over time. That's why I was proposing a case match binding for going to a smaller range. Some time ago I was reading a blog post (I think it was from Patrick Walton) about why you abandoned type state and how it can be replaced with a less dynamic system that is easier to reason about. In that system the dynamic type state was replaced by a more static type parameter. I don't want type state for integers but this 'replacement'. (I don't know how it was called, need to read it up again) Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0
Isaac Dupree m...@isaac.cedarswampstudios.org wrote: In general, Rust is a systems language, so fixed-size integral types are important to have. They are better-behaved than in C and C++ in that signed types are modulo, not undefined behaviour, on overflow. It could be nice to have integral types that are task-failure on overflow as an option too. As you note, bignum integers are important too; it's good they're available. I think bignum rationals would be a fine additional choice to have (Haskell and GMP offer them, for example). Wrapping overflow is just as bad as undefined behavior IMO. I cannot remember a single case of using signed integers where wrapping would make any sense. And you lose some optimization opportunities. Trapping overflow is a bit better security wise, but performance is worse. Also IIRC it does not play nicely with existing code that assumes otherwise. Checking only at runtime is also not optimal. Bigints are secure but IMO not suited as default for a systems PL. So why not take the path of the rust memory management and enforce bounds statically? It would need annotations on the types, like lifetimes, but it would be very rusty. Like C but safe. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Rust forum
David Piepgrass qwertie...@gmail.com wrote: Okay, well, I've never liked mailing lists at all, because: 1. In non-digest mode, My inbox gets flooded. 2. In digest mode, it's quite inconvenient to write a reply, having to cut out all the messages that I don't want to reply to and manually edit the subject line. Also, unrelated messages are grouped together while threads are broken apart, making discussions harder to follow. 3. In email I don't get a threaded view. If I go to mailing list archives to see a threaded view, I can't reply. Just use NNTP (gmane.comp.lang.rust.devel on news.gmane.org). Most newsreader support threaded view (Thunderbird does). You can configure the mailing list s.t. mails are not actually delivered to your email address even if you are registered. But looking at your email address you are already using gmane. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Struct members in trait definitions
Andres Osinski andres.osin...@gmail.com wrote: Hi all, I have a question which I'm sure must have already been discussed and dealt with, but I wanted to understand the design rationale: A lot of trait-level functionality would be enhanced if a trait could specify members to be included in the struct which implements the trait. This can be solved in practice by wrapping member access in accessor methods, but I fail to see why that would be preferable. IMO this would completely defeat the advantage of traits over inheritance based interfaces. The beauty of traits is, that the trait and the type are separated, only connected by the implementation: - You can add an implementation for your custom trait to any existing type. - You can add an implementation for any existing trait to your custom type. Now if you add a fields specification to the trait, the former isn't true anymore. The type has now a dependency on the trait since it must at least contain a field of a given type, if not even with a given name. If you the concrete type is under your control, this is obviously not a problem, as it is the case with inheritance based interfaces. But you cannot simply assume that for every use case. Tobi ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev