From banderson at mozilla.com Sat Dec 1 02:21:04 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 1 Dec 2012 02:21:04 -0800 (PST) Subject: [rust-dev] Changes to .rc files, etc. In-Reply-To: <1291678926.1823370.1354343279884.JavaMail.root@mozilla.com> Message-ID: <2144285860.1829973.1354357264422.JavaMail.root@mozilla.com> Hey, Rusties. I've recently made some significant changes to how Rust handles crate (.rc) files, directories and the ever-mysterious 'companion modules'. In brief, there is no longer a special crate syntax. .rc files and .rs files are parsed the same, and in all ways interpreted identically, by the compiler. Rust no longer implicitly merges .rs files from special locations. Overall things are simpler and should be less surprising, though expressing directory structure in Rust will be awkward in new ways, requiring attributes. # What crate files were Until now Rust has had a special, declarative syntax for crate (.rc) files. This was a sort of manifest, where important details about resources used by the crate (libraries, source files, syntax extensions) were available for quick inspection by build tools. Crate files looked like this: // Attributes about this crate #[link(...)]; #[etc]; // The module *and* directory structure // module foo, loaded from foo.rs mod foo; // module bar, and directory bar mod bar { // module baz, sourced from bar/baz.rs mod baz; } The crate file mapped out both the directory and module structure of the project, but it did some surprising things by convention to fill in the non-leaf nodes in the module heirarchy. First, given a crate file foo.rc, rustc would also look for foo.rs and treat that as the top-level 'crate' module (called a 'companion module'). The differences and relationship between the two was a consistent source of confusion. Next, it would do a similar thing with modules that corresponded to file system directories. In the above example it would implicitly load ./bar.rs, if it existed, as the content of the module representing the directory `bar`. This resulted in the following sort of project structure: myproject.rc myproject.rs foo.rs bar.rs bar/ baz.rs quuz.rs It places the implementation of mod `bar` outside of the directory containing its related submodules, `baz` and `quux`. While that is a tantalizingly logical way to lay out hierarchical modules, it turns out that's not usually what you want - `bar` and it's submodules make up a modular unit of code and want to be in the same directory on the file system. Over time the distinction between .rc files and .rs files blurred and important metadata, such as `extern mod` statements, could appear in any source file. Cargo must parse the full source tree to discover crate dependencies. Most things that you might want to express about a crate can be done through attributes, making less of a need for a dedicated crate language. Things were generally not feeling quite right, so we're just removing the crate language completely and seeing how that works out. # So how does it work now? Now Rust parses .rc files and .rs files the same. The `mod foo;` syntax works anywhere, loading a file with the module name plus `.rs`, in the same directory as the current source file. Rust no longer has any module syntax that also implies directory structure. A typical crate without a directory hierarchy might look like so: #[link(name = "core", vers = "0.5", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; #[comment = "The Rust core library"]; #[license = "MIT"]; #[crate_type = "lib"]; // External crate declarations extern mod std; extern mod zmq; // Imports use std::serialization; // Modules sourced from other files mod foo; mod bar; // Top level declarations, etc. trait Bazzable; Adding directory structure to crates requires, for the time being at least, the use of the `path` attribute to explicitly load a module from a subdirectory. The recommended pattern is to load subdirectory modules from a file called `mod.rs`, located in the subdirectory. // module foo, loaded from foo.rs mod foo; // module bar, loaded from bar/mod.rs #[path = "bar/mod.rs"] mod bar; The contents of `bar/mod.rs` are parsed for the module `bar`, and `bar/mod.rs` can declare further modules to load from the `bar` directory. File's are loaded relative to the current source file so, being already located in directory `bar`, `bar/mod.rs` can load additional submodules from the `bar` directory without using the `path` attributive. The file name `mod.rs` is preferred for this purpose because, being a keyword, there is no chance it will collide with an actual module that you would want to load. This strategy does have the disadvantage that you will have many emacs buffers called `mod.rs`. Alternately, if you tend to only put code at the leaf nodes of the module tree and liked the old pattern then this will work: // Just a normal module mod bar { #[path = "bar/baz.rs"] mod baz; // Could be other stuff here } Note that, even though `baz` is declared in a submodule, the path must explicitly specify the directory - `bar/baz.rs`. The parser doesn't try to do anything smart by assuming things in mod `bar` are in directory `bar`. # Why have .rc files? We're still using the .rc extension for crate source files because cargo identifies crates by file extension. Anyway, that's the whole story. Have fun. -Brian The issues: https://github.com/mozilla/rust/issues/2176 https://github.com/mozilla/rust/issues/1277 From graydon at mozilla.com Mon Dec 3 09:59:23 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 03 Dec 2012 09:59:23 -0800 Subject: [rust-dev] updated development policy Message-ID: <50BCE87B.9050101@mozilla.com> Hi, I've updated the github.com/mozilla/rust development policy[1] slightly to reflect a change we agreed to[2] last month as part of the 0.5 cycle: that all substantial incoming changes should go via pull requests and review, and that we hope to have a bot in control of the final integration at some point. Hopefully this doesn't cause any upset. Let us know if you feel it's unnecessarily restrictive. It's mostly just to avoid "broken trunk syndrome". Nobody likes a checkout that doesn't build, especially compilers. We feel like it's time to be stabilizing things, and more-careful review of changes is a natural part of that process. -Graydon [1] https://github.com/mozilla/rust/wiki/Note-development-policy [2] https://github.com/mozilla/rust/wiki/Meeting-weekly-2012-10-09 From elliottslaughter at gmail.com Wed Dec 5 12:02:08 2012 From: elliottslaughter at gmail.com (Elliott Slaughter) Date: Wed, 5 Dec 2012 12:02:08 -0800 Subject: [rust-dev] Uniqueness and Reference Immutability for Safe Parallelism Message-ID: Hi there, I wonder if the Rust borrowing experts here (Niko especially, but maybe others) have seen this paper from MSR? The interesting aspect of this paper is that they can "recover" uniqueness of pointers without needing to limit the scope of (what are effectively) borrows. I'm not actually sufficiently familiar with Rust's borrowing to know if this would be useful to you or not. http://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf -- Elliott Slaughter "Don't worry about what anybody else is going to do. The best way to predict the future is to invent it." - Alan Kay -------------- next part -------------- An HTML attachment was scrubbed... URL: From rust-dev at tomlee.co Wed Dec 5 12:49:20 2012 From: rust-dev at tomlee.co (Tom Lee) Date: Wed, 5 Dec 2012 12:49:20 -0800 Subject: [rust-dev] Managed & owned boxes in Rust Message-ID: Hey folks, Don't mean to spam, but I wrote a blog post last night about memory management in Rust as I understand it, both based on my own experience with the language so far and a few conversations on the #rust channel: http://tomlee.co/2012/12/managed-and-owned-boxes-in-the-rust-programming-language/ If anybody's up for giving it a read over, I'm really keen to know if I'm "getting it" or if I'm still confused :) I think I'm essentially rewording what's in the tutorial, but for some reason I struggled to digest the details for a while. I'm still not sure I understand why the exchange stack is exposed syntactically if you can't directly use it to transfer ownership between tasks (i.e. you still have to resort to pipes etc. which use the exchange stack under the hood). Appreciate any clarification or thoughts! Cheers, Tom -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Wed Dec 5 14:37:59 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 05 Dec 2012 14:37:59 -0800 Subject: [rust-dev] Uniqueness and Reference Immutability for Safe Parallelism In-Reply-To: References: Message-ID: <50BFCCC7.40108@mozilla.com> On 12/05/2012 12:02 PM, Elliott Slaughter wrote: > Hi there, > > I wonder if the Rust borrowing experts here (Niko especially, but > maybe others) have seen this paper from MSR? The interesting aspect of > this paper is that they can "recover" uniqueness of pointers without > needing to limit the scope of (what are effectively) borrows. I'm not > actually sufficiently familiar with Rust's borrowing to know if this > would be useful to you or not. > > http://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf > > Hi Elliott! I found it very interesting myself and think it's worth a read for people interested in or working on Rust. Of course, I don't know the answer to your question. Just saying 'hi'. Regards, Brian From niko at alum.mit.edu Wed Dec 5 18:07:55 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 05 Dec 2012 18:07:55 -0800 Subject: [rust-dev] Managed & owned boxes in Rust In-Reply-To: References: Message-ID: <50BFFDFB.50908@alum.mit.edu> Great article. Regarding why ~[T] and ~T behave somewhat differently, the reason is that the size of [T] is not known to the compiler! It's kind of like how in C, if you have T[3], that's a perfectly fine type, but T[] is sort of a degenerate type that gets converted to T* willy-nilly. The reason is that the compiler can't really manipulate an "unknown number of T's in a row", which is what [T] (Rust) and T[] (C) represent. As an example, it can't put such a value on the stack, since it doesn't know how much stack space to allocate (well, it can't put that on the stack without using alloca() or something similar). Niko Tom Lee wrote: > Hey folks, > > Don't mean to spam, but I wrote a blog post last night about memory > management in Rust as I understand it, both based on my own experience > with the language so far and a few conversations on the #rust channel: > > http://tomlee.co/2012/12/managed-and-owned-boxes-in-the-rust-programming-language/ > > If anybody's up for giving it a read over, I'm really keen to know if > I'm "getting it" or if I'm still confused :) I think I'm essentially > rewording what's in the tutorial, but for some reason I struggled to > digest the details for a while. > > I'm still not sure I understand why the exchange stack is exposed > syntactically if you can't directly use it to transfer ownership > between tasks (i.e. you still have to resort to pipes etc. which use > the exchange stack under the hood). > > Appreciate any clarification or thoughts! > > Cheers, > Tom > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From niko at alum.mit.edu Wed Dec 5 18:20:04 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 05 Dec 2012 18:20:04 -0800 Subject: [rust-dev] Uniqueness and Reference Immutability for Safe Parallelism In-Reply-To: References: Message-ID: <50C000D4.8080600@alum.mit.edu> Yes, I loved that paper and I did find the techniques they used very interesting. For those who did not read the paper, they have a rule in their type system which says approximately: "Given a function that takes one unique value and any number of deeply read-only values as input, the unique value will still be unique after the function even if it is aliased during the function." The reasoning here is that in order to be aliased after the function terminates, the value must have been stored somewhere, but all of the inputs to the function were deeply read-only, so it cannot have been stored anywhere. We could potentially apply similar reasoning, but I'm not sure how much it would buy us, given the borrowed pointer system, which is ultimately more flexible. They of course use this rule to avoid having a borrowed pointer system at all. pcwalton and I have kicked around similar ideas as a replacement for purity. Basically pure functions would be removed, but the borrow checker would consider functions that do not have access to mutable state as being pure. Another place I had thought of using similar reasoning was to build a library for fork-join parallelism [1, 2], where the closures that are being executed in parallel only have access to immutable/read-only state. I think this would be very cool, but there are a few things standing in the way (ref-counted @ boxes, const bounds on closures). But in that last case the reasoning wouldn't be part of the type system but more an argument why the library is sound. Niko [1] https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea [2] https://github.com/RiverTrail/RiverTrail/ Elliott Slaughter wrote: > Hi there, > > I wonder if the Rust borrowing experts here (Niko especially, but > maybe others) have seen this paper from MSR? The interesting aspect of > this paper is that they can "recover" uniqueness of pointers without > needing to limit the scope of (what are effectively) borrows. I'm not > actually sufficiently familiar with Rust's borrowing to know if this > would be useful to you or not. > > http://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf > > -- > Elliott Slaughter > > "Don't worry about what anybody else is going to do. The best way to > predict the future is to invent it." - Alan Kay > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From pwalton at mozilla.com Wed Dec 5 18:24:01 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 05 Dec 2012 18:24:01 -0800 Subject: [rust-dev] Managed & owned boxes in Rust In-Reply-To: <50BFFDFB.50908@alum.mit.edu> References: <50BFFDFB.50908@alum.mit.edu> Message-ID: <50C001C1.7050601@mozilla.com> On 12/5/12 6:07 PM, Niko Matsakis wrote: > Great article. Regarding why ~[T] and ~T behave somewhat differently, > the reason is that the size of [T] is not known to the compiler! It's > kind of like how in C, if you have T[3], that's a perfectly fine type, > but T[] is sort of a degenerate type that gets converted to T* > willy-nilly. The reason is that the compiler can't really manipulate an > "unknown number of T's in a row", which is what [T] (Rust) and T[] (C) > represent. As an example, it can't put such a value on the stack, since > it doesn't know how much stack space to allocate (well, it can't put > that on the stack without using alloca() or something similar). We have talked about special-casing "&*" in the grammar to mean "borrow" regardless of the type of pointer, and we could also conceivably special-case "@*" and "~*", which would make what you wrote work. Basically you would be permitted to dereference &[T]/@[T]/~[T]/&str/@str/~str for the sole purpose of borrowing it or copying its contents into another heap. Patrick From niko at alum.mit.edu Wed Dec 5 19:01:00 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 05 Dec 2012 19:01:00 -0800 Subject: [rust-dev] Managed & owned boxes in Rust In-Reply-To: <50C001C1.7050601@mozilla.com> References: <50BFFDFB.50908@alum.mit.edu> <50C001C1.7050601@mozilla.com> Message-ID: <50C00A6C.2040002@alum.mit.edu> The question of interconverting between @ and ~ etc seems to come up more often than I had expected. I'm not sure if this is simply due to immature library design or whether it will continue to be true going forward. But adding `@*`, `&*`, and `~*` as operators in their own right might be a good way to address the problem, though there will always be other ways that `@T` and `@[T]` are not interchangeable. Niko Patrick Walton wrote: > On 12/5/12 6:07 PM, Niko Matsakis wrote: >> Great article. Regarding why ~[T] and ~T behave somewhat differently, >> the reason is that the size of [T] is not known to the compiler! It's >> kind of like how in C, if you have T[3], that's a perfectly fine type, >> but T[] is sort of a degenerate type that gets converted to T* >> willy-nilly. The reason is that the compiler can't really manipulate an >> "unknown number of T's in a row", which is what [T] (Rust) and T[] (C) >> represent. As an example, it can't put such a value on the stack, since >> it doesn't know how much stack space to allocate (well, it can't put >> that on the stack without using alloca() or something similar). > > We have talked about special-casing "&*" in the grammar to mean > "borrow" regardless of the type of pointer, and we could also > conceivably special-case "@*" and "~*", which would make what you > wrote work. Basically you would be permitted to dereference > &[T]/@[T]/~[T]/&str/@str/~str for the sole purpose of borrowing it or > copying its contents into another heap. > > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From rust-dev at tomlee.co Thu Dec 6 22:49:44 2012 From: rust-dev at tomlee.co (Tom Lee) Date: Thu, 6 Dec 2012 22:49:44 -0800 Subject: [rust-dev] Managed & owned boxes in Rust In-Reply-To: <50BFFDFB.50908@alum.mit.edu> References: <50BFFDFB.50908@alum.mit.edu> Message-ID: Ah awesome. Thanks! I've updated the blog post with your explanation. :) Cheers, Tom On Wed, Dec 5, 2012 at 6:07 PM, Niko Matsakis wrote: > Great article. Regarding why ~[T] and ~T behave somewhat differently, the > reason is that the size of [T] is not known to the compiler! It's kind of > like how in C, if you have T[3], that's a perfectly fine type, but T[] is > sort of a degenerate type that gets converted to T* willy-nilly. The > reason is that the compiler can't really manipulate an "unknown number of > T's in a row", which is what [T] (Rust) and T[] (C) represent. As an > example, it can't put such a value on the stack, since it doesn't know how > much stack space to allocate (well, it can't put that on the stack without > using alloca() or something similar). > > > Niko > > Tom Lee wrote: > >> Hey folks, >> >> Don't mean to spam, but I wrote a blog post last night about memory >> management in Rust as I understand it, both based on my own experience with >> the language so far and a few conversations on the #rust channel: >> >> http://tomlee.co/2012/12/**managed-and-owned-boxes-in-** >> the-rust-programming-language/ >> >> If anybody's up for giving it a read over, I'm really keen to know if I'm >> "getting it" or if I'm still confused :) I think I'm essentially rewording >> what's in the tutorial, but for some reason I struggled to digest the >> details for a while. >> >> I'm still not sure I understand why the exchange stack is exposed >> syntactically if you can't directly use it to transfer ownership between >> tasks (i.e. you still have to resort to pipes etc. which use the exchange >> stack under the hood). >> >> Appreciate any clarification or thoughts! >> >> Cheers, >> Tom >> ______________________________**_________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/**listinfo/rust-dev >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Fri Dec 7 11:58:53 2012 From: stevej at fruitless.org (Steve Jenson) Date: Fri, 7 Dec 2012 11:58:53 -0800 Subject: [rust-dev] Request for feedback Message-ID: Hi rust gurus, Today I ported the purely functional Pairing Heap found in Okasaki's Purely Functional Data Structures to Rust. I was hoping that some of you might take a look at it and give me feedback on where I could be using Rust's idioms better. https://github.com/stevej/rustled/blob/master/pairing_heap.rs The code I wrote is a little longer than Okasaki's example, mostly due to Standard ML's more concise pattern matching. (see page 54 for comparison) Is there a way to do pattern matching in argument lists as in Haskell or SML? Thanks! Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Fri Dec 7 12:54:31 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 07 Dec 2012 12:54:31 -0800 Subject: [rust-dev] Request for feedback In-Reply-To: References: Message-ID: <50C25787.7040702@mozilla.com> On 12/7/12 11:58 AM, Steve Jenson wrote: > Hi rust gurus, > > Today I ported the purely functional Pairing Heap found in Okasaki's > Purely Functional Data Structures to Rust. I was hoping that some of you > might take a look at it and give me feedback on where I could be using > Rust's idioms better. > > https://github.com/stevej/rustled/blob/master/pairing_heap.rs > > The code I wrote is a little longer than Okasaki's example, mostly due > to Standard ML's more concise pattern matching. (see page 54 for > comparison) Is there a way to do pattern matching in argument lists as > in Haskell or SML? Yes, in Rust 0.5 this works. I noticed several things: * Using explicit self (&self) will help make your levels of indirection consistent between `self` and `other` in a few functions. This works better in 0.5 than it does in 0.4. * Braces aren't necessary after the => in patterns unless you want multiple statements. * I'm confused as to why you need an @record as your type in PairingHeap_ (note that records are deprecated in favor of structs). In Rust 0.5 you can say pub enum PairingHeap { Empty, PairingHeapCell { head: E, rest: @List> } } * You can use "self" as the return value in a trait. * In 0.5 you can use #[deriving_eq] for your enum to avoid writing the Eq definition, although I'm not sure that works for struct-like enum variants as in PairingHeapCell above (I should check this). * @ signs are required for pattern matching because pattern matching never dereferences through pointers implicitly. * You have a bunch of "return" expressions in which "return" can be left off. * Some of your if statements could be replaced with pattern guards. * is_empty() could just be: pure fn is_empty(&self) -> bool { *self == Empty_ } Patrick From ben.striegel at gmail.com Fri Dec 7 13:28:19 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Fri, 7 Dec 2012 16:28:19 -0500 Subject: [rust-dev] Request for feedback In-Reply-To: References: Message-ID: Rather than using a function as a constructor, like: pure fn PairingHeap(initial_value: E) -> PairingHeap { ... } let heap = PairingHeap(1); I believe it's more idiomatic to instead use a static method, as in: impl PairingHeap : Eq { static fn new(initial_value: E) -> PairingHeap { ... } ... } let heap = PairingHeap::new(1); Though this probably only works in 0.5. IIRC there are also plans to make Ord inherit from Eq, so all the places where you have `` can eventually be reduced to just ``. -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Sat Dec 8 10:51:31 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 8 Dec 2012 10:51:31 -0800 Subject: [rust-dev] Request for feedback In-Reply-To: <50C25787.7040702@mozilla.com> References: <50C25787.7040702@mozilla.com> Message-ID: On Fri, Dec 7, 2012 at 12:54 PM, Patrick Walton wrote: > On 12/7/12 11:58 AM, Steve Jenson wrote: > >> Hi rust gurus, >> >> Today I ported the purely functional Pairing Heap found in Okasaki's >> Purely Functional Data Structures to Rust. I was hoping that some of you >> might take a look at it and give me feedback on where I could be using >> Rust's idioms better. >> >> https://github.com/stevej/**rustled/blob/master/pairing_**heap.rs >> >> The code I wrote is a little longer than Okasaki's example, mostly due >> to Standard ML's more concise pattern matching. (see page 54 for >> comparison) Is there a way to do pattern matching in argument lists as >> in Haskell or SML? >> > > Yes, in Rust 0.5 this works. > > I noticed several things: > > * Using explicit self (&self) will help make your levels of indirection > consistent between `self` and `other` in a few functions. This works better > in 0.5 than it does in 0.4. > > * Braces aren't necessary after the => in patterns unless you want > multiple statements. > > * I'm confused as to why you need an @record as your type in PairingHeap_ > (note that records are deprecated in favor of structs). I'm still learning how things are done in Rust, I cribbed the @record inside an enum variant from libcore/dlist.rs (see DList). The library code has been a treasure trove of ideas but the downside is that it can be hard to form a coherent picture of how things are meant to be used in the latest version of the language. I switched to PairingHeapCell(E, @List>) which has the benefit of working better with pattern matching. In Rust 0.5 you can say > > pub enum PairingHeap { > Empty, > PairingHeapCell { > head: E, > rest: @List> > } > } > That looks much nicer. * You can use "self" as the return value in a trait. > Oh, that's just what I wanted! > * In 0.5 you can use #[deriving_eq] for your enum to avoid writing the Eq > definition, although I'm not sure that works for struct-like enum variants > as in PairingHeapCell above (I should check this). > > * @ signs are required for pattern matching because pattern matching never > dereferences through pointers implicitly. > > * You have a bunch of "return" expressions in which "return" can be left > off. > Tom pointed out to me that a semi-colon at the end of an expression turns it into a statement which is why I had switched to return statements. I'm glad to see I can leave off both the semi-colon and the return and just use an expression. > * Some of your if statements could be replaced with pattern guards. > > * is_empty() could just be: > > pure fn is_empty(&self) -> bool { *self == Empty_ } > Great, thanks a bunch for all this useful feedback, both to you and Benjamin. Anything that worked with 0.4 I switched to, the rest I'll do after 0.5 lands. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sun Dec 9 22:20:37 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 09 Dec 2012 22:20:37 -0800 Subject: [rust-dev] RFC: Method call syntax as sugar Message-ID: <50C57F35.9090200@mozilla.com> Hi everyone, This has been proposed in some form several times by different people, and I think we could possibly make it work now. It would be a low-priority, backwards-compatible change that would make the language somewhat simpler. Today, there is the distinction between static methods (invokable as functions, but not using dot notation) and non-static methods (invokable using dot notation, but not as functions). This proposal would unify the two. Briefly, suppose that we have a method call like: a.foo(b, ...) Assuming `a` does not have object type, this would be equivalent to this: NAMESPACE::foo(OPERATION(a), b...) Where `NAMESPACE` is one of: 1. The anonymous trait associated with the type of `a`, if `a` is an enum or struct (or coercible to one, or a pointer to one) and has an anonymous trait defined for it. (Note on terminology: the "anonymous trait" is the new name for a "trait-less impl" or "an inherent implementation".) 2. The traits in scope at the call site. And `OPERATION` is one of: 1. One or more dereference operations (`*a`). 2. An address-of operation (`&a`, `&const a`, `&mut a`). 3. A coercion from `~[T]` or `@[T]` to `&[T]` (or the mutable variants to the corresponding mutable slice) followed by an address-of operation. (This is probably the ugliest rule here, but it seems necessary to allow `for [ 1, 2, 3 ].each |x| { ... }` to work.) So, in our example above, if `a` had type `T`, we might transform `a.foo(b)` to `T::foo(&a, b)`. The other change that needs to happen is that what we've been calling "explicit self" needs to become syntactic sugar for an explicit first argument. For instance: struct T { ... } impl T { fn foo(&self, b: int) { ... } } Is exactly the same as: struct T { ... } impl T { /*static*/ fn foo(self: &T, b: int) { ... } } (The keyword `static` is commented out because, while it is necessary today for backwards compatibility, it will not be necessary, and in fact will likely be removed, in the near future.) The most immediate practical benefit of this would be that methods that today must be invoked with dot notation would become useful as arguments to higher-order functions. The other main benefit is that the language design becomes simpler and tidier. We no longer need to think of the method call as a core construct in the language (except for objects) but rather as a form of sugar guided by scope and type information. Again, none of this is particularly high-priority, as I don't think it'll have much immediate practical impact, but I do think it's a simplification worth considering. Thoughts? Patrick From niko at alum.mit.edu Mon Dec 10 08:15:32 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 10 Dec 2012 08:15:32 -0800 Subject: [rust-dev] RFC: Method call syntax as sugar In-Reply-To: <50C57F35.9090200@mozilla.com> References: <50C57F35.9090200@mozilla.com> Message-ID: <50C60AA4.6020005@alum.mit.edu> I am a fan of this idea. Niko Patrick Walton wrote: > Hi everyone, > > This has been proposed in some form several times by different people, > and I think we could possibly make it work now. It would be a > low-priority, backwards-compatible change that would make the language > somewhat simpler. > > Today, there is the distinction between static methods (invokable as > functions, but not using dot notation) and non-static methods > (invokable using dot notation, but not as functions). This proposal > would unify the two. > > Briefly, suppose that we have a method call like: > > a.foo(b, ...) > > Assuming `a` does not have object type, this would be equivalent to this: > > NAMESPACE::foo(OPERATION(a), b...) > > Where `NAMESPACE` is one of: > > 1. The anonymous trait associated with the type of `a`, if `a` is an > enum or struct (or coercible to one, or a pointer to one) and has an > anonymous trait defined for it. (Note on terminology: the "anonymous > trait" is the new name for a "trait-less impl" or "an inherent > implementation".) > > 2. The traits in scope at the call site. > > And `OPERATION` is one of: > > 1. One or more dereference operations (`*a`). > > 2. An address-of operation (`&a`, `&const a`, `&mut a`). > > 3. A coercion from `~[T]` or `@[T]` to `&[T]` (or the mutable variants > to the corresponding mutable slice) followed by an address-of > operation. (This is probably the ugliest rule here, but it seems > necessary to allow `for [ 1, 2, 3 ].each |x| { ... }` to work.) > > So, in our example above, if `a` had type `T`, we might transform > `a.foo(b)` to `T::foo(&a, b)`. > > The other change that needs to happen is that what we've been calling > "explicit self" needs to become syntactic sugar for an explicit first > argument. For instance: > > struct T { ... } > > impl T { > fn foo(&self, b: int) { ... } > } > > Is exactly the same as: > > struct T { ... } > > impl T { > /*static*/ fn foo(self: &T, b: int) { ... } > } > > (The keyword `static` is commented out because, while it is necessary > today for backwards compatibility, it will not be necessary, and in > fact will likely be removed, in the near future.) > > The most immediate practical benefit of this would be that methods > that today must be invoked with dot notation would become useful as > arguments to higher-order functions. The other main benefit is that > the language design becomes simpler and tidier. We no longer need to > think of the method call as a core construct in the language (except > for objects) but rather as a form of sugar guided by scope and type > information. > > Again, none of this is particularly high-priority, as I don't think > it'll have much immediate practical impact, but I do think it's a > simplification worth considering. > > Thoughts? > > Patrick > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From erick.tryzelaar at gmail.com Mon Dec 10 08:25:55 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Mon, 10 Dec 2012 08:25:55 -0800 Subject: [rust-dev] RFC: Method call syntax as sugar In-Reply-To: <50C60AA4.6020005@alum.mit.edu> References: <50C57F35.9090200@mozilla.com> <50C60AA4.6020005@alum.mit.edu> Message-ID: I like this too. If this does unify methods and functions, will this allow us to eventually do a move out of self (#3724)? On Mon, Dec 10, 2012 at 8:15 AM, Niko Matsakis wrote: > I am a fan of this idea. > > > > Niko > > > Patrick Walton wrote: > >> Hi everyone, >> >> This has been proposed in some form several times by different people, >> and I think we could possibly make it work now. It would be a low-priority, >> backwards-compatible change that would make the language somewhat simpler. >> >> Today, there is the distinction between static methods (invokable as >> functions, but not using dot notation) and non-static methods (invokable >> using dot notation, but not as functions). This proposal would unify the >> two. >> >> Briefly, suppose that we have a method call like: >> >> a.foo(b, ...) >> >> Assuming `a` does not have object type, this would be equivalent to this: >> >> NAMESPACE::foo(OPERATION(a), b...) >> >> Where `NAMESPACE` is one of: >> >> 1. The anonymous trait associated with the type of `a`, if `a` is an enum >> or struct (or coercible to one, or a pointer to one) and has an anonymous >> trait defined for it. (Note on terminology: the "anonymous trait" is the >> new name for a "trait-less impl" or "an inherent implementation".) >> >> 2. The traits in scope at the call site. >> >> And `OPERATION` is one of: >> >> 1. One or more dereference operations (`*a`). >> >> 2. An address-of operation (`&a`, `&const a`, `&mut a`). >> >> 3. A coercion from `~[T]` or `@[T]` to `&[T]` (or the mutable variants to >> the corresponding mutable slice) followed by an address-of operation. (This >> is probably the ugliest rule here, but it seems necessary to allow `for [ >> 1, 2, 3 ].each |x| { ... }` to work.) >> >> So, in our example above, if `a` had type `T`, we might transform >> `a.foo(b)` to `T::foo(&a, b)`. >> >> The other change that needs to happen is that what we've been calling >> "explicit self" needs to become syntactic sugar for an explicit first >> argument. For instance: >> >> struct T { ... } >> >> impl T { >> fn foo(&self, b: int) { ... } >> } >> >> Is exactly the same as: >> >> struct T { ... } >> >> impl T { >> /*static*/ fn foo(self: &T, b: int) { ... } >> } >> >> (The keyword `static` is commented out because, while it is necessary >> today for backwards compatibility, it will not be necessary, and in fact >> will likely be removed, in the near future.) >> >> The most immediate practical benefit of this would be that methods that >> today must be invoked with dot notation would become useful as arguments to >> higher-order functions. The other main benefit is that the language design >> becomes simpler and tidier. We no longer need to think of the method call >> as a core construct in the language (except for objects) but rather as a >> form of sugar guided by scope and type information. >> >> Again, none of this is particularly high-priority, as I don't think it'll >> have much immediate practical impact, but I do think it's a simplification >> worth considering. >> >> Thoughts? >> >> Patrick >> ______________________________**_________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/**listinfo/rust-dev >> > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Dec 10 08:26:59 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 10 Dec 2012 08:26:59 -0800 Subject: [rust-dev] RFC: Method call syntax as sugar In-Reply-To: References: <50C57F35.9090200@mozilla.com> <50C60AA4.6020005@alum.mit.edu> Message-ID: <50C60D53.4020900@mozilla.com> On 12/10/12 8:25 AM, Erick Tryzelaar wrote: > I like this too. If this does unify methods and functions, will this > allow us to eventually do a move out of self (#3724)? That's on the agenda either way. Might get to it this week. Patrick From peter.ronnquist at gmail.com Mon Dec 10 14:34:52 2012 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Mon, 10 Dec 2012 23:34:52 +0100 Subject: [rust-dev] problems with adding an element to a ' @' vector. Message-ID: Hi, I am having problems with adding an element to a '@' vector in rust 0.4. The following works fine with a "~" vector but not with a '@' vector: let mut objects_1 : &mut ~[Object] = &mut ~[]; let mut objects_2 : &mut @[Object] = &mut @[]; objects_1.push(Bat_(bat)); objects_2.push(Bat_(bat)); // Line 124 rustc says: banoid.rs:124:24: 124:38 error: attempted access of field `push` on type `&mut @[Object]`, but no field or method with that name was found banoid.rs:124 objects_2.push(Bat_(bat)); It looks like the vector module only implements push(...) for "impl ~[T]: MutableVector". I would appreciate if anyone could comment on this. Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Dec 10 14:38:50 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 10 Dec 2012 14:38:50 -0800 Subject: [rust-dev] problems with adding an element to a ' @' vector. In-Reply-To: References: Message-ID: <50C6647A.5030705@mozilla.com> On 12/10/12 2:34 PM, Peter Ronnquist wrote: > Hi, > > I am having problems with adding an element to a '@' vector in rust 0.4. > > The following works fine with a "~" vector but not with a '@' vector: > > let mut objects_1 : &mut ~[Object] = &mut ~[]; > let mut objects_2 : &mut @[Object] = &mut @[]; > > objects_1.push(Bat_(bat)); > objects_2.push(Bat_(bat)); // Line 124 Appending to an `@` vector would require copying the entire vector, just as with arrays in Java. (We should still probably support `push` on it with this performance caveat, but that's the reason why we don't right now.) If you want to append to a vector, you probably want the `DVec` type, or a ~vector. Patrick From peter.ronnquist at gmail.com Mon Dec 10 15:35:21 2012 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Tue, 11 Dec 2012 00:35:21 +0100 Subject: [rust-dev] problems with adding an element to a ' @' vector. Message-ID: >On 12/10/12 2:34 PM, Peter Ronnquist wrote: >>* Hi,*>>**>>* I am having problems with adding an element to a '@' vector in rust 0.4.*>>**>>* The following works fine with a "~" vector but not with a '@' vector:*>>**>>* let mut objects_1 : &mut ~[Object] = &mut ~[];*>>* let mut objects_2 : &mut @[Object] = &mut @[];*>>**>>* objects_1.push(Bat_(bat));*>>* objects_2.push(Bat_(bat)); // Line 124>* >Appending to an `@` vector would require copying the entire vector, just >as with arrays in Java. (We should still probably support `push` on it >with this performance caveat, but that's the reason why we don't right now.) > >If you want to append to a vector, you probably want the `DVec` type, or >a ~vector. > >Patrick I will try DVec,thank you for the quick reply. Regards Peter -------------- next part -------------- An HTML attachment was scrubbed... URL: From arkaitzj at gmail.com Mon Dec 10 15:49:31 2012 From: arkaitzj at gmail.com (arkaitzj at gmail.com) Date: Mon, 10 Dec 2012 23:49:31 +0000 Subject: [rust-dev] problems with adding an element to a ' @' vector. In-Reply-To: <50C6647A.5030705@mozilla.com> References: <50C6647A.5030705@mozilla.com> Message-ID: Aren't both ~vector and @vector dynamic memory? why can we append to a ~vector but not to a @vector? -- Arkaitz On Mon, Dec 10, 2012 at 10:38 PM, Patrick Walton wrote: > On 12/10/12 2:34 PM, Peter Ronnquist wrote: > >> Hi, >> >> I am having problems with adding an element to a '@' vector in rust 0.4. >> >> The following works fine with a "~" vector but not with a '@' vector: >> >> let mut objects_1 : &mut ~[Object] = &mut ~[]; >> let mut objects_2 : &mut @[Object] = &mut @[]; >> >> objects_1.push(Bat_(bat)); >> objects_2.push(Bat_(bat)); // Line 124 >> > > Appending to an `@` vector would require copying the entire vector, just > as with arrays in Java. (We should still probably support `push` on it with > this performance caveat, but that's the reason why we don't right now.) > > If you want to append to a vector, you probably want the `DVec` type, or a > ~vector. > > Patrick > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Dec 10 16:03:00 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 10 Dec 2012 16:03:00 -0800 Subject: [rust-dev] problems with adding an element to a ' @' vector. In-Reply-To: References: <50C6647A.5030705@mozilla.com> Message-ID: <50C67834.2000005@mozilla.com> On 12/10/12 3:49 PM, arkaitzj at gmail.com wrote: > Aren't both ~vector and @vector dynamic memory? why can we append to a > ~vector but not to a @vector? Because the pointer points to an object that looks like this: ---> [ length ] [ element 1 ] [ element 2 ] [ element 3 ] Now suppose that the allocator didn't leave any room for more elements after it. In general we have to assume this, because we can't leave an infinite amount of space after our arrays. Thus in general appending to a vector requires reallocating the entire vector and move it to some new location in memory. The problem is that, after we do that, we have to update all the pointers to point to the new location. In the case of ~[T] this is easy. There is only one pointer, and it was passed into push(), so we can just update it. With @[T] it's not so easy though. We have no idea at compile time how many pointers there are to the vector, and even at runtime finding all the pointers and updating them would be a quite complex and expensive operation. So we have to copy the array. Patrick From nejucomo at gmail.com Mon Dec 10 16:13:20 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 10 Dec 2012 16:13:20 -0800 Subject: [rust-dev] problems with adding an element to a ' @' vector. In-Reply-To: <50C67834.2000005@mozilla.com> References: <50C6647A.5030705@mozilla.com> <50C67834.2000005@mozilla.com> Message-ID: On Mon, Dec 10, 2012 at 4:03 PM, Patrick Walton wrote: > On 12/10/12 3:49 PM, arkaitzj at gmail.com wrote: >> >> Aren't both ~vector and @vector dynamic memory? why can we append to a >> ~vector but not to a @vector? > > > Because the pointer points to an object that looks like this: > > ---> [ length ] [ element 1 ] [ element 2 ] [ element 3 ] > > Now suppose that the allocator didn't leave any room for more elements after > it. In general we have to assume this, because we can't leave an infinite > amount of space after our arrays. Thus in general appending to a vector > requires reallocating the entire vector and move it to some new location in > memory. The problem is that, after we do that, we have to update all the > pointers to point to the new location. > > In the case of ~[T] this is easy. There is only one pointer, and it was > passed into push(), so we can just update it. With @[T] it's not so easy > though. We have no idea at compile time how many pointers there are to the > vector, and even at runtime finding all the pointers and updating them would > be a quite complex and expensive operation. So we have to copy the array. > I just read Patrick Walton's response, and I wanted to respond with a different take, based on types and mutability instead of performance: Caveat emptor: I'm a semi-lurker on the sidelines of rust, so consider every assertion that follows as suspect. I'd like feedback on the correctness so we can put this kind of clarification in the tutorial: @[T] is a reference to a local-heap, transitively immutable vector where each element is a T. @[mut T] is a reference to a local-heap mutable vector. Each element is a mutable T, and the vector itself can be mutated. As Patrick described, operations like "extend this vector with new elements" might be expensive to implement. ~[mut T] is a reference to a shared-heap mutable vector, which can be mutated along the same lines as @[mut T]. ~[T] is a funny type. Let's think about it by looking at vec::push's signature: pub fn push(v: &mut ~[T], initval: T) { ... } When the caller of push passes a ~[T], the code is allowing push to borrow a *mutable reference*. Because this is the only reference at the time of the call, it is safe to mutate the v parameter. So if such mutable borrowing is possible, then what's the difference between ~[mut T] and ~[T]? I think the answer is probably nothing, or maybe there are weird discrepancies. The similarities are so close, that I believe ~[mut T] is actually being deprecated as a type specification. The distinction between ~[mut T] and ~T also applies to just ~T and ~mut T. > > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev Regards, Nathan Wilcox ps: Nicholas Matsakis describes the rational around mutability and types in some blog posts. These are two relevant posts: http://smallcultfollowing.com/babysteps/blog/2012/05/28/moving-mutability-into-the-type/ http://smallcultfollowing.com/babysteps/blog/2012/07/24/generalizing-inherited-mutability/ I'm not certain if everything proposed there defines the future of rust. The second blog post really helped me understand the motivation for this design. From nejucomo at gmail.com Mon Dec 10 16:27:55 2012 From: nejucomo at gmail.com (Nathan) Date: Mon, 10 Dec 2012 16:27:55 -0800 Subject: [rust-dev] problems with adding an element to a ' @' vector. In-Reply-To: References: <50C6647A.5030705@mozilla.com> <50C67834.2000005@mozilla.com> Message-ID: On Mon, Dec 10, 2012 at 4:13 PM, Nathan wrote: > On Mon, Dec 10, 2012 at 4:03 PM, Patrick Walton wrote: >> On 12/10/12 3:49 PM, arkaitzj at gmail.com wrote: >>> >>> Aren't both ~vector and @vector dynamic memory? why can we append to a >>> ~vector but not to a @vector? >> >> >> Because the pointer points to an object that looks like this: >> >> ---> [ length ] [ element 1 ] [ element 2 ] [ element 3 ] >> >> Now suppose that the allocator didn't leave any room for more elements after >> it. In general we have to assume this, because we can't leave an infinite >> amount of space after our arrays. Thus in general appending to a vector >> requires reallocating the entire vector and move it to some new location in >> memory. The problem is that, after we do that, we have to update all the >> pointers to point to the new location. >> >> In the case of ~[T] this is easy. There is only one pointer, and it was >> passed into push(), so we can just update it. With @[T] it's not so easy >> though. We have no idea at compile time how many pointers there are to the >> vector, and even at runtime finding all the pointers and updating them would >> be a quite complex and expensive operation. So we have to copy the array. >> > > > I just read Patrick Walton's response, and I wanted to respond with a > different take, based on types and mutability instead of performance: > > > Caveat emptor: I'm a semi-lurker on the sidelines of rust, so consider > every assertion that follows as suspect. I'd like feedback on the > correctness so we can put this kind of clarification in the tutorial: > > > @[T] is a reference to a local-heap, transitively immutable vector > where each element is a T. > > @[mut T] is a reference to a local-heap mutable vector. Each element > is a mutable T, and the vector itself can be mutated. As Patrick > described, operations like "extend this vector with new elements" > might be expensive to implement. > > ~[mut T] is a reference to a shared-heap mutable vector, which can be > mutated along the same lines as @[mut T]. > > ~[T] is a funny type. Let's think about it by looking at vec::push's signature: > > pub fn push(v: &mut ~[T], initval: T) { ... } > > When the caller of push passes a ~[T], the code is allowing push to > borrow a *mutable reference*. Because this is the only reference at > the time of the call, it is safe to mutate the v parameter. > > So if such mutable borrowing is possible, then what's the difference > between ~[mut T] and ~[T]? I think the answer is probably nothing, or > maybe there are weird discrepancies. The similarities are so close, > that I believe ~[mut T] is actually being deprecated as a type > specification. > > The distinction between ~[mut T] and ~T also applies to just ~T and ~mut T. > > >> >> Patrick >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev > > Regards, > Nathan Wilcox > > ps: Nicholas Matsakis describes the rational around mutability and > types in some blog posts. These are two relevant posts: > > http://smallcultfollowing.com/babysteps/blog/2012/05/28/moving-mutability-into-the-type/ > > http://smallcultfollowing.com/babysteps/blog/2012/07/24/generalizing-inherited-mutability/ > > I'm not certain if everything proposed there defines the future of > rust. The second blog post really helped me understand the motivation > for this design. Here's another thought: For those of us coming from languages with uniform representation and aliasable references all over the place (think python lists or java Vectors), we may be confused into believing this: type T1 = @[mut T] -is actually something like this: type T2 = @{ mut v: @[mut @T] } Basically I believe T2 is similar to a python list reference, which I believe contains a sequential array of references. Lengthening the array may involve reassigning v to a new address, but in python land all references to the list are a T2 (whose value is an address), not the address in v. Also, in T2 every element is itself a reference, and each of these references may be reassigned. (That's why I have the second "mut". Is this necessary?) Is this comparison a. accurate, and b. helpful to those familiar with java Vectors or python lists? Nathan Wilcox From graydon at mozilla.com Mon Dec 10 18:12:35 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 10 Dec 2012 18:12:35 -0800 Subject: [rust-dev] snapshot process slight change Message-ID: <50C69693.5080400@mozilla.com> Hi, In the process of changing around the AWS infrastructure, I'm moving the snapshots (and eventually docs, distribution files, etc.) from dl.rust-lang.org to static.rust-lang.org. This is ... more or less to ensure no service interruption, while living with the global namespace of amazon S3 buckets. Can't have two buckets named dl.rust-lang.org simultaneously. Yay. Most people should not notice. If you _do_ notice something funny going on (in particular, if you are making snapshots) you should come talk to me on IRC and/or try to use static.rust-lang.org and the new snapshots coming out of the buildbot cluster (which go to static.) rather than those coming out of the rustbot cluster (which go to dl.) If all this sounds mysterious and outside your experience of developing with rust, feel free to ignore! It Should All Just Keep Working. Thanks, -Graydon From abhijeet.gaiha at gmail.com Mon Dec 10 20:10:17 2012 From: abhijeet.gaiha at gmail.com (Abhijeet Gaiha) Date: Tue, 11 Dec 2012 09:40:17 +0530 Subject: [rust-dev] TCP Library Selection Message-ID: Hi, Looks like there are three different libraries for TCP socket functionality: Net_tcp Uv_ll Net::tcp Could someone enlighten me as to which one is the recommended library to use? Thanks very much! Regards, Abhijeet -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Dec 10 21:05:34 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 10 Dec 2012 21:05:34 -0800 Subject: [rust-dev] TCP Library Selection In-Reply-To: References: Message-ID: <50C6BF1E.1050100@mozilla.com> On 12/10/12 8:10 PM, Abhijeet Gaiha wrote: > Hi, > > Looks like there are three different libraries for TCP socket functionality: > Net_tcp > Uv_ll > Net::tcp > > Could someone enlighten me as to which one is the recommended library to > use? > Thanks very much! net_tcp is an alias of net::tcp. Either one is recommended. uv_ll is for direct, unsafe interaction with the libuv event loop. net_tcp is built on top of it internally. It's not recommended for ordinary use. Patrick From lucian.branescu at gmail.com Tue Dec 11 10:24:57 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Tue, 11 Dec 2012 18:24:57 +0000 Subject: [rust-dev] RFC: Method call syntax as sugar In-Reply-To: <50C60AA4.6020005@alum.mit.edu> References: <50C57F35.9090200@mozilla.com> <50C60AA4.6020005@alum.mit.edu> Message-ID: Me too. This looks much like Python's bound methods to me. Would it be possible to use the unsugared syntax as well? I know multimethods aren't planned or necessarily a goal, but this change makes the potentially possible at some point. On 10 December 2012 16:15, Niko Matsakis wrote: > I am a fan of this idea. > > > > Niko > > > Patrick Walton wrote: > >> Hi everyone, >> >> This has been proposed in some form several times by different people, >> and I think we could possibly make it work now. It would be a low-priority, >> backwards-compatible change that would make the language somewhat simpler. >> >> Today, there is the distinction between static methods (invokable as >> functions, but not using dot notation) and non-static methods (invokable >> using dot notation, but not as functions). This proposal would unify the >> two. >> >> Briefly, suppose that we have a method call like: >> >> a.foo(b, ...) >> >> Assuming `a` does not have object type, this would be equivalent to this: >> >> NAMESPACE::foo(OPERATION(a), b...) >> >> Where `NAMESPACE` is one of: >> >> 1. The anonymous trait associated with the type of `a`, if `a` is an enum >> or struct (or coercible to one, or a pointer to one) and has an anonymous >> trait defined for it. (Note on terminology: the "anonymous trait" is the >> new name for a "trait-less impl" or "an inherent implementation".) >> >> 2. The traits in scope at the call site. >> >> And `OPERATION` is one of: >> >> 1. One or more dereference operations (`*a`). >> >> 2. An address-of operation (`&a`, `&const a`, `&mut a`). >> >> 3. A coercion from `~[T]` or `@[T]` to `&[T]` (or the mutable variants to >> the corresponding mutable slice) followed by an address-of operation. (This >> is probably the ugliest rule here, but it seems necessary to allow `for [ >> 1, 2, 3 ].each |x| { ... }` to work.) >> >> So, in our example above, if `a` had type `T`, we might transform >> `a.foo(b)` to `T::foo(&a, b)`. >> >> The other change that needs to happen is that what we've been calling >> "explicit self" needs to become syntactic sugar for an explicit first >> argument. For instance: >> >> struct T { ... } >> >> impl T { >> fn foo(&self, b: int) { ... } >> } >> >> Is exactly the same as: >> >> struct T { ... } >> >> impl T { >> /*static*/ fn foo(self: &T, b: int) { ... } >> } >> >> (The keyword `static` is commented out because, while it is necessary >> today for backwards compatibility, it will not be necessary, and in fact >> will likely be removed, in the near future.) >> >> The most immediate practical benefit of this would be that methods that >> today must be invoked with dot notation would become useful as arguments to >> higher-order functions. The other main benefit is that the language design >> becomes simpler and tidier. We no longer need to think of the method call >> as a core construct in the language (except for objects) but rather as a >> form of sugar guided by scope and type information. >> >> Again, none of this is particularly high-priority, as I don't think it'll >> have much immediate practical impact, but I do think it's a simplification >> worth considering. >> >> Thoughts? >> >> Patrick >> ______________________________**_________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/**listinfo/rust-dev >> > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Tue Dec 11 10:29:00 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 11 Dec 2012 10:29:00 -0800 Subject: [rust-dev] RFC: Method call syntax as sugar In-Reply-To: References: <50C57F35.9090200@mozilla.com> <50C60AA4.6020005@alum.mit.edu> Message-ID: <50C77B6C.5040104@mozilla.com> On 12/11/12 10:24 AM, Lucian Branescu wrote: > Me too. This looks much like Python's bound methods to me. Would it be > possible to use the unsugared syntax as well? Yes. Patrick From rust-dev at tomlee.co Thu Dec 13 00:17:29 2012 From: rust-dev at tomlee.co (Tom Lee) Date: Thu, 13 Dec 2012 00:17:29 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup Message-ID: Hey folks, So turns out I'm still struggling with types a little. This time it's related to mutability & function signatures. Apologies in advance if I screw up terminology. Take the following code, which prints out the unique elements of a vector: extern mod std; use std; fn main() { let mut values = ~["foo", "bar", "foo", "baz"]; do std::sort::quick_sort(values) |x, y| { str::le(*x, *y) } vec::dedup(&mut values); for vec::each(values) |v| { io::println(*v) } } I got this to compile & execute after several false starts, largely via some educated guesses, but I'm still not convinced I fully understand why this appeases the angry statically typed rustc gods. If you good folks could weigh in & help me out it would be much appreciated! 1. let mut values = ~["foo", "bar", "foo", "baz"]; Alright, so this is telling me that 'values' can be reassigned to some other value (i.e. 'values' is a mutable variable). As near as I can tell, because the 'mut' is on the left hand side, this appears to have no impact on the actual type of 'values' except that the variable itself be assigned different values in the local scope. Is that correct? 2. vec::dedup(&mut values); Here is where things get messy to me for all sorts of reasons. Looking at the signature of vec::dedup: http://dl.rust-lang.org/doc/core/vec.html#function-dedup I can see that vec::dedup accepts a mutable, borrowed pointer to a ~[T]. I *think* so that we can dig into the guts of the vector e.g.: let p = p as *mut T // snip ... let _dropped = move *ptr::mut_offset(p, next_to_read); // snip ... *ptr::mut_offset(p, last_written) = move *ptr::mut_offset(p, next_to_read); It looks like the 'move' operations here are directly modifying the contents of the vector by moving data around in the vector. This strikes me as kind of strange. I've allocated an immutable vector on the exchange stack and so make the assumption that the contents of the vector is in effect fixed. Is that assumption cast to the wind as soon as I start working with a mutable, borrowed pointer to that same vector? Or is this just the consequence of a bit of a sleazy optimization, where the function signature makes it *look* like we're going to return the deduped result in 'v' when in fact we're modifying it in-place? I'm not sure there's a coherent question here, but I feel like I'm missing something. Hopefully somebody can understand what I'm rambling on about & shed some light :) Cheers, Tom From hsivonen at iki.fi Thu Dec 13 07:03:11 2012 From: hsivonen at iki.fi (Henri Sivonen) Date: Thu, 13 Dec 2012 17:03:11 +0200 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: <50A58A0D.9050101@mozilla.com> References: <4F8438AF.9090003@alum.mit.edu> <506F2F17.1080703@mozilla.com> <5075C2E9.4060303@mozilla.com> <50A58A0D.9050101@mozilla.com> Message-ID: On Fri, Nov 16, 2012 at 2:34 AM, Brian Anderson wrote: > Tim got labeled break and continue work for 'loop', and I believe for > 'while' as well. It does not yet work on 'for' loops. Here's a test case to > crib off of: > > https://github.com/mozilla/rust/blob/incoming/src/test/run-pass/issue-2216.rs Thanks Tim! I believe I have now the control flow stuff handled. You can see the current output of the translator at http://hsivonen.iki.fi/rust-temp/ . (As you can see, array and object referencing is very much not done.) -- Henri Sivonen hsivonen at iki.fi http://hsivonen.iki.fi/ From pwalton at mozilla.com Thu Dec 13 08:48:59 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 13 Dec 2012 08:48:59 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup In-Reply-To: References: Message-ID: <50CA06FB.2010507@mozilla.com> On 12/13/12 12:17 AM, Tom Lee wrote: > It looks like the 'move' operations here are directly modifying the > contents of the vector by moving data around in the vector. This > strikes me as kind of strange. I've allocated an immutable vector on > the exchange stack and so make the assumption that the contents of the > vector is in effect fixed. Is that assumption cast to the wind as soon > as I start working with a mutable, borrowed pointer to that same > vector? Mutability inherits through ownership in Rust. This line actually declares a mutable vector: let mut values = ~["foo", "bar", "foo", "baz"]; For example, this will compile: values[0] = ~"widget"; The reason why it works this way is so that you can transform values from mutable to immutable and vice versa by simply moving them to a mutable or immutable location. For instance, you could build up a hashtable by mutating it, then place it in an immutable ARC box for many tasks to access in parallel. Patrick From graydon at mozilla.com Thu Dec 13 10:52:23 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 13 Dec 2012 10:52:23 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup In-Reply-To: References: Message-ID: <50CA23E7.50808@mozilla.com> On 12-12-13 12:17 AM, Tom Lee wrote: > It looks like the 'move' operations here are directly modifying the > contents of the vector by moving data around in the vector. This > strikes me as kind of strange. I've allocated an immutable vector on > the exchange stack and so make the assumption that the contents of the > vector is in effect fixed. Is that assumption cast to the wind as soon > as I start working with a mutable, borrowed pointer to that same > vector? More or less. Mutability "inherits" (not sure I love that term, but it's what we're using) along the ownership path to a memory cell. So while -- operationally -- you and I both know that there's a difference between: // "Mutating a cell in a vector" foo[0] = 1 and // "Mutating the vector variable" foo = [1] + foo[1..] The _observational_ difference, on an owned value (i.e. you're the only person who can even see the vector in question) is really just that the latter would do a bunch of allocation, copying and freeing, and wind up pointing to a different place containing exactly the same result. From the perspective of the surrounding code, if it's not actually paying attention to pointer values, those two lines are identical. So after much struggling with library idiom evaluation, we decided that differentiating the two in the type system was more cost than benefit -- it meant we had to have two different paths for a lot of code that differed only in where the obligatory word 'mut' showed up -- and rearranged mutability so that it "inherits" through the ownership path. That brings with it the significant benefit that we can often toggle the mutability from the entire datatype by assigning it to a read-only or read-write owner. > Or is this just the consequence of a bit of a sleazy optimization, > where the function signature makes it *look* like we're going to > return the deduped result in 'v' when in fact we're modifying it > in-place? More or less. One person's sleazy optimization is another person's essential one. De-dupe might be a bit surprising but for a lot of operations (mostly vector operations -- it's the "arbitrary size" type after all), doing them "in place" is the difference between acceptable performance and "ugh, I'll just go do this in C". Our goal is to minimize the number of cases where users feel they have to switch to C "for performance reasons". > I'm not sure there's a coherent question here, but I feel like I'm > missing something. Hopefully somebody can understand what I'm rambling > on about & shed some light :) Rambling questions -- so long as they're not too hostile! -- are good. They point out a need for docs that clarify and make-explicit. We'll need a lot more discussion about this in the docs eventually. Keep pointing out things that don't make sense and we'll try to make sure they're well covered. (And just as likely someone who can explain this better will tell me I'm mis-representing it now, and we'll all learn something!) -Graydon From catamorphism at gmail.com Thu Dec 13 11:11:30 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Thu, 13 Dec 2012 11:11:30 -0800 Subject: [rust-dev] Fall-through in alt, break&continue by label In-Reply-To: References: <4F8438AF.9090003@alum.mit.edu> <506F2F17.1080703@mozilla.com> <5075C2E9.4060303@mozilla.com> <50A58A0D.9050101@mozilla.com> Message-ID: On Thu, Dec 13, 2012 at 7:03 AM, Henri Sivonen wrote: > On Fri, Nov 16, 2012 at 2:34 AM, Brian Anderson wrote: >> Tim got labeled break and continue work for 'loop', and I believe for >> 'while' as well. It does not yet work on 'for' loops. Here's a test case to >> crib off of: >> >> https://github.com/mozilla/rust/blob/incoming/src/test/run-pass/issue-2216.rs > > Thanks Tim! > > I believe I have now the control flow stuff handled. You can see the > current output of the translator at http://hsivonen.iki.fi/rust-temp/ > . (As you can see, array and object referencing is very much not > done.) > That's great! Maybe we don't need `break` out of `for` loops after all... (though there is an open issue on it: https://github.com/mozilla/rust/issues/4131 ) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From stevej at fruitless.org Fri Dec 14 15:51:42 2012 From: stevej at fruitless.org (Steve Jenson) Date: Fri, 14 Dec 2012 15:51:42 -0800 Subject: [rust-dev] purely function red-black tree Message-ID: I recently ported Matt Might's Scala port of Okasaki's purely functional red-black tree to Rust and am looking for some feedback. https://github.com/stevej/rustled/blob/master/red_black_tree.rs I've written this for 0.4 and will update it with other feedback I've received for 0.5 when that lands. Thanks! Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.striegel at gmail.com Sat Dec 15 08:58:40 2012 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Sat, 15 Dec 2012 11:58:40 -0500 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: Would this trait: pub trait Map { pure fn get(k: K) -> @Option; pure fn put(k: K, v: V) -> self; pure fn delete(k: K) -> self; pure fn traverse(f: fn((&K), (@Option))); } be something that ought to live somewhere in the standard library? I also see that you have an impl of this trait in which you also define a bunch of methods that don't belong to the trait. I didn't even know that was possible! If you feel that those methods (blacken, modifiedWith, balance, modWith) don't belong in the Map trait, perhaps split their definitions off into a separate "anonymous" impl for now, and then when 0.5 rolls around you can define a trait that inherits from the Map trait and requires those additional methods. On Fri, Dec 14, 2012 at 6:51 PM, Steve Jenson wrote: > I recently ported Matt Might's Scala port of Okasaki's purely functional > red-black tree to Rust and am looking for some feedback. > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs > > I've written this for 0.4 and will update it with other feedback I've > received for 0.5 when that lands. > > Thanks! > Steve > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sat Dec 15 11:46:18 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 15 Dec 2012 11:46:18 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: <50CCD38A.5070205@mozilla.com> On 12/15/12 8:58 AM, Benjamin Striegel wrote: > Would this trait: > > pub trait Map { > pure fn get(k: K) -> @Option; > pure fn put(k: K, v: V) -> self; > pure fn delete(k: K) -> self; > pure fn traverse(f: fn((&K), (@Option))); > } > > be something that ought to live somewhere in the standard library? Yes, probably, although it shouldn't have @s in it for the benefit of those who don't want to use the garbage collector. > I also see that you have an impl of this trait in which you also define > a bunch of methods that don't belong to the trait. I didn't even know > that was possible! It's not possible in 0.5. Patrick From stevej at fruitless.org Sat Dec 15 16:38:57 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 15 Dec 2012 16:38:57 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CCD38A.5070205@mozilla.com> References: <50CCD38A.5070205@mozilla.com> Message-ID: On Sat, Dec 15, 2012 at 11:46 AM, Patrick Walton wrote: > On 12/15/12 8:58 AM, Benjamin Striegel wrote: > >> Would this trait: >> >> pub trait Map { >> pure fn get(k: K) -> @Option; >> pure fn put(k: K, v: V) -> self; >> pure fn delete(k: K) -> self; >> pure fn traverse(f: fn((&K), (@Option))); >> } >> >> be something that ought to live somewhere in the standard library? >> > > Yes, probably, although it shouldn't have @s in it for the benefit of > those who don't want to use the garbage collector. I could use advice here. Is it possible for me to write a single trait that can be used by both users that want to use managed boxes and people who wish otherwise? IOW, what is the best way to abstract away the @sign in this trait? > I also see that you have an impl of this trait in which you also define >> a bunch of methods that don't belong to the trait. I didn't even know >> that was possible! >> > > It's not possible in 0.5. What is the rationale for making this impossible? Thanks, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Sat Dec 15 16:45:15 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 15 Dec 2012 16:45:15 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: On Sat, Dec 15, 2012 at 8:58 AM, Benjamin Striegel wrote: > Would this trait: > > pub trait Map { > pure fn get(k: K) -> @Option; > pure fn put(k: K, v: V) -> self; > pure fn delete(k: K) -> self; > pure fn traverse(f: fn((&K), (@Option))); > } > > be something that ought to live somewhere in the standard library? > I just renamed it to PersistentMap as a mutable Map would not typically return itself on modification, that's a hallmark of a functional persistent data structure. Also, traverse should probably belong in its own trait. > I also see that you have an impl of this trait in which you also define a > bunch of methods that don't belong to the trait. I didn't even know that > was possible! If you feel that those methods (blacken, modifiedWith, > balance, modWith) don't belong in the Map trait, perhaps split their > definitions off into a separate "anonymous" impl for now, and then when 0.5 > rolls around you can define a trait that inherits from the Map trait and > requires those additional methods. > The private methods are part of the RBMap specialization of the Map trait and are required to reduce boilerplate. They don't belong in a Map trait proper. There's a design choice here about implementations of traits that isn't clear to me. Why restrict any given implementation of them to publicly defined methods? Also, can you show me an example of using an anonymous trait? That seems neat. Best, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From nejucomo at gmail.com Sat Dec 15 19:02:14 2012 From: nejucomo at gmail.com (Nathan) Date: Sat, 15 Dec 2012 19:02:14 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: On Sat, Dec 15, 2012 at 4:45 PM, Steve Jenson wrote: > > > > On Sat, Dec 15, 2012 at 8:58 AM, Benjamin Striegel > wrote: >> >> Would this trait: >> >> pub trait Map { >> pure fn get(k: K) -> @Option; >> pure fn put(k: K, v: V) -> self; >> pure fn delete(k: K) -> self; >> pure fn traverse(f: fn((&K), (@Option))); >> } >> >> be something that ought to live somewhere in the standard library? > > > I just renamed it to PersistentMap as a mutable Map would not typically > return itself on modification, that's a hallmark of a functional persistent > data structure. > > Also, traverse should probably belong in its own trait. > It seems like traversal over keys *and* values is quite useful, because it's common for applications to need both, and doing a separate lookup when a traversal is already "close to" the value would be a shame (changing asymptotic bounds on some applications). There is already an Iter trait. Is traversal simply an Iter over either K or (K, V) ? > >> >> I also see that you have an impl of this trait in which you also define a >> bunch of methods that don't belong to the trait. I didn't even know that was >> possible! If you feel that those methods (blacken, modifiedWith, balance, >> modWith) don't belong in the Map trait, perhaps split their definitions off >> into a separate "anonymous" impl for now, and then when 0.5 rolls around you >> can define a trait that inherits from the Map trait and requires those >> additional methods. > > > The private methods are part of the RBMap specialization of the Map trait > and are required to reduce boilerplate. They don't belong in a Map trait > proper. > The rust way to do this is to have the trait methods call helper functions which are in scope, but not attached to the trait, I believe. > There's a design choice here about implementations of traits that isn't > clear to me. Why restrict any given implementation of them to publicly > defined methods? > >From an abstract type standpoint, all trait impls are *only* the methods declared in the trait. I'll go out on a limb and guess that this also makes the compiler and runtime simpler, because the representation of an impl is the same across all types for a given trait. I'm not sure that's true, just a guess. There's nothing to stop impl methods from calling other functions whose privacy is protected by the module system, so impls can use type-specific helper code. > Also, can you show me an example of using an anonymous trait? That seems > neat. > > Best, > Steve > Regards, Nathan Wilcox > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From pwalton at mozilla.com Sat Dec 15 19:15:50 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 15 Dec 2012 19:15:50 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: <50CCD38A.5070205@mozilla.com> Message-ID: <50CD3CE6.3090903@mozilla.com> On 12/15/12 4:38 PM, Steve Jenson wrote: > I could use advice here. Is it possible for me to write a single trait > that can be used by both users that want to use managed boxes and people > who wish otherwise? IOW, what is the best way to abstract away the @sign > in this trait? It depends on how you implement the red-black tree. With your current implementation, I think you're probably going to have to expose the GC to the user, because that implementation of red-black trees doesn't do manual memory management. There's no real way to abstract over methods of automatic storage reclamation in general (and adding such a mechanism would be pretty complex). If you're OK with having get() copy out the value instead of returning a reference to it, then you could avoid exposing the GC to the user, at the cost of copying every value you put in (which is not as bad as it sounds, since the cost of a copy of an @ box is practically zero). However, if you modify the algorithm to use unique pointers throughout, then your methods like get() can probably return a borrowed pointer instead. > What is the rationale for making this impossible? You can put private methods on the anonymous trait associated with the type instead. Say `impl RBMap { ... }` (i.e. leave off the trait) to put methods in the anonymous trait. Patrick From pwalton at mozilla.com Sat Dec 15 19:20:04 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 15 Dec 2012 19:20:04 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CD3CE6.3090903@mozilla.com> References: <50CCD38A.5070205@mozilla.com> <50CD3CE6.3090903@mozilla.com> Message-ID: <50CD3DE4.6040903@mozilla.com> On 12/15/12 7:15 PM, Patrick Walton wrote: > However, if you modify the algorithm to use unique pointers throughout, > then your methods like get() can probably return a borrowed pointer > instead. To add: For anyone interested in making data structures that don't use the garbage collector, look at the manually-memory-managed map here: https://github.com/mozilla/rust/blob/master/src/libcore/send_map.rs It's probably the best example of a GC-free data structure so far. Patrick From ttaubert at mozilla.com Mon Dec 17 06:42:27 2012 From: ttaubert at mozilla.com (Tim Taubert) Date: Mon, 17 Dec 2012 15:42:27 +0100 Subject: [rust-dev] simple hash map for storing structs that contain ~str and/or ~[] Message-ID: <50CF2F53.3000702@mozilla.com> I'm trying to create simple hash map with an interface like this: trait Map { fn find(&const self, k: &K) -> Option; fn insert(&mut self, k: K, +v: V); fn remove(&mut self, k: &K); } The implementation itself is subject to change and I'll experiment with that a bit. I copied some of the parts from send_map and tried the following: struct Item { v: uint } fn test() { let item = Item {v: 0}; let mut map = LinearMap::new(); map.insert(~"foo", item); assert map.find(&~"foo") == Some(item); } This works fine until I try to store structs that contain a ~str or ~[]. I'm getting this error: warning: instantiating copy type parameter with a not implicitly copyable type assert map.find(&~"foo") == None; Is there anything I can do about this other than using managed boxes? I really don't want to force people to use GC. Thanks, - Tim From pwalton at mozilla.com Mon Dec 17 07:42:42 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 17 Dec 2012 07:42:42 -0800 Subject: [rust-dev] simple hash map for storing structs that contain ~str and/or ~[] In-Reply-To: <50CF2F53.3000702@mozilla.com> References: <50CF2F53.3000702@mozilla.com> Message-ID: <50CF3D72.8030906@mozilla.com> On 12/17/12 6:42 AM, Tim Taubert wrote: > Is there anything I can do about this other than using managed boxes? I > really don't want to force people to use GC. Try returning a reference from find() instead. It's warning you that find() is copying out the data (since it returns V and not &V). Incidentally, that warning may be turned off by default in the future, since it's incompatible with the new Clone trait and can be annoying in cases like this. Patrick From ttaubert at mozilla.com Mon Dec 17 08:11:55 2012 From: ttaubert at mozilla.com (Tim Taubert) Date: Mon, 17 Dec 2012 17:11:55 +0100 Subject: [rust-dev] simple hash map for storing structs that contain ~str and/or ~[] In-Reply-To: <50CF3D72.8030906@mozilla.com> References: <50CF2F53.3000702@mozilla.com> <50CF3D72.8030906@mozilla.com> Message-ID: <50CF444B.3050309@mozilla.com> On 12/17/2012 04:42 PM, Patrick Walton wrote: > On 12/17/12 6:42 AM, Tim Taubert wrote: >> Is there anything I can do about this other than using managed boxes? I >> really don't want to force people to use GC. > > Try returning a reference from find() instead. It's warning you that > find() is copying out the data (since it returns V and not &V). Sorry, to clarify: rustc shows the same warnings for insert() and remove(), so it's not only find(). > Incidentally, that warning may be turned off by default in the future, > since it's incompatible with the new Clone trait and can be annoying in > cases like this. > > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From ttaubert at mozilla.com Mon Dec 17 09:43:07 2012 From: ttaubert at mozilla.com (Tim Taubert) Date: Mon, 17 Dec 2012 18:43:07 +0100 Subject: [rust-dev] simple hash map for storing structs that contain ~str and/or ~[] In-Reply-To: <50CF3D72.8030906@mozilla.com> References: <50CF2F53.3000702@mozilla.com> <50CF3D72.8030906@mozilla.com> Message-ID: <50CF59AB.5050007@mozilla.com> On 12/17/2012 04:42 PM, Patrick Walton wrote: > Try returning a reference from find() instead. It's warning you that > find() is copying out the data (since it returns V and not &V). I read up on borrowed pointers and made find() return &self/V. After turning this: impl LinearMap: Map { into this: impl LinearMap: Map { (removing the Copy trait from V) it all worked as expected. Thanks for leading me into the right direction! - Tim From graydon at mozilla.com Mon Dec 17 11:28:03 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 17 Dec 2012 11:28:03 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: <50CF7243.3000108@mozilla.com> On 12-12-14 03:51 PM, Steve Jenson wrote: > I recently ported Matt Might's Scala port of Okasaki's purely functional > red-black tree to Rust and am looking for some feedback. > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs > > I've written this for 0.4 and will update it with other feedback I've > received for 0.5 when that lands. Nice! The only things I'd ask are: - I can't tell at a glance (sorry, RB-trees are always very subtle) whether this is an LLRB. If not, could you make it so? It's likely just a simplification to a couple of the functions. - Would you mind, once all feedback is incorporated, if we pull this into the stdlib? We have a bug open discussing cleanup and (re)organization of the container types, fwiw, over here: https://github.com/mozilla/rust/issues/3863 Thanks for taking an interest in this. -Graydon From graydon at mozilla.com Mon Dec 17 11:46:56 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 17 Dec 2012 11:46:56 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CF7243.3000108@mozilla.com> References: <50CF7243.3000108@mozilla.com> Message-ID: <50CF76B0.9090609@mozilla.com> On 12-12-17 11:28 AM, Graydon Hoare wrote: > On 12-12-14 03:51 PM, Steve Jenson wrote: >> I recently ported Matt Might's Scala port of Okasaki's purely functional >> red-black tree to Rust and am looking for some feedback. >> >> https://github.com/stevej/rustled/blob/master/red_black_tree.rs >> >> I've written this for 0.4 and will update it with other feedback I've >> received for 0.5 when that lands. > > Nice! The only things I'd ask are: > > - I can't tell at a glance (sorry, RB-trees are always very subtle) > whether this is an LLRB. If not, could you make it so? It's likely > just a simplification to a couple of the functions. Er, except of course, there's also: https://github.com/fawek/llrbt.rs I think we need some better coordination of library development :) -Graydon From erick.tryzelaar at gmail.com Mon Dec 17 13:34:43 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Mon, 17 Dec 2012 13:34:43 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CF76B0.9090609@mozilla.com> References: <50CF7243.3000108@mozilla.com> <50CF76B0.9090609@mozilla.com> Message-ID: Is it important for `traverse` to pass along an option type? Is it important to inform end users that a key has been deleted? Or is that implementation specific? If so, I suggest rewriting `traverse` to something like this (assuming this actually works): impl RBMap: iter::BaseIter<(&K, &V)> { pure fn each(f: fn(&(&K, &V))) { match *self { Leaf => (), Tree(_, left, ref key, maybe_value, right) => { left.traverse(f); match maybe_value { Some(ref value) => f(&(key, value)), None => {}, } right.traverse(f); } } } } On Mon, Dec 17, 2012 at 11:46 AM, Graydon Hoare wrote: > On 12-12-17 11:28 AM, Graydon Hoare wrote: > > On 12-12-14 03:51 PM, Steve Jenson wrote: > >> I recently ported Matt Might's Scala port of Okasaki's purely functional > >> red-black tree to Rust and am looking for some feedback. > >> > >> https://github.com/stevej/rustled/blob/master/red_black_tree.rs > >> > >> I've written this for 0.4 and will update it with other feedback I've > >> received for 0.5 when that lands. > > > > Nice! The only things I'd ask are: > > > > - I can't tell at a glance (sorry, RB-trees are always very subtle) > > whether this is an LLRB. If not, could you make it so? It's likely > > just a simplification to a couple of the functions. > > Er, except of course, there's also: > > https://github.com/fawek/llrbt.rs > > I think we need some better coordination of library development :) > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mneumann at ntecs.de Mon Dec 17 18:03:54 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 18 Dec 2012 03:03:54 +0100 Subject: [rust-dev] Reading shared immutable data Message-ID: <50CFCF0A.3090203@ntecs.de> Hi, We have a very huge immutable data structure that we want to share (read-only) between many light-weight threads. From what I have seen, I should use Arc. Is there any other way to share the data between threads? And when using Arc, can I access the data in parallel by all threads? Best regards, Michael From pwalton at mozilla.com Mon Dec 17 18:11:16 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 17 Dec 2012 18:11:16 -0800 Subject: [rust-dev] Reading shared immutable data In-Reply-To: <50CFCF0A.3090203@ntecs.de> References: <50CFCF0A.3090203@ntecs.de> Message-ID: <50CFD0C4.7070004@mozilla.com> On 12/17/12 6:03 PM, Michael Neumann wrote: > Hi, > > We have a very huge immutable data structure that we want to share > (read-only) between many light-weight threads. > From what I have seen, I should use Arc. Is there any other way to > share the data between threads? You can also: * Use a reader-writer lock (RWLock). This is still safe. * Use unsafe code by casting to an unsafe pointer and sending the unsafe pointer over a channel; do this only as a last resort. * Turn your shared state into a task and have other tasks access the data by sending it messages. This is the classical actor model solution, but usually ARC will be more efficient. > And when using Arc, can I access the data in parallel by all threads? Yes. The only synchronization cost you'll pay is the cost of an atomic CPU instruction whenever you send the data. Patrick From mneumann at ntecs.de Mon Dec 17 18:27:45 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 18 Dec 2012 03:27:45 +0100 Subject: [rust-dev] Reading shared immutable data In-Reply-To: <50CFD0C4.7070004@mozilla.com> References: <50CFCF0A.3090203@ntecs.de> <50CFD0C4.7070004@mozilla.com> Message-ID: <50CFD4A1.3070207@ntecs.de> Am 18.12.2012 03:11, schrieb Patrick Walton: > On 12/17/12 6:03 PM, Michael Neumann wrote: >> Hi, >> >> We have a very huge immutable data structure that we want to share >> (read-only) between many light-weight threads. >> From what I have seen, I should use Arc. Is there any other way to >> share the data between threads? > > You can also: > > * Use a reader-writer lock (RWLock). This is still safe. I will look into this. > * Use unsafe code by casting to an unsafe pointer and sending the > unsafe pointer over a channel; do this only as a last resort. But don't I get into problems with GC when I do that? So I create the data structure heap allocated in one thread, then get an unsafe pointer to it and sent this to all other threads. Of course in the originating thread I need to keep the reference to the data, otherwise the unsafe pointer will point to garbage. > * Turn your shared state into a task and have other tasks access the > data by sending it messages. This is the classical actor model > solution, but usually ARC will be more efficient. But this doesn't allow for parallelism, and that's what we want. > >> And when using Arc, can I access the data in parallel by all threads? > > Yes. The only synchronization cost you'll pay is the cost of an atomic > CPU instruction whenever you send the data. I would just send the data once at thread creation. Hm, I have to play with that. Thanks a lot! Michael From pwalton at mozilla.com Mon Dec 17 18:29:57 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 17 Dec 2012 18:29:57 -0800 Subject: [rust-dev] Reading shared immutable data In-Reply-To: <50CFD4A1.3070207@ntecs.de> References: <50CFCF0A.3090203@ntecs.de> <50CFD0C4.7070004@mozilla.com> <50CFD4A1.3070207@ntecs.de> Message-ID: <50CFD525.1020206@mozilla.com> On 12/17/12 6:27 PM, Michael Neumann wrote: > Am 18.12.2012 03:11, schrieb Patrick Walton: >> * Use unsafe code by casting to an unsafe pointer and sending the >> unsafe pointer over a channel; do this only as a last resort. > > But don't I get into problems with GC when I do that? So I create the > data structure heap allocated in one thread, then get an unsafe pointer > to it and sent > this to all other threads. Of course in the originating thread I need to > keep the reference to the data, otherwise the unsafe pointer will point > to garbage. Right. You'd need to keep a reference to it alive. Patrick From rust-dev at tomlee.co Mon Dec 17 22:53:22 2012 From: rust-dev at tomlee.co (Tom Lee) Date: Mon, 17 Dec 2012 22:53:22 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup In-Reply-To: <50CA23E7.50808@mozilla.com> References: <50CA23E7.50808@mozilla.com> Message-ID: Alright, brace yourself for more stupid questions, Graydon. :) On Thu, Dec 13, 2012 at 10:52 AM, Graydon Hoare wrote: > On 12-12-13 12:17 AM, Tom Lee wrote: > > > It looks like the 'move' operations here are directly modifying the > > contents of the vector by moving data around in the vector. This > > strikes me as kind of strange. I've allocated an immutable vector on > > the exchange stack and so make the assumption that the contents of the > > vector is in effect fixed. Is that assumption cast to the wind as soon > > as I start working with a mutable, borrowed pointer to that same > > vector? > > More or less. Mutability "inherits" (not sure I love that term, but it's > what we're using) along the ownership path to a memory cell. I'm still not sure I grok the terminology, sorry. :) Specifically, I'm not sure what you mean by an "ownership path". Presumably ownership relates to something like this: // 1. x "owns" the memory on the RHS, and so the RHS "inherits" the mutability of x? let mut x = ~[1, 2, 3]; So here, though the data type of the RHS is immutable, the underlying memory is *not* because the "owner" of that memory is mutable? So while -- > operationally -- you and I both know that there's a difference between: > > // "Mutating a cell in a vector" > foo[0] = 1 > > and > > // "Mutating the vector variable" > foo = [1] + foo[1..] > > The _observational_ difference, on an owned value (i.e. you're the only > person who can even see the vector in question) is really just that the > latter would do a bunch of allocation, copying and freeing, and wind up > pointing to a different place containing exactly the same result. From > the perspective of the surrounding code, if it's not actually paying > attention to pointer values, those two lines are identical. So after much struggling with library idiom evaluation, we decided that > differentiating the two in the type system was more cost than benefit -- > it meant we had to have two different paths for a lot of code that > differed only in where the obligatory word 'mut' showed up -- and > rearranged mutability so that it "inherits" through the ownership path. > That brings with it the significant benefit that we can often toggle the > mutability from the entire datatype by assigning it to a read-only or > read-write owner. Are you talking about something like this? // x is the owner & thus the underlying memory is mutable. let mut x = ~[1, 2, 3]; x[0] = 10; // ok, x[0] is reassigned // y is the owner & the underlying memory is now immutable. let y = move x; y[0] = 10; // compile time error: y is immutable. Okay, I think that answers a few of my questions. I'm guessing when you talk about mutability being "inherited" here, you're referring to the fact the type system will enforce things like borrowed pointers? Something like: let mut x = ~[1, 2, 3]; foo(&mut x); // ok: x is mutable, mutable borrowed pointer let mut y = ~[4, 5, 6]; foo(&mut y); // compile error: y is immutable, but we want a mutable borrowed pointer I think that makes sense. The only question I'd have here is why we need to be specific about whether the borrowed pointer is immutable or not? Couldn't it be inferred from the underlying variable? What do we gain by being explicit? > Or is this just the consequence of a bit of a sleazy optimization, > > where the function signature makes it *look* like we're going to > > return the deduped result in 'v' when in fact we're modifying it > > in-place? > > More or less. One person's sleazy optimization is another person's > essential one. De-dupe might be a bit surprising but for a lot of > operations (mostly vector operations -- it's the "arbitrary size" type > after all), doing them "in place" is the difference between acceptable > performance and "ugh, I'll just go do this in C". Our goal is to > minimize the number of cases where users feel they have to switch to C > "for performance reasons". > Argh, I just spent another hour being confused because I was somehow looking at what must have been an old implementation of vec::dedup with a type signature that implied no mutability at all. :) Oh I totally get that, I only say "sleazy" because my understanding of 'mut' at the time was flawed (or I was looking at the wrong code again :)). Makes perfect sense now. > > I'm not sure there's a coherent question here, but I feel like I'm > > missing something. Hopefully somebody can understand what I'm rambling > > on about & shed some light :) > > Rambling questions -- so long as they're not too hostile! -- are good. > They point out a need for docs that clarify and make-explicit. We'll > need a lot more discussion about this in the docs eventually. Keep > pointing out things that don't make sense and we'll try to make sure > they're well covered. > > Will do! I think I understand things a little better, but still got a way to go. Phew. I think this deserves another blog post. :) Thanks for taking the time to respond in detail! Cheers, Tom -------------- next part -------------- An HTML attachment was scrubbed... URL: From mneumann at ntecs.de Tue Dec 18 10:35:51 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 18 Dec 2012 19:35:51 +0100 Subject: [rust-dev] Warn about implicit integer conversion Message-ID: <50D0B787.2040804@ntecs.de> Hi, let a: u8 = 10_000; // this does not fit inside u8! io::println(fmt!("%?", a)); // print "10" I would have expected that rust would warn me if I try to assign an integer constant that doesn't fit into the types range. Maybe there exists a warning that I can enable? Best, Michael From banderson at mozilla.com Tue Dec 18 12:56:04 2012 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 18 Dec 2012 12:56:04 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D0B787.2040804@ntecs.de> References: <50D0B787.2040804@ntecs.de> Message-ID: <50D0D864.1070601@mozilla.com> On 12/18/2012 10:35 AM, Michael Neumann wrote: > Hi, > > let a: u8 = 10_000; // this does not fit inside u8! > io::println(fmt!("%?", a)); // print "10" > > I would have expected that rust would warn me if I try to assign an > integer constant that doesn't fit into the types range. > Maybe there exists a warning that I can enable? > This is a surprise to me too. Perhaps the compiler just doesn't do this check yet. There is a lint check called type_limits that is enabled by default but it only deals with comparison operators. From vince.raiken at gmail.com Tue Dec 18 15:09:11 2012 From: vince.raiken at gmail.com (vince.raiken at gmail.com) Date: Tue, 18 Dec 2012 23:09:11 -0000 Subject: [rust-dev] "constants may only refer to crate-local constants" Any way to get around this? Message-ID: Hi, I'm just poking around a bit with Rust, and I wanted to set a const to float::consts::pi, but the rustc compiler (which is the most recent as of a few/week or two ago) won't let me. Is there any way to do this, or set some kind of global to that value? I didn't see any other kind of global I could create when I read through the 0.5 documentation. And this isn't documented as far as I could see. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Tue Dec 18 15:32:22 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 18 Dec 2012 15:32:22 -0800 Subject: [rust-dev] "constants may only refer to crate-local constants" Any way to get around this? In-Reply-To: References: Message-ID: <50D0FD06.4020803@mozilla.com> On 12/18/12 3:09 PM, vince.raiken at gmail.com wrote: > Hi, I'm just poking around a bit with Rust, and I wanted to set a > const to float::consts::pi, but the rustc compiler (which is the most > recent as of a few/week or two ago) won't let me. Is there any way to do > this, or set some kind of global to that value? I didn't see any other > kind of global I could create when I read through the 0.5 documentation. > And this isn't documented as far as I could see. This should be supported, but it's not yet implemented. We will need to serialize ASTs to do this in the general case and it's a decent amount of work. Patrick From graydon at mozilla.com Tue Dec 18 16:15:52 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 18 Dec 2012 16:15:52 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D0B787.2040804@ntecs.de> References: <50D0B787.2040804@ntecs.de> Message-ID: <50D10738.8050404@mozilla.com> On 12-12-18 10:35 AM, Michael Neumann wrote: > Hi, > > let a: u8 = 10_000; // this does not fit inside u8! > io::println(fmt!("%?", a)); // print "10" > > I would have expected that rust would warn me if I try to assign an > integer constant that doesn't fit into the types range. > Maybe there exists a warning that I can enable? Yikes. Unfortunate. This is another of those cases I dreaded the occurrence of when finally argued into accepting literal-suffix inference. Oh well. I think I know what's going on here, and it's a bit of a sad story, but one we can probably salvage some of. I'll file a bug. Note that if you write "10_000u8" (explicitly giving a suffix), rustc complains as it should. What's happening instead is that you're invoking literal-suffix inference[1] by not providing a suffix, and it's deciding that you mean u8 (correctly), and it's _then_ accepting that in 2s complement arithmetic, overflow of that sort is completely legitimate. Which, you know, it is. If you had written this as: let a : u8 = 100 * 100; I suspect your reaction would have been less shocked. It feels a bit more reasonable, somehow. But it comes down to the same issue: we draw a line about which overflows to check at compile time. I agree it'd be nice to check inferred _literals_. And possibly, now that we have a better-defined notion of an integer constant expression, we might consider _all_ constant-expression overflows to be compile-time errors. I'm not sure if that's wise or not; it'll make abstracting a constant into a function more observable (you'll be toggling overflow checks) and there might be important intentional-overflow expressions that it makes hard, or impossible, to write. We can explore this matter more in the bug itself. Probably lkuper has more to say about this, but for the time being, watch this bug and we'll try to fix it up at least a little more in the next release cycle: https://github.com/mozilla/rust/issues/4220 -Graydon [1] Note: it is _not_ doing size-based type inference. We decided not to do that. It will simply pick either a unique type from its environment (u8) or an under-constrained type variable if it can't figure out which type you mean, and emit an error. From pwalton at mozilla.com Tue Dec 18 16:45:34 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 18 Dec 2012 16:45:34 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup In-Reply-To: References: <50CA23E7.50808@mozilla.com> Message-ID: <50D10E2E.40604@mozilla.com> On 12/17/12 10:53 PM, Tom Lee wrote: > So here, though the data type of the RHS is immutable, the underlying > memory is /not/ because the "owner" of that memory is mutable? More or less, yes. An ownership path is any path that is either flat in memory or involves ~ pointers. Since having two sources of mutability is confusing, we've talked about getting rid of mutability in the type, and making mutability *only* a property of the owner. > Are you talking about something like this? > > // x is the owner & thus the underlying memory is mutable. > let mut x = ~[1, 2, 3]; > x[0] = 10; // ok, x[0] is reassigned > > // y is the owner & the underlying memory is now immutable. > let y = move x; > y[0] = 10; // compile time error: y is immutable. Yes. > Okay, I think that answers a few of my questions. I'm guessing when you > talk about mutability being "inherited" here, you're referring to the > fact the type system will enforce things like borrowed pointers? > Something like: > > let mut x = ~[1, 2, 3]; > foo(&mut x); // ok: x is mutable, mutable borrowed pointer > > let mut y = ~[4, 5, 6]; > foo(&mut y); // compile error: y is immutable, but we > want a mutable borrowed pointer (I assume you mean "let y = ..." here) > I think that makes sense. The only question I'd have here is why we need > to be specific about whether the borrowed pointer is immutable or not? > Couldn't it be inferred from the underlying variable? What do we gain by > being explicit? The kind of pointer you take can actually be different from the mutability of the underlying type. This may sound strange, but it's actually really important for usability, as it allows you to do things like iterate over a mutable hash table with `each`. This code compiles: use core::*; fn main() { let mut mymap = send_map::linear::LinearMap(); mymap.insert(~"foo", ~"bar"); mymap.insert(~"baz", ~"boo"); for mymap.each |&key, &value| { io::println(key + ~"=" + value); } } Notice that the signatures of `LinearMap::each()` and `LinearMap::insert()` are as follows: // Mutable self: fn insert(&mut self, k: K, +v: V) -> bool; // Immutable self: pure fn each(&self, blk: fn(k: &K, v: &V) -> bool); There are several things to note here: * Method call syntax causes the compiler to choose the right type of pointer for the `self` parameter automatically. * `each` takes an immutable pointer. You might ask why it doesn't take a `const` pointer (`const` being the supertype of immutable and mutable), or why there isn't an `each_mut` for mutable hash tables. The reason is that it's unsafe to mutate a hash table while you iterate over it. With a garbage collector, doing so merely results in unpredictable behavior; without one, it results in crashes and segfaults. So we forbid this entirely in Rust with the type system--you cannot mutate a container while you iterate over it. * This raises the question of how it can possibly be safe to take an immutable pointer to something that's mutable. This is where *borrowing* comes in. Taking a pointer to a uniquely owned variable *borrows* that variable--you cannot access the original variable in any way that would cause the pointers you created to become invalid. In this case, since we created an immutable pointer to the hash table with the call to `LinearMap::each()`, we cannot violate the guarantee of immutability by mutating the hash table while that pointer exists. The compiler enforces this. For example, if I try to mutate the hash table inside the loop: use core::*; fn main() { let mut mymap = send_map::linear::LinearMap(); mymap.insert(~"foo", ~"bar"); mymap.insert(~"baz", ~"boo"); for mymap.each |&key, &value| { mymap.insert(~"quux", ~"qux"); } } I get the following error: test2.rs:8:12: 8:17 error: loan of mutable local variable as mutable conflicts with prior loan test2.rs:8 mymap.insert(~"quux", ~"qux"); ^~~~~ test2.rs:7:12: 7:17 note: prior loan as immutable granted here test2.rs:7 for mymap.each |&key, &value| { As you can see, the compiler is complaining that I have an immutable *loan* of the variable `mymap` (where a "loan" basically means "a pointer that I've created"), but I tried to mutate the hash map, violating the rule that immutable pointers must point to immutable data. So, to answer your question: For convenience's sake, the mutability of your pointer may differ from the mutability of the object, as long as the compiler can prove that you aren't doing anything illogical. In general, we don't know which kind of pointer you want, since in many cases a value may legally be pointed to by either an immutable or a mutable pointer. So, with the exception of method calls, we require that you be explicit about mutability of pointers. Patrick From stevej at fruitless.org Tue Dec 18 16:45:54 2012 From: stevej at fruitless.org (Steve Jenson) Date: Tue, 18 Dec 2012 16:45:54 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: Message-ID: On Sat, Dec 15, 2012 at 7:02 PM, Nathan wrote: > > Also, traverse should probably belong in its own trait. > > > > It seems like traversal over keys *and* values is quite useful, > because it's common for applications to need both, and doing a > separate lookup when a traversal is already "close to" the value would > be a shame (changing asymptotic bounds on some applications). > > There is already an Iter trait. Is traversal simply an Iter over > either K or (K, V) ? Thanks, I converted my code to implement BaseIter (although my implementation of size_hint is a little hacky since I'm not tracking the size of the tree) > > The private methods are part of the RBMap specialization of the Map trait > > and are required to reduce boilerplate. They don't belong in a Map trait > > proper. > > > > The rust way to do this is to have the trait methods call helper > functions which are in scope, but not attached to the trait, I > believe. Aha, that helps things click for me. Thanks again, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Tue Dec 18 16:55:35 2012 From: stevej at fruitless.org (Steve Jenson) Date: Tue, 18 Dec 2012 16:55:35 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: <50CF7243.3000108@mozilla.com> <50CF76B0.9090609@mozilla.com> Message-ID: Thanks, I started with this definition and implemented BaseIter for my RBTree. https://github.com/stevej/rustled/commit/85cf4340eb1c0b985e27a48fe2603e6b75ffcb45 size_hint returns None as I'm not tracking size. I think that's ok? It's hard to tell from the BaseIter documentation. On Mon, Dec 17, 2012 at 1:34 PM, Erick Tryzelaar wrote: > Is it important for `traverse` to pass along an option type? Is it > important to inform end users that a key has been deleted? Or is that > implementation specific? If so, I suggest rewriting `traverse` to something > like this (assuming this actually works): > > > > impl RBMap: iter::BaseIter<(&K, &V)> { > > > pure fn each(f: fn(&(&K, &V))) { > match *self { > > > Leaf => (), > Tree(_, left, ref key, maybe_value, right) => { > > > left.traverse(f); > match maybe_value { > > > Some(ref value) => f(&(key, value)), > None => {}, > > > } > right.traverse(f); > } > > > > } > } > } > > > > > On Mon, Dec 17, 2012 at 11:46 AM, Graydon Hoare wrote: > >> On 12-12-17 11:28 AM, Graydon Hoare wrote: >> > On 12-12-14 03:51 PM, Steve Jenson wrote: >> >> I recently ported Matt Might's Scala port of Okasaki's purely >> functional >> >> red-black tree to Rust and am looking for some feedback. >> >> >> >> https://github.com/stevej/rustled/blob/master/red_black_tree.rs >> >> >> >> I've written this for 0.4 and will update it with other feedback I've >> >> received for 0.5 when that lands. >> > >> > Nice! The only things I'd ask are: >> > >> > - I can't tell at a glance (sorry, RB-trees are always very subtle) >> > whether this is an LLRB. If not, could you make it so? It's likely >> > just a simplification to a couple of the functions. >> >> Er, except of course, there's also: >> >> https://github.com/fawek/llrbt.rs >> >> I think we need some better coordination of library development :) >> >> -Graydon >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Tue Dec 18 16:56:57 2012 From: stevej at fruitless.org (Steve Jenson) Date: Tue, 18 Dec 2012 16:56:57 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CF76B0.9090609@mozilla.com> References: <50CF7243.3000108@mozilla.com> <50CF76B0.9090609@mozilla.com> Message-ID: On Mon, Dec 17, 2012 at 11:46 AM, Graydon Hoare wrote: > On 12-12-17 11:28 AM, Graydon Hoare wrote: > > On 12-12-14 03:51 PM, Steve Jenson wrote: > >> I recently ported Matt Might's Scala port of Okasaki's purely functional > >> red-black tree to Rust and am looking for some feedback. > >> > >> https://github.com/stevej/rustled/blob/master/red_black_tree.rs > >> > >> I've written this for 0.4 and will update it with other feedback I've > >> received for 0.5 when that lands. > > > > Nice! The only things I'd ask are: > > > > - I can't tell at a glance (sorry, RB-trees are always very subtle) > > whether this is an LLRB. If not, could you make it so? It's likely > > just a simplification to a couple of the functions. > > Er, except of course, there's also: > > https://github.com/fawek/llrbt.rs > > I think we need some better coordination of library development :) > That's a mutable LLRB tree whereas mine is immutable. Since the language provides optional mutability, is it a goal to have both pure functional and mutable versions of common data structures and traits? -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Tue Dec 18 17:11:46 2012 From: stevej at fruitless.org (Steve Jenson) Date: Tue, 18 Dec 2012 17:11:46 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CF7243.3000108@mozilla.com> References: <50CF7243.3000108@mozilla.com> Message-ID: On Mon, Dec 17, 2012 at 11:28 AM, Graydon Hoare wrote: > > Nice! The only things I'd ask are: > > - I can't tell at a glance (sorry, RB-trees are always very subtle) > whether this is an LLRB. If not, could you make it so? It's likely > just a simplification to a couple of the functions. > I rewrote it to be left-leaning and was able to remove a bunch of code. Thanks for the suggestion. - Would you mind, once all feedback is incorporated, if we pull this > into the stdlib? We have a bug open discussing cleanup and > (re)organization of the container types, fwiw, over here: > > https://github.com/mozilla/rust/issues/3863 > > Thanks for taking an interest in this. > I'd be thrilled for that. Plenty of feedback to accept first, though. -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Tue Dec 18 17:13:27 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 18 Dec 2012 17:13:27 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: <50CF7243.3000108@mozilla.com> <50CF76B0.9090609@mozilla.com> Message-ID: <50D114B7.4070306@mozilla.com> On 12-12-18 04:56 PM, Steve Jenson wrote: > That's a mutable LLRB tree whereas mine is immutable. Ah. Good point. > Since the language provides optional mutability, is it a goal to have > both pure functional and mutable versions of common data structures and > traits? In some sense. Specifically, some number of container types will wind up multiply-implemented between "managed an immutable" and "owned and freezable/thawable", since they have different semantics. Immutable managed types often permit substructure sharing between multiple copies of the type. Owned types, if built carefully, just lose their mutator methods when accessed through an immutable owner[1]. One can go a step further and make a third "managed and mutable" version of a datatype sometimes too, but (we hope) that will be rarer. -Graydon [1] Which is, incidentally, rad. From stevej at fruitless.org Tue Dec 18 17:16:57 2012 From: stevej at fruitless.org (Steve Jenson) Date: Tue, 18 Dec 2012 17:16:57 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: <50CD3CE6.3090903@mozilla.com> References: <50CCD38A.5070205@mozilla.com> <50CD3CE6.3090903@mozilla.com> Message-ID: On Sat, Dec 15, 2012 at 7:15 PM, Patrick Walton wrote: > On 12/15/12 4:38 PM, Steve Jenson wrote: > >> I could use advice here. Is it possible for me to write a single trait >> that can be used by both users that want to use managed boxes and people >> who wish otherwise? IOW, what is the best way to abstract away the @sign >> in this trait? >> > > It depends on how you implement the red-black tree. With your current > implementation, I think you're probably going to have to expose the GC to > the user, because that implementation of red-black trees doesn't do manual > memory management. There's no real way to abstract over methods of > automatic storage reclamation in general (and adding such a mechanism would > be pretty complex). > > If you're OK with having get() copy out the value instead of returning a > reference to it, then you could avoid exposing the GC to the user, at the > cost of copying every value you put in (which is not as bad as it sounds, > since the cost of a copy of an @ box is practically zero). However, if you > modify the algorithm to use unique pointers throughout, then your methods > like get() can probably return a borrowed pointer instead. I'll tackle this within the next few days, once I understand send_map better. Thanks! -------------- next part -------------- An HTML attachment was scrubbed... URL: From lindsey at rockstargirl.org Tue Dec 18 20:17:41 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Tue, 18 Dec 2012 23:17:41 -0500 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D10738.8050404@mozilla.com> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> Message-ID: On Tue, Dec 18, 2012 at 7:15 PM, Graydon Hoare wrote: > On 12-12-18 10:35 AM, Michael Neumann wrote: >> Hi, >> >> let a: u8 = 10_000; // this does not fit inside u8! >> io::println(fmt!("%?", a)); // print "10" >> >> I would have expected that rust would warn me if I try to assign an >> integer constant that doesn't fit into the types range. >> Maybe there exists a warning that I can enable? > > Yikes. Unfortunate. This is another of those cases I dreaded the > occurrence of when finally argued into accepting literal-suffix > inference. Oh well. > > I think I know what's going on here, and it's a bit of a sad story, but > one we can probably salvage some of. I'll file a bug. > > Note that if you write "10_000u8" (explicitly giving a suffix), rustc > complains as it should. > > What's happening instead is that you're invoking literal-suffix > inference[1] by not providing a suffix, and it's deciding that you mean > u8 (correctly), and it's _then_ accepting that in 2s complement > arithmetic, overflow of that sort is completely legitimate. Which, you > know, it is. [...] > > [...] > > Probably lkuper has more to say about this, but for the time being, > watch this bug and we'll try to fix it up at least a little more in the > next release cycle: > > https://github.com/mozilla/rust/issues/4220 Our thinking at the time we implemented suffix inference was that if you went so far as to write the optional type annotation, then you should get the type you asked for, no questions asked, overflows and all. After all, sometimes people do want intentional overflow. But if it's causing nasty surprises, then, yeah, it should be revisited. Lindsey From graydon at mozilla.com Wed Dec 19 15:00:42 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 19 Dec 2012 15:00:42 -0800 Subject: [rust-dev] 0.5 prerelease testing Message-ID: <50D2471A.1010701@mozilla.com> Hi, We've posted a prerelease of 0.5 to: http://static.rust-lang.org/dist/rust-0.5.tar.gz This is _not_ a signed release, just a candidate. We expect to post a couple more before we sign it. At this point we're just curious to get more platform coverage. If you happen to have a some spare cycles to give it a test build and report back, we'd greatly appreciate knowing about any success or failure of "make check" on various systems. (Please report a file sha1sum or such when you reply, as we might update / overwrite that file as we're picking final showstoppers out.) Thanks, -Graydon From giles at thaumas.net Wed Dec 19 17:40:02 2012 From: giles at thaumas.net (Ralph Giles) Date: Wed, 19 Dec 2012 17:40:02 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D2471A.1010701@mozilla.com> References: <50D2471A.1010701@mozilla.com> Message-ID: <50D26C72.7000803@thaumas.net> On 12-12-19 3:00 PM, Graydon Hoare wrote: > We've posted a prerelease of 0.5 to: > > http://static.rust-lang.org/dist/rust-0.5.tar.gz Doesn't build on MacOS 10.5: checking for GCC atomic builtins... no configure: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing ... compile: rt/x86_64-apple-darwin/rust_builtin.o /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::increment(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:35: error: '__sync_add_and_fetch' was not declared in this scope /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::decrement(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:40: error: '__sync_sub_and_fetch' was not declared in this scope /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::read(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:50: error: '__sync_add_and_fetch' was not declared in this scope make: *** [rt/x86_64-apple-darwin/rust.o] Error 1 make: *** Waiting for unfinished jobs.... /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::increment(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:35: error: '__sync_add_and_fetch' was not declared in this scope /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::decrement(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:40: error: '__sync_sub_and_fetch' was not declared in this scope /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static T sync::read(T&) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_task.h:204: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:50: error: '__sync_add_and_fetch' was not declared in this scope /Users/giles/rust-0.5/src/rt/sync/sync.h: In static member function 'static bool sync::compare_and_swap(T*, T, T) [with T = intptr_t]': /Users/giles/rust-0.5/src/rt/rust_builtin.cpp:833: instantiated from here /Users/giles/rust-0.5/src/rt/sync/sync.h:20: error: '__sync_bool_compare_and_swap' was not declared in this scope make: *** [rt/x86_64-apple-darwin/rust_builtin.o] Error 1 $ sw_vers ProductName: Mac OS X ProductVersion: 10.5.8 BuildVersion: 9L31a $ cc --version i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490) -r From banderson at mozilla.com Wed Dec 19 18:01:11 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 19 Dec 2012 18:01:11 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D26C72.7000803@thaumas.net> References: <50D2471A.1010701@mozilla.com> <50D26C72.7000803@thaumas.net> Message-ID: <50D27167.6010602@mozilla.com> On 12/19/2012 05:40 PM, Ralph Giles wrote: > On 12-12-19 3:00 PM, Graydon Hoare wrote: > >> We've posted a prerelease of 0.5 to: >> >> http://static.rust-lang.org/dist/rust-0.5.tar.gz > Doesn't build on MacOS 10.5: Thanks! I've long wondered whether Rust actually works on 10.5, which is the oldest OS X I think we could reasonably support (older versions are missing rpath). Now we know. From catamorphism at gmail.com Wed Dec 19 18:32:19 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Wed, 19 Dec 2012 19:32:19 -0700 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D2471A.1010701@mozilla.com> References: <50D2471A.1010701@mozilla.com> Message-ID: Built for me without a hitch: Mac OS X 10.7.3, uname -a says: Darwin Tims-MacBook-Pro.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 SHA1(rust-0.5.tar.gz)= 7d818abf16c0061278658b8cfc6e0e0859885b5f Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From mozilla at mcpherrin.ca Wed Dec 19 19:32:04 2012 From: mozilla at mcpherrin.ca (Matthew McPherrin) Date: Wed, 19 Dec 2012 22:32:04 -0500 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2471A.1010701@mozilla.com> Message-ID: Everything seems fine here 132bee6d5b24b22f101b446a908cdcdcc89df1a7 rust-0.5.tar.gz make -j64 check says result: ok. 998 passed; 0 failed; 74 ignored Debian Squeeze. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lethaljellybean at gmail.com Wed Dec 19 20:08:55 2012 From: lethaljellybean at gmail.com (Simon Symeonidis) Date: Wed, 19 Dec 2012 23:08:55 -0500 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2471A.1010701@mozilla.com> Message-ID: Greetings, Compiled with no issues. uname -a Linux aeolus 3.6.10-1-ARCH #1 SMP PREEMPT Tue Dec 11 09:40:17 CET 2012 x86_64 GNU/Linux sha1sum rust.tar.gz 7d818abf16c0061278658b8cfc6e0e0859885b5f make check Everything passed Cheers! On Wed, Dec 19, 2012 at 9:32 PM, Tim Chevalier wrote: > Built for me without a hitch: Mac OS X 10.7.3, uname -a says: Darwin > Tims-MacBook-Pro.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 > 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 > > SHA1(rust-0.5.tar.gz)= 7d818abf16c0061278658b8cfc6e0e0859885b5f > > Cheers, > Tim > > -- > Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt > "We know there'd hardly be no one in prison / If rights to food, > clothes, and shelter were given." -- Boots Riley > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From amitsinghai.jain at gmail.com Wed Dec 19 20:50:01 2012 From: amitsinghai.jain at gmail.com (Amit Jain) Date: Thu, 20 Dec 2012 13:50:01 +0900 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2471A.1010701@mozilla.com> Message-ID: Every thing fine on macosx 10.6.8 too. On Dec 20, 2012 1:09 PM, "Simon Symeonidis" wrote: > Greetings, > Compiled with no issues. > > uname -a > Linux aeolus 3.6.10-1-ARCH #1 SMP PREEMPT Tue Dec 11 09:40:17 CET > 2012 x86_64 GNU/Linux > sha1sum rust.tar.gz > 7d818abf16c0061278658b8cfc6e0e0859885b5f > make check > Everything passed > > Cheers! > > On Wed, Dec 19, 2012 at 9:32 PM, Tim Chevalier > wrote: > > Built for me without a hitch: Mac OS X 10.7.3, uname -a says: Darwin > > Tims-MacBook-Pro.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 > > 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 > > > > SHA1(rust-0.5.tar.gz)= 7d818abf16c0061278658b8cfc6e0e0859885b5f > > > > Cheers, > > Tim > > > > -- > > Tim Chevalier * http://catamorphism.org/ * Often in error, never in > doubt > > "We know there'd hardly be no one in prison / If rights to food, > > clothes, and shelter were given." -- Boots Riley > > _______________________________________________ > > Rust-dev mailing list > > Rust-dev at mozilla.org > > https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lindsey at rockstargirl.org Wed Dec 19 20:50:32 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Wed, 19 Dec 2012 23:50:32 -0500 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D27167.6010602@mozilla.com> References: <50D2471A.1010701@mozilla.com> <50D26C72.7000803@thaumas.net> <50D27167.6010602@mozilla.com> Message-ID: On Wed, Dec 19, 2012 at 9:01 PM, Brian Anderson wrote: > On 12/19/2012 05:40 PM, Ralph Giles wrote: >> >> On 12-12-19 3:00 PM, Graydon Hoare wrote: >> >>> We've posted a prerelease of 0.5 to: >>> >>> http://static.rust-lang.org/dist/rust-0.5.tar.gz >> >> Doesn't build on MacOS 10.5: > > > Thanks! I've long wondered whether Rust actually works on 10.5, which is the > oldest OS X I think we could reasonably support (older versions are missing > rpath). Now we know. According to my notes from back then, I apparently did get Rust to build on my 10.5 Mac once, back in March 2011 (the pre-0.1 days). But all my notes say is that I had to use gcc 4.2 rather than 4.0.1 (Xcode should come with both, although 4.0.1 is the default) to get it to work. Unfortunately, I didn't go into any more detail than that, and now I wonder if I was hallucinating. In the time since then, I've tried several times to build it, but something has always gone wrong while building rt -- a missing header file, I think. I've never seen the error that Ralph had, though. Trying it again just now, I got this: /Users/lkuper/rust/src/rt/rust_sched_driver.cpp: In member function 'void rust_sched_driver::start_main_loop()': /Users/lkuper/rust/src/rt/rust_sched_driver.cpp:33: error: 'pthread_setname_np' was not declared in this scope I don't think it should be impossible to make work, but I never had the energy to dig in, and I never supposed that anyone else cared about 10.5 -- apparently, I was wrong about that! :) Lindsey From eric.holk at gmail.com Wed Dec 19 20:54:05 2012 From: eric.holk at gmail.com (Eric Holk) Date: Wed, 19 Dec 2012 20:54:05 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2471A.1010701@mozilla.com> <50D26C72.7000803@thaumas.net> <50D27167.6010602@mozilla.com> Message-ID: <7AC8DAC5-D5C5-4DAE-873F-69E9F6D7C0D5@gmail.com> On Dec 19, 2012, at 8:50 PM, Lindsey Kuper wrote: > /Users/lkuper/rust/src/rt/rust_sched_driver.cpp: In member function > 'void rust_sched_driver::start_main_loop()': > /Users/lkuper/rust/src/rt/rust_sched_driver.cpp:33: error: > 'pthread_setname_np' was not declared in this scope > > I don't think it should be impossible to make work, but I never had > the energy to dig in, and I never supposed that anyone else cared > about 10.5 -- apparently, I was wrong about that! :) I think I added the call to pthread_setname_np. If I recall correctly, there's a POSIX version and a non-portable version. I think Mac has the _np version but not the POSIX version, and Linux et al. have the POSIX version. There should be some #ifdefs around that code that might need tweaked if we want Mac OS 10.5 support. -Eric From giles at thaumas.net Wed Dec 19 21:30:36 2012 From: giles at thaumas.net (Ralph Giles) Date: Wed, 19 Dec 2012 21:30:36 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2471A.1010701@mozilla.com> <50D26C72.7000803@thaumas.net> <50D27167.6010602@mozilla.com> Message-ID: <50D2A27C.9000203@thaumas.net> On 12-12-19 8:50 PM, Lindsey Kuper wrote: > I don't think it should be impossible to make work, but I never had > the energy to dig in, and I never supposed that anyone else cared > about 10.5 -- apparently, I was wrong about that! :) I don't care that much, personally, it's not my primary system. Graydon just asked for broad testing. Apple's focus on supporting only the most recent two releases means it would be nice to have a language tool which worked across a wider range over OS versions though. Cheers, -r From banderson at mozilla.com Wed Dec 19 22:15:02 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 19 Dec 2012 22:15:02 -0800 (PST) Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D2A27C.9000203@thaumas.net> Message-ID: <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> I created an issue for it at least: https://github.com/mozilla/rust/issues/4232 A suitably motivated individual should be able to get this working without too much hassle. Thanks again. ----- Original Message ----- From: "Ralph Giles" To: "Lindsey Kuper" Cc: "Brian Anderson" , rust-dev at mozilla.org Sent: Wednesday, December 19, 2012 9:30:36 PM Subject: Re: [rust-dev] 0.5 prerelease testing On 12-12-19 8:50 PM, Lindsey Kuper wrote: > I don't think it should be impossible to make work, but I never had > the energy to dig in, and I never supposed that anyone else cared > about 10.5 -- apparently, I was wrong about that! :) I don't care that much, personally, it's not my primary system. Graydon just asked for broad testing. Apple's focus on supporting only the most recent two releases means it would be nice to have a language tool which worked across a wider range over OS versions though. Cheers, -r From gaozm55 at gmail.com Thu Dec 20 03:34:13 2012 From: gaozm55 at gmail.com (James Gao) Date: Thu, 20 Dec 2012 19:34:13 +0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> Message-ID: 7d818abf16c0061278658b8cfc6e0e0859885b5f *rust-0.5.tar.gz downloaded stage0 binary: "*rust-0.5\dl\rust-stage0\bin\rustc.exe*" is still failed to execute on *Win8 x64*. Error message is "The application was unable to start correctly (0xc0000142). Click OK to close the application." The crash binary is extracted from the snapshot package "* rust-stage0-2012-12-14-dbc52ce-winnt-i386-92ac1ac09a262a59f40160c9dcf535e1c8ea8e75.tar.bz2 *" On Thu, Dec 20, 2012 at 2:15 PM, Brian Anderson wrote: > I created an issue for it at least: > https://github.com/mozilla/rust/issues/4232 > > A suitably motivated individual should be able to get this working without > too much hassle. > > Thanks again. > > > ----- Original Message ----- > From: "Ralph Giles" > To: "Lindsey Kuper" > Cc: "Brian Anderson" , rust-dev at mozilla.org > Sent: Wednesday, December 19, 2012 9:30:36 PM > Subject: Re: [rust-dev] 0.5 prerelease testing > > On 12-12-19 8:50 PM, Lindsey Kuper wrote: > > > I don't think it should be impossible to make work, but I never had > > the energy to dig in, and I never supposed that anyone else cared > > about 10.5 -- apparently, I was wrong about that! :) > > I don't care that much, personally, it's not my primary system. Graydon > just asked for broad testing. > > Apple's focus on supporting only the most recent two releases means it > would be nice to have a language tool which worked across a wider range > over OS versions though. > > Cheers, > -r > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Dec 20 05:58:12 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 20 Dec 2012 05:58:12 -0800 Subject: [rust-dev] purely function red-black tree In-Reply-To: References: <50CCD38A.5070205@mozilla.com> <50CD3CE6.3090903@mozilla.com> Message-ID: <50D31974.3050602@alum.mit.edu> Hello, While Patrick's advice to avoid @ is good in general, in this case I think it does not apply. Persistent or purely functional data structures basically must use @ so that they can share pointers into their internal nodes. I do hope that when Rust's libraries become more mature we will offer a suite of persistent data structures like this one. I expect that they will make use of distinct traits (it only makes sense, since the operations are different: "addKey(K, V) -> M" instead of "put(K, V)", and so forth). Traditional imperative data structures, though, are best designed to be freezable, as Patrick said. That provides maximum flexibility to their users. A freezable data structure (like the aforementioned send_map) is one that uses only ~ pointers and has no mutability declarations. It instead relies purely on inherited mutability. At some point we need to write a tutorial on freezability, I've got one 25% finished but haven't had time to revisit it. For now I think the best introduction is still this old blog post: http://smallcultfollowing.com/babysteps/blog/2012/07/24/generalizing-inherited-mutability/ Niko Steve Jenson wrote: > On Sat, Dec 15, 2012 at 7:15 PM, Patrick Walton > wrote: > > On 12/15/12 4:38 PM, Steve Jenson wrote: > > I could use advice here. Is it possible for me to write a > single trait > that can be used by both users that want to use managed boxes > and people > who wish otherwise? IOW, what is the best way to abstract away > the @sign > in this trait? > > > It depends on how you implement the red-black tree. With your > current implementation, I think you're probably going to have to > expose the GC to the user, because that implementation of > red-black trees doesn't do manual memory management. There's no > real way to abstract over methods of automatic storage reclamation > in general (and adding such a mechanism would be pretty complex). > > If you're OK with having get() copy out the value instead of > returning a reference to it, then you could avoid exposing the GC > to the user, at the cost of copying every value you put in (which > is not as bad as it sounds, since the cost of a copy of an @ box > is practically zero). However, if you modify the algorithm to use > unique pointers throughout, then your methods like get() can > probably return a borrowed pointer instead. > > > I'll tackle this within the next few days, once I understand send_map > better. Thanks! > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Dec 20 05:59:44 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 20 Dec 2012 05:59:44 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> Message-ID: <50D319D0.2010402@alum.mit.edu> Lindsey Kuper wrote: > Our thinking at the time we implemented suffix inference was that if > you went so far as to write the optional type annotation, then you > should get the type you asked for, no questions asked, overflows and > all. After all, sometimes people do want intentional overflow. But > if it's causing nasty surprises, then, yeah, it should be revisited. I think the best thing would be a simple lint check that visits each literal and checks whether it can fit into the type assigned to it. It will catch many simple cases like this one. Niko From niko at alum.mit.edu Thu Dec 20 06:02:36 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 20 Dec 2012 06:02:36 -0800 Subject: [rust-dev] Vectors, mutability & vec::dedup In-Reply-To: <50CA23E7.50808@mozilla.com> References: <50CA23E7.50808@mozilla.com> Message-ID: <50D31A7C.1020203@alum.mit.edu> Graydon Hoare wrote: > The_observational_ difference, on an owned value (i.e. you're the only > person who can even see the vector in question) is really just that the > latter would do a bunch of allocation, copying and freeing, and wind up > pointing to a different place containing exactly the same result. From > the perspective of the surrounding code, if it's not actually paying > attention to pointer values, those two lines are identical. There is one difference here that's been brought to my attention and is worth pointing out (though I don't think it's a problem). If the objects in question have a destructor, then: x = X { f: x.f + 1 }; and x.f += 1; are observationally different, since the first one will run a destructor but the second will not. I think the bottom line here is that if you have destructors, you should probably use privacy to guard the values of those fields that you do not want modified. One change that one could imagine is adding some sort of qualifier for fields that cannot be modified *directly*, so that the first assignment would be legal but the second not. Note that we still could not say that `f` is *immutable*, because it could still be mutated, but you could call it "const" or something like that. I personally would prefer to see how far we can get using privacy instead just to keep things simple, but this remains a potentially useful addition. Declaring fields that should not be changed after the object is constructed is after all not uncommon. Niko From graydon at mozilla.com Thu Dec 20 09:45:34 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 09:45:34 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D319D0.2010402@alum.mit.edu> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> <50D319D0.2010402@alum.mit.edu> Message-ID: <50D34EBE.7020607@mozilla.com> On 12-12-20 05:59 AM, Niko Matsakis wrote: > > > Lindsey Kuper wrote: >> Our thinking at the time we implemented suffix inference was that if >> you went so far as to write the optional type annotation, then you >> should get the type you asked for, no questions asked, overflows and >> all. After all, sometimes people do want intentional overflow. But >> if it's causing nasty surprises, then, yeah, it should be revisited. > > > I think the best thing would be a simple lint check that visits each > literal and checks whether it can fit into the type assigned to it. It > will catch many simple cases like this one. It is certainly the simplest thing for this case, but I'd also like not to paper it over, but to address the bug its general form. The question of exactly what constant-folding to do in the front/middle ends, and what sorts of conditions during that count as errors, is worth nailing down; it will resurface (already has, I've seen several "surprise" constant / non-constant behaviors, and heard others stubbing toes on same). It's already partly-implemented, and I think there's a plan coming into focus, just needs more care / thought. -Graydon From niko at alum.mit.edu Thu Dec 20 11:17:08 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 20 Dec 2012 11:17:08 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D34EBE.7020607@mozilla.com> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> <50D319D0.2010402@alum.mit.edu> <50D34EBE.7020607@mozilla.com> Message-ID: <50D36434.1080604@alum.mit.edu> This makes sense. What I really meant was: Let's not try to do this checking during the type check itself, as we initially did, but rather as a later lint step. This also allows you to disable it if you know what you're doing and for some reason the code is cleaner as you wrote it. Niko Graydon Hoare wrote: > On 12-12-20 05:59 AM, Niko Matsakis wrote: >> Lindsey Kuper wrote: >>> Our thinking at the time we implemented suffix inference was that if >>> you went so far as to write the optional type annotation, then you >>> should get the type you asked for, no questions asked, overflows and >>> all. After all, sometimes people do want intentional overflow. But >>> if it's causing nasty surprises, then, yeah, it should be revisited. >> I think the best thing would be a simple lint check that visits each >> literal and checks whether it can fit into the type assigned to it. It >> will catch many simple cases like this one. > > It is certainly the simplest thing for this case, but I'd also like not > to paper it over, but to address the bug its general form. The question > of exactly what constant-folding to do in the front/middle ends, and > what sorts of conditions during that count as errors, is worth nailing > down; it will resurface (already has, I've seen several "surprise" > constant / non-constant behaviors, and heard others stubbing toes on same). > > It's already partly-implemented, and I think there's a plan coming into > focus, just needs more care / thought. > > -Graydon > -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Thu Dec 20 11:26:36 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 11:26:36 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D36434.1080604@alum.mit.edu> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> <50D319D0.2010402@alum.mit.edu> <50D34EBE.7020607@mozilla.com> <50D36434.1080604@alum.mit.edu> Message-ID: <50D3666C.8050608@mozilla.com> On 12-12-20 11:17 AM, Niko Matsakis wrote: > This makes sense. What I really meant was: Let's not try to do this > checking during the type check itself, as we initially did, but rather > as a later lint step. This also allows you to disable it if you know > what you're doing and for some reason the code is cleaner as you wrote it. Agreed. It's fine for a lint pass outside the type checker, I just want the semantics clearly defined in terms of a class of constant expressions. (We'll also probably need or want some more general overflow-checking attributes anyways. I've had at least 3 people react in horror when I told them that while divide-by-zero is trapped, integer-overflow _isn't_ trapped by default in my nice "safe language" :) -Graydon From graydon at mozilla.com Thu Dec 20 12:05:09 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 12:05:09 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> Message-ID: <50D36F75.9080404@mozilla.com> On 12-12-20 03:34 AM, James Gao wrote: > 7d818abf16c0061278658b8cfc6e0e0859885b5f *rust-0.5.tar.gz > > downloaded stage0 binary: "*rust-0.5\dl\rust-stage0\bin\rustc.exe*" is > still failed to execute on *Win8 x64*. Error message is "The application > was unable to start correctly (0xc0000142). Click OK to close the > application." > > The crash binary is extracted from the snapshot package > "*rust-stage0-2012-12-14-dbc52ce-winnt-i386-92ac1ac09a262a59f40160c9dcf535e1c8ea8e75.tar.bz2*" Oh dear. That's somewhat worrying. Does anyone else have a windows machine they can test on? Our windows buildhosts are ok but there are a whole lot of flavours of windows out there. -Graydon From jon.mb at proinbox.com Thu Dec 20 12:22:50 2012 From: jon.mb at proinbox.com (John Mija) Date: Thu, 20 Dec 2012 20:22:50 +0000 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D36F75.9080404@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> Message-ID: <50D3739A.2060207@proinbox.com> I've Windows XP under VirtualBox. I'll test it tomorrow. El 20/12/12 20:05, Graydon Hoare escribi?: > On 12-12-20 03:34 AM, James Gao wrote: >> 7d818abf16c0061278658b8cfc6e0e0859885b5f *rust-0.5.tar.gz >> >> downloaded stage0 binary: "*rust-0.5\dl\rust-stage0\bin\rustc.exe*" is >> still failed to execute on *Win8 x64*. Error message is "The application >> was unable to start correctly (0xc0000142). Click OK to close the >> application." >> >> The crash binary is extracted from the snapshot package >> "*rust-stage0-2012-12-14-dbc52ce-winnt-i386-92ac1ac09a262a59f40160c9dcf535e1c8ea8e75.tar.bz2*" > > Oh dear. That's somewhat worrying. Does anyone else have a windows > machine they can test on? Our windows buildhosts are ok but there are a > whole lot of flavours of windows out there. > > -Graydon > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > From niko at alum.mit.edu Thu Dec 20 12:39:33 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 20 Dec 2012 12:39:33 -0800 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D3666C.8050608@mozilla.com> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> <50D319D0.2010402@alum.mit.edu> <50D34EBE.7020607@mozilla.com> <50D36434.1080604@alum.mit.edu> <50D3666C.8050608@mozilla.com> Message-ID: <50D37785.6010804@alum.mit.edu> Graydon Hoare wrote: > (We'll also probably need or want some more general overflow-checking > attributes anyways. I've had at least 3 people react in horror when I > told them that while divide-by-zero is trapped, integer-overflow _isn't_ > trapped by default in my nice "safe language" :) +1 I tend to think that int/uint should trap on overflow, but not i8/i16/i32/i64 etc Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucian.branescu at gmail.com Thu Dec 20 12:56:20 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Thu, 20 Dec 2012 20:56:20 +0000 Subject: [rust-dev] Warn about implicit integer conversion In-Reply-To: <50D3666C.8050608@mozilla.com> References: <50D0B787.2040804@ntecs.de> <50D10738.8050404@mozilla.com> <50D319D0.2010402@alum.mit.edu> <50D34EBE.7020607@mozilla.com> <50D36434.1080604@alum.mit.edu> <50D3666C.8050608@mozilla.com> Message-ID: You can add me to the list of horrified people :) I'd prefer overflow to something one opts into for small portions of their code, much like unsafe blocks. On Dec 20, 2012 7:26 PM, "Graydon Hoare" wrote: > On 12-12-20 11:17 AM, Niko Matsakis wrote: > > This makes sense. What I really meant was: Let's not try to do this > > checking during the type check itself, as we initially did, but rather > > as a later lint step. This also allows you to disable it if you know > > what you're doing and for some reason the code is cleaner as you wrote > it. > > Agreed. It's fine for a lint pass outside the type checker, I just want > the semantics clearly defined in terms of a class of constant expressions. > > (We'll also probably need or want some more general overflow-checking > attributes anyways. I've had at least 3 people react in horror when I > told them that while divide-by-zero is trapped, integer-overflow _isn't_ > trapped by default in my nice "safe language" :) > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Thu Dec 20 13:03:21 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 20 Dec 2012 13:03:21 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D36F75.9080404@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> Message-ID: <50D37D19.6050901@mozilla.com> On 12/20/2012 12:05 PM, Graydon Hoare wrote: > On 12-12-20 03:34 AM, James Gao wrote: >> 7d818abf16c0061278658b8cfc6e0e0859885b5f *rust-0.5.tar.gz >> >> downloaded stage0 binary: "*rust-0.5\dl\rust-stage0\bin\rustc.exe*" is >> still failed to execute on *Win8 x64*. Error message is "The application >> was unable to start correctly (0xc0000142). Click OK to close the >> application." >> >> The crash binary is extracted from the snapshot package >> "*rust-stage0-2012-12-14-dbc52ce-winnt-i386-92ac1ac09a262a59f40160c9dcf535e1c8ea8e75.tar.bz2*" > Oh dear. That's somewhat worrying. Does anyone else have a windows > machine they can test on? Our windows buildhosts are ok but there are a > whole lot of flavours of windows out there. > I'll test on Windows 7 x64 today. What's the status of the windows installers? From graydon at mozilla.com Thu Dec 20 14:53:58 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 14:53:58 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D37D19.6050901@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> Message-ID: <50D39706.5070009@mozilla.com> On 12-12-20 01:03 PM, Brian Anderson wrote: > I'll test on Windows 7 x64 today. What's the status of the windows > installers? Candidate builds are up: http://static.rust-lang.org/dist/rust-0.5-install.exe If windows folks want to give that a spin, much appreciated. -Graydon From sebastian.sylvan at gmail.com Thu Dec 20 15:09:30 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Thu, 20 Dec 2012 15:09:30 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D39706.5070009@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> Message-ID: Works fine for me (installing, building and running hello world), Windows 8 RTM 64 bit. Only after uninstalling 0.4 first though. First time through (assuming the installer would uninstall previous versions) I got complaints about there being multiple core crates. Uninstalling and reinstalling fixed it. On Thu, Dec 20, 2012 at 2:53 PM, Graydon Hoare wrote: > On 12-12-20 01:03 PM, Brian Anderson wrote: > > > I'll test on Windows 7 x64 today. What's the status of the windows > > installers? > > Candidate builds are up: > > http://static.rust-lang.org/dist/rust-0.5-install.exe > > If windows folks want to give that a spin, much appreciated. > > -Graydon > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- Sebastian Sylvan -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Thu Dec 20 15:38:13 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 20 Dec 2012 15:38:13 -0800 (PST) Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D39706.5070009@mozilla.com> Message-ID: <831815026.4530529.1356046693163.JavaMail.root@mozilla.com> ----- Original Message ----- > From: "Graydon Hoare" > To: rust-dev at mozilla.org > Sent: Thursday, December 20, 2012 2:53:58 PM > Subject: Re: [rust-dev] 0.5 prerelease testing > > On 12-12-20 01:03 PM, Brian Anderson wrote: > > > I'll test on Windows 7 x64 today. What's the status of the windows > > installers? > > Candidate builds are up: > > http://static.rust-lang.org/dist/rust-0.5-install.exe > Tested on Windows 7 x64. The installer worked fine. Trying to extract the tarball results in this oddness: ``` $ tar xzf rust-0.5.tar.gz tar: rust-0.5/src/llvm/tools/clang/tools/scan-build/c++-analyzer: Cannot create symlink to `ccc-analyzer': No such file or directory tar: Exiting with failure status due to previous errors ``` From mneumann at ntecs.de Thu Dec 20 17:58:03 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Fri, 21 Dec 2012 02:58:03 +0100 Subject: [rust-dev] net::tcp::TcpSocket slow? Message-ID: <50D3C22B.1040806@ntecs.de> Hi, I am writing a redis client [1] for rust but somehow TCP performance seems to be veery slow. I basically just sent a string to redis and read the response (I commented out parsing). Doing this 10_000 times takes about 4.5 seconds, while doing the same in Ruby takes just 0.7 seconds. Is there anything I can do about it, or is this a known issue? I use methods TcpSocket.{write,read}. Best, Michael [1]: https://github.com/mneumann/rust-redis From banderson at mozilla.com Thu Dec 20 18:12:22 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 20 Dec 2012 18:12:22 -0800 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3C22B.1040806@ntecs.de> References: <50D3C22B.1040806@ntecs.de> Message-ID: <50D3C586.5060007@mozilla.com> On 12/20/2012 05:58 PM, Michael Neumann wrote: > Hi, > > I am writing a redis client [1] for rust but somehow TCP performance > seems to be veery slow. I basically just sent a string > to redis and read the response (I commented out parsing). Doing this > 10_000 times takes about 4.5 seconds, while doing the same in Ruby > takes just 0.7 seconds. > Is there anything I can do about it, or is this a known issue? > Thanks for doing that test. I've been curious. Your results don't suprise me though - std::net needs a lot of work still. I can imagine what some of the problems are. First, stack switching. Switching between Rust and C code has bad performance due to bad branch prediction. Some workloads can spend 10% of their time stalling in the stack switch. Second, working with uv involves sending a bunch of little work units to a dedicated uv task. This is because callbacks from uv into Rust *must not fail* or the runtime will crash. Where typical uv code runs directly in the event callbacks, Rust dispatches most or all of that work to other tasks. This imposes significant context switching and locking overhead. On top of that, all the uv-based code is using the old, lower-performance communication primitives in `core::oldcomm`. These need to be converted to `core::pipes`, but there are some additional blockers preventing it. If anybody wants to improve std::net I can help point out the various issues. From mneumann at ntecs.de Thu Dec 20 18:19:33 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Fri, 21 Dec 2012 03:19:33 +0100 Subject: [rust-dev] Use of moved variable Message-ID: <50D3C735.9050408@ntecs.de> Hi, When I try to compile this program, I get a "Use of moved variable" error. fn fun(b: ~[u8]) { // ... } fn main() { let bytes: ~[u8] = ~[1,2,3]; loop { fun(bytes); } } t.rs:8:13: 8:18 error: use of moved variable: `bytes` t.rs:8 loop { fun(bytes); } ^~~~~ I can avoid the problem, by rewriting the program towards this: fn fun(b: ~[u8]) -> ~[u8] { b } fn main() { let mut bytes: ~[u8] = ~[1,2,3]; loop { bytes = fun(bytes); } } I find this somehow very unintuitive, but of course I understand that the variable "has to move back". Of course I can rewrite function "fun" to use &[u8] as parameter, but I want to call TcpSocket.write, which only accepts a ~ [u8] and I don't know how to convert a &[u8] into a ~[u8]. As & can point to managed boxes I don't think it's possible to convert safely. So is there another "nice" solution to the problem? Maybe I am missing something... Best, Michael From eric.holk at gmail.com Thu Dec 20 18:40:16 2012 From: eric.holk at gmail.com (Eric Holk) Date: Thu, 20 Dec 2012 18:40:16 -0800 Subject: [rust-dev] Use of moved variable In-Reply-To: <50D3C735.9050408@ntecs.de> References: <50D3C735.9050408@ntecs.de> Message-ID: You could use vec::from_slice [1] to convert a slice to a unique vector, although for really performance sensitive work this may not be desirable because it introduces an extra copy. The better option is probably to see if it's possible to rewrite TcpSocket.write to use &[u8] instead. I'd be surprised if there are serious issues; it was probably just written that way before slices were in common usage. -Eric [1]: http://dl.rust-lang.org/doc/core/vec.html#function-from_slice On Dec 20, 2012, at 6:19 PM, Michael Neumann wrote: > Hi, > > When I try to compile this program, I get a "Use of moved variable" error. > > fn fun(b: ~[u8]) { > // ... > } > > fn main() { > let bytes: ~[u8] = ~[1,2,3]; > > loop { fun(bytes); } > } > > t.rs:8:13: 8:18 error: use of moved variable: `bytes` > t.rs:8 loop { fun(bytes); } > ^~~~~ > I can avoid the problem, by rewriting the program towards this: > > fn fun(b: ~[u8]) -> ~[u8] { b } > > fn main() { > let mut bytes: ~[u8] = ~[1,2,3]; > > loop { > bytes = fun(bytes); > } > } > > I find this somehow very unintuitive, but of course I understand that the variable "has to move back". > Of course I can rewrite function "fun" to use &[u8] as parameter, but I want to call TcpSocket.write, which only accepts > a ~ [u8] and I don't know how to convert a &[u8] into a ~[u8]. As & can point to managed boxes I don't think it's possible > to convert safely. > > So is there another "nice" solution to the problem? Maybe I am missing something... > > Best, > > Michael > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From gaozm55 at gmail.com Thu Dec 20 18:57:03 2012 From: gaozm55 at gmail.com (James Gao) Date: Fri, 21 Dec 2012 10:57:03 +0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D39706.5070009@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> Message-ID: The same problem occurs, Win8 Ent RTM 64bit, chcp=936. I found that rustrt.dll depends on some MingW dll, which version of MingW should I use? On Fri, Dec 21, 2012 at 6:53 AM, Graydon Hoare wrote: > Candidate builds are up: > > http://static.rust-lang.org/dist/rust-0.5-install.exe > > If windows folks want to give that a spin, much appreciated. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gaozm55 at gmail.com Thu Dec 20 19:36:16 2012 From: gaozm55 at gmail.com (James Gao) Date: Fri, 21 Dec 2012 11:36:16 +0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D39706.5070009@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> Message-ID: rustc.exe from installer is also crash, here I dump some information from WinDbg: 0:000> g (1d50.c1c): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=43467590 ebx=00000000 ecx=43467590 edx=015b1470 esi=0115840c edi=0028fd24 eip=6fc65c3c esp=0028f8b8 ebp=0028f8bc iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 *** ERROR: Symbol file could not be found. Defaulted to export symbols for d:\MinGW\bin\libstdc++-6.dll - libstdc___6!ZNKSs7_M_dataEv+0xc: 6fc65c3c 8b00 mov eax,dword ptr [eax] ds:002b:43467590=???????? *** ERROR: Symbol file could not be found. Defaulted to export symbols for D:\Rust-0.5\bin\rustllvm.dll - 0:000> lmvm libstdc___6 start end module name 6fc40000 6fd41000 libstdc___6 (export symbols) d:\MinGW\bin\libstdc++-6.dll Loaded symbol image file: d:\MinGW\bin\libstdc++-6.dll Image path: d:\MinGW\bin\libstdc++-6.dll Image name: libstdc++-6.dll Timestamp: Tue Oct 16 20:45:19 2012 (507D56DF) CheckSum: 00105565 ImageSize: 00101000 Translations: 0000.04b0 0000.04e0 0409.04b0 0409.04e0 0:000> k ChildEBP RetAddr WARNING: Stack unwind information not available. Following frames may be wrong. *0028f8bc 6fc65b6f libstdc___6!ZNKSs7_M_dataEv+0xc* 0028f8c8 6fc8aa98 libstdc___6!ZNKSs6_M_repEv+0x13 0028f908 00f28c22 libstdc___6!ZNSs6assignERKSs+0x14 0028f948 00751167 rustllvm!LLVMMoveToNextSection+0x119fe 0028f988 77a42846 rustllvm+0x1167 0028f9a8 77a42893 ntdll!LdrGetProcedureAddressForCaller+0x1ab 0028f9f0 77a49cb3 ntdll!LdrGetProcedureAddressForCaller+0x1f8 0028fa74 77a49b87 ntdll!RtlIsCriticalSectionLockedByThread+0x1019 0028fa94 77a4abce ntdll!RtlIsCriticalSectionLockedByThread+0xeed 0028fabc 77a4abce ntdll!RtlAllocateActivationContextStack+0xa1 0028fae4 77a4e5b4 ntdll!RtlAllocateActivationContextStack+0xa1 0028fc98 77a4d900 ntdll!vsnwprintf+0xf7e 0028fcf0 77a4aa8f ntdll!vsnwprintf+0x2ca 0028fd00 77a4aa59 ntdll!LdrInitializeThunk+0x46 0028fd10 00000000 ntdll!LdrInitializeThunk+0x10 0:000> lm start end module name 00400000 00409000 image00400000 (deferred) 00750000 014a8000 rustllvm (export symbols) D:\Rust-0.5\bin\rustllvm.dll 61900000 61b43000 rustrt (deferred) 63000000 631c8000 core_c3ca5d77d81b46c1_0_5 (deferred) 63c00000 63f3b000 syntax_84efebcb12c867a2_0_5 (deferred) 66b80000 66d37000 std_4782a756585a81_0_5 (deferred) 6a040000 6aa5c000 rustc_c84825241471686d_0_5 (deferred) 6e940000 6e964000 libgcc_s_dw2_1 (deferred) 6fc40000 6fd41000 libstdc___6 (export symbols) d:\MinGW\bin\libstdc++-6.dll 75010000 75061000 bcryptPrimitives (deferred) 75070000 75079000 CRYPTBASE (deferred) 75080000 7509c000 SspiCli (deferred) 750a0000 75151000 msvcrt (deferred) 75320000 753ce000 ADVAPI32 (deferred) 753d0000 76496000 SHELL32 (deferred) 766c0000 766f4000 sechost (deferred) 76760000 76780000 IMM32 (deferred) 76780000 767c0000 SHLWAPI (deferred) 76a50000 76b66000 USER32 (deferred) 76c00000 76cac000 RPCRT4 (deferred) 76cb0000 76d00000 WS2_32 (deferred) 76eb0000 76ec2000 IMAGEHLP (deferred) 77080000 7715d000 MSCTF (deferred) 77160000 77296000 combase (deferred) 772a0000 772a6000 PSAPI (deferred) 77460000 77590000 KERNEL32 (deferred) 77590000 77598000 NSI (deferred) 775c0000 776bd000 GDI32 (deferred) 77880000 77926000 KERNELBASE (deferred) 779f0000 77b47000 ntdll (export symbols) C:\Windows\SYSTEM32\ntdll.dll On Fri, Dec 21, 2012 at 6:53 AM, Graydon Hoare wrote: > Candidate builds are up: > > http://static.rust-lang.org/dist/rust-0.5-install.exe > > If windows folks want to give that a spin, much appreciated. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gaozm55 at gmail.com Thu Dec 20 19:42:43 2012 From: gaozm55 at gmail.com (James Gao) Date: Fri, 21 Dec 2012 11:42:43 +0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> Message-ID: Confirm the problem here is caused by incompatible version of libstdc++-6.dll, I copy an old version libstdc++-6.dll, then rustc works fine. Can we pack the correct libstdc++-6.dll in the installer and stage0 snapshot packages? On Fri, Dec 21, 2012 at 10:57 AM, James Gao wrote: > The same problem occurs, Win8 Ent RTM 64bit, chcp=936. I found that > rustrt.dll depends on some MingW dll, which version of MingW should I use? > > > On Fri, Dec 21, 2012 at 6:53 AM, Graydon Hoare wrote: > >> Candidate builds are up: >> >> http://static.rust-lang.org/dist/rust-0.5-install.exe >> >> If windows folks want to give that a spin, much appreciated. >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Thu Dec 20 19:47:48 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 19:47:48 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> Message-ID: <50D3DBE4.3070809@mozilla.com> On 12-12-20 07:42 PM, James Gao wrote: > Confirm the problem here is caused by incompatible version of > libstdc++-6.dll, I copy an old version libstdc++-6.dll, then rustc works > fine. > > Can we pack the correct libstdc++-6.dll in the installer and stage0 > snapshot packages? I'm afraid not, not presently. We've struggled with this issue in previous releases and attempted to be as explicit as possible about dependencies on mingw in the meantime. We will be fixing it when we can. It bites us every single time. Thanks for your testing though. -Graydon From pwalton at mozilla.com Thu Dec 20 20:17:42 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 20 Dec 2012 23:17:42 -0500 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3C586.5060007@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> Message-ID: <50D3E2E6.4020301@mozilla.com> I just profiled this. Some thoughts: On 12/20/12 9:12 PM, Brian Anderson wrote: > First, stack switching. Switching between Rust and C code has bad > performance due to bad branch prediction. Some workloads can spend > 10% of their time stalling in the stack switch. This didn't seem too high, actually. It should only be ~20,000 stack switches (read and write) if we solve the following issue: > Second, working with uv involves sending a bunch of little work units to > a dedicated uv task. This is because callbacks from uv into Rust *must > not fail* or the runtime will crash. Where typical uv code runs directly > in the event callbacks, Rust dispatches most or all of that work to > other tasks. This imposes significant context switching and locking > overhead. This is actually the problem. If you're using a nonblocking I/O library (libuv) for a fundamentally blocking workload (sending lots of requests to redis and blocking on the response for each one), *and* you're multiplexing userland green threads on top of it, then you're going to get significantly worse performance than you would if you had used a blocking I/O setup. We can make some of the performance differential up by switching uv over to pipes, and maybe we can play dirty tricks like having the main thread spin on the read lock so that we don't have to fall into the scheduler to punt it awake, but I still don't see any way we will make up the 10x performance difference for this particular use case without a fundamental change to the architecture. Work stealing doesn't seem to be a viable solution here since the uv task really needs to be one-task-per-thread. Maybe the best thing is just to make the choice of nonblocking versus blocking I/O a choice that tasks can make on an individual basis. It's a footgun to be sure; if you use blocking I/O you run the risk of starving other tasks on the same scheduler to death, so perhaps we should restrict this mode to schedulers with 1:1 scheduling. But this would be in line with the general principle that we've been following that the choice of 1:1 and M:N scheduling should be left to the user, because there are performance advantages and disadvantages to each mode. Once this sort of switch is implemented, I would suspect the performance differential between Ruby and Rust to be much less. Patrick From gaozm55 at gmail.com Thu Dec 20 20:33:56 2012 From: gaozm55 at gmail.com (James Gao) Date: Fri, 21 Dec 2012 12:33:56 +0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D3DBE4.3070809@mozilla.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> <50D3DBE4.3070809@mozilla.com> Message-ID: OK, how about supply a seperate package for these this run-time dll, or give the exact version/hash for the dll? On Fri, Dec 21, 2012 at 11:47 AM, Graydon Hoare wrote: > On 12-12-20 07:42 PM, James Gao wrote: > > Confirm the problem here is caused by incompatible version of > > libstdc++-6.dll, I copy an old version libstdc++-6.dll, then rustc works > > fine. > > > > Can we pack the correct libstdc++-6.dll in the installer and stage0 > > snapshot packages? > > I'm afraid not, not presently. We've struggled with this issue in > previous releases and attempted to be as explicit as possible about > dependencies on mingw in the meantime. We will be fixing it when we can. > It bites us every single time. > > Thanks for your testing though. > > -Graydon > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Thu Dec 20 20:41:11 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 20 Dec 2012 20:41:11 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D37D19.6050901@mozilla.com> <50D39706.5070009@mozilla.com> <50D3DBE4.3070809@mozilla.com> Message-ID: <50D3E867.3090504@mozilla.com> On 12-12-20 08:33 PM, James Gao wrote: > OK, how about supply a seperate package for these this run-time dll, or > give the exact version/hash for the dll? We point directly to the version of mingw we test with on the website. https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust Longer term we're trying to move away from depending on this, and hope to use clang and/or the windows compiler(s) rather than mingw. We did not manage to allocate resources to fixing it in this cycle, nor to providing any other compensations. I'm sorry, hopefully this will improve in future releases. -Graydon From banderson at mozilla.com Thu Dec 20 21:17:49 2012 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 20 Dec 2012 21:17:49 -0800 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3E2E6.4020301@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> Message-ID: <50D3F0FD.6080208@mozilla.com> On 12/20/2012 08:17 PM, Patrick Walton wrote: > I just profiled this. Some thoughts: Thanks. > > On 12/20/12 9:12 PM, Brian Anderson wrote: >> First, stack switching. Switching between Rust and C code has bad >> performance due to bad branch prediction. Some workloads can spend >> 10% of their time stalling in the stack switch. > > This didn't seem too high, actually. It should only be ~20,000 stack > switches (read and write) if we solve the following issue: > >> Second, working with uv involves sending a bunch of little work units to >> a dedicated uv task. This is because callbacks from uv into Rust *must >> not fail* or the runtime will crash. Where typical uv code runs directly >> in the event callbacks, Rust dispatches most or all of that work to >> other tasks. This imposes significant context switching and locking >> overhead. > > This is actually the problem. If you're using a nonblocking I/O > library (libuv) for a fundamentally blocking workload (sending lots of > requests to redis and blocking on the response for each one), *and* > you're multiplexing userland green threads on top of it, then you're > going to get significantly worse performance than you would if you had > used a blocking I/O setup. We can make some of the performance > differential up by switching uv over to pipes, and maybe we can play > dirty tricks like having the main thread spin on the read lock so that > we don't have to fall into the scheduler to punt it awake, but I still > don't see any way we will make up the 10x performance difference for > this particular use case without a fundamental change to the > architecture. Work stealing doesn't seem to be a viable solution here > since the uv task really needs to be one-task-per-thread. I'm still optimistic, though I agree that the throughput of using pipes and tasks to create synchronous interfaces on top of uv must be lower than if using uv as intended, particularly if you multiplex data across many tasks. In the best case you essentially just want to be able to quickly transfer large buffers from the client task to the I/O task, or the other way. In a dual-core setup pipes should be able to do that very fast, rarely yielding to the (Rust) scheduler. I'm assuming that we can do that without copying buffers to and from the uv loop, and I also assume that the current implementation requires copies. You'll still pay the cost of dealing with the uv async callback (don't recall exactly what it's called but it's how you wake up the loop from another thread), so it's going to be slower, but as the general purpose I/O subsystem I think it will be the best choice because it doesn't block your task, so you can write task oriented code and it will do the right thing. > Maybe the best thing is just to make the choice of nonblocking versus > blocking I/O a choice that tasks can make on an individual basis. It's > a footgun to be sure; if you use blocking I/O you run the risk of > starving other tasks on the same scheduler to death, so perhaps we > should restrict this mode to schedulers with 1:1 scheduling. But this > would be in line with the general principle that we've been following > that the choice of 1:1 and M:N scheduling should be left to the user, > because there are performance advantages and disadvantages to each mode. I agree that we need multiple strategies, ideally that implement common traits. In order to have competitive performance in high-throughput applications we need to use uv as intended and run our code inside the uv callbacks. Right now there is no high-level API for this, so I think that when we revisit this stuff one of the first things we need to do is add those modules and get them solid and fast. Then rebuild everything on top of that. -Brian From jon.mb at proinbox.com Fri Dec 21 01:33:26 2012 From: jon.mb at proinbox.com (John Mija) Date: Fri, 21 Dec 2012 09:33:26 +0000 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D3739A.2060207@proinbox.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D3739A.2060207@proinbox.com> Message-ID: <50D42CE6.3040401@proinbox.com> I've installed Windows XP 64bits (under VirtualBox), and I'm using the GCC suite from TDM because its 64-bits version works ok. http://tdm-gcc.tdragon.net/download I could install correctly the Rust through its installer, but when I run "rustc" it shows an error due it's unable to locate the library "libgcc_s_dw2-1.dll" El 20/12/12 20:22, John Mija escribi?: > I've Windows XP under VirtualBox. I'll test it tomorrow. > > El 20/12/12 20:05, Graydon Hoare escribi?: >> On 12-12-20 03:34 AM, James Gao wrote: >>> 7d818abf16c0061278658b8cfc6e0e0859885b5f *rust-0.5.tar.gz >>> >>> downloaded stage0 binary: "*rust-0.5\dl\rust-stage0\bin\rustc.exe*" is >>> still failed to execute on *Win8 x64*. Error message is "The application >>> was unable to start correctly (0xc0000142). Click OK to close the >>> application." >>> >>> The crash binary is extracted from the snapshot package >>> "*rust-stage0-2012-12-14-dbc52ce-winnt-i386-92ac1ac09a262a59f40160c9dcf535e1c8ea8e75.tar.bz2*" >>> >> >> Oh dear. That's somewhat worrying. Does anyone else have a windows >> machine they can test on? Our windows buildhosts are ok but there are a >> whole lot of flavours of windows out there. >> >> -Graydon >> >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > From graydon at mozilla.com Fri Dec 21 05:40:27 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 21 Dec 2012 05:40:27 -0800 Subject: [rust-dev] 0.5 prerelease testing In-Reply-To: <50D42CE6.3040401@proinbox.com> References: <50D2A27C.9000203@thaumas.net> <173077141.4430086.1355984102868.JavaMail.root@mozilla.com> <50D36F75.9080404@mozilla.com> <50D3739A.2060207@proinbox.com> <50D42CE6.3040401@proinbox.com> Message-ID: <50D466CB.7020303@mozilla.com> On 21/12/2012 1:33 AM, John Mija wrote: > I've installed Windows XP 64bits (under VirtualBox), and I'm using the > GCC suite from TDM because its 64-bits version works ok. > > http://tdm-gcc.tdragon.net/download > > I could install correctly the Rust through its installer, but when I run > "rustc" it shows an error due it's unable to locate the library > "libgcc_s_dw2-1.dll" Yes. Unfortunately this is the same issue everyone runs into on windows. We only support one very specific version of mingw. It really doesn't work with other ones. We're trying to fix this, as I mentioned elsewhere in the thread, but it's not fixed this time. Sorry. Thanks for your testing. -Graydon From graydon at mozilla.com Fri Dec 21 07:45:23 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 21 Dec 2012 07:45:23 -0800 Subject: [rust-dev] Rust 0.5 released Message-ID: <50D48413.7080503@mozilla.com> Mozilla and the Rust community are pleased to announce version 0.5 of the Rust compiler and associated tools. The brief release notes are included in this announcement, and there is further explanation in the detailed release [notes] on the wiki. Documentation and all the links in this email are available on the [website]. As usual, version 0.5 should be considered an alpha release, suitable for early adopters and language enthusiasts. Please file [bugs]. [notes]: https://github.com/mozilla/rust/wiki/Doc-detailed-release-notes [website]: http://www.rust-lang.org [bugs]: http://github.com/mozilla/rust/issues This release is available as both a tarball and a Windows installer: * http://dl.rust-lang.org/dist/rust-0.5.tar.gz http://dl.rust-lang.org/dist/rust-0.5.tar.gz.asc SHA256 (of .tar.gz): d326d22707f0562d669c11efbc33ae812ddbf76ab78f07087fc5beb095a8928a * http://dl.rust-lang.org/dist/rust-0.5-install.exe http://dl.rust-lang.org/dist/rust-0.5-install.exe.asc SHA256 (of .exe): df1c565de6e6eed1d76243b24c0cf25de3b170f8d48834254f3f5105f52b3099 Note that the GPG signing key from last year has expired due to a short expiry window. The key has been updated on the website. The new key URL, ID and fingerprint are: http://www.rust-lang.org/rust-key.gpg.ascii 4096R/5B1E4B9A 2012-12-21 032D 6808 57D4 1FF8 A0E3 2AC5 F21A 43A7 5B1E 4B9A Rust Language (Tag and Release Signing Key) Regrettably, installing 0.5 over 0.4 will not work as expected. Please uninstall first. Note that the Windows installer still requires a somewhat specific version of MinGW and Msys to operate; recent builds of MinGW provide versions of GCC that are incompatible. Rust presently builds and tests with release 20110802, containing GCC 4.5. [Details] can be found on the wiki. [details]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust Thanks to everybody who has contributed[1]. Regards, The Rust Team Version 0.5 (December 2012) --------------------------- * ~900 changes, numerous bugfixes * Syntax changes * Removed `<-` move operator * Completed transition from `#fmt` extension syntax to `fmt!` * Removed old fixed length vector syntax - `[T]/N` * New token quasi-quoters, `quote_tokens!`, `quote_expr!`, etc. * Macros may now expand to items and statements * `a.b()` is always parsed as a method call, never as a field * `Eq` and `IterBytes` implementations automatically generated with `#[deriving_eq]` and `#[deriving_iter_bytes]` respectively * Removed the special crate language for `.rc` files * Function arguments may consist of any irrefutable pattern * Semantic changes * `&` and `~` pointers may point to objects * Tuple structs - `struct Foo(Bar, Baz)`. Replace newtype enums. * Enum variants may be structs * Destructors can be added to all nominal types via Drop trait * Structs and nullary enum variants may be constants * Values that cannot be implicitly copied are automatically moved without writing `move` explicitly * `&T` may now be coerced to `*T` * Coercions happen in `let` statements as well as function calls * `use` statements now take crate-relative paths * The module and type namespaces have been merged so that static method names can be resolved under the trait in which they are declared * Improved support for language features * Trait inheritance works in many scenarios * Support for explicit self arguments in methods - `self`, `&self` `@self`, and `~self` all generally work as expected * Static methods work in more situations * Experimental: Traits may declare default methods for impls to use * Libraries * New condition handling system in `core::condition` * Timsort added to `std::sort` * New priority queue, `std::priority_queue` * Pipes for serializable types, `std::flatpipes' * Serialization overhauled to be trait-based * Expanded `getopts` definitions * Moved futures to `std` * More functions are pure now * `core::comm` renamed to `oldcomm`. Still deprecated * `rustdoc` and `cargo` are libraries now * Misc * Added a preliminary REPL, `rusti` * License changed from MIT to dual MIT/APL2 [1]: Contributors to Rust 0.5: a_m0d Andrew Dunham Arkaitz Jimenez Ben Striegel Bilal Husain Brian Anderson Brian J. Burg Brian Leibig Cat's Eye Technologies Damien Grassart Daniel Micay Daniel Patterson Eric Holk Erick Tryzelaar Gabriel Gareth Daniel Smith Graydon Hoare Huon Wilson Isaac Aggrey Jakub Wieczorek Jesse Jones Jimmy Lu Josh Matthews Jyun-Yan You Kevin Cantu Lindsey Kuper Luca Bruno Luqman Aden Mahmut Bulut Michael Arntzenius Niko Matsakis Patrick Walton Paul Stansifer Philipp Br?schweiler Simon BD Tim Chevalier Tim Taubert Tony Young Tycho Sci Viktor Dahl Zack Corr From graydon at mozilla.com Fri Dec 21 08:00:01 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 21 Dec 2012 08:00:01 -0800 Subject: [rust-dev] Rust 0.5 released In-Reply-To: <50D48413.7080503@mozilla.com> References: <50D48413.7080503@mozilla.com> Message-ID: <50D48781.7020501@mozilla.com> On 12-12-21 07:45 AM, Graydon Hoare wrote: > This release is available as both a tarball and a Windows installer: > > * http://dl.rust-lang.org/dist/rust-0.5.tar.gz > http://dl.rust-lang.org/dist/rust-0.5.tar.gz.asc > SHA256 (of .tar.gz): > d326d22707f0562d669c11efbc33ae812ddbf76ab78f07087fc5beb095a8928a > > * http://dl.rust-lang.org/dist/rust-0.5-install.exe > http://dl.rust-lang.org/dist/rust-0.5-install.exe.asc > SHA256 (of .exe): > df1c565de6e6eed1d76243b24c0cf25de3b170f8d48834254f3f5105f52b3099 *Sighs* unfortunately as _everything_ that could possibly wrong has gone wrong with this release, I must point out that those URLs were not available on _that_ S3 bucket when the announcement was posted, but only on the _new_ S3 bucket, static.rust-lang.org. The website had/has the right links, the email didn't. Anyway, I've copied the release artifacts to _both_ now, so it doesn't matter which link you follow. Same signatures and checksums and whatnot. Just .. you might have got a 404 and/or downloaded a prerelease candidate if you clicked those links in the past 10 minutes. Sorry for the mistake. Let me know if you find any further blunders. Long night. -Graydon From pwalton at mozilla.com Fri Dec 21 09:19:18 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 12:19:18 -0500 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3F0FD.6080208@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D3F0FD.6080208@mozilla.com> Message-ID: <50D49A16.9020005@mozilla.com> On 12/21/12 12:17 AM, Brian Anderson wrote > In order to have competitive performance in high-throughput applications > we need to use uv as intended and run our code inside the uv callbacks. > Right now there is no high-level API for this, so I think that when we > revisit this stuff one of the first things we need to do is add those > modules and get them solid and fast. Then rebuild everything on top of > that. How do we deal with failure? Do you mean that the code inside the uv callbacks should be trusted not to fail and that user-level code should still be synchronous? Patrick From pwalton at mozilla.com Fri Dec 21 09:37:28 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 12:37:28 -0500 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3F0FD.6080208@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D3F0FD.6080208@mozilla.com> Message-ID: <50D49E58.7030404@mozilla.com> On 12/21/12 12:17 AM, Brian Anderson wrote: > In the best case you essentially just want to be able to quickly > transfer large buffers from the client task to the I/O task, or the > other way. In a dual-core setup pipes should be able to do that very > fast, rarely yielding to the (Rust) scheduler. Well, my point is that in *this* benchmark we will still lose. The benchmark that Michael wrote waits on the results of each Redis query before sending the next one. This makes the main thread always fall asleep, so every pipe send will have to fall into the scheduler to punt the main thread awake. It's basically the worst case for our setup. I suspect the performance of this benchmark would be better if: (1) The code were written in a more asynchronous "fire-and-forget" style rather than waiting on the results of each query before sending the next one; and/or: (2) There were large (like, 100,000+) numbers of tasks involved, so that the performance advantages of M:N threading over 1:1 threading start to kick in. But, as written, this benchmark is fundamentally better served by 1:1 blocking APIs. Patrick From banderson at mozilla.com Fri Dec 21 11:30:03 2012 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 21 Dec 2012 11:30:03 -0800 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D49A16.9020005@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D3F0FD.6080208@mozilla.com> <50D49A16.9020005@mozilla.com> Message-ID: <50D4B8BB.6030707@mozilla.com> On 12/21/2012 09:19 AM, Patrick Walton wrote: > On 12/21/12 12:17 AM, Brian Anderson wrote >> In order to have competitive performance in high-throughput applications >> we need to use uv as intended and run our code inside the uv callbacks. >> Right now there is no high-level API for this, so I think that when we >> revisit this stuff one of the first things we need to do is add those >> modules and get them solid and fast. Then rebuild everything on top of >> that. > > How do we deal with failure? Do you mean that the code inside the uv > callbacks should be trusted not to fail and that user-level code > should still be synchronous? To start with we would just have to trust the code not to fail, but I expect we will solve this problem somehow. User-level code that wants to be super fast would by asynchronous and need to understand the failure issue. From erick.tryzelaar at gmail.com Fri Dec 21 15:22:52 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 21 Dec 2012 15:22:52 -0800 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D4B8BB.6030707@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D3F0FD.6080208@mozilla.com> <50D49A16.9020005@mozilla.com> <50D4B8BB.6030707@mozilla.com> Message-ID: Would we gain any significant performance if we made evented IO syscalls like Go instead of going through libuv? On Fri, Dec 21, 2012 at 11:30 AM, Brian Anderson wrote: > On 12/21/2012 09:19 AM, Patrick Walton wrote: > >> On 12/21/12 12:17 AM, Brian Anderson wrote >> >>> In order to have competitive performance in high-throughput applications >>> we need to use uv as intended and run our code inside the uv callbacks. >>> Right now there is no high-level API for this, so I think that when we >>> revisit this stuff one of the first things we need to do is add those >>> modules and get them solid and fast. Then rebuild everything on top of >>> that. >>> >> >> How do we deal with failure? Do you mean that the code inside the uv >> callbacks should be trusted not to fail and that user-level code should >> still be synchronous? >> > > To start with we would just have to trust the code not to fail, but I > expect we will solve this problem somehow. User-level code that wants to be > super fast would by asynchronous and need to understand the failure issue. > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Fri Dec 21 15:34:33 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 18:34:33 -0500 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D3F0FD.6080208@mozilla.com> <50D49A16.9020005@mozilla.com> <50D4B8BB.6030707@mozilla.com> Message-ID: <50D4F209.7060207@mozilla.com> On 12/21/12 6:22 PM, Erick Tryzelaar wrote: > Would we gain any significant performance if we made evented IO syscalls > like Go instead of going through libuv? Maybe for Unix, but in order to make it work efficiently on Windows we'd basically just be reinventing libuv. Patrick From pwalton at mozilla.com Fri Dec 21 19:31:26 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 22:31:26 -0500 Subject: [rust-dev] REPL is broken in 0.5 Message-ID: <50D5298E.5060200@mozilla.com> All inputs fail with: rust: task failed at 'no mode for lval', /Users/pwalton/Source/rust/master/src/librustc/middle/liveness.rs:1573 I'll look into this; I feel we should probably do a 0.5.1 to fix this. Thoughts? Patrick From pwalton at mozilla.com Fri Dec 21 19:42:34 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 22:42:34 -0500 Subject: [rust-dev] REPL is broken in 0.5 In-Reply-To: <50D5298E.5060200@mozilla.com> References: <50D5298E.5060200@mozilla.com> Message-ID: <50D52C2A.7040002@mozilla.com> On 12/21/12 10:31 PM, Patrick Walton wrote: > All inputs fail with: > > rust: task failed at 'no mode for lval', > /Users/pwalton/Source/rust/master/src/librustc/middle/liveness.rs:1573 > > I'll look into this; I feel we should probably do a 0.5.1 to fix this. > Thoughts? Fixed in incoming, although I'm still having troubles with fmt symbols in the REPL. Trying a clobber build. Patrick From pwalton at mozilla.com Fri Dec 21 20:51:26 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 21 Dec 2012 23:51:26 -0500 Subject: [rust-dev] REPL is broken in 0.5 In-Reply-To: <50D52C2A.7040002@mozilla.com> References: <50D5298E.5060200@mozilla.com> <50D52C2A.7040002@mozilla.com> Message-ID: <50D53C4E.2090302@mozilla.com> On 12/21/12 10:42 PM, Patrick Walton wrote: > On 12/21/12 10:31 PM, Patrick Walton wrote: >> All inputs fail with: >> >> rust: task failed at 'no mode for lval', >> /Users/pwalton/Source/rust/master/src/librustc/middle/liveness.rs:1573 >> >> I'll look into this; I feel we should probably do a 0.5.1 to fix this. >> Thoughts? > > Fixed in incoming, although I'm still having troubles with fmt symbols > in the REPL. Trying a clobber build. Would anyone mind testing the REPL in incoming? Patrick From mneumann at ntecs.de Sat Dec 22 06:15:20 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Sat, 22 Dec 2012 15:15:20 +0100 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3E2E6.4020301@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> Message-ID: <50D5C078.4060507@ntecs.de> Am 21.12.2012 05:17, schrieb Patrick Walton: > I just profiled this. Some thoughts: > > On 12/20/12 9:12 PM, Brian Anderson wrote: >> First, stack switching. Switching between Rust and C code has bad >> performance due to bad branch prediction. Some workloads can spend >> 10% of their time stalling in the stack switch. > > This didn't seem too high, actually. It should only be ~20,000 stack > switches (read and write) if we solve the following issue: > >> Second, working with uv involves sending a bunch of little work units to >> a dedicated uv task. This is because callbacks from uv into Rust *must >> not fail* or the runtime will crash. Where typical uv code runs directly >> in the event callbacks, Rust dispatches most or all of that work to >> other tasks. This imposes significant context switching and locking >> overhead. > > This is actually the problem. If you're using a nonblocking I/O > library (libuv) for a fundamentally blocking workload (sending lots of > requests to redis and blocking on the response for each one), *and* > you're multiplexing userland green threads on top of it, then you're > going to get significantly worse performance than you would if you had > used a blocking I/O setup. We can make some of the performance > differential up by switching uv over to pipes, and maybe we can play > dirty tricks like having the main thread spin on the read lock so that > we don't have to fall into the scheduler to punt it awake, but I still > don't see any way we will make up the 10x performance difference for > this particular use case without a fundamental change to the > architecture. Work stealing doesn't seem to be a viable solution here > since the uv task really needs to be one-task-per-thread. > > Maybe the best thing is just to make the choice of nonblocking versus > blocking I/O a choice that tasks can make on an individual basis. It's > a footgun to be sure; if you use blocking I/O you run the risk of > starving other tasks on the same scheduler to death, so perhaps we > should restrict this mode to schedulers with 1:1 scheduling. But this > would be in line with the general principle that we've been following > that the choice of 1:1 and M:N scheduling should be left to the user, > because there are performance advantages and disadvantages to each mode. > > Once this sort of switch is implemented, I would suspect the > performance differential between Ruby and Rust to be much less. So I think I should benchmark it against Erlang for example or any other evented language which also do message passing instead of direct callbacks. I can imagine that if I would use libuv directly (lets say in C), and as such avoid message sending and scheduling, it would have similar performance to the blocking solution. Would you agree? The best thing I can do is to use blocking I/O here anyway as it's better to have just one connection to Redis and multiplex that, so I can easily use one native thread for that. I am just very new to Rust, and the only thing I found was tcp_net. So I think I should define my own FFI socket calls, right? Thanks! Best, Michael From pwalton at mozilla.com Sat Dec 22 08:35:50 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 22 Dec 2012 11:35:50 -0500 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D5C078.4060507@ntecs.de> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D5C078.4060507@ntecs.de> Message-ID: <50D5E166.40305@mozilla.com> On 12/22/12 9:15 AM, Michael Neumann wrote: > The best thing I can do is to use blocking I/O here anyway as it's > better to have just one connection to Redis and multiplex that, so I can > easily use one native thread for that. > I am just very new to Rust, and the only thing I found was tcp_net. So I > think I should define my own FFI socket calls, right? Yes, that's what I would do. I think there may be some bindings to BSD sockets in cargo -- Brian would know better here. The scheduler modes here might be useful to ensure that your task gets its own OS thread: http://dl.rust-lang.org/doc/0.4/core/task.html#enum-schedmode Patrick From stevej at fruitless.org Sat Dec 22 10:27:04 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 22 Dec 2012 10:27:04 -0800 Subject: [rust-dev] how to call closures stored in struct slots (a 0.5 question) Message-ID: In 0.4, I had a struct that stored a fn that I later called as if it were a method. In 0.5, this has ceased. what is the new syntax for calling functions stored in slots? Here's the small code example (please excuse how naive it is): https://github.com/stevej/rustled/blob/master/lazy.rs#L28 and here is the 0.5 compiler error I receive: lazy.rs:28:21: 28:33 error: type `lazy::Lazy<'a>` does not implement any method in scope named `code` lazy.rs:28 let result = self.code(); Thanks, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Sat Dec 22 10:28:26 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 22 Dec 2012 10:28:26 -0800 Subject: [rust-dev] how to call closures stored in struct slots (a 0.5 question) In-Reply-To: References: Message-ID: On Sat, Dec 22, 2012 at 10:27 AM, Steve Jenson wrote: > In 0.4, I had a struct that stored a fn that I later called as if it were a > method. In 0.5, this has ceased. what is the new syntax for calling > functions stored in slots? > > Here's the small code example (please excuse how naive it is): > > https://github.com/stevej/rustled/blob/master/lazy.rs#L28 > > and here is the 0.5 compiler error I receive: > > lazy.rs:28:21: 28:33 error: type `lazy::Lazy<'a>` does not implement any > method in scope named `code` > lazy.rs:28 let result = self.code(); (Warning: not tested.) I believe the way to do this is to write: let result = (self.code)(); Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From stevej at fruitless.org Sat Dec 22 10:31:35 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 22 Dec 2012 10:31:35 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) Message-ID: I've converted the red-black tree I wrote to use iter::BaseIter but am now fighting with lifetime analysis with the switch to 0.5. https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L91 And the error I'm getting with 0.5 is: http://pastebin.com/YK8v7EdA I've read the docs on lifetimes several times now but it's not quite enough to get me over this hurdle. Thanks! Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Sat Dec 22 10:32:48 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sat, 22 Dec 2012 10:32:48 -0800 Subject: [rust-dev] how to call closures stored in struct slots (a 0.5 question) In-Reply-To: References: Message-ID: Yes, that's it! Are these migration-related questions suited for this list or should I use github issues? thanks again, steve On Sat, Dec 22, 2012 at 10:28 AM, Tim Chevalier wrote: > On Sat, Dec 22, 2012 at 10:27 AM, Steve Jenson > wrote: > > In 0.4, I had a struct that stored a fn that I later called as if it > were a > > method. In 0.5, this has ceased. what is the new syntax for calling > > functions stored in slots? > > > > Here's the small code example (please excuse how naive it is): > > > > https://github.com/stevej/rustled/blob/master/lazy.rs#L28 > > > > and here is the 0.5 compiler error I receive: > > > > lazy.rs:28:21: 28:33 error: type `lazy::Lazy<'a>` does not implement any > > method in scope named `code` > > lazy.rs:28 let result = self.code(); > > (Warning: not tested.) I believe the way to do this is to write: > > let result = (self.code)(); > > Cheers, > Tim > > > > -- > Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt > "We know there'd hardly be no one in prison / If rights to food, > clothes, and shelter were given." -- Boots Riley > -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Sat Dec 22 10:34:17 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 22 Dec 2012 10:34:17 -0800 Subject: [rust-dev] how to call closures stored in struct slots (a 0.5 question) In-Reply-To: References: Message-ID: On Sat, Dec 22, 2012 at 10:32 AM, Steve Jenson wrote: > Yes, that's it! > > Are these migration-related questions suited for this list or should I use > github issues? > github issues should generally be for situations where you're pretty sure that rustc/libraries are wrong or need improvement. The list or IRC is great for asking questions where you don't think there's a compiler bug. So you're doing it right :-) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From lucian.branescu at gmail.com Sat Dec 22 10:42:33 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Sat, 22 Dec 2012 18:42:33 +0000 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: References: Message-ID: I think the problem is the compiler can't guarantee the managed box will survive, so it won't allow a borrowed pointer. I think there are problems in general with @ and borrowing. I've converted the red-black tree I wrote to use iter::BaseIter but am now fighting with lifetime analysis with the switch to 0.5. https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L91 And the error I'm getting with 0.5 is: http://pastebin.com/YK8v7EdA I've read the docs on lifetimes several times now but it's not quite enough to get me over this hurdle. Thanks! Steve _______________________________________________ Rust-dev mailing list Rust-dev at mozilla.org https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sat Dec 22 13:27:34 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 22 Dec 2012 16:27:34 -0500 Subject: [rust-dev] REPL is broken in 0.5 In-Reply-To: <50D53C4E.2090302@mozilla.com> References: <50D5298E.5060200@mozilla.com> <50D52C2A.7040002@mozilla.com> <50D53C4E.2090302@mozilla.com> Message-ID: <50D625C6.7000409@mozilla.com> On 12/21/12 11:51 PM, Patrick Walton wrote: > On 12/21/12 10:42 PM, Patrick Walton wrote: >> On 12/21/12 10:31 PM, Patrick Walton wrote: >>> All inputs fail with: >>> >>> rust: task failed at 'no mode for lval', >>> /Users/pwalton/Source/rust/master/src/librustc/middle/liveness.rs:1573 >>> >>> I'll look into this; I feel we should probably do a 0.5.1 to fix this. >>> Thoughts? >> >> Fixed in incoming, although I'm still having troubles with fmt symbols >> in the REPL. Trying a clobber build. > > Would anyone mind testing the REPL in incoming? OK, I have fixed the REPL. I will look into respinning a 0.5.1 release for this, if there are no objections. Patrick From mneumann at ntecs.de Sat Dec 22 16:11:02 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Sun, 23 Dec 2012 01:11:02 +0100 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D5E166.40305@mozilla.com> References: <50D3C22B.1040806@ntecs.de> <50D3C586.5060007@mozilla.com> <50D3E2E6.4020301@mozilla.com> <50D5C078.4060507@ntecs.de> <50D5E166.40305@mozilla.com> Message-ID: <50D64C16.9080806@ntecs.de> Am 22.12.2012 17:35, schrieb Patrick Walton: > On 12/22/12 9:15 AM, Michael Neumann wrote: >> The best thing I can do is to use blocking I/O here anyway as it's >> better to have just one connection to Redis and multiplex that, so I can >> easily use one native thread for that. >> I am just very new to Rust, and the only thing I found was tcp_net. So I >> think I should define my own FFI socket calls, right? > > Yes, that's what I would do. I think there may be some bindings to BSD > sockets in cargo -- Brian would know better here. > > The scheduler modes here might be useful to ensure that your task gets > its own OS thread: > http://dl.rust-lang.org/doc/0.4/core/task.html#enum-schedmode Thanks! I rerun the same benchmark on a faster box with many cores. Now there is almost no difference in the single-thread case compared against Ruby. I get 15k requests per second. Once I use multiple threads, Rust is the clear winner. It maxes out at 30k requests per second, which I think is somehow the limit what can be obtained (I've seen this number in several other HTTP benchmarks). Each thread uses a separate connection of course. I tried to create a separate iotask for each socket connection as well, but somehow when I do so: let iotask = uv::iotask::spawn_iotask(task::task()); performance decreases to 50% when compared against: let iotask = uv::global_loop::get(); I wonder what the reason for this is... Anyway, I am quite happy to see that Rust's network performance is quite competitive! Best, Michael From mneumann at ntecs.de Sun Dec 23 07:43:55 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Sun, 23 Dec 2012 16:43:55 +0100 Subject: [rust-dev] Misc questions and ideas Message-ID: <20121223164355.00004e6b@unknown> Hi, I've spent the last days hacking in Rust and a few questions and ideas have accumulated over that time. * If I use unique ~pointers, there is absolutely no runtime overhead, so neither ref-counting nor GC is involved, right? * Heap-allocated pointers incur ref-counting. So when I pass a @pointer, I will basically pass a struct heap_ptr {ptr: *byte, cnt: uint} around. Right? * vec::build_sized() somehow seems to be pretty slow. When I use it, instead of a for() loop, my rust-msgpack library slows down by factor 2 for loading msgpack data. Also, I would have expected that vec::build_sized() will call my supplied function "n" times. IMHO the name is little bit misleading here. * I do not fully understand the warning of the following script: fn main() { let bytes = io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); } t2.rs:2:14: 2:78 warning: instantiating copy type parameter with a not implicitly copyable type t2.rs:2 let bytes = io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Does it mean that it will copy the ~str again? When I use pattern matching instead of get(), I don't get this warning, but it seems to be slower. Will it just silence the warning??? * This is also strange to me: fn nowarn(bytes: &[u8]) {} fn main() { let bytes = ~[1,2,3]; nowarn(bytes); let br = io::BytesReader { bytes: bytes, pos: 0 }; // FAILS } t.rs:6:36: 6:41 error: mismatched types: expected `&/[u8]` but found `~[u8]` ([] storage differs: expected & but found ~) t.rs:6 let br = io::BytesReader { bytes: bytes, pos: 0 }; ^~~~~ It implicitly converts the ~pointer into a borrowed pointer when calling the function, but the same does not work when using the BytesReader struct. I think, I should use a make_bytes_reader function, but I didn't found one. * String literals seem to be not immutable. Is that right. That means they are always "heap" allocated. I wished they were immutable, so that writing ~"my string" is stored in read-only memory. I never thought this would be possible: let s = ~"my string"; let mut s2 = s; s2[0] = 'c' as u8; Is there a way how a function which takes a ~str can state that it will not modify the content? In this regard I very much like the way the D language handles this. It uses "const" to state that it won't modify the value, while the value itself may be mutable. Then there is "immutable", and a value declared as such will not change during the whole lifetime. Of course in Rust, thanks to unique pointers, there is less need for immutability, as you cannot share a unique pointer between threads. * Appending to strings. It's easy to push an element to an array by doing: let mut v: ~[int] = ~[1,2]; v.push(3); v.push(4); But when I want to append to a string, I have to write: let mut s: ~str = ~""; let mut s = str::append(s, "abc"); let mut s = str::append(s, "def"); I found this a bit counter-intuitive. I know there exists "+=", but this will always create a new string. A "<<" operator would be really nice to append to strings (or to arrays). * Default initializers for structs. Would be nice to specify them like: struct S {a: int = 4, b: int = 3}; I know I can use the ".." notation, and this is very cool and more flexible, but I will have to type in a lot of code if the struct get pretty large. const DefaultS = S{a: 4, b: 3}; // imagine this has 100 fields :) let s = S{a: 4, ..DefaultS}; * Metaprogramming Given an arbitrary struct S {...} with some fields, it would be nice to somehow derive S.serialize and S.deserialize functions automatically. Are there any ideas how to do that? In C++ I use the preprocessor and templates for that. In D, thanks to compile-time-code-evaluation, I can write code that will introspect the struct during compile-time and then generate code. I guess I could write a macro like: define_ser_struct!(S, field1, int, field2, uint, ...) which would generate the struct S and two functions for serialization. Would that be possible with macros? Thanks in advance, Michael From pwalton at mozilla.com Sun Dec 23 09:20:07 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 23 Dec 2012 12:20:07 -0500 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <20121223164355.00004e6b@unknown> References: <20121223164355.00004e6b@unknown> Message-ID: <50D73D47.1070107@mozilla.com> On 12/23/12 10:43 AM, Michael Neumann wrote: > Hi, > > I've spent the last days hacking in Rust and a few questions and ideas > have accumulated over that time. > > * If I use unique ~pointers, there is absolutely no runtime overhead, > so neither ref-counting nor GC is involved, right? Well, you have to malloc and free, but I assume you aren't counting that. There is no reference counting or GC, and the GC is totally unaware of such pointers. (There is one caveat: when we have tracing GC, it must scan ~ pointers that contain @ pointers, just as it must scan the stack. Such pointers are generally uncommon though.) > * Heap-allocated pointers incur ref-counting. So when I pass a > @pointer, I will basically pass a > > struct heap_ptr {ptr: *byte, cnt: uint} > > around. Right? They currently do thread-unsafe reference counting, but we would like to eventually change that to tracing GC. However, the structure is different: we use intrusive reference counting, so it's actually a pointer to this structure: pointer --> [ ref count, type_info, next alloc, prev alloc, data... ] You're only passing one word around, not two. The reference count is inside the object pointed to. This setup saves one allocation over C++ std::shared_ptr. > * vec::build_sized() somehow seems to be pretty slow. When I use it, > instead of a for() loop, my rust-msgpack library slows down by > factor 2 for loading msgpack data. > > Also, I would have expected that vec::build_sized() will call my > supplied function "n" times. IMHO the name is little bit > misleading here. You want vec::from_fn() instead. vec::build_sized() is not commonly used and could probably be renamed without too much trouble. I suspect the performance problem you're seeing with it is due to not supplying enough LLVM inline hints. LLVM's inline heuristics are not well tuned to Rust at the moment; we work around it by writing #[inline(always)] in a lot of places, but we should probably have the compiler insert those automatically for certain uses of higher-order functions. When LLVM inlines properly, the higher-order functions generally compile down into for loops. > * I do not fully understand the warning of the following script: > > fn main() { > let bytes = > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > } > > t2.rs:2:14: 2:78 warning: instantiating copy type parameter with a not > implicitly copyable type t2.rs:2 let bytes = > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Does it mean that it will copy the ~str again? When I use pattern > matching instead of get(), I don't get this warning, but it seems to > be slower. Will it just silence the warning??? Yes, it means it will copy the string again. To avoid this, you want result::unwrap() or option::unwrap() instead. I've been thinking for some time that .unwrap() should change to .get() and .get() should change to .copy_value() or something. > > * This is also strange to me: > > fn nowarn(bytes: &[u8]) {} > > fn main() { > let bytes = ~[1,2,3]; > nowarn(bytes); > let br = io::BytesReader { bytes: bytes, pos: 0 }; // FAILS > } > > t.rs:6:36: 6:41 error: mismatched types: expected `&/[u8]` but found > `~[u8]` ([] storage differs: expected & but found ~) t.rs:6 let br = > io::BytesReader { bytes: bytes, pos: 0 }; ^~~~~ > > It implicitly converts the ~pointer into a borrowed pointer when > calling the function, but the same does not work when using the > BytesReader struct. I think, I should use a make_bytes_reader > function, but I didn't found one. This is a missing feature that should be in the language. Struct literals are basically just like functions; their fields should cause coercions as well. > * String literals seem to be not immutable. Is that right. That means > they are always "heap" allocated. I wished they were immutable, so > that writing ~"my string" is stored in read-only memory. ~"my string" isn't designed to be stored in read-only memory. You want `&static/str` instead; since it's a borrowed pointer, it cannot be mutated. `static` is the read-only memory region. > Is there a way how a function which takes a ~str can state that it > will not modify the content? Take an `&str` (or an `&~str`) instead. Functions that take `~str` require that the caller give up its ownership of the string. If you, the caller, give up a string, then you give up your say in how it is used, including mutability. However, if you as the callee *borrow* the string via `&str` or `&~str`, then you are not allowed to change its mutability, since you are not the owner. > In this regard I very much like the way the D language handles this. > It uses "const" to state that it won't modify the value, while the > value itself may be mutable. Then there is "immutable", and a value > declared as such will not change during the whole lifetime. We have a "const" qualifier as well, which means what "const" does in D. It has a good chance of becoming redundant and going away, however, with the changes suggested in the blog post "Imagine Never Hearing the Words 'Aliasable, Mutable' Again". Having the ability to declare that a data type is forever immutable is something we've talked about a lot, but we'd have to add a lot of type system machinery for it to be as flexible as we'd like. Being able to arbitrarily freeze and thaw deep data structures is a very powerful feature, and having data types specify that they must be immutable forever is at odds with that. (For that matter, the `mut` keyword on struct fields is at odds with that in the other direction, which is why I'd like to get rid of that too.) > Of course in Rust, thanks to unique pointers, there is less need for > immutability, as you cannot share a unique pointer between threads. You can share unique pointers between threads with an ARC data type, actually (in `std::arc`). The ARC demands that the pointer be immutable and will not allow it to be mutated. > * Appending to strings. It's easy to push an element to an array by > doing: > > let mut v: ~[int] = ~[1,2]; > v.push(3); > v.push(4); > > But when I want to append to a string, I have to write: > > let mut s: ~str = ~""; > let mut s = str::append(s, "abc"); > let mut s = str::append(s, "def"); > > I found this a bit counter-intuitive. I know there exists "+=", but > this will always create a new string. A "<<" operator would be really > nice to append to strings (or to arrays). There should probably be a ".append()" method on strings with a "&mut self" argument. Then you could write: let mut s = ~""; s.append("abc"); s.append("def"); There are also plans to make "+=" separately overloadable. This would allow += to work in this case, I believe. > * Default initializers for structs. Would be nice to specify them like: > > struct S {a: int = 4, b: int = 3}; > > I know I can use the ".." notation, and this is very cool and more > flexible, but I will have to type in a lot of code if the struct get > pretty large. > > const DefaultS = S{a: 4, b: 3}; // imagine this has 100 fields :) > let s = S{a: 4, ..DefaultS}; Perhaps. This might be a good job for a macro at first, then we can see about folding it into the language if it's widely used. > * Metaprogramming > > Given an arbitrary struct S {...} with some fields, it would be nice > to somehow derive S.serialize and S.deserialize functions > automatically. Are there any ideas how to do that? In C++ I use the > preprocessor and templates for that. In D, thanks to > compile-time-code-evaluation, I can write code that will introspect > the struct during compile-time and then generate code. There are #[auto_encode] and #[auto_decode] syntax extensions that exist already, actually (although the documentation is almost nonexistent). These are polymorphic over the actual serialization method, so you can choose the actual serialization format. There is also a visitor you can use for reflection, although it will be slower than generating the code at compile time. We currently have syntax extensions written as compiler plugins. These allow you to write any code you want and have it executed at compile time. There are two main issues with them at the moment: (1) they have to be compiled as part of the compiler itself; (2) they expose too many internals of the `rustc` compiler, making your code likely to break when we change the compiler (or on alternative compilers implementing the Rust language, if they existed). The plan to fix (1) is to allow plugins to be written as separate crates and dynamically loaded; we've also talked about, longer-term, allowing them to be JIT'd, allowing you to execute any code you wish at compile time. The plan to fix (2) is to make the syntax extensions operate on token trees, not AST nodes, basically along the lines of Scheme syntax objects. > I guess I could write a macro like: > > define_ser_struct!(S, field1, int, field2, uint, ...) > > which would generate the struct S and two functions for > serialization. Would that be possible with macros? Yes, you should be able do this with macros today, now that macros can expand to items. Patrick From fw at deneb.enyo.de Sun Dec 23 13:03:09 2012 From: fw at deneb.enyo.de (Florian Weimer) Date: Sun, 23 Dec 2012 22:03:09 +0100 Subject: [rust-dev] net::tcp::TcpSocket slow? In-Reply-To: <50D3C22B.1040806@ntecs.de> (Michael Neumann's message of "Fri, 21 Dec 2012 02:58:03 +0100") References: <50D3C22B.1040806@ntecs.de> Message-ID: <87obhkjxbm.fsf@mid.deneb.enyo.de> * Michael Neumann: > I am writing a redis client [1] for rust but somehow TCP performance > seems to be veery slow. I basically just sent a string > to redis and read the response (I commented out parsing). Doing this > 10_000 times takes about 4.5 seconds, while doing the same in Ruby > takes just 0.7 seconds. Perhaps you just need to disable the Nagle algorithm (that is, enable the TCP_NODELAY socket option). I'm not sure if Rust uses the code for that in libuv. From mneumann at ntecs.de Sun Dec 23 13:25:22 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Sun, 23 Dec 2012 22:25:22 +0100 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <50D73D47.1070107@mozilla.com> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> Message-ID: <20121223222522.00002f1f@unknown> Am Sun, 23 Dec 2012 12:20:07 -0500 schrieb Patrick Walton : > On 12/23/12 10:43 AM, Michael Neumann wrote: > > Hi, > > > > I've spent the last days hacking in Rust and a few questions and > > ideas have accumulated over that time. > > > > * If I use unique ~pointers, there is absolutely no runtime > > overhead, so neither ref-counting nor GC is involved, right? > > Well, you have to malloc and free, but I assume you aren't counting > that. There is no reference counting or GC, and the GC is totally > unaware of such pointers. > > (There is one caveat: when we have tracing GC, it must scan ~ > pointers that contain @ pointers, just as it must scan the stack. > Such pointers are generally uncommon though.) What is the big advantage of having a tracing GC over ref counting? With GC we'd get rid of the extra indirection and extra operations during aliasing, so it's basically a performance issue, right? > > * Heap-allocated pointers incur ref-counting. So when I pass a > > @pointer, I will basically pass a > > > > struct heap_ptr {ptr: *byte, cnt: uint} > > > > around. Right? > > They currently do thread-unsafe reference counting, but we would like > to eventually change that to tracing GC. However, the structure is > different: we use intrusive reference counting, so it's actually a > pointer to this structure: > > pointer --> [ ref count, type_info, next alloc, prev alloc, data... ] Oh, I see, there is actually no double indirection, as [pointer+x] always points to the data. Neat! > You're only passing one word around, not two. The reference count is > inside the object pointed to. This setup saves one allocation over > C++ std::shared_ptr. > > > * vec::build_sized() somehow seems to be pretty slow. When I use it, > > instead of a for() loop, my rust-msgpack library slows down by > > factor 2 for loading msgpack data. > > > > Also, I would have expected that vec::build_sized() will call my > > supplied function "n" times. IMHO the name is little bit > > misleading here. > > You want vec::from_fn() instead. vec::build_sized() is not commonly > used and could probably be renamed without too much trouble. Actually I was thinking of sth like in Ruby: Array.new(size=10) {|i| i % 2} gives: [0, 1, 0, 1, 0, 1, 0, 1...] fn make_sized(n: uint, f: fn(uint) ->? T) ->? ~[T] { let mut v: ~[T] = vec::with_capacity(n); let mut i: uint = 0; while (i < n) { v.push(f(i)); i += 1; } v } do vec::make_sized(10) |i| {i % 2} > I suspect the performance problem you're seeing with it is due to not > supplying enough LLVM inline hints. LLVM's inline heuristics are not > well tuned to Rust at the moment; we work around it by writing > #[inline(always)] in a lot of places, but we should probably have the > compiler insert those automatically for certain uses of higher-order > functions. When LLVM inlines properly, the higher-order functions > generally compile down into for loops. Is this an issue the LLVM developers are working on? > > * I do not fully understand the warning of the following script: > > > > fn main() { > > let bytes = > > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > > } > > > > t2.rs:2:14: 2:78 warning: instantiating copy type parameter with > > a not implicitly copyable type t2.rs:2 let bytes = > > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > > Does it mean that it will copy the ~str again? When I use pattern > > matching instead of get(), I don't get this warning, but it > > seems to be slower. Will it just silence the warning??? > > Yes, it means it will copy the string again. To avoid this, you want > result::unwrap() or option::unwrap() instead. I've been thinking for > some time that .unwrap() should change to .get() and .get() should > change to .copy_value() or something. Yes, I think sth with copy in the name would be less surprising. Ok, unwrap makes sense. Or maybe get() and get_copy()? > > > > * This is also strange to me: > > > > fn nowarn(bytes: &[u8]) {} > > > > fn main() { > > let bytes = ~[1,2,3]; > > nowarn(bytes); > > let br = io::BytesReader { bytes: bytes, pos: 0 }; // FAILS > > } > > > > t.rs:6:36: 6:41 error: mismatched types: expected `&/[u8]` but > > found `~[u8]` ([] storage differs: expected & but found ~) t.rs:6 > > let br = io::BytesReader { bytes: bytes, pos: 0 }; ^~~~~ > > > > It implicitly converts the ~pointer into a borrowed pointer when > > calling the function, but the same does not work when using the > > BytesReader struct. I think, I should use a make_bytes_reader > > function, but I didn't found one. > > This is a missing feature that should be in the language. Struct > literals are basically just like functions; their fields should cause > coercions as well. Ok. > > * String literals seem to be not immutable. Is that right. That > > means they are always "heap" allocated. I wished they were > > immutable, so that writing ~"my string" is stored in read-only > > memory. > > ~"my string" isn't designed to be stored in read-only memory. You > want `&static/str` instead; since it's a borrowed pointer, it cannot > be mutated. `static` is the read-only memory region. I understand. Makes sense. > > Is there a way how a function which takes a ~str can state that > > it will not modify the content? > > Take an `&str` (or an `&~str`) instead. Functions that take `~str` > require that the caller give up its ownership of the string. If you, > the caller, give up a string, then you give up your say in how it is > used, including mutability. However, if you as the callee *borrow* > the string via `&str` or `&~str`, then you are not allowed to change > its mutability, since you are not the owner. So a "const" function (in terms of C++ ;-) would always take a &str pointer? Makes absolute sense to me. > > In this regard I very much like the way the D language handles > > this. It uses "const" to state that it won't modify the value, > > while the value itself may be mutable. Then there is "immutable", > > and a value declared as such will not change during the whole > > lifetime. > > We have a "const" qualifier as well, which means what "const" does in > D. It has a good chance of becoming redundant and going away, > however, with the changes suggested in the blog post "Imagine Never > Hearing the Words 'Aliasable, Mutable' Again". > > Having the ability to declare that a data type is forever immutable > is something we've talked about a lot, but we'd have to add a lot of > type system machinery for it to be as flexible as we'd like. Being > able to arbitrarily freeze and thaw deep data structures is a very > powerful feature, and having data types specify that they must be > immutable forever is at odds with that. (For that matter, the `mut` > keyword on struct fields is at odds with that in the other direction, > which is why I'd like to get rid of that too.) > > > Of course in Rust, thanks to unique pointers, there is less need > > for immutability, as you cannot share a unique pointer between > > threads. > > You can share unique pointers between threads with an ARC data type, > actually (in `std::arc`). The ARC demands that the pointer be > immutable and will not allow it to be mutated. > > > * Appending to strings. It's easy to push an element to an array by > > doing: > > > > let mut v: ~[int] = ~[1,2]; > > v.push(3); > > v.push(4); > > > > But when I want to append to a string, I have to write: > > > > let mut s: ~str = ~""; > > let mut s = str::append(s, "abc"); > > let mut s = str::append(s, "def"); > > > > I found this a bit counter-intuitive. I know there exists "+=", > > but this will always create a new string. A "<<" operator would be > > really nice to append to strings (or to arrays). > > There should probably be a ".append()" method on strings with a "&mut > self" argument. Then you could write: > > let mut s = ~""; > s.append("abc"); > s.append("def"); > > There are also plans to make "+=" separately overloadable. This would > allow += to work in this case, I believe. Ideally there would be an operator, as writing .append() all the time is quite tedious. > > * Default initializers for structs. Would be nice to specify them > > like: > > > > struct S {a: int = 4, b: int = 3}; > > > > I know I can use the ".." notation, and this is very cool and > > more flexible, but I will have to type in a lot of code if the > > struct get pretty large. > > > > const DefaultS = S{a: 4, b: 3}; // imagine this has 100 fields :) > > let s = S{a: 4, ..DefaultS}; > > Perhaps. This might be a good job for a macro at first, then we can > see about folding it into the language if it's widely used. > > > * Metaprogramming > > > > Given an arbitrary struct S {...} with some fields, it would be > > nice to somehow derive S.serialize and S.deserialize functions > > automatically. Are there any ideas how to do that? In C++ I use > > the preprocessor and templates for that. In D, thanks to > > compile-time-code-evaluation, I can write code that will > > introspect the struct during compile-time and then generate code. > > There are #[auto_encode] and #[auto_decode] syntax extensions that > exist already, actually (although the documentation is almost > nonexistent). These are polymorphic over the actual serialization > method, so you can choose the actual serialization format. There is > also a visitor you can use for reflection, although it will be slower > than generating the code at compile time. Hm, this is interesting. Is there somewhere a simple example how to use #[auto_encode] and what my msgpack library needs to implement to work with it? > We currently have syntax extensions written as compiler plugins. > These allow you to write any code you want and have it executed at > compile time. There are two main issues with them at the moment: (1) > they have to be compiled as part of the compiler itself; (2) they > expose too many internals of the `rustc` compiler, making your code > likely to break when we change the compiler (or on alternative > compilers implementing the Rust language, if they existed). The plan > to fix (1) is to allow plugins to be written as separate crates and > dynamically loaded; we've also talked about, longer-term, allowing > them to be JIT'd, allowing you to execute any code you wish at > compile time. The plan to fix (2) is to make the syntax extensions > operate on token trees, not AST nodes, basically along the lines of > Scheme syntax objects. I see. So it would be possible to write a syntax extension called for example iter_fields!(struct_Type) which could be used to generate i.e. custom serializers. But that would be probably similar to #auto_encode, just that it could be more user-defined. > > > I guess I could write a macro like: > > > > define_ser_struct!(S, field1, int, field2, uint, ...) > > > > which would generate the struct S and two functions for > > serialization. Would that be possible with macros? > > Yes, you should be able do this with macros today, now that macros > can expand to items. Great. I will try that as an example to learn more about macros. Thanks! Best, Michael From pwalton at mozilla.com Sun Dec 23 13:45:49 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 23 Dec 2012 16:45:49 -0500 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <20121223222522.00002f1f@unknown> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> <20121223222522.00002f1f@unknown> Message-ID: <50D77B8D.7010909@mozilla.com> On 12/23/12 4:25 PM, Michael Neumann wrote: > What is the big advantage of having a tracing GC over ref counting? > With GC we'd get rid of the extra indirection and extra operations > during aliasing, so it's basically a performance issue, right? Yes, and we might also be able to allow temporary parallel access to GC'd data for pure functions only. If we can root the data in one task then we can potentially temporarily operate on @ data in parallel. Unfortunately that's hard to do for reference counted data, because our reference counts are not thread-safe for performance reasons. > Actually I was thinking of sth like in Ruby: > > Array.new(size=10) {|i| i % 2} > > gives: > > [0, 1, 0, 1, 0, 1, 0, 1...] Use `vec::from_fn`. For example: rusti> do vec::from_fn(10) |i| { i % 2 } ~[0, 1, 0, 1, 0, 1, 0, 1, 0, 1] > Is this an issue the LLVM developers are working on? It's more of a Rust-specific thing. `rustc` should be providing more hints to LLVM so that it does the right thing. I think that, to a first approximation, any higher-order function in Rust would benefit from `always_inline` or at least `inlinehint`. LLVM's built-in inlining heuristics are more tuned to C++; I don't think that's likely to change, given upstream LLVM's goals. Maybe if C++11 uses more higher-order functions. In any case, this should be something fixable in `rustc` itself; I don't think LLVM will need to change much if any. > Yes, I think sth with copy in the name would be less surprising. Ok, > unwrap makes sense. Or maybe get() and get_copy()? Yeah, `get_copy` sounds reasonable to me. > So a "const" function (in terms of C++ ;-) would always take a &str > pointer? Makes absolute sense to me. Yes. You can temporarily "borrow" a ~str as immutable. > Ideally there would be an operator, as writing .append() all the time is > quite tedious. I think `+=` will have this signature: trait AddAssign { fn add_assign(&mut self, other: &Rhs) -> Result; } Which would allow += to work as you suggest. > Hm, this is interesting. Is there somewhere a simple example how to use > #[auto_encode] and what my msgpack library needs to implement to work > with it? Unfortunately I'm not an expert on `auto_encode`. Erick Tryzelaar, Brian Anderson, or Graydon may know better. > I see. So it would be possible to write a syntax extension called for > example iter_fields!(struct_Type) which could be used to generate i.e. > custom serializers. But that would be probably similar to #auto_encode, > just that it could be more user-defined. Well, you'd need to write it on the struct definition, so that it has access to the struct contents (as syntax extensions run before typechecking). Actually, #[auto_encode] is a syntax extension itself, as some syntax extensions can be written using #[] "attribute" notation. This should eventually extend to user-defined syntax extensions as well. Patrick From mneumann at ntecs.de Sun Dec 23 14:53:02 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Sun, 23 Dec 2012 23:53:02 +0100 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <50D73D47.1070107@mozilla.com> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> Message-ID: <20121223235302.00002de3@unknown> Am Sun, 23 Dec 2012 12:20:07 -0500 schrieb Patrick Walton : > On 12/23/12 10:43 AM, Michael Neumann wrote: > > Hi, > > [...] > > > * I do not fully understand the warning of the following script: > > > > fn main() { > > let bytes = > > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > > } > > > > t2.rs:2:14: 2:78 warning: instantiating copy type parameter with > > a not implicitly copyable type t2.rs:2 let bytes = > > io::read_whole_file(&path::Path("/tmp/matching.msgpack")).get(); > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > > Does it mean that it will copy the ~str again? When I use pattern > > matching instead of get(), I don't get this warning, but it > > seems to be slower. Will it just silence the warning??? > > Yes, it means it will copy the string again. To avoid this, you want > result::unwrap() or option::unwrap() instead. I've been thinking for > some time that .unwrap() should change to .get() and .get() should > change to .copy_value() or something. That's strange. If I use result::unwrap() it is consistently becoming much slower! But the warning goes away. While get() is faster, but there is this warning. Btw, there is also no .unwrap(), just result::unwrap(). I believe that unwrap() is copying, while get() is passing a reference somehow. Michael From pwalton at mozilla.com Sun Dec 23 15:08:31 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 23 Dec 2012 18:08:31 -0500 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <20121223235302.00002de3@unknown> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> <20121223235302.00002de3@unknown> Message-ID: <50D78EEF.5090502@mozilla.com> On 12/23/12 5:53 PM, Michael Neumann wrote: > That's strange. If I use result::unwrap() it is consistently becoming > much slower! But the warning goes away. While get() is faster, but > there is this warning. Btw, there is also no .unwrap(), just > result::unwrap(). I believe that unwrap() is copying, while get() is > passing a reference somehow. This is not what I see. This program: fn f() -> Result<~str,~str> { Ok(~"hello world") } fn main() { for uint::range(0, 0x1234567) |_| { let _ = f().get(); } } Has this performance: real 0m15.991s user 0m15.899s sys 0m0.016s While this program: fn f() -> Result<~str,~str> { Ok(~"hello world") } fn main() { for uint::range(0, 0x1234567) |_| { let _ = result::unwrap(f()); } } Has this performance: real 0m4.318s user 0m4.255s sys 0m0.013s Patrick From pwalton at mozilla.com Sun Dec 23 15:08:51 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 23 Dec 2012 18:08:51 -0500 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <50D78EEF.5090502@mozilla.com> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> <20121223235302.00002de3@unknown> <50D78EEF.5090502@mozilla.com> Message-ID: <50D78F03.8040906@mozilla.com> One more thing: Be sure you're using rustc -O. rustc will do much more inlining this way. Patrick From stevej at fruitless.org Sun Dec 23 16:54:18 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sun, 23 Dec 2012 16:54:18 -0800 Subject: [rust-dev] Request for feedback In-Reply-To: <50C25787.7040702@mozilla.com> References: <50C25787.7040702@mozilla.com> Message-ID: On Fri, Dec 7, 2012 at 12:54 PM, Patrick Walton wrote: > On 12/7/12 11:58 AM, Steve Jenson wrote: > >> Hi rust gurus, >> >> Today I ported the purely functional Pairing Heap found in Okasaki's >> Purely Functional Data Structures to Rust. I was hoping that some of you >> might take a look at it and give me feedback on where I could be using >> Rust's idioms better. >> >> https://github.com/stevej/**rustled/blob/master/pairing_**heap.rs >> >> The code I wrote is a little longer than Okasaki's example, mostly due >> to Standard ML's more concise pattern matching. (see page 54 for >> comparison) Is there a way to do pattern matching in argument lists as >> in Haskell or SML? >> > > Yes, in Rust 0.5 this works. > > I noticed several things: > > * Using explicit self (&self) will help make your levels of indirection > consistent between `self` and `other` in a few functions. This works better > in 0.5 than it does in 0.4. > > * Braces aren't necessary after the => in patterns unless you want > multiple statements. > > * I'm confused as to why you need an @record as your type in PairingHeap_ > (note that records are deprecated in favor of structs). In Rust 0.5 you can > say > > pub enum PairingHeap { > Empty, > PairingHeapCell { > head: E, > rest: @List> > } > } > > * You can use "self" as the return value in a trait. > > * In 0.5 you can use #[deriving_eq] for your enum to avoid writing the Eq > definition, although I'm not sure that works for struct-like enum variants > as in PairingHeapCell above (I should check this). > Unfortunately, deriving_eq doesn't work for this enum (the same error is reported 3 times): rustc -g -o bin/algorithms --lib crate.rc pairing_heap.rs:14:0: 15:3 error: instantiating a type parameter with an incompatible type (needs `copy`, got ``, missing `copy`) pairing_heap.rs:14 #[deriving_eq] pairing_heap.rs:15 pub enum PairingHeap { pairing_heap.rs:14:0: 15:3 error: instantiating a type parameter with an incompatible type (needs `copy`, got ``, missing `copy`) pairing_heap.rs:14 #[deriving_eq] pairing_heap.rs:15 pub enum PairingHeap { pairing_heap.rs:14:0: 15:3 error: instantiating a type parameter with an incompatible type (needs `copy`, got ``, missing `copy`) pairing_heap.rs:14 #[deriving_eq] pairing_heap.rs:15 pub enum PairingHeap { error: aborting due to 3 previous errors make: *** [all] Error 101 Best, Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From stevej at fruitless.org Sun Dec 23 17:05:47 2012 From: stevej at fruitless.org (Steve Jenson) Date: Sun, 23 Dec 2012 17:05:47 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: References: Message-ID: That explanation makes sense, it seems like the lifetime analysis improved from 0.4 (where this code worked) to 0.5? Since it seems that you can't use borrowed pointers to shared heap items in an arglist, I went ahead and created a new type of iter called BareIter. trait BareIter { pure fn each(&self, blk: fn(v: A) -> bool); } and converted my use of BaseIter to BareIter. On Sat, Dec 22, 2012 at 10:42 AM, Lucian Branescu wrote: > I think the problem is the compiler can't guarantee the managed box will > survive, so it won't allow a borrowed pointer. > > I think there are problems in general with @ and borrowing. > I've converted the red-black tree I wrote to use iter::BaseIter but am > now fighting with lifetime analysis with the switch to 0.5. > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L91 > > And the error I'm getting with 0.5 is: > > http://pastebin.com/YK8v7EdA > > I've read the docs on lifetimes several times now but it's not quite > enough to get me over this hurdle. > > > Thanks! > Steve > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Mon Dec 24 12:14:16 2012 From: steven099 at gmail.com (Steven Blenkinsop) Date: Mon, 24 Dec 2012 15:14:16 -0500 Subject: [rust-dev] Help understanding lifetimes. Message-ID: I was trying to see how to use region pointers to return nested data in a data structure containing unique pointers. This works: struct T1 { value: int } struct T2 { t1: ~T1 } fn value(t2: &r/T2) -> &r/int { &t2.t1.value } fn main() { let t2 = ~T2{ t1: ~T1{ value: 5 } }; io::println(fmt!("%d", *value(t2))); } This makes sense to me, since the data structure as a whole is immutable for the duration of the borrow, so the lifetime of all nested values should be the lifetime of the owning reference. However, if I try to introduce an option type, I can't figure out how to get it to work. struct T1 { value: int } struct T2 { t1: option::Option<~T1> } If I try to borrow T1.value inside a match in fn value, it tells me it's an illegal borrow since the borrowed value is only valid inside the match. Is there a way to get this to work, or is it impossible, and if the latter, what's the reasoning for this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Mon Dec 24 12:16:44 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Mon, 24 Dec 2012 12:16:44 -0800 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: Message-ID: Can you post the code that doesn't work? I have an idea of what might be going on, but it's easier for me to explain if I see the code you're trying to compile :-) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From steven099 at gmail.com Mon Dec 24 12:29:06 2012 From: steven099 at gmail.com (Steven Blenkinsop) Date: Mon, 24 Dec 2012 15:29:06 -0500 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: Message-ID: Here's something I tried that seemed the closest to working, but I don't know if I'm on the right track at all: struct T1 { value: int } struct T2 { t1: option::Option<~T1> } fn value(t2: &r/T2, def: &r/int) -> &r/int { match t2.t1 { Some(ref t1) => &t1.value, None => def } } fn main() { let t2 = ~T2{ t1: Some(~T1{ value: 5 }) }; let def = ~0; io::println(fmt!("%d", *value(t2, def))); } Here's the error: test.rs:6:19: 6:21 error: illegal borrow: borrowed value does not live long enough test.rs:6 Some(ref t1) => &t1.value, ^~ test.rs:4:43: 9:1 note: borrowed pointer must be valid for the lifetime &r as defined on the block at 4:43... test.rs:4 fn value(t2: &r/T2, def: &r/int) -> &r/int { test.rs:5 match t2.t1 { test.rs:6 Some(ref t1) => &t1.value, test.rs:7 None => def test.rs:8 } test.rs:9 } test.rs:6:18: 6:27 note: ...but borrowed value is only valid for the block at 6:18 test.rs:6 Some(ref t1) => &t1.value, ^~~~~~~~~ On Mon, Dec 24, 2012 at 3:16 PM, Tim Chevalier wrote: > Can you post the code that doesn't work? I have an idea of what might > be going on, but it's easier for me to explain if I see the code > you're trying to compile :-) > > Cheers, > Tim > > -- > Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt > "We know there'd hardly be no one in prison / If rights to food, > clothes, and shelter were given." -- Boots Riley > -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Mon Dec 24 12:48:52 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Mon, 24 Dec 2012 12:48:52 -0800 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: Message-ID: I suspect this is a borrowck bug (or at least shortcoming), but I don't know the borrowck rules well enough to say for sure. I suggest filing this code as an issue. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "We know there'd hardly be no one in prison / If rights to food, clothes, and shelter were given." -- Boots Riley From pwalton at mozilla.com Mon Dec 24 12:49:36 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 24 Dec 2012 15:49:36 -0500 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: Message-ID: <50D8BFE0.8020305@mozilla.com> On 12/24/12 3:48 PM, Tim Chevalier wrote: > I suspect this is a borrowck bug (or at least shortcoming), but I > don't know the borrowck rules well enough to say for sure. I suggest > filing this code as an issue. I vote bug as well. Patrick From mneumann at ntecs.de Mon Dec 24 15:13:42 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 25 Dec 2012 00:13:42 +0100 Subject: [rust-dev] Misc questions and ideas In-Reply-To: <50D78EEF.5090502@mozilla.com> References: <20121223164355.00004e6b@unknown> <50D73D47.1070107@mozilla.com> <20121223235302.00002de3@unknown> <50D78EEF.5090502@mozilla.com> Message-ID: <50D8E1A6.8010300@ntecs.de> Am 24.12.2012 00:08, schrieb Patrick Walton: > On 12/23/12 5:53 PM, Michael Neumann wrote: >> That's strange. If I use result::unwrap() it is consistently becoming >> much slower! But the warning goes away. While get() is faster, but >> there is this warning. Btw, there is also no .unwrap(), just >> result::unwrap(). I believe that unwrap() is copying, while get() is >> passing a reference somehow. > > This is not what I see. This program: > > fn f() -> Result<~str,~str> { > Ok(~"hello world") > } > > fn main() { > for uint::range(0, 0x1234567) |_| { > let _ = f().get(); > } > } > > Has this performance: > > real 0m15.991s > user 0m15.899s > sys 0m0.016s > > While this program: > > fn f() -> Result<~str,~str> { > Ok(~"hello world") > } > > fn main() { > for uint::range(0, 0x1234567) |_| { > let _ = result::unwrap(f()); > } > } > > Has this performance: > > real 0m4.318s > user 0m4.255s > sys 0m0.013s I now see the same behaviour when I measure result::unwrap vs .get(). Hm, I think my benchmark was just flawed because it run under a VM on a laptop. Michael From steven099 at gmail.com Mon Dec 24 18:41:31 2012 From: steven099 at gmail.com (Steven Blenkinsop) Date: Mon, 24 Dec 2012 21:41:31 -0500 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: <50D8BFE0.8020305@mozilla.com> References: <50D8BFE0.8020305@mozilla.com> Message-ID: On Monday, December 24, 2012, Patrick Walton wrote: > On 12/24/12 3:48 PM, Tim Chevalier wrote: > >> I suspect this is a borrowck bug (or at least shortcoming), but I >> don't know the borrowck rules well enough to say for sure. I suggest >> filing this code as an issue. >> > > I vote bug as well. > > Patrick > Okay. I'm glad I'm not completely off base thinking this might work ;). I'll file an issue. -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Mon Dec 24 21:25:36 2012 From: steven099 at gmail.com (Steven Blenkinsop) Date: Tue, 25 Dec 2012 00:25:36 -0500 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: <50D8BFE0.8020305@mozilla.com> Message-ID: Turns out the issue was borrowing from a reborrowed value. i.e. this doesn't work: fn rereborrow(v: &r/int) -> &r/int { &*&*v } I've filed an issue: https://github.com/mozilla/rust/issues/4285 Incidentally, I can make my original code work by eliminating the intermediate borrow: struct T1 { value: int } struct T2 { t1: option::Option<~T1> } fn value(t2: &r/T2, def: &r/int) -> &r/int { match t2.t1 { Some(~T1{value: ref value}) => value, None => def } } fn main() { let t2 = ~T2{ t1: Some(~T1{ value: 5 }) }; let def = ~0; io::println(fmt!("%d", *value(t2, def))); } -------------- next part -------------- An HTML attachment was scrubbed... URL: From mneumann at ntecs.de Tue Dec 25 11:25:13 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 25 Dec 2012 20:25:13 +0100 Subject: [rust-dev] Implementation inheritance or mixins Message-ID: <50D9FD99.3040206@ntecs.de> Hi, I am trying to switch over my msgpack implementation [1] to use the Encoder/Decoder trait from serialize.rs. I want to implement a basic encoder and a more optimized one (in terms of generated storage). Most of the emit_() functions will be shared between the two, just integers would be emitted based on their actual range and not depending on their type. Now my question is wheather I can reuse some code by using something like a Mixin? Is there something like this: struct Encoder { ... } pub impl Encoder : serialize::Encoder { fn emit_nil ... ... } struct OptEncoder { ... } pub impl OptEncoder : serialize::Encoder { include Encoder fn emit_uint(...) { ... } // overwrite emit_uint } Or how would you implement that? Actually what I want is some way to literally "include" some functions into the scope of an implementation (like a mixin). Similar in the way Ruby or Sather handles this. Merry Christmas! Michael From lucian.branescu at gmail.com Tue Dec 25 11:43:58 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Tue, 25 Dec 2012 19:43:58 +0000 Subject: [rust-dev] Implementation inheritance or mixins In-Reply-To: <50D9FD99.3040206@ntecs.de> References: <50D9FD99.3040206@ntecs.de> Message-ID: Traits are basically what you want here. You can have a trait with the emit method and implement it on both structs. On 25 Dec 2012 19:25, "Michael Neumann" wrote: > Hi, > > I am trying to switch over my msgpack implementation [1] to use the > Encoder/Decoder trait from serialize.rs. I want to implement a basic > encoder and a more optimized one (in terms of generated storage). > Most of the emit_() functions will be shared between the two, just > integers would be emitted based on their actual range and not depending > on their type. Now my question is wheather I can reuse some code by > using something like a Mixin? > > Is there something like this: > > struct Encoder { ... } > > pub impl Encoder : serialize::Encoder { > fn emit_nil ... > ... > } > > struct OptEncoder { ... } > > pub impl OptEncoder : serialize::Encoder { > include Encoder > > fn emit_uint(...) { ... } // overwrite emit_uint > } > > Or how would you implement that? > > Actually what I want is some way to literally "include" some functions into > the scope of an implementation (like a mixin). Similar in the way Ruby or > Sather handles this. > > Merry Christmas! > > Michael > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mneumann at ntecs.de Tue Dec 25 13:49:03 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 25 Dec 2012 22:49:03 +0100 Subject: [rust-dev] Changing serialize.rs and auto_encode to support msgpack Message-ID: <50DA1F4F.8090804@ntecs.de> Hi, Please see the attached diff. This would be needed to use the Encoder for msgpack. Msgpack only supports arrays, and the number of entries must be known before the items are written out. So read_struct has to write the number of fields. JSON as an example doesn't has this problem as it uses delimiters for array ([ item1, item2 ]). But Msgpack writes this as "2" item1, item2. I tried to compile rust again with this change, but somehow it doesn't work as read_struct calls generated by auto_decode/auto_encode for structs now take 3 arguments instead of 2. It would be great to accept this patch, otherwise msgpack cannot use the Encoder which is a pity. Best, Michael -------------- next part -------------- diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 59e0a1e..80f5741 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -360,7 +360,7 @@ pub mod reader { f() } - fn read_struct(&self, name: &str, f: fn() -> T) -> T { + fn read_struct(&self, name: &str, _len: uint, f: fn() -> T) -> T { debug!("read_struct(name=%s)", name); f() } @@ -631,7 +631,7 @@ pub mod writer { } fn emit_rec(&self, f: fn()) { f() } - fn emit_struct(&self, _name: &str, f: fn()) { f() } + fn emit_struct(&self, _name: &str, _len: uint, f: fn()) { f() } fn emit_field(&self, name: &str, _idx: uint, f: fn()) { self._emit_label(name); f() diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 770d621..2ac807e 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -148,7 +148,7 @@ pub impl Encoder: serialize::Encoder { f(); self.wr.write_char('}'); } - fn emit_struct(&self, _name: &str, f: fn()) { + fn emit_struct(&self, _name: &str, _len: uint, f: fn()) { self.wr.write_char('{'); f(); self.wr.write_char('}'); @@ -261,7 +261,7 @@ pub impl PrettyEncoder: serialize::Encoder { self.indent -= 2; self.wr.write_char('}'); } - fn emit_struct(&self, _name: &str, f: fn()) { + fn emit_struct(&self, _name: &str, _len: uint, f: fn()) { self.emit_rec(f) } fn emit_field(&self, name: &str, idx: uint, f: fn()) { @@ -861,7 +861,7 @@ pub impl Decoder: serialize::Decoder { move value } - fn read_struct(&self, _name: &str, f: fn() -> T) -> T { + fn read_struct(&self, _name: &str, _len: uint, f: fn() -> T) -> T { debug!("read_struct()"); let value = f(); self.pop(); diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs index ef26a8c..8a8a7b5 100644 --- a/src/libstd/prettyprint.rs +++ b/src/libstd/prettyprint.rs @@ -160,7 +160,7 @@ pub impl Encoder: serialize::Encoder { self.wr.write_str(~"}"); } - fn emit_struct(&self, name: &str, f: fn()) { + fn emit_struct(&self, name: &str, _len: uint, f: fn()) { self.wr.write_str(fmt!("%s {", name)); f(); self.wr.write_str(~"}"); diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 9b19492..a1b4b57 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -54,7 +54,7 @@ pub trait Encoder { fn emit_vec_elt(&self, idx: uint, f: fn()); fn emit_rec(&self, f: fn()); - fn emit_struct(&self, name: &str, f: fn()); + fn emit_struct(&self, name: &str, _len: uint, f: fn()); fn emit_field(&self, f_name: &str, f_idx: uint, f: fn()); fn emit_tup(&self, len: uint, f: fn()); @@ -95,7 +95,7 @@ pub trait Decoder { fn read_vec_elt(&self, idx: uint, f: fn() -> T) -> T; fn read_rec(&self, f: fn() -> T) -> T; - fn read_struct(&self, name: &str, f: fn() -> T) -> T; + fn read_struct(&self, name: &str, _len: uint, f: fn() -> T) -> T; fn read_field(&self, name: &str, idx: uint, f: fn() -> T) -> T; fn read_tup(&self, sz: uint, f: fn() -> T) -> T; diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 1058910..f994930 100644 diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 8eb3738..680fa16 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -25,7 +25,7 @@ would generate two implementations like: impl node_id: Encodable { fn encode(s: &S) { - do s.emit_struct("Node") { + do s.emit_struct("Node", 1) { s.emit_field("id", 0, || s.emit_uint(self)) } } @@ -33,7 +33,7 @@ would generate two implementations like: impl node_id: Decodable { static fn decode(d: &D) -> Node { - do d.read_struct("Node") { + do d.read_struct("Node", 1) { Node { id: d.read_field(~"x", 0, || decode(d)) } @@ -686,6 +686,7 @@ fn mk_struct_ser_impl( ), ~[ cx.lit_str(span, @cx.str_of(ident)), + cx.lit_uint(span, vec::len(fields)), cx.lambda_stmts(span, fields), ] ); @@ -712,6 +713,7 @@ fn mk_struct_deser_impl( ), ~[ cx.lit_str(span, @cx.str_of(ident)), + cx.lit_uint(span, vec::len(fields)), cx.lambda_expr( cx.expr( span, From mneumann at ntecs.de Tue Dec 25 13:50:02 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Tue, 25 Dec 2012 22:50:02 +0100 Subject: [rust-dev] Implementation inheritance or mixins In-Reply-To: References: <50D9FD99.3040206@ntecs.de> Message-ID: <50DA1F8A.4000605@ntecs.de> Am 25.12.2012 20:43, schrieb Lucian Branescu: > > Traits are basically what you want here. You can have a trait with the > emit method and implement it on both structs. > Thanks. I'll try that. It's a new concept to me :). Michael From pwalton at mozilla.com Tue Dec 25 13:58:05 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 25 Dec 2012 16:58:05 -0500 Subject: [rust-dev] Implementation inheritance or mixins In-Reply-To: <50D9FD99.3040206@ntecs.de> References: <50D9FD99.3040206@ntecs.de> Message-ID: <50DA216D.60103@mozilla.com> On 12/25/12 2:25 PM, Michael Neumann wrote: > Hi, > > I am trying to switch over my msgpack implementation [1] to use the > Encoder/Decoder trait from serialize.rs. I want to implement a basic > encoder and a more optimized one (in terms of generated storage). > Most of the emit_() functions will be shared between the two, just > integers would be emitted based on their actual range and not depending > on their type. Now my question is wheather I can reuse some code by > using something like a Mixin? > > Is there something like this: > > struct Encoder { ... } > > pub impl Encoder : serialize::Encoder { > fn emit_nil ... > ... > } > > struct OptEncoder { ... } > > pub impl OptEncoder : serialize::Encoder { > include Encoder > > fn emit_uint(...) { ... } // overwrite emit_uint > } > > Or how would you implement that? > > Actually what I want is some way to literally "include" some functions into > the scope of an implementation (like a mixin). Similar in the way Ruby or > Sather handles this. Macros might be your best bet in terms of readability, but you can't have them expand into methods at the moment. (This should be fixed in the future.) Using traits you could do something like: struct BaseEncoder { ... } struct Encoder(BaseEncoder); struct OptEncoder(BaseEncoder); trait EncoderMethods { fn get_base_encoder(&self) -> &self/BaseEncoder; fn do_emit_uint(...) { ... } } impl Encoder : EncoderMethods { fn get_base_encoder(&self) -> &self/BaseEncoder { &*self } fn do_emit_uint(...) { /* Encoder-specific impl of emit_uint */ } } impl OptEncoder : EncoderMethods { fn get_base_encoder(&self) -> &self/BaseEncoder { &*self } fn do_emit_uint(...) { /* Encoder-specific impl of emit_uint */ } } /* this is the magic implementation */ impl T : serialize::Encoder { fn emit_uint(...) { self.do_emit_uint(...) } fn emit_int(...) { self.get_base_encoder()... } // implement other shared methods here } Patrick From mneumann at ntecs.de Wed Dec 26 05:08:42 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Wed, 26 Dec 2012 14:08:42 +0100 Subject: [rust-dev] Trying to get simple TCP server working Message-ID: <50DAF6DA.10105@ntecs.de> Hi, I am trying to write a very simple TCP server (code given below), which just reads from a socket, but somehow the read() blocks forever. Any idea what I am doing wrong? I also tried to create a task for each new incoming connection, but the same happens. I actually found this example on the internet... When I do "wget http://127.0.0.1:4000/" it prints - Server is listening - New client - Accepted! - Unwrapped and then it blocks forever. I also cannot create new connections at this point. Best, Michael /* * Simple TCP server */ extern mod std; use std::net::tcp; use std::net::ip; use std::uv; fn main() { tcp::listen(ip::v4::parse_addr("127.0.0.1"), 4000, 100, uv::global_loop::get(), |_comm_chan|{ error!("Server is listening"); }, |new_client, _comm_chan|{ error!("New client"); let result = tcp::accept(new_client); if result.is_ok(){ error!("Accepted!"); let socket = result::unwrap(move result); error!("Unwrapped"); // Now do stuff with this socket let data = socket.read(100); // XXX: This blocks io::println(fmt!("%?", data)); }else{ error!("Not accepted!"); } } */ }); } From pwalton at mozilla.com Wed Dec 26 08:41:54 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 26 Dec 2012 11:41:54 -0500 Subject: [rust-dev] Trying to get simple TCP server working In-Reply-To: <50DAF6DA.10105@ntecs.de> References: <50DAF6DA.10105@ntecs.de> Message-ID: <50DB28D2.3070505@mozilla.com> On 12/26/12 8:08 AM, Michael Neumann wrote: > Hi, > > I am trying to write a very simple TCP server (code given below), which > just reads from a > socket, but somehow the read() blocks forever. Any idea what I am doing > wrong? > I also tried to create a task for each new incoming connection, but the > same happens. > I actually found this example on the internet... Please file an issue. Patrick From pnathan at vandals.uidaho.edu Wed Dec 26 09:23:08 2012 From: pnathan at vandals.uidaho.edu (Paul Nathan) Date: Wed, 26 Dec 2012 09:23:08 -0800 Subject: [rust-dev] "expected type parameter but found type parameters" Message-ID: <62D822AB-5196-48B3-AD4A-10489622DE5E@vandals.uidaho.edu> Good morning, I am exploring Rust's traits in relation to working on data structures. Unfortunately, I have managed to back myself into a hole with an error message that I can't understand the problem with; to wit, "has an incompatible type: expected type parameter but found type parameter" is an error I don't understand. I've stuffed the code up on github: https://github.com/pnathan/flaky-data-structures/tree/non-compiling Here's my Rust version: $ rustc --version rustc 0.5 (8b98e5a 2012-12-20 17:01:38 -0800) host: x86_64-apple-darwin And here are the error messages: $ make rustc --test linear/linear.rs -o linear/test_linear linear/linear.rs:50:4: 59:5 error: method `head` has an incompatible type: expected type parameter but found type parameter linear/linear.rs:50 fn head (list: @List_Data) -> Option { linear/linear.rs:51 match (list) { linear/linear.rs:52 @Nil => { linear/linear.rs:53 None linear/linear.rs:54 } linear/linear.rs:55 @Cons(e, _) => { ... linear/linear.rs:60:4: 62:5 error: method `length` has an incompatible type: expected type parameter but found type parameter linear/linear.rs:60 fn length(list: @List_Data) -> u64 { linear/linear.rs:61 0 linear/linear.rs:62 } linear/linear.rs:68:4: 70:5 error: method `size` has an incompatible type: expected type parameter but found type parameter linear/linear.rs:68 fn size (cont: @List_Data) -> u64 { linear/linear.rs:69 0 linear/linear.rs:70 } linear/linear.rs:76:4: 80:5 error: method `peek` has an incompatible type: expected type parameter but found type parameter linear/linear.rs:76 fn peek(list : @List_Data) -> Option<@T> { linear/linear.rs:77 None linear/linear.rs:78 // head linear/linear.rs:79 //head(list) linear/linear.rs:80 } linear/linear.rs:82:4: 84:5 error: method `pop` has an incompatible type: expected type parameter but found type parameter linear/linear.rs:82 fn pop(list : @List_Data) -> (Option<@T>, @List<@T>) { linear/linear.rs:83 (None, @Nil) linear/linear.rs:84 } linear/linear.rs:51:8: 58:9 error: mismatched types: expected `core::option::Option<'b>` but found `core::option::Option<@'b>` (expected type parameter but found @-ptr) linear/linear.rs:51 match (list) { linear/linear.rs:52 @Nil => { linear/linear.rs:53 None linear/linear.rs:54 } linear/linear.rs:55 @Cons(e, _) => { linear/linear.rs:56 Some(e) ... linear/linear.rs:83:8: 83:20 error: mismatched types: expected `(core::option::Option<@'b>, at List<@'b>)` but found `(core::option::Option<>, at List_Data<>)` (expected trait List but found @-ptr) linear/linear.rs:83 (None, @Nil) ^~~~~~~~~~~~ error: aborting due to 7 previous errors make: *** [test_linear] Error 101 Regards, Paul Nathan From pwalton at mozilla.com Wed Dec 26 10:18:53 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 26 Dec 2012 13:18:53 -0500 Subject: [rust-dev] "expected type parameter but found type parameters" In-Reply-To: <62D822AB-5196-48B3-AD4A-10489622DE5E@vandals.uidaho.edu> References: <62D822AB-5196-48B3-AD4A-10489622DE5E@vandals.uidaho.edu> Message-ID: <50DB3F8D.2060900@mozilla.com> On 12/26/12 12:23 PM, Paul Nathan wrote: > Good morning, > > I am exploring Rust's traits in relation to working on data > structures. Unfortunately, I have managed to back myself into a hole > with an error message that I can't understand the problem with; to > wit, "has an incompatible type: expected type parameter but found > type parameter" is an error I don't understand. > > I've stuffed the code up on github: > https://github.com/pnathan/flaky-data-structures/tree/non-compiling Remove the extra from your methods. You want the traits to look like: trait Queue : List { fn peek(seq: @self) -> Option<@T>; fn pop(seq: @self) -> (Option<@T>, @self); } Not like: trait Queue : List { fn peek(seq: @self) -> Option<@T>; fn pop(seq: @self) -> (Option<@T>, @self); } Patrick From mneumann at ntecs.de Thu Dec 27 04:11:08 2012 From: mneumann at ntecs.de (Michael Neumann) Date: Thu, 27 Dec 2012 13:11:08 +0100 Subject: [rust-dev] Trying to get simple TCP server working In-Reply-To: <50DB28D2.3070505@mozilla.com> References: <50DAF6DA.10105@ntecs.de> <50DB28D2.3070505@mozilla.com> Message-ID: <50DC3ADC.40606@ntecs.de> Am 26.12.2012 17:41, schrieb Patrick Walton: > On 12/26/12 8:08 AM, Michael Neumann wrote: >> Hi, >> >> I am trying to write a very simple TCP server (code given below), which >> just reads from a >> socket, but somehow the read() blocks forever. Any idea what I am doing >> wrong? >> I also tried to create a task for each new incoming connection, but the >> same happens. >> I actually found this example on the internet... > > Please file an issue. https://github.com/mozilla/rust/issues/4296 Michael From niko at alum.mit.edu Thu Dec 27 15:16:46 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 27 Dec 2012 15:16:46 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: References: Message-ID: <50DCD6DE.5050409@alum.mit.edu> I'm sorry for not replying more quickly, I was not checking e-mail over xmas break. I do not know of any general problems with @ and borrowing. In any event, this is a misdiagnosis. The problem is this: the declaration of iter looks like this: impl RBMap: iter::BaseIter<(&K, &V)> In the context of a type declaration, an & means `&self`, where `self` is the lifetime parameter associated with the type/impl/whatever (just as the impl has two type parameters K and V, it also has an implicit lifetime parameter `self`). So, this declaration written out more explicitly would be: impl RBMap: iter::BaseIter<(&self/K, &self/V)> However, your method declaration is: pure fn each(&self, f: fn(&(&K, &V)) -> bool) { ... } In the context of a function declaration, & means "a fresh lifetime". So this winds up being short for a declaration life this: pure fn each(&self, f: fn(&a/(&a/K, &a/V)) -> bool) { ... } However, the trait declares that `each` should have this type: pure fn each(&self, f: fn(&a/(&self/K, &self/V)) -> bool) { ... } So I think that if you change your declaraiton of `each()` to: pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { ... } It will work just fine. I apologize for the cryptic error message. Working on it. I think the system of defaults regarding types like `&T` needs to change. I hope that a more explicit notation would make the problem more obvious. But that's a subject for another e-mail. Niko Lucian Branescu wrote: > > I think the problem is the compiler can't guarantee the managed box > will survive, so it won't allow a borrowed pointer. > > I think there are problems in general with @ and borrowing. > > I've converted the red-black tree I wrote to use iter::BaseIter but am > now fighting with lifetime analysis with the switch to 0.5. > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L91 > > And the error I'm getting with 0.5 is: > > http://pastebin.com/YK8v7EdA > > I've read the docs on lifetimes several times now but it's not quite > enough to get me over this hurdle. > > > Thanks! > Steve > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Dec 27 15:26:16 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 27 Dec 2012 15:26:16 -0800 Subject: [rust-dev] Help understanding lifetimes. In-Reply-To: References: <50D8BFE0.8020305@mozilla.com> Message-ID: <50DCD918.2040601@alum.mit.edu> This is actually bug 3148: https://github.com/mozilla/rust/issues/3148 You can use explicit type declarations as a workaround for the time being. Your rewrite also works in the same manner: it overcomes a shortcoming in the region inferencer. I hope we can fix this soon, it's not terribly difficult. Niko Steven Blenkinsop wrote: > Turns out the issue was borrowing from a reborrowed value. i.e. this > doesn't work: > > fn rereborrow(v: &r/int) -> &r/int { > &*&*v > } > > I've filed an issue: https://github.com/mozilla/rust/issues/4285 > > Incidentally, I can make my original code work by eliminating the > intermediate borrow: > > struct T1 { value: int } > struct T2 { t1: option::Option<~T1> } > > fn value(t2: &r/T2, def: &r/int) -> &r/int { > match t2.t1 { > Some(~T1{value: ref value}) => value, > None => def > } > } > > fn main() { > let t2 = ~T2{ t1: Some(~T1{ value: 5 }) }; > let def = ~0; > io::println(fmt!("%d", *value(t2, def))); > } > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From gaozm55 at gmail.com Fri Dec 28 01:40:29 2012 From: gaozm55 at gmail.com (James Gao) Date: Fri, 28 Dec 2012 17:40:29 +0800 Subject: [rust-dev] How to assert or get sizeof(T) at compile time? Message-ID: Hi, How can I static_assert(expr) or evaluate sizeof(T) at compile time? Having these operators/keywords, we can optmize or check many code when compiling. See the following snippet: fn dump_memory(t : T) { ... let buff : [u8 * sizeof T] = ....; statc_assert (sizeof T < 1024*1024); .... } -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Fri Dec 28 11:19:20 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 28 Dec 2012 11:19:20 -0800 Subject: [rust-dev] How to assert or get sizeof(T) at compile time? In-Reply-To: References: Message-ID: <50DDF0B8.2020007@mozilla.com> On 12/28/12 1:40 AM, James Gao wrote: > Hi, > > How can I static_assert(expr) or evaluate sizeof(T) at compile time? > Having these operators/keywords, we can optmize or check many code when > compiling. See the following snippet: > > fn dump_memory(t : T) { > ... > let buff : [u8 * sizeof T] = ....; > statc_assert (sizeof T < 1024*1024); > .... > } You can't do either of these today, unless you write a syntax extension and build it into the compiler. `sizeof()` might be nice to build into the language, for the reason you suggest. That said, there's a real limit to how complex we can make the constant evaluation system without going off the cliff of language complexity. Even the ability to say `[u8 * ]` interacts with other language features in surprisingly complex ways (although I think we should support it anyway). I suspect `static_assert` wouldn't be useful unless we added things like D's compile-time function evaluation or C++'s `constexpr`, which strikes me as crossing the line. We already have a system planned for doing arbitrary code evaluation at compile time: the syntax extension system. When we get the ability to dynamically link syntax extensions into the compiler, you'll be able to perform arbitrary static assertions at compile time by writing a syntax extension that reports an error if some condition doesn't hold. (To make it really convenient to use, we'll probably want to allow syntax extensions to be written within the same crate that they're used.) In general, I think this is a more flexible and less ad-hoc system than compile-time function evaluation; Lisp and Scheme dialects use it to great effect, for instance. Patrick From stevej at fruitless.org Fri Dec 28 13:20:46 2012 From: stevej at fruitless.org (Steve Jenson) Date: Fri, 28 Dec 2012 13:20:46 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: <50DCD6DE.5050409@alum.mit.edu> References: <50DCD6DE.5050409@alum.mit.edu> Message-ID: On Thu, Dec 27, 2012 at 3:16 PM, Niko Matsakis wrote: > I'm sorry for not replying more quickly, I was not checking e-mail over > xmas break. I do not know of any general problems with @ and borrowing. > In any event, this is a misdiagnosis. > No problem with reply timing. > The problem is this: the declaration of iter looks like this: > > impl RBMap: iter::BaseIter<(&K, &V)> > > In the context of a type declaration, an & means `&self`, where `self` is > the lifetime parameter associated with the type/impl/whatever (just as the > impl has two type parameters K and V, it also has an implicit lifetime > parameter `self`). So, this declaration written out more explicitly would > be: > > impl RBMap: iter::BaseIter<(&self/K, > &self/V)> > > However, your method declaration is: > > pure fn each(&self, f: fn(&(&K, &V)) -> bool) { ... } > > In the context of a function declaration, & means "a fresh lifetime". So > this winds up being short for a declaration life this: > > pure fn each(&self, f: fn(&a/(&a/K, &a/V)) -> bool) { ... } > > However, the trait declares that `each` should have this type: > > pure fn each(&self, f: fn(&a/(&self/K, &self/V)) -> bool) { ... } > > So I think that if you change your declaraiton of `each()` to: > > pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { ... } > > It will work just fine. I apologize for the cryptic error message. > Working on it. > Unfortunately not but a much more interesting set of error messages about lifetimes is coming out now: http://pastebin.com/SYwCw1ac And here is a link to the each method again (I pushed this broken version to github so I can share the exact changes I made) https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L96 Thanks a bunch for all of your clarifying comments and blog posts. Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From colin.mailinglist at gmail.com Sun Dec 30 03:17:04 2012 From: colin.mailinglist at gmail.com (Colin Fleming) Date: Mon, 31 Dec 2012 00:17:04 +1300 Subject: [rust-dev] Newbie questions about memory management Message-ID: Hi all, I'm playing around with Rust a little having been interested in it for a while. I've read the language and borrowed pointers tutorials but I'm still struggling with what seems like a fairly trivial example. I have a StringReader type: struct StringReader { data: &str, mut next: uint } and I'm trying to create a constructor for it: impl StringReader { static fn new(value: &str) -> StringReader { StringReader { data: value, next: 0 } } } I can't do this because the compiler "cannot infer an appropriate lifetime", which I take to mean that it can't work out the lifetime of 'value', probably because I shouldn't be using a borrowed pointer here. I tried a named lifetime, to indicate that the returned StringReader pointer should be valid as long as the string is: static fn new(value: &lifetime/str) -> &lifetime/StringReader { &StringReader { data: value, next: 0 } } but that doesn't work either since the lifetime of the return value is not the same as the lifetime of the param. I also tried by value: struct StringReader { data: str, mut next: uint } static fn new(value: str) -> StringReader { StringReader { data: value, next: 0 } } but to my amazement "bare `str` is not a type" - I'd expected this just to create an inefficient copying version. The only thing I've managed to get to work is an owned string: struct StringReader { data: ~str, mut next: uint } static fn new(value: ~str) -> StringReader { StringReader { data: value, next: 0 } } Is this my best option here? What is the best practice for constructors? Another thing that I don't quite understand: according to the tutorials, a struct constructed so: StringReader { data: value, next: 0 } is allocated on the stack. How does this work with the return value of the constructor? Since the return value is only in scope in the constructor body, I suppose this means that the return value of the constructor is copied - isn't this inefficient for constructors? Thanks for any and all clarification, Colin -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sun Dec 30 06:48:28 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 30 Dec 2012 06:48:28 -0800 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: References: Message-ID: <50E0543C.5030204@alum.mit.edu> You have two options. If you wish to use a borrowed pointer, you may write the function `new()` like so: static fn new(value: &lifetime/str) -> StringReader/&lifetime { StringReader { data: value, next: 0 } } The notation StringReader/&lifetime is (probably) not well-documented. What it means is: "a StringReader instance which contains borrowed pointers with the lifetime `lifetime`". So basically it is specifying the lifetime of the `value` field, in this case. Note that if the `StringReader` had multiple borrowed pointers contained within, they would all have to have the same lifetime. Alternatively, you could have the StringReader own the data it is reading from, in which case you would want to use an `@str` or `~str`, just as you showed. Ultimately, we would probably want both types in the standard library, since each can be useful in different circumstances. Regarding your second question, the compiler makes some effort to construct data precisely into the location where it is needed. So in the constructor function above, what happens is that a pointer into the caller's stack is passed as an implicit first parameter. The struct is then written directly into the caller's stack. This works so long as the return expression itself constructs the struct (more generally, so long as you return an rvalue). It would not work if you stored the struct into a variable and returned that. e.g., although there is no semantic difference, this program would *not* be optimized: static fn new(value: &lifetime/str) -> StringReader/&lifetime { let r = StringReader { data: value, next: 0 }; return r; } Here the compiler would produce a memcpy. Niko Colin Fleming wrote: > Hi all, > > I'm playing around with Rust a little having been interested in it for > a while. I've read the language and borrowed pointers tutorials but > I'm still struggling with what seems like a fairly trivial example. > > I have a StringReader type: > > struct StringReader { > data: &str, > mut next: uint > } > > and I'm trying to create a constructor for it: > > impl StringReader { > static fn new(value: &str) -> StringReader { > StringReader { data: value, next: 0 } > } > } > > I can't do this because the compiler "cannot infer an appropriate > lifetime", which I take to mean that it can't work out the lifetime of > 'value', probably because I shouldn't be using a borrowed pointer here. > > I tried a named lifetime, to indicate that the returned StringReader > pointer should be valid as long as the string is: > > static fn new(value: &lifetime/str) -> &lifetime/StringReader { > &StringReader { data: value, next: 0 } > } > > but that doesn't work either since the lifetime of the return value is > not the same as the lifetime of the param. > > I also tried by value: > > struct StringReader { > data: str, > mut next: uint > } > > static fn new(value: str) -> StringReader { > StringReader { data: value, next: 0 } > } > > but to my amazement "bare `str` is not a type" - I'd expected this > just to create an inefficient copying version. > > The only thing I've managed to get to work is an owned string: > > struct StringReader { > data: ~str, > mut next: uint > } > > static fn new(value: ~str) -> StringReader { > StringReader { data: value, next: 0 } > } > > Is this my best option here? What is the best practice for constructors? > > Another thing that I don't quite understand: according to the > tutorials, a struct constructed so: > > StringReader { data: value, next: 0 } > > is allocated on the stack. How does this work with the return value of > the constructor? Since the return value is only in scope in the > constructor body, I suppose this means that the return value of the > constructor is copied - isn't this inefficient for constructors? > > Thanks for any and all clarification, > Colin > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: From colin.mailinglist at gmail.com Sun Dec 30 12:50:49 2012 From: colin.mailinglist at gmail.com (Colin Fleming) Date: Mon, 31 Dec 2012 09:50:49 +1300 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: <50E0543C.5030204@alum.mit.edu> References: <50E0543C.5030204@alum.mit.edu> Message-ID: Great, thanks for the clarifications, Niko, that helps a lot. I think I'll probably use the borrowed pointer notation. I'm assuming that the compiler optimisation you describe works for any function returning an rvalue, not just for something that looks like a constructor (i.e. functions called "new" are not special in any way)? Thanks, Colin On 31 December 2012 03:48, Niko Matsakis wrote: > You have two options. > > If you wish to use a borrowed pointer, you may write the function `new()` > like so: > > static fn new(value: &lifetime/str) -> StringReader/&lifetime { > StringReader { data: value, next: 0 } > } > > The notation StringReader/&lifetime is (probably) not well-documented. > What it means is: "a StringReader instance which contains borrowed > pointers with the lifetime `lifetime`". So basically it is specifying the > lifetime of the `value` field, in this case. Note that if the > `StringReader` had multiple borrowed pointers contained within, they would > all have to have the same lifetime. > > Alternatively, you could have the StringReader own the data it is reading > from, in which case you would want to use an `@str` or `~str`, just as you > showed. Ultimately, we would probably want both types in the standard > library, since each can be useful in different circumstances. > > Regarding your second question, the compiler makes some effort to > construct data precisely into the location where it is needed. So in the > constructor function above, what happens is that a pointer into the > caller's stack is passed as an implicit first parameter. The struct is > then written directly into the caller's stack. This works so long as the > return expression itself constructs the struct (more generally, so long as > you return an rvalue). It would not work if you stored the struct into a > variable and returned that. > > e.g., although there is no semantic difference, this program would *not* > be optimized: > > static fn new(value: &lifetime/str) -> StringReader/&lifetime { > let r = StringReader { data: value, next: 0 }; > return r; > } > > Here the compiler would produce a memcpy. > > > Niko > > > > Colin Fleming wrote: > > Hi all, > > I'm playing around with Rust a little having been interested in it for a > while. I've read the language and borrowed pointers tutorials but I'm still > struggling with what seems like a fairly trivial example. > > I have a StringReader type: > > struct StringReader { > data: &str, > mut next: uint > } > > and I'm trying to create a constructor for it: > > impl StringReader { > static fn new(value: &str) -> StringReader { > StringReader { data: value, next: 0 } > } > } > > I can't do this because the compiler "cannot infer an appropriate > lifetime", which I take to mean that it can't work out the lifetime of > 'value', probably because I shouldn't be using a borrowed pointer here. > > I tried a named lifetime, to indicate that the returned StringReader > pointer should be valid as long as the string is: > > static fn new(value: &lifetime/str) -> &lifetime/StringReader { > &StringReader { data: value, next: 0 } > } > > but that doesn't work either since the lifetime of the return value is not > the same as the lifetime of the param. > > I also tried by value: > > struct StringReader { > data: str, > mut next: uint > } > > static fn new(value: str) -> StringReader { > StringReader { data: value, next: 0 } > } > > but to my amazement "bare `str` is not a type" - I'd expected this just to > create an inefficient copying version. > > The only thing I've managed to get to work is an owned string: > > struct StringReader { > data: ~str, > mut next: uint > } > > static fn new(value: ~str) -> StringReader { > StringReader { data: value, next: 0 } > } > > Is this my best option here? What is the best practice for constructors? > > Another thing that I don't quite understand: according to the tutorials, a > struct constructed so: > > StringReader { data: value, next: 0 } > > is allocated on the stack. How does this work with the return value of the > constructor? Since the return value is only in scope in the constructor > body, I suppose this means that the return value of the constructor is > copied - isn't this inefficient for constructors? > > Thanks for any and all clarification, > Colin > > _______________________________________________ > Rust-dev mailing listRust-dev at mozilla.orghttps://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sun Dec 30 12:52:04 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 30 Dec 2012 12:52:04 -0800 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: References: <50E0543C.5030204@alum.mit.edu> Message-ID: <50E0A974.5020603@mozilla.com> On 12/30/12 12:50 PM, Colin Fleming wrote: > Great, thanks for the clarifications, Niko, that helps a lot. I think > I'll probably use the borrowed pointer notation. > > I'm assuming that the compiler optimisation you describe works for any > function returning an rvalue, not just for something that looks like a > constructor (i.e. functions called "new" are not special in any way)? Yep. C++-style return value optimization is part of Rust's ABI and mandated by the language. Patrick From colin.mailinglist at gmail.com Sun Dec 30 12:52:54 2012 From: colin.mailinglist at gmail.com (Colin Fleming) Date: Mon, 31 Dec 2012 09:52:54 +1300 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: <50E0A974.5020603@mozilla.com> References: <50E0543C.5030204@alum.mit.edu> <50E0A974.5020603@mozilla.com> Message-ID: Great, thanks Patrick. On 31 December 2012 09:52, Patrick Walton wrote: > On 12/30/12 12:50 PM, Colin Fleming wrote: > >> Great, thanks for the clarifications, Niko, that helps a lot. I think >> I'll probably use the borrowed pointer notation. >> >> I'm assuming that the compiler optimisation you describe works for any >> function returning an rvalue, not just for something that looks like a >> constructor (i.e. functions called "new" are not special in any way)? >> > > Yep. C++-style return value optimization is part of Rust's ABI and > mandated by the language. > > Patrick > > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucian.branescu at gmail.com Sun Dec 30 12:56:28 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Sun, 30 Dec 2012 20:56:28 +0000 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: <50E0A974.5020603@mozilla.com> References: <50E0543C.5030204@alum.mit.edu> <50E0A974.5020603@mozilla.com> Message-ID: Would it be possible to have a more general mechanism for creating and relinquishing objects? The rvalue trick seems obscure and only situationally useful. On 30 Dec 2012 20:52, "Patrick Walton" wrote: > On 12/30/12 12:50 PM, Colin Fleming wrote: > >> Great, thanks for the clarifications, Niko, that helps a lot. I think >> I'll probably use the borrowed pointer notation. >> >> I'm assuming that the compiler optimisation you describe works for any >> function returning an rvalue, not just for something that looks like a >> constructor (i.e. functions called "new" are not special in any way)? >> > > Yep. C++-style return value optimization is part of Rust's ABI and > mandated by the language. > > Patrick > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sun Dec 30 12:58:47 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 30 Dec 2012 12:58:47 -0800 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: References: <50E0543C.5030204@alum.mit.edu> <50E0A974.5020603@mozilla.com> Message-ID: <50E0AB07.50903@mozilla.com> On 12/30/12 12:56 PM, Lucian Branescu wrote: > Would it be possible to have a more general mechanism for creating and > relinquishing objects? The rvalue trick seems obscure and only > situationally useful. Broadly speaking, that's what "move" is for. Did you want something beyond that? Patrick From niko at alum.mit.edu Sun Dec 30 13:16:02 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 30 Dec 2012 13:16:02 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: References: <50DCD6DE.5050409@alum.mit.edu> Message-ID: <50E0AF12.8020006@alum.mit.edu> The errors you are seeing now are in fact related to borrowing @T values, as suggested in a previous message. In this case, your problem is that you need to have values with the same lifetime as the this pointer, but the default match construct copies value out. This means that the lifetime of the copied-out values is limited to the current stack frame. You can address this using `ref` mode. Unfortunately, due to the bug with lifetime inference cited earlier, you will need to provide explicit hints to help the type checker out. Hopefully this will be fixed soon. In any case, I've made the requisite changes here: https://github.com/nikomatsakis/rustled/commit/aea45eeeea2b328f5f3c6515de21be2039a9498d and opened a pull request: https://github.com/stevej/rustled/pull/1 regards, Niko Steve Jenson wrote: > On Thu, Dec 27, 2012 at 3:16 PM, Niko Matsakis > wrote: > > I'm sorry for not replying more quickly, I was not checking e-mail > over xmas break. I do not know of any general problems with @ and > borrowing. In any event, this is a misdiagnosis. > > > No problem with reply timing. > > The problem is this: the declaration of iter looks like this: > > impl RBMap: iter::BaseIter<(&K, > &V)> > > In the context of a type declaration, an & means `&self`, where > `self` is the lifetime parameter associated with the > type/impl/whatever (just as the impl has two type parameters K and > V, it also has an implicit lifetime parameter `self`). So, this > declaration written out more explicitly would be: > > impl RBMap: > iter::BaseIter<(&self/K, &self/V)> > > However, your method declaration is: > > pure fn each(&self, f: fn(&(&K, &V)) -> bool) { ... } > > In the context of a function declaration, & means "a fresh > lifetime". So this winds up being short for a declaration life this: > > pure fn each(&self, f: fn(&a/(&a/K, &a/V)) -> bool) { ... } > > However, the trait declares that `each` should have this type: > > pure fn each(&self, f: fn(&a/(&self/K, &self/V)) -> bool) { ... } > > So I think that if you change your declaraiton of `each()` to: > > pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { ... } > > It will work just fine. I apologize for the cryptic error > message. Working on it. > > > Unfortunately not but a much more interesting set of error messages > about lifetimes is coming out now: http://pastebin.com/SYwCw1ac > > And here is a link to the each method again (I pushed this broken > version to github so I can share the exact changes I made) > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L96 > > Thanks a bunch for all of your clarifying comments and blog posts. > > Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sun Dec 30 13:16:56 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 30 Dec 2012 13:16:56 -0800 Subject: [rust-dev] Question about lifetime analysis (a 0.5 transition question) In-Reply-To: References: <50DCD6DE.5050409@alum.mit.edu> Message-ID: <50E0AF48.6080703@alum.mit.edu> Oh, one other thing: Your each() method does not obey the for protocol! When the callback returns false, you should abort iteration altogether. This presumably means you need to do the recursion in a helper method that itself returns bool so that you can detect when to carry on and when to abort. Niko Steve Jenson wrote: > On Thu, Dec 27, 2012 at 3:16 PM, Niko Matsakis > wrote: > > I'm sorry for not replying more quickly, I was not checking e-mail > over xmas break. I do not know of any general problems with @ and > borrowing. In any event, this is a misdiagnosis. > > > No problem with reply timing. > > The problem is this: the declaration of iter looks like this: > > impl RBMap: iter::BaseIter<(&K, > &V)> > > In the context of a type declaration, an & means `&self`, where > `self` is the lifetime parameter associated with the > type/impl/whatever (just as the impl has two type parameters K and > V, it also has an implicit lifetime parameter `self`). So, this > declaration written out more explicitly would be: > > impl RBMap: > iter::BaseIter<(&self/K, &self/V)> > > However, your method declaration is: > > pure fn each(&self, f: fn(&(&K, &V)) -> bool) { ... } > > In the context of a function declaration, & means "a fresh > lifetime". So this winds up being short for a declaration life this: > > pure fn each(&self, f: fn(&a/(&a/K, &a/V)) -> bool) { ... } > > However, the trait declares that `each` should have this type: > > pure fn each(&self, f: fn(&a/(&self/K, &self/V)) -> bool) { ... } > > So I think that if you change your declaraiton of `each()` to: > > pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { ... } > > It will work just fine. I apologize for the cryptic error > message. Working on it. > > > Unfortunately not but a much more interesting set of error messages > about lifetimes is coming out now: http://pastebin.com/SYwCw1ac > > And here is a link to the each method again (I pushed this broken > version to github so I can share the exact changes I made) > > https://github.com/stevej/rustled/blob/master/red_black_tree.rs#L96 > > Thanks a bunch for all of your clarifying comments and blog posts. > > Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucian.branescu at gmail.com Sun Dec 30 13:26:17 2012 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Sun, 30 Dec 2012 21:26:17 +0000 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: <50E0AB07.50903@mozilla.com> References: <50E0543C.5030204@alum.mit.edu> <50E0A974.5020603@mozilla.com> <50E0AB07.50903@mozilla.com> Message-ID: Ah, good point. I guess it just seems I'd be likely to not figure out why a programme gets slower when I add a let. On 30 Dec 2012 20:58, "Patrick Walton" wrote: > On 12/30/12 12:56 PM, Lucian Branescu wrote: > >> Would it be possible to have a more general mechanism for creating and >> relinquishing objects? The rvalue trick seems obscure and only >> situationally useful. >> > > Broadly speaking, that's what "move" is for. Did you want something beyond > that? > > Patrick > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From colin.mailinglist at gmail.com Sun Dec 30 13:55:13 2012 From: colin.mailinglist at gmail.com (Colin Fleming) Date: Mon, 31 Dec 2012 10:55:13 +1300 Subject: [rust-dev] Newbie questions about memory management In-Reply-To: References: <50E0543C.5030204@alum.mit.edu> <50E0A974.5020603@mozilla.com> <50E0AB07.50903@mozilla.com> Message-ID: Having thought about this some more, it seems like the concept of lifetime is closely related to the allocation strategy. Is the compiler clever enough to return a type allocated in a different way depending on the parameter I pass it? i.e. will the compiler generate different code in the following cases: static fn new(value: &lifetime/str) -> StringReader/&lifetime { StringReader { data: value, next: 0 } } // Get these from somewhere let x = @"abc" let y = ~"abc" let on_the_stack = StringReader::new("abc") let managed = StringReader::new(x) let owned = StringReader::new(y) I'm assuming not, since I assume that T, ~T and @T are distinct types, although I guess the compiler could compile 3 specialisations, similar to monomorphism. But I guess that the lifetime here is actually the stack-bound lifetime of the local variables (x and y) and not of the data that they point to - is this right? If so, this implies that the rvalue trick only really lets you take borrowed pointers to stack-bound variables, which seems a little limited. On 31 December 2012 10:26, Lucian Branescu wrote: > Ah, good point. I guess it just seems I'd be likely to not figure out why > a programme gets slower when I add a let. > On 30 Dec 2012 20:58, "Patrick Walton" wrote: > >> On 12/30/12 12:56 PM, Lucian Branescu wrote: >> >>> Would it be possible to have a more general mechanism for creating and >>> relinquishing objects? The rvalue trick seems obscure and only >>> situationally useful. >>> >> >> Broadly speaking, that's what "move" is for. Did you want something >> beyond that? >> >> Patrick >> >> > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sun Dec 30 20:35:52 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 30 Dec 2012 20:35:52 -0800 Subject: [rust-dev] RFC: "impl Trait for Type" Message-ID: <50E11628.7030105@mozilla.com> There's recently been some evidence that the current state of affairs regarding where methods go is confusing; I think that our current impl syntax is resulting in some confusion. In particular, the difference I'm concerned about is this one (which I've explained on my blog [1]). This code compiles: struct Foo { x: int, y: int } impl Foo { static fn new() -> Foo { Foo { x: 1, y: 2 } } } fn main() { let x = Foo::new(); } But this code does not: trait Constructible { static fn new() -> self; } struct Foo { ... /* as before */ ... } impl Foo : Constructible { static fn new() -> Foo { Foo { x: 1, y: 2 } } } fn main() { let x = Foo::new(); } Can you spot the bug? It's that the latter `impl` (with the `:`) is a trait implementation, not a type implementation, so it does not define a new name. Therefore, the call to `Foo::new()` does not resolve. With trait implementations, the methods it defines are scoped to the item on the *right-hand* side of the `:`, not the left-hand side. In this example, they're scoped to `Constructible`. The way to fix this is to change the code to: fn main() { let x = Constructible::new(); } This state of affairs strikes me as confusing to C++/Java/C# users, who might be expecting the methods to be available in `Foo` as well as the `Constructible` interface. Indeed this was the case in earlier versions of Rust (and is the case today in some cases), but I worry that this feature is dangerous, as we might want our type to later implement a different typeclass with a different method called `new` and there would then be a name clash. I also did a small survey of programming language syntax. Of the languages I'm aware of with typeclasses, here are the syntaxes I've seen for typeclass implementations: * Haskell: `instance Typeclass Type where ...` * C++1x concepts proposal: `concept_map Concept { ... }` * Roy: `instance name = Typeclass Type { ... }` * Felix: `instance Typeclass[Type] { ... }` * Clojure: `(extend-type Type PROTOCOL ...)` With the exception of Clojure, the languages seem to weigh heavily in favor of putting the typeclass before the type. Again, this makes sense to me, because the typeclass is where the methods are scoped to. A while back, Niko proposed `impl Trait for Type`, which seems popular, based on an informal survey of the IRC channel. I like its clarity as well. With this change, the non-compiling example above would read this way: trait Constructible { static fn new() -> self; } struct Foo { ... /* as before */ ... } impl Constructible for Foo { static fn new() -> Foo { Foo { x: 1, y: 2 } } } fn main() { let x = Foo::new(); // ERROR unresolved name } Now it seems easier to understand why this does not compile: the `new()` method is part of `Constructible`, not part of `Foo`. Because `Constructible` is on the left, it doesn't look like we've placed the `new` method in the `Foo` namespace. I understand that there was an objection last time this syntax was brought up that our trait syntax in generics is `T:Trait`, and therefore it's more consistent to say `impl T : Trait`. However, it seems to me that the situation back then is different from the situation now in these ways: 1. It's no longer possible to implement more than one trait per `impl` declaration. This means that there will always be a difference between the generic syntax and the `impl` syntax no matter what we do: the generic syntax supports multiple traits, while the `impl` syntax supports just one. 2. The consequences of the programmer not understanding where the methods go are more severe now. Compared to the situation in the past, the programmer is now more likely to notice the difference between scoping the methods to the trait and scoping the methods to the type for two reasons: (a) As noted before, I don't think that it'll work long-term to automatically make methods on trait implementations accessible without importing the trait, as Rust does today for non-static methods defined in the same module as the type. Besides the fact that I've always worried that this little-known rule is too subtle (did anybody else know about this?), it'll cause problems if I implement a method named `foo` on trait `A`, code starts to depend on calling `foo` without importing `A`, and then later on I implement a different method called `foo` on trait `B`; it'll break the original code. (b) We have static methods now, and they don't leak out of their containing scopes; as such, they must be explicitly qualified with the trait that they belong to. This means that the scope that each method belongs to is now very apparent to the programmer and can't be swept under the rug. So I'd like to consider changing the syntax for trait implementations only to `impl Trait for Type { ... }` for Rust 0.6. I understand that this is a late-stage proposal, and for that I apologize. But I worry more about the potential for confusion, as typeclasses are an uncommon feature in languages to begin with. Above all, I'd like to know whether others agree that this is confusing, and whether others think the new syntax is an improvement. Thanks, Patrick [1]: http://pcwalton.github.com/blog/2012/12/30/the-two-meanings-of-impl/ From garethdanielsmith at gmail.com Mon Dec 31 03:05:48 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Mon, 31 Dec 2012 11:05:48 +0000 Subject: [rust-dev] RFC: "impl Trait for Type" In-Reply-To: <50E11628.7030105@mozilla.com> References: <50E11628.7030105@mozilla.com> Message-ID: <50E1718C.9040707@gmail.com> I agree it is confusing and that the proposed syntax would probably be less so. But, I think that: impl Trait for Type { ... } Is still possible to confuse with: impl Type { ... } Because they both start with the same keyword. Though perhaps this is not significant. Gareth From pwalton at mozilla.com Mon Dec 31 08:54:26 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 31 Dec 2012 08:54:26 -0800 Subject: [rust-dev] RFC: "impl Trait for Type" In-Reply-To: <50E1718C.9040707@gmail.com> References: <50E11628.7030105@mozilla.com> <50E1718C.9040707@gmail.com> Message-ID: <50E1C342.20401@mozilla.com> On 12/31/12 3:05 AM, Gareth Smith wrote: > Because they both start with the same keyword. Though perhaps this is > not significant. Agreed, I considered this. There are a couple of reasons why I didn't propose a different keyword: 1. Rust tries hard to reuse keywords in general, since everyone likes a small set of keywords. 2. I didn't really like any of the obvious options. The most obvious keyword to switch to would be "inst" to mirror Haskell and so forth, but is "impl"/"inst" really less confusing? I suspect many programmers would want to "implement" a trait and would choose "impl". Patrick From colin.mailinglist at gmail.com Mon Dec 31 14:17:00 2012 From: colin.mailinglist at gmail.com (Colin Fleming) Date: Tue, 1 Jan 2013 11:17:00 +1300 Subject: [rust-dev] RFC: "impl Trait for Type" In-Reply-To: <50E1C342.20401@mozilla.com> References: <50E11628.7030105@mozilla.com> <50E1718C.9040707@gmail.com> <50E1C342.20401@mozilla.com> Message-ID: As a (very) new user of Rust, I would definitely have found this confusing. I think the proposal makes it much clearer what is happening, and I think that reusing 'impl' is fine - the two 'impl' forms are sufficiently different to avoid any confusion. Cheers, Colin On 1 January 2013 05:54, Patrick Walton wrote: > On 12/31/12 3:05 AM, Gareth Smith wrote: > >> Because they both start with the same keyword. Though perhaps this is >> not significant. >> > > Agreed, I considered this. There are a couple of reasons why I didn't > propose a different keyword: > > 1. Rust tries hard to reuse keywords in general, since everyone likes a > small set of keywords. > > 2. I didn't really like any of the obvious options. The most obvious > keyword to switch to would be "inst" to mirror Haskell and so forth, but is > "impl"/"inst" really less confusing? I suspect many programmers would want > to "implement" a trait and would choose "impl". > > Patrick > > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Mon Dec 31 14:18:46 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 31 Dec 2012 14:18:46 -0800 Subject: [rust-dev] RFC: "impl Trait for Type" In-Reply-To: <50E1C342.20401@mozilla.com> References: <50E11628.7030105@mozilla.com> <50E1718C.9040707@gmail.com> <50E1C342.20401@mozilla.com> Message-ID: <50E20F46.6020704@alum.mit.edu> I think of it was "implementing a type" (that is, defining the methods that are intrinsic to a type) vs "implementing a trait". It feels pretty natural to me to think of it that way. Niko Patrick Walton wrote: > On 12/31/12 3:05 AM, Gareth Smith wrote: >> Because they both start with the same keyword. Though perhaps this is >> not significant. > > Agreed, I considered this. There are a couple of reasons why I didn't > propose a different keyword: > > 1. Rust tries hard to reuse keywords in general, since everyone likes > a small set of keywords. > > 2. I didn't really like any of the obvious options. The most obvious > keyword to switch to would be "inst" to mirror Haskell and so forth, > but is "impl"/"inst" really less confusing? I suspect many programmers > would want to "implement" a trait and would choose "impl". > > Patrick > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev