From mneumann at ntecs.de Fri Feb 1 03:09:43 2013 From: mneumann at ntecs.de (Michael Neumann) Date: Fri, 01 Feb 2013 12:09:43 +0100 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510AF22D.3040509@mozilla.com> References: <510AF22D.3040509@mozilla.com> Message-ID: <510BA277.6070701@ntecs.de> Am 31.01.2013 23:37, schrieb Patrick Walton: > Hi everyone, > > With the revamp of the scheduler underway, I'd like to propose a > change to the way C functions work. > > Currently, we generate a shim and a stack switch for every function > call from Rust to C and likewise from C to Rust, except for functions > annotated with `#[rust_stack]`. These wrappers result in a significant > performance overhead. For some workloads this performance overhead is > acceptable in order to maintain small stacks. For some workloads the > performance overhead is undesirable. > > For instance, the DOM in Servo requires lots of very small calls from > JavaScript to Rust. The overhead of stack switching swamps most of the > time here. Popular Web benchmarks will do things like > `someElement.clientX;` over and over, which require calls from > JavaScript to Rust to retrieve a cached value. So we must carefully > consider every CPU cycle spent in the C-to-Rust transition. > > To address these issues I would like to propose a somewhat radical > change: don't have the compiler generate stack switching stubs at all. > Instead, the scheduler can expose a primitive that generates the stack > switch, and it's the programmer's responsibility to perform the stack > switch to call out to C functions. To avoid the obvious footgun here, > I propose a lint pass, on by default, that ensures that functions not > annotated with `#[rust_stack]` are called inside a stack switching > helper. > > The rationale here is as follows: > > 1. It should be possible to group many C calls under a single stack > switching operation. For example: > > do stackswitch { > c_function_1(); > c_function_2(); > c_function_3(); > } wouldn't it be possible for this case to just do: extern mod lib_c { #[rust_stack] fn c_function_1(); #[rust_stack] fn c_function_2(); #[rust_stack] fn c_function_3(); } and then calling it like above with *one* "do stackswitch"? The default would still be to do a stack switch. If you need to call c_function_1 sometimes with a stack switch, and sometimes in a group of other functions (with just one stack switch for that group), we could have something like this: extern mod lib_c { // This is the default fn c_function_1(); #[rust_stack] fn c_function_1() as rs_c_function1(); } Then use lib_c::c_function_1() when you want a stack switch, or rs_c_function1() without. One could go further and auto generate for mod lib_c a sub module called "rs" (for rust stack), where each function has a #[rust_stack] directive in front of it, so you don't have to declare it twice. This woudl give use: lib_c::c_function_1() and lib_c::rs::c_function_1(). Regards, Michael From a.stavonin at gmail.com Fri Feb 1 04:14:18 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Fri, 1 Feb 2013 21:14:18 +0900 Subject: [rust-dev] Autiincrement values in loops Message-ID: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> Have we a pretty looks solution for auto incrementation counters during loops? I mean something like C/C++ style for loop.I found an example in the manual "10.5 For loops" but it looks ugly with counter outside the loop. Is it only way for solving problem? Thanks. From josh at joshmatthews.net Fri Feb 1 04:23:13 2013 From: josh at joshmatthews.net (Josh Matthews) Date: Fri, 1 Feb 2013 12:23:13 +0000 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> Message-ID: The int/uint::range methods would seem to do the job: for uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } Cheers, Josh On 1 February 2013 12:14, Alexander Stavonin wrote: > Have we a pretty looks solution for auto incrementation counters during loops? I mean something like C/C++ style for loop.I found an example in the manual "10.5 For loops" but it looks ugly with counter outside the loop. Is it only way for solving problem? > > Thanks. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From a.stavonin at gmail.com Fri Feb 1 04:28:34 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Fri, 1 Feb 2013 21:28:34 +0900 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> Message-ID: <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Thanks, it better than nothing, but? It works only for i++; how can I write i += 2 or i--? On Feb 1, 2013, at 9:23 PM, Josh Matthews wrote: > The int/uint::range methods would seem to do the job: for > uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } > > Cheers, > Josh > > On 1 February 2013 12:14, Alexander Stavonin wrote: >> Have we a pretty looks solution for auto incrementation counters during loops? I mean something like C/C++ style for loop.I found an example in the manual "10.5 For loops" but it looks ugly with counter outside the loop. Is it only way for solving problem? >> >> 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 josh at joshmatthews.net Fri Feb 1 04:32:27 2013 From: josh at joshmatthews.net (Josh Matthews) Date: Fri, 1 Feb 2013 12:32:27 +0000 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: Well, constant increments of N can be simulated with |let i = i * N;| in the body of the loop. There's an issue open right now about making range do the right thing when presented with a range going in reverse. Cheers, Josh On 1 February 2013 12:28, Alexander Stavonin wrote: > Thanks, it better than nothing, but? It works only for i++; how can I write > i += 2 or i--? > > On Feb 1, 2013, at 9:23 PM, Josh Matthews wrote: > > The int/uint::range methods would seem to do the job: for > uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } > > Cheers, > Josh > > On 1 February 2013 12:14, Alexander Stavonin wrote: > > Have we a pretty looks solution for auto incrementation counters during > loops? I mean something like C/C++ style for loop.I found an example in the > manual "10.5 For loops" but it looks ugly with counter outside the loop. Is > it only way for solving problem? > > Thanks. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > From josh at joshmatthews.net Fri Feb 1 04:34:41 2013 From: josh at joshmatthews.net (Josh Matthews) Date: Fri, 1 Feb 2013 12:34:41 +0000 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: Actually my first suggestion won't work except in trivial circumstances (ie. starting from zero). Sorry. On 1 February 2013 12:32, Josh Matthews wrote: > Well, constant increments of N can be simulated with |let i = i * N;| > in the body of the loop. There's an issue open right now about making > range do the right thing when presented with a range going in reverse. > > Cheers, > Josh > > On 1 February 2013 12:28, Alexander Stavonin wrote: >> Thanks, it better than nothing, but? It works only for i++; how can I write >> i += 2 or i--? >> >> On Feb 1, 2013, at 9:23 PM, Josh Matthews wrote: >> >> The int/uint::range methods would seem to do the job: for >> uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } >> >> Cheers, >> Josh >> >> On 1 February 2013 12:14, Alexander Stavonin wrote: >> >> Have we a pretty looks solution for auto incrementation counters during >> loops? I mean something like C/C++ style for loop.I found an example in the >> manual "10.5 For loops" but it looks ugly with counter outside the loop. Is >> it only way for solving problem? >> >> Thanks. >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> From simon.sapin at exyr.org Fri Feb 1 04:37:32 2013 From: simon.sapin at exyr.org (Simon Sapin) Date: Fri, 01 Feb 2013 13:37:32 +0100 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: <510BB70C.2060409@exyr.org> Le 01/02/2013 13:28, Alexander Stavonin a ?crit : > Thanks, it better than nothing, but? It works only for i++; how can I > write /i += 2 /or /i--/? The range() function is very simple: https://github.com/mozilla/rust/blob/release-0.5/src/libcore/int-template.rs#L48 #[inline(always)] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: T, hi: T, it: fn(T) -> bool) { let mut i = lo; while i < hi { if !it(i) { break } i += 1 as T; } } It?s quite easy to write your own variant with a "step" parameter: pub pure fn range_step(lo: int, hi: int, step: int, it: fn(int) -> bool) { let mut i = lo; while i < hi { if !it(i) { break } i += step; } } Maybe range_step() could be added to libcore? -- Simon Sapin From lucian.branescu at gmail.com Fri Feb 1 04:38:56 2013 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Fri, 1 Feb 2013 12:38:56 +0000 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <510BB70C.2060409@exyr.org> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> <510BB70C.2060409@exyr.org> Message-ID: It's also possible to write something like python's enumerate, to get: for enumerate(some_vector) Ii, e| { ... } In general, rust loops are closer to Python's and functional map than C++'s looping constructs. On 1 February 2013 12:37, Simon Sapin wrote: > Le 01/02/2013 13:28, Alexander Stavonin a ?crit : > >> Thanks, it better than nothing, but? It works only for i++; how can I >> write /i += 2 /or /i--/? >> > > The range() function is very simple: > > https://github.com/mozilla/**rust/blob/release-0.5/src/** > libcore/int-template.rs#L48 > > #[inline(always)] > /// Iterate over the range [`lo`..`hi`) > pub fn range(lo: T, hi: T, it: fn(T) -> bool) { > let mut i = lo; > while i < hi { > if !it(i) { break } > i += 1 as T; > } > } > > > It?s quite easy to write your own variant with a "step" parameter: > > pub pure fn range_step(lo: int, hi: int, step: int, > it: fn(int) -> bool) { > let mut i = lo; > while i < hi { > if !it(i) { break } > i += step; > } > } > > > Maybe range_step() could be added to libcore? > > -- > Simon Sapin > > ______________________________**_________________ > 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 a.stavonin at gmail.com Fri Feb 1 04:45:40 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Fri, 1 Feb 2013 21:45:40 +0900 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <510BB70C.2060409@exyr.org> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> <510BB70C.2060409@exyr.org> Message-ID: <7C9B1D31-9FFF-4FF4-AA89-9279955DC055@gmail.com> I guess, the solution will not work for -1 ? -10 On Feb 1, 2013, at 9:37 PM, Simon Sapin wrote: > Le 01/02/2013 13:28, Alexander Stavonin a ?crit : >> Thanks, it better than nothing, but? It works only for i++; how can I >> write /i += 2 /or /i--/? > > The range() function is very simple: > > https://github.com/mozilla/rust/blob/release-0.5/src/libcore/int-template.rs#L48 > > #[inline(always)] > /// Iterate over the range [`lo`..`hi`) > pub fn range(lo: T, hi: T, it: fn(T) -> bool) { > let mut i = lo; > while i < hi { > if !it(i) { break } > i += 1 as T; > } > } > > > It?s quite easy to write your own variant with a "step" parameter: > > pub pure fn range_step(lo: int, hi: int, step: int, > it: fn(int) -> bool) { > let mut i = lo; > while i < hi { > if !it(i) { break } > i += step; > } > } > > > Maybe range_step() could be added to libcore? > > -- > Simon Sapin From simon.sapin at exyr.org Fri Feb 1 04:52:30 2013 From: simon.sapin at exyr.org (Simon Sapin) Date: Fri, 01 Feb 2013 13:52:30 +0100 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <7C9B1D31-9FFF-4FF4-AA89-9279955DC055@gmail.com> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> <510BB70C.2060409@exyr.org> <7C9B1D31-9FFF-4FF4-AA89-9279955DC055@gmail.com> Message-ID: <510BBA8E.8000807@exyr.org> Le 01/02/2013 13:45, Alexander Stavonin a ?crit : > I guess, the solution will not work for -1 ? -10 Oh, for negative steps my previous implementation is buggy indeed. But it can be fixed: pub pure fn range_step(lo: int, hi: int, step: int, it: fn(int) -> bool) { let mut i = lo; if step > 0 { while i < hi { if !it(i) { break } i += step; } } else if step < 0 { while i > hi { if !it(i) { break } i += step; } } else { fail "Got step = 0." } } for range_step(-1, -11, -1) |i| { ? } -- Simon Sapin From simon.sapin at exyr.org Fri Feb 1 05:05:56 2013 From: simon.sapin at exyr.org (Simon Sapin) Date: Fri, 01 Feb 2013 14:05:56 +0100 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> <510BB70C.2060409@exyr.org> Message-ID: <510BBDB4.4090707@exyr.org> Le 01/02/2013 13:38, Lucian Branescu a ?crit : > It's also possible to write something like python's enumerate, to get: > for enumerate(some_vector) Ii, e| { ... } > > In general, rust loops are closer to Python's and functional map than > C++'s looping constructs. Python?s enumerate() works on any iterable, not just lists. Is it possible to chain rust for-loops to get something that works not just on vectors? The best I can think of (untested) is: fn enumerate(inner_loop: &fn(&fn(T) -> bool), it: &fn(uint, T) -> bool) { let i = 0u; for inner_loop |el| { if !it(i, el) { break } i += 1; } } for enumarate(|it| { some_str.each_char(it) }) |i, ch| { ? } ? but it?s not pretty, and doesn?t work with eg. vec::each2 which gives two arguments to its own `it`. -- Simon Sapin From ben.striegel at gmail.com Fri Feb 1 05:48:59 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Fri, 1 Feb 2013 08:48:59 -0500 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: There's already a function to do this: fn main() { for int::range_step(0, 10, 2) |i| { log(error, i); } for int::range_step(10, 0, -1) |i| { log(error, i); } } On Fri, Feb 1, 2013 at 7:28 AM, Alexander Stavonin wrote: > Thanks, it better than nothing, but? It works only for i++; how can I > write *i += 2 *or *i--*? > > On Feb 1, 2013, at 9:23 PM, Josh Matthews wrote: > > The int/uint::range methods would seem to do the job: for > uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } > > Cheers, > Josh > > On 1 February 2013 12:14, Alexander Stavonin wrote: > > Have we a pretty looks solution for auto incrementation counters during > loops? I mean something like C/C++ style for loop.I found an example in the > manual "10.5 For loops" but it looks ugly with counter outside the loop. > Is it only way for solving problem? > > Thanks. > _______________________________________________ > 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 ben.striegel at gmail.com Fri Feb 1 05:50:42 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Fri, 1 Feb 2013 08:50:42 -0500 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: Though note that this function is relatively new, you'll need to be on a recent unstable version rather than 0.5. On Fri, Feb 1, 2013 at 8:48 AM, Benjamin Striegel wrote: > There's already a function to do this: > > fn main() { > for int::range_step(0, 10, 2) |i| { > log(error, i); > } > > for int::range_step(10, 0, -1) |i| { > log(error, i); > } > } > > > On Fri, Feb 1, 2013 at 7:28 AM, Alexander Stavonin wrote: > >> Thanks, it better than nothing, but? It works only for i++; how can I >> write *i += 2 *or *i--*? >> >> On Feb 1, 2013, at 9:23 PM, Josh Matthews wrote: >> >> The int/uint::range methods would seem to do the job: for >> uint::range(0, 10) |i| { io::println(fmt!("%u", i)); } >> >> Cheers, >> Josh >> >> On 1 February 2013 12:14, Alexander Stavonin >> wrote: >> >> Have we a pretty looks solution for auto incrementation counters during >> loops? I mean something like C/C++ style for loop.I found an example in the >> manual "10.5 For loops" but it looks ugly with counter outside the loop. >> Is it only way for solving problem? >> >> Thanks. >> _______________________________________________ >> 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 Fri Feb 1 06:38:19 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 01 Feb 2013 06:38:19 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: References: Message-ID: <510BD35B.2040203@alum.mit.edu> What you want is something like this (and corresponding changes to the impl): pub trait TupleVal { pub pure fn _1(&self) -> &self/T; pub pure fn _2(&self) -> &self/T; } The `&self` declaration is called an "explicit self" declaration. What you have currently written is called "implicit self" and is deprecated. Explicit self also tells the compiler what sort of pointer you expect: in this case, a borrowed pointer to the receiver. The lifetime of this borrowed pointer is always called "self". Therefore, the return type `&self/T` says: "a pointer with the same lifetime as the receiver to T". Note that this syntax is likely to change in the future, although the precise form is not yet finalized. I suspect it will be something like: pub trait TupleVal { pub pure fn _1(&'v self) -> &'v T; pub pure fn _2(&'v self) -> &'v T; } which makes the connection between the lifetime of the self pointer and the lifetime of the return value more explicit. Niko Alexander Stavonin wrote: > I want to add function like _1(), _2(), etc for Rust tuple. > Unfortunately I do not understand how to tell compiler lifetime of > returning result in case of `trait` > > pub trait TupleVal { > pub pure fn _1() -> T; > pub pure fn _2() -> T; > } > > impl (T, T): TupleVal { > pure fn _1() -> T { > let (a, _) = self; > a > } > pure fn _2() -> T { > let (_, b) = self; > b > } > } > > And the errors: > > test.rs:31:21: 31:25 error: moving out of self reference > test.rs:31 let (a, _) = self; > ^~~~ > test.rs:35:21: 35:25 error: moving out of self reference > test.rs:35 let (_, b) = self; > ^~~~ > error: aborting due to 2 previous errors > > How can I tell the compiler returning values lifetime? Actually it > couldn't be more than lifetime of self. > _______________________________________________ > 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 bruce at strapper.net Fri Feb 1 06:39:42 2013 From: bruce at strapper.net (Bruce M. Axtens) Date: Fri, 01 Feb 2013 22:39:42 +0800 Subject: [rust-dev] Rust 0.5 for Windows Message-ID: <510BD3AE.4000504@strapper.net> I'm having problems with the installer for 0.5 on Windows. I end up with folders containing a mix of normal length files and zero length files. When I try to run rustc.exe I get a dialog about some libgcc*.dll not being present Any clues? Kind regards, Bruce. From mneumann at ntecs.de Fri Feb 1 08:43:38 2013 From: mneumann at ntecs.de (Michael Neumann) Date: Fri, 01 Feb 2013 17:43:38 +0100 Subject: [rust-dev] Misc questions In-Reply-To: <51085EAD.5090204@mozilla.com> References: <5101C9FD.7030204@ntecs.de> <5101D3E6.7070902@mozilla.com> <5101F572.3090202@mozilla.com> <5103BDD3.9000401@ntecs.de> <5103C593.4080904@ntecs.de> <5103C6EC.5050500@ntecs.de> <5106F19D.8010802@mozilla.com> <51070BA2.6000608@ntecs.de> <51071E46.5080709@mozilla.com> <510725EA.2090907@mozilla.com> <51072D7D.8090609@mozilla.com> <5107C4E7.70609@ntecs.de> <51085EAD.5090204@mozilla.com> Message-ID: <510BF0BA.9080006@ntecs.de> Am 30.01.2013 00:43, schrieb Brian Anderson: > On 01/29/2013 04:47 AM, Michael Neumann wrote: >> Am 29.01.2013 03:01, schrieb Brian Anderson: >>> On 01/28/2013 05:29 PM, Graydon Hoare wrote: >>>> On 13-01-28 04:56 PM, Brian Anderson wrote: >>>> >>>>>> I think libuv is doing too much here. For example, if I don't >>>>>> want to >>>>>> remove the socket from the event >>>>>> queue, just disable the callback, then this is not possible. I'd >>>>>> prefer when I could just tell libuv that >>>>>> I am interested in event X (on Windows: I/O completion, on UNIX: I/O >>>>>> availability). >>>> Yet the optimization you suggest has to do with recycling the buffer, >>>> not listening for one kind of event vs. another. >>>> >>>> In general I'm not interested in trying to "get underneath" the >>>> abstraction uv is providing. It's providing an IOCP-oriented >>>> interface, >>>> I would like to code to that and make the rust IO library not have to >>>> worry when it's on windows vs. unix. That's the point of the >>>> abstraction >>>> uv provides, and it's valuable. If it means bouncing off epoll a >>>> few too >>>> many times (or reallocating a buffer a few too many times), I'm not >>>> too >>>> concerned. Those should both be O(1) operations. >>>> >>>>> Is it possible to do this optimization later or do we need to plan >>>>> for >>>>> this ahead of time? I would prefer to use the uv API as it's >>>>> presented >>>>> to start with. >>>> The optimization to use a caller-provided buffer should (a) not be >>>> necessary to get us started and (b) be equally possible on either >>>> platform, unix or windows, _so long as_ we're actually sleeping a task >>>> during its period of interest in IO (either the pre-readiness sleep >>>> or a >>>> post-issue, pre-completion sleep). In other words, if we're simulating >>>> sync IO, then we can use a task-local buffer. If we're _not_ >>>> simulating >>>> sync IO (I sure hope we do!) then we should let uv allocate and free >>>> dynamic buffers as it needs them. >>>> >>>> But I really hope we wind up structuring it so it simulates sync IO. >>>> We're providing a task abstraction. Users _want_ the sync IO >>>> abstraction >>>> the same way they want the sequential control flow abstraction. >>> >>> Presenting the scheduler-originating I/O as synchronous is what I >>> intend. I am not sure that we can guarantee that a task is actually >>> waiting for I/O when an I/O event occurs that that task is waiting >>> for. A task may block on some other unrelated event while the event >>> loop is doing I/O. Pseudocode: >>> >>> let port = IOPort::connect(); // Assume we're doing I/O reads using >>> something portlike >>> while port.recv() { >>> // Block on a different port, while uv continues doing I/O on >>> our behalf >>> let intermediate_value = some_other_port.recv(); >>> } >>> >>> This is why I'm imagining that the scheduler will sometimes need to >>> buffer. >> >> I don't think so. Let me explain. >> >> This anyway is only a problem (which can be solved) iff we want to be >> able to treat I/O like a >> port and want to wait for either one to resume our thread. And I >> assume we want this, so >> that we can listen on an I/O socket AND for example for incoming >> messages at the same time. >> >> The kernel provides a way to do (task-local) blocking I/O operations. >> There is no way for the >> task to return from a read() call unless data comes in or in case of >> EOF (or any other error >> condition).This behaves basically like a blocking POSIX read() call, >> just that it is converted >> into asynchronous read by libuv under the hood. To expose I/O as >> port, we have to start >> a new task: >> >> let fd = open(...); >> let (po, ch) = streams::pipe(); >> do task::spawn { >> loop { >> let buf: ~[u8] = vec::from_fn(1000, || 0); >> let nread = fd.read(buf, 1000); >> if nread > 0 { >> ch.send(Data(buf)) >> } >> else if nread == 0 { >> ch.send(EOF) >> } >> else { >> ch.send(Error) >> } >> } >> } > > Yes, a single call to 'read' will not return until some I/O arrives, > but after 'read' returns I/O continues to arrive and that I/O needs to > be stored somewhere if the task doesn't immediately block in another > call to 'read' on that same fd. Taking the above example: > > loop { > // This will block until data arrives at which point the task will > be context-switched in and the data returned. > let nread = fd.read(buf, 1000); > > // This will put the task to sleep waiting on a message on cmd_port > let command = cmd_port.recv(); > } > > Until data arrives on cmd_port the task cannot be scheduled. While the > task is asleep the I/O loop can't be blocked since other tasks are > using it too. So in the meantime uv continues to receive data from the > open fd and it needs to live somewhere until the task calls 'read' > again on the same fd. Perhaps there's something I don't understand > about the uv API here, but I think that once we start reading uv is > going to continually provide us with data whether we are ready for it > or not. > >> >> // now we can treat `po` as a Port and call select() on it >> >> >> But I don't think channel I/O will be used that often. >> >> Note that one big advantage is that we can specify the buffer size >> ourself! >> When we would let libuv create a buffer for us, how would it know the >> buffer size? The alloc_cb you provide to libuv upon uv_start_read() >> will get >> a suggested_size parameter passed, but this is 64k by default, and libuv >> cannot know what kind of I/O protocol you are handling. When I do >> line oriented I/O, I would not need a full 64k buffer allocated for >> every >> read, which in the worst case would only return one byte in it in case >> of a very slow sender (send one byte each second). Or is 64k enough >> for receiving a very large packet. We clearly want a way to tell the I/O >> system how large we expect the packet to be that will arrive over I/O >> otherwise this is completely useless IMHO. > > I am not sure how to do this with the forementioned issues - when we > receive the alloc_cb the task may not have been able to communicate to > the event loop the size of the next buffer. Imagine this sequence of > events: > > * task issues fd.read(buf, 1000); > * alloc_cb arrives. great, 'read' already told us the size of the next > buffer. > * task wakes up and starts handling data > * task goes to sleep for some other reason > * alloc_cb arrives. how big is the buffer supposed to be? > * task wakes up and issues fd.read(buf, 1000). What can we do with > '1000'? we already missed the underlying read event > >> >> We would still have one separate iotask per scheduler.This is a native >> thread and runs the I/O loop. There is no way to do that inside the >> scheduler as we would block any task while waiting for I/O. > > I have something different in mind. There is no iotask. The scheduler > is the event loop and I/O callbacks are interleaved with running > tasks. There will be no thread synchronization required to pass data > from the event loop to a task - only context switches to schedule and > deschedule the task. > > I don't anticipate problems with blocking the scheduler - when an > external event requires the scheduler to wake up it will create an > async_cb to run some scheduler code. > >> >> The callbacks like on_read_cb would simply notify the scheduler >> that the task that was responsible for doing this read operation >> can now resume. As the scheduler lives in another thread >> (the thread in which all tasks of that scheduler live in) >> and might be active, we need to do some locking here. >> When the scheduler gets activated next time, either by >> issuing a blocking I/O operation, giving up by using task::yield >> or by waiting for a message on a port, or when sending a message >> blocks, the scheduler can decide which task to schedule next >> and consider those for which I/O has arrived as well. >> >> One thing to consider is that we'd need a way to return the number >> of bytes written to the buffer to the calling task of read(). >> We should store this in the same manner as the pointer to the buffer >> and the buffer_size in the stream_t handle. This is safe, as one I/O >> object is always exclusively used by one task. > > I am not familiar enough with the mechanics of the uv API enough to > understand this point. I think though that it assumes that the > synchronous code will handle I/O events as they arrive and we will be > passing the uv handles from the async code to the sync code (therefore > uv won't be overwriting a handle while a Rust task is in possession of > it). For the reasons I mentioned before I don't see how this is > possible (in the general case) since the scheduler may need to buffer > data until it can be acted on by the task. > >> We can call this field >> last_nread for example, and when the scheduler reactivates a >> task blocked on a read I/O, we would simply return this field as number >> of read bytes. >> >> In short: >> >> * A task can either block on exactly *one* I/O object >> * or on a channel/port. >> * Each I/O object belongs exclusivly to one task >> * I/O and Port/Chan are two different things >> * I/O is "lower" than Port/Chan, but can be easily >> wrapped into an Port/Chan abstraction (see code above) >> * When a task blocks on an I/O event, it blocks until >> this I/O event arrives. >> * A task can only ever block on *one* I/O event >> * For Channel I/O (I/O over Port/Chan) a separate task >> in needed for each connection object. >> * We have on iotask per scheduler. > > I mostly agree with these points but some are at odds with my previous > statements. > > Please forgive me for not responding to the remaining points in > detail. We can discuss more later. I think I now understood how you want to implement the scheduler. The scheduler will schedule tasks as long as they can communicate with each other via channels, i.e. as long as there is at least one task that is not blocked on a channel. If all tasks are blocked on a channel, the scheduler will enter it's I/O loop (uv_run_loop). It will only awake from it if I/O arrives (or uv_async_send is called from a different scheduler). This is optimal in terms of performance. Only if tasks communicate across a scheduler boundary it is little bit more expensive, as it will (potentially) awake the receiving scheduler from it's I/O loop. But I think this is negliglible, and models nicely how processors in a SMP system wake up each other using IPIs (inter processor interrupts). Except inter-scheduler communication, there are no locks needed at all, assuming one scheduler corresponds to one native thread. I think this system is easier to implement that what I proposed, and it performs better. As I/O can be performed asynchronously depending on the OS (on Windows), you need to allocate buffers, but this is no problem IMHO. Regards, Michael From simon.sapin at exyr.org Fri Feb 1 08:48:57 2013 From: simon.sapin at exyr.org (Simon Sapin) Date: Fri, 01 Feb 2013 17:48:57 +0100 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> Message-ID: <510BF1F9.6050405@exyr.org> Le 01/02/2013 14:50, Benjamin Striegel a ?crit : > Though note that this function is relatively new, you'll need to be on a > recent unstable version rather than 0.5. Is it a bug that it?s not documented? http://static.rust-lang.org/doc/core/int.html -- Simon Sapin From matthieu.monrocq at gmail.com Fri Feb 1 09:23:03 2013 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Fri, 1 Feb 2013 18:23:03 +0100 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510BA277.6070701@ntecs.de> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> Message-ID: On Fri, Feb 1, 2013 at 12:09 PM, Michael Neumann wrote: > Am 31.01.2013 23:37, schrieb Patrick Walton: > > Hi everyone, >> >> With the revamp of the scheduler underway, I'd like to propose a change >> to the way C functions work. >> >> Currently, we generate a shim and a stack switch for every function call >> from Rust to C and likewise from C to Rust, except for functions annotated >> with `#[rust_stack]`. These wrappers result in a significant performance >> overhead. For some workloads this performance overhead is acceptable in >> order to maintain small stacks. For some workloads the performance overhead >> is undesirable. >> >> For instance, the DOM in Servo requires lots of very small calls from >> JavaScript to Rust. The overhead of stack switching swamps most of the time >> here. Popular Web benchmarks will do things like `someElement.clientX;` >> over and over, which require calls from JavaScript to Rust to retrieve a >> cached value. So we must carefully consider every CPU cycle spent in the >> C-to-Rust transition. >> >> To address these issues I would like to propose a somewhat radical >> change: don't have the compiler generate stack switching stubs at all. >> Instead, the scheduler can expose a primitive that generates the stack >> switch, and it's the programmer's responsibility to perform the stack >> switch to call out to C functions. To avoid the obvious footgun here, I >> propose a lint pass, on by default, that ensures that functions not >> annotated with `#[rust_stack]` are called inside a stack switching helper. >> >> The rationale here is as follows: >> >> 1. It should be possible to group many C calls under a single stack >> switching operation. For example: >> >> do stackswitch { >> c_function_1(); >> c_function_2(); >> c_function_3(); >> } >> > > wouldn't it be possible for this case to just do: > > extern mod lib_c { > #[rust_stack] > fn c_function_1(); > > #[rust_stack] > fn c_function_2(); > > #[rust_stack] > fn c_function_3(); > } > > and then calling it like above with *one* "do stackswitch"? > > The default would still be to do a stack switch. If you need to call > c_function_1 sometimes with a stack switch, and sometimes > in a group of other functions (with just one stack switch for that group), > we could have something like this: > > extern mod lib_c { > > // This is the default > fn c_function_1(); > > #[rust_stack] > fn c_function_1() as rs_c_function1(); > > } > > Then use lib_c::c_function_1() when you want a stack switch, or > rs_c_function1() without. One could go further > and auto generate for mod lib_c a sub module called "rs" (for rust stack), > where each function has a #[rust_stack] > directive in front of it, so you don't have to declare it twice. > > This woudl give use: lib_c::c_function_1() and lib_c::rs::c_function_1(). > > Regards, > > Michael > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > I would have a stupid proposal: what if the C function declaration was annotated not with #[rust_stack] but with #[stack 5k] instead. That is, instead of having a single blunt tool, let the programmer declare how much stack is necessary for the C function and let the compiler reason about it to guarantee that enough stack is available. extern mod lib_c { #[stack 4k] fn c_function_1(); #[stack unlimited] fn c_function_2(); #[stack 16k] fn c_function_3(); } Then when the compiler sees a bunch of C functions: fn func(x: int) { c_function_1(); c_function_1(); c_function_1(); c_function_3(); } => if one is marked as "unlimited", then it performs stack switching (once); this can deferred to the branch the function is called in if judged "better". => otherwise, it evaluates the maximum amount of stack needed and prepares it at the beginning of the function, as usual Advantages: + Code is not invalidated, only the function declarations are, and it's easy enough to do a bulk replace #[rust_stack] -> #[stack 4k] + The information can bubble up at "func" automatically, so that caller of "func" can perform the switch/reservation themselves if it's judged profitable. Disadvantages: - Myth of the sufficiently smart compiler spotted. -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.striegel at gmail.com Fri Feb 1 10:07:22 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Fri, 1 Feb 2013 13:07:22 -0500 Subject: [rust-dev] Autiincrement values in loops In-Reply-To: <510BF1F9.6050405@exyr.org> References: <3B3F85CB-3A1A-46F7-9B8C-D74E8AEEBDBF@gmail.com> <1F1572D9-0EED-4F33-A29A-9797C4D36020@gmail.com> <510BF1F9.6050405@exyr.org> Message-ID: It's possible that the documentation hasn't been updated, or that perhaps the documentation is only for the master branch (I'm not sure if range_step is on master yet). On Fri, Feb 1, 2013 at 11:48 AM, Simon Sapin wrote: > Le 01/02/2013 14:50, Benjamin Striegel a ?crit : > > Though note that this function is relatively new, you'll need to be on a >> recent unstable version rather than 0.5. >> > > Is it a bug that it?s not documented? > > http://static.rust-lang.org/**doc/core/int.html > > -- > Simon Sapin > -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Fri Feb 1 10:13:03 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 01 Feb 2013 10:13:03 -0800 Subject: [rust-dev] Rust 0.5 for Windows In-Reply-To: <510BD3AE.4000504@strapper.net> References: <510BD3AE.4000504@strapper.net> Message-ID: <510C05AF.2080401@mozilla.com> On 13-02-01 06:39 AM, Bruce M. Axtens wrote: > I'm having problems with the installer for 0.5 on Windows. I end up with > folders containing a mix of normal length files and zero length files. > When I try to run rustc.exe I get a dialog about some libgcc*.dll not > being present The 0-length files are build artifacts (they act as sequence-points for make, since it cannot easily guess the actual hash-based output filenames of the libraries); they're harmless and we're just not being terribly precise in avoiding them when building the package. The absence of libgcc DLLs has to do with our dependency on mingw. As outlined in the getting started page: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust we currently depend on a very specific version of mingw. We're hoping to move to mingw-w64 in the near future and then (eventually) to no longer depend on mingw at all; it's only being used for running the PE linker and a small number of runtime library features presently; we should eventually be able to make do without it. -Graydon From erick.tryzelaar at gmail.com Fri Feb 1 10:13:21 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 1 Feb 2013 10:13:21 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: <510BD35B.2040203@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> Message-ID: This would be nice addition. However, can the methods start at zero instead of one? On Fri, Feb 1, 2013 at 6:38 AM, Niko Matsakis wrote: > What you want is something like this (and corresponding changes to the > impl): > > pub trait TupleVal { > pub pure fn _1(&self) -> &self/T; > pub pure fn _2(&self) -> &self/T; > } > > The `&self` declaration is called an "explicit self" declaration. What > you have currently written is called "implicit self" and is deprecated. > Explicit self also tells the compiler what sort of pointer you expect: in > this case, a borrowed pointer to the receiver. The lifetime of this > borrowed pointer is always called "self". Therefore, the return type > `&self/T` says: "a pointer with the same lifetime as the receiver to T". > > Note that this syntax is likely to change in the future, although the > precise form is not yet finalized. I suspect it will be something like: > > pub trait TupleVal { > pub pure fn _1(&'v self) -> &'v T; > pub pure fn _2(&'v self) -> &'v T; > } > > which makes the connection between the lifetime of the self pointer and > the lifetime of the return value more explicit. > > > Niko > > > Alexander Stavonin wrote: > > I want to add function like _1(), _2(), etc for Rust tuple. Unfortunately > I do not understand how to tell compiler lifetime of returning result in > case of `trait` > > pub trait TupleVal { > pub pure fn _1() -> T; > pub pure fn _2() -> T; > } > > impl (T, T): TupleVal { > pure fn _1() -> T { > let (a, _) = self; > a > } > pure fn _2() -> T { > let (_, b) = self; > b > } > } > > And the errors: > > test.rs:31:21: 31:25 error: moving out of self reference > test.rs:31 let (a, _) = self; > ^~~~ > test.rs:35:21: 35:25 error: moving out of self reference > test.rs:35 let (_, b) = self; > ^~~~ > error: aborting due to 2 previous errors > > How can I tell the compiler returning values lifetime? Actually it > couldn't be more than lifetime of self. > > _______________________________________________ > Rust-dev mailing listRust-dev at mozilla.orghttps://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 catamorphism at gmail.com Fri Feb 1 10:18:13 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Fri, 1 Feb 2013 10:18:13 -0800 Subject: [rust-dev] Rust 0.5 for Windows In-Reply-To: <510C05AF.2080401@mozilla.com> References: <510BD3AE.4000504@strapper.net> <510C05AF.2080401@mozilla.com> Message-ID: On Fri, Feb 1, 2013 at 10:13 AM, Graydon Hoare wrote: > On 13-02-01 06:39 AM, Bruce M. Axtens wrote: >> I'm having problems with the installer for 0.5 on Windows. I end up with >> folders containing a mix of normal length files and zero length files. >> When I try to run rustc.exe I get a dialog about some libgcc*.dll not >> being present > > The 0-length files are build artifacts (they act as sequence-points for > make, since it cannot easily guess the actual hash-based output > filenames of the libraries); they're harmless and we're just not being > terribly precise in avoiding them when building the package. I added this to the FAQ, btw: https://github.com/mozilla/rust/wiki/Doc-usage-FAQ and would welcome any suggestions from anyone as to how to organize the FAQs on the wiki better; they're not the easiest thing to navigate right now. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From pnkfelix at mozilla.com Fri Feb 1 10:21:32 2013 From: pnkfelix at mozilla.com (Felix S Klock II) Date: Fri, 01 Feb 2013 19:21:32 +0100 Subject: [rust-dev] Rust 0.5 for Windows In-Reply-To: <510C05AF.2080401@mozilla.com> References: <510BD3AE.4000504@strapper.net> <510C05AF.2080401@mozilla.com> Message-ID: <510C07AC.4030305@mozilla.com> On Fri Feb 1 19:13:03 2013, Graydon Hoare wrote: > (they act as sequence-points for make, since it cannot easily guess > the actual hash-based output filenames of the libraries) I was idly wondering about those hashy filenames: Is the long term plan to continue to encoding hashes into the filenames? Or is there non-zero chance that the infrastructure of Rust will change so that one can easily predict the output file name for a library, to accommodate tools like make. (Sorry if the answer to the above question is already documented somewhere obvious, I had not noticed it addressed when I was going through the documentation.) I suppose I might just as well implement the empty-file work-around myself, I had not really thought terribly hard about the problem and was just doing "make clean; make" whenever I needed to in my little Rust experiments so far. Cheers, -Felix -- irc: pnkfelix on irc.mozilla.org email: {fklock, pnkfelix}@mozilla.org From cpeterson at mozilla.com Fri Feb 1 10:36:11 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Fri, 01 Feb 2013 10:36:11 -0800 Subject: [rust-dev] Container framework? Message-ID: <510C0B1B.5040005@mozilla.com> strcat and I have been casually brainstorming about container traits. Has there been previous discussion about standardizing a container trait hierarchy and method naming convention? Below is a rough sketch of a simple container framework, inspired by Scala, Python, and C++ STL. Scala has a well-organized trait hierarchy, but I'm partial to C++ STL's method names because they are short and consistent. :) * trait Container * trait Iterable? * trait Map * struct LinearMap (and any future hash-based maps) * trait OrderedMap? (range queries, forward/reverse iteration) * struct TreeMap * struct TrieMap? * trait Set * struct LinearSet (and any future hash-based sets) * struct BitSet (includes bit op methods like flip() and to_uint()) * trait OrderedSet? * struct TreeSet * struct TrieSet? * trait Seq (Sequence) * struct Stack * trait Queue * trait List (or trait Deque?) * struct Deque? (vec-based. Vec? VecDeque? "ArrayDeque" like Java?) * struct LinkedList * struct PriorityQueue Links: * Brainstorming wiki: https://etherpad.mozilla.org/h7KjhELWXk * Scala collections: http://www.scala-lang.org/docu/files/collections-api/collections.html * Python containers: http://www.python.org/dev/peps/pep-3119/#abcs-for-containers-and-iterators * C++ STL containers: http://en.cppreference.com/w/cpp/container chris From graydon at mozilla.com Fri Feb 1 11:06:22 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 01 Feb 2013 11:06:22 -0800 Subject: [rust-dev] Rust 0.5 for Windows In-Reply-To: <510C07AC.4030305@mozilla.com> References: <510BD3AE.4000504@strapper.net> <510C05AF.2080401@mozilla.com> <510C07AC.4030305@mozilla.com> Message-ID: <510C122E.90408@mozilla.com> On 13-02-01 10:21 AM, Felix S Klock II wrote: > On Fri Feb 1 19:13:03 2013, Graydon Hoare wrote: >> (they act as sequence-points for make, since it cannot easily guess >> the actual hash-based output filenames of the libraries) > > I was idly wondering about those hashy filenames: Is the long term plan > to continue to encoding hashes into the filenames? Or is there non-zero > chance that the infrastructure of Rust will change so that one can > easily predict the output file name for a library, to accommodate tools > like make. Yes the plan is to continue hashing metadata into filename suffixes; it's to prevent short-name collisions. It's actually not a lot of work to make that name something you can _query_ though. We just haven't put a command-line option on rustc. -Graydon From graydon at mozilla.com Fri Feb 1 11:24:44 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 01 Feb 2013 11:24:44 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510C0B1B.5040005@mozilla.com> References: <510C0B1B.5040005@mozilla.com> Message-ID: <510C167C.3070202@mozilla.com> On 13-02-01 10:36 AM, Chris Peterson wrote: > strcat and I have been casually brainstorming about container traits. > Has there been previous discussion about standardizing a container trait > hierarchy and method naming convention? Not much; what we've had was encoded mostly in the core::iter and core::container libraries. > Below is a rough sketch of a simple container framework, inspired by > Scala, Python, and C++ STL. Scala has a well-organized trait hierarchy, > but I'm partial to C++ STL's method names because they are short and > consistent. :) > > * trait Container > * trait Iterable? > * trait Map > * struct LinearMap (and any future hash-based maps) > * trait OrderedMap? (range queries, forward/reverse iteration) > * struct TreeMap > * struct TrieMap? > * trait Set > * struct LinearSet (and any future hash-based sets) > * struct BitSet (includes bit op methods like flip() and to_uint()) > * trait OrderedSet? > * struct TreeSet > * struct TrieSet? > * trait Seq (Sequence) > * struct Stack > * trait Queue > * trait List (or trait Deque?) > * struct Deque? (vec-based. Vec? VecDeque? "ArrayDeque" > like Java?) > * struct LinkedList > * struct PriorityQueue Very happy to have people looking at organizing this stuff! It's been disorganized for a while. A few bits of preference: - I think Queue and Stack are both traits, extensions of Seq. - I think the double-ended circular vec struct (implemented unsafely) should probably be called Buf. It's the replacement for DVec. Alternatively call it Queue and come up with another name for the "can access at either end" trait. "Deque" is enough of a C++-ism that I'm ok leaving it behind. - I think of List and DoubleList as concrete types, not traits. - I am still against calling HashMap "LinearMap". It's too specific; like requiring "LLRBTree" or "AATree" when over "TreeMap". It's fine to have these as submodules implementing the same outer interface but to most users, "HashMap" is as specific as they'll want to get. - I'd prefer List as a concrete type implementing Seq - Need to differentiate owned types from persistent / managed types; many or most of these types need both forms. Thanks for taking an interest! -Graydon From erick.tryzelaar at gmail.com Fri Feb 1 11:48:56 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 1 Feb 2013 11:48:56 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510C167C.3070202@mozilla.com> References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> Message-ID: FYI, I'm in the process of converting fun_treemap into an AA Tree and implement much of the container traits. In the process, I've extracted out the mutation functions from Map and Set into their own "Mutable{Map,Set}" trait, and added "Immutable{Map,Set}" traits for persistent types. So please talk to me before any of you start handling the mutable/persistent type issue. On Fri, Feb 1, 2013 at 11:24 AM, Graydon Hoare wrote: > On 13-02-01 10:36 AM, Chris Peterson wrote: > > strcat and I have been casually brainstorming about container traits. > > Has there been previous discussion about standardizing a container trait > > hierarchy and method naming convention? > > Not much; what we've had was encoded mostly in the core::iter and > core::container libraries. > > > Below is a rough sketch of a simple container framework, inspired by > > Scala, Python, and C++ STL. Scala has a well-organized trait hierarchy, > > but I'm partial to C++ STL's method names because they are short and > > consistent. :) > > > > * trait Container > > * trait Iterable? > > * trait Map > > * struct LinearMap (and any future hash-based maps) > > * trait OrderedMap? (range queries, forward/reverse iteration) > > * struct TreeMap > > * struct TrieMap? > > * trait Set > > * struct LinearSet (and any future hash-based sets) > > * struct BitSet (includes bit op methods like flip() and > to_uint()) > > * trait OrderedSet? > > * struct TreeSet > > * struct TrieSet? > > * trait Seq (Sequence) > > * struct Stack > > * trait Queue > > * trait List (or trait Deque?) > > * struct Deque? (vec-based. Vec? VecDeque? "ArrayDeque" > > like Java?) > > * struct LinkedList > > * struct PriorityQueue > > Very happy to have people looking at organizing this stuff! It's been > disorganized for a while. A few bits of preference: > > - I think Queue and Stack are both traits, extensions of Seq. > > - I think the double-ended circular vec struct (implemented unsafely) > should probably be called Buf. It's the replacement for DVec. > Alternatively call it Queue and come up with another name for the > "can access at either end" trait. "Deque" is enough of a C++-ism > that I'm ok leaving it behind. > > - I think of List and DoubleList as concrete types, not traits. > > - I am still against calling HashMap "LinearMap". It's too specific; > like requiring "LLRBTree" or "AATree" when over "TreeMap". It's fine > to have these as submodules implementing the same outer interface > but to most users, "HashMap" is as specific as they'll want to get. > > - I'd prefer List as a concrete type implementing Seq > > - Need to differentiate owned types from persistent / managed types; > many or most of these types need both forms. > > Thanks for taking an interest! > > -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 cpeterson at mozilla.com Fri Feb 1 11:50:32 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Fri, 01 Feb 2013 11:50:32 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510C167C.3070202@mozilla.com> References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> Message-ID: <510C1C88.6050008@mozilla.com> On 2/1/13 11:24 AM, Graydon Hoare wrote: > - I think the double-ended circular vec struct (implemented unsafely) > should probably be called Buf. It's the replacement for DVec. > Alternatively call it Queue and come up with another name for the > "can access at either end" trait. "Deque" is enough of a C++-ism > that I'm ok leaving it behind. > > - I think of List and DoubleList as concrete types, not traits. So List would be a singly-linked list? I thought List might be a reasonable synonym for Deque. I like Buf. chris From cpeterson at mozilla.com Fri Feb 1 11:54:45 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Fri, 01 Feb 2013 11:54:45 -0800 Subject: [rust-dev] Container framework? In-Reply-To: References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> Message-ID: <510C1D85.3010500@mozilla.com> On 2/1/13 11:48 AM, Erick Tryzelaar wrote: > FYI, I'm in the process of converting fun_treemap into an AA Tree and > implement much of the container traits. In the process, I've extracted > out the mutation functions from Map and Set into their own > "Mutable{Map,Set}" trait, and added "Immutable{Map,Set}" traits for > persistent types. So please talk to me before any of you start > handling the mutable/persistent type issue. Is it necessary to differentiate Mutable- and Immutable- container traits when mutating methods would take `&mut self` and read-only accessors take `&self`? chris From erick.tryzelaar at gmail.com Fri Feb 1 12:20:05 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 1 Feb 2013 12:20:05 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510C1D85.3010500@mozilla.com> References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> <510C1D85.3010500@mozilla.com> Message-ID: On Friday, February 1, 2013, Chris Peterson wrote: > > Is it necessary to differentiate Mutable- and Immutable- container traits > when mutating methods would take `&mut self` and read-only accessors take > `&self`? Well, we need the MutableMap-style traits, but we could fold the ImmutableMap-style "insert into a copy" methods to Map. I don't think we can rely on "&mut self" helping us out because it could be a source of bugs. For example, if w forget a hashmap is currently immutable and do "m.remove(x);" nothing actually happened. It'd be safer if either we have different method names between persistent insert/remove and mutating insert/remove, or just say if a type is mutable and you want a copy you do "let n = copy m; n.insert(x)". -------------- next part -------------- An HTML attachment was scrubbed... URL: From deansherthompson at gmail.com Fri Feb 1 13:51:49 2013 From: deansherthompson at gmail.com (Dean Thompson) Date: Fri, 01 Feb 2013 13:51:49 -0800 Subject: [rust-dev] idea for Rust playground - seeking comments Message-ID: Rust Dev, Pablo Fernandez and I are planning to build a simple "Rust playground" -- a site where people can try running small Rust programs and then record examples of working or broken Rust code. We wrote down our current strawman approach at https://github.com/rusthub/rustpad . We would greatly value feedback from this group before we begin. Dean -------------- next part -------------- An HTML attachment was scrubbed... URL: From marijnh at gmail.com Fri Feb 1 14:02:46 2013 From: marijnh at gmail.com (Marijn Haverbeke) Date: Fri, 1 Feb 2013 23:02:46 +0100 Subject: [rust-dev] idea for Rust playground - seeking comments In-Reply-To: References: Message-ID: See also http://codemirror.net/mode/rust/ . Unfortunately, the syntax has changed massively since I wrote that highlighting mode. On the bright side, I believe the syntax became somewhat more regular, so (though I'm not sure about this) a lot of the complexity in the highlighter (and believe me, it is complex) might no longer be needed. Best, Marijn On Fri, Feb 1, 2013 at 10:51 PM, Dean Thompson wrote: > Rust Dev, > > Pablo Fernandez and I are planning to build a simple "Rust playground" -- a > site where people can try running small Rust programs and then record > examples of working or broken Rust code. We wrote down our current strawman > approach at https://github.com/rusthub/rustpad . We would greatly value > feedback from this group before we begin. > > Dean > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From rvs2372 at gmail.com Fri Feb 1 03:29:44 2013 From: rvs2372 at gmail.com (Ranvijay Singh) Date: Fri, 1 Feb 2013 16:59:44 +0530 Subject: [rust-dev] Compilation Error in Rust in Nesting of Modules In-Reply-To: References: Message-ID: Hi, I am getting compilation error while implementing the nesting of modules as per the Rust Language tutorial. Below is the description of my code structure. Inside example directory,I created a file orig.rs and declared 3 modules a, b and c inside it. Inside module c, I declared another module inner_mod. I created 3 files a.rs, b.rs and c.rs and one directory c, all inside the example directory.Also, I created another file inner_mod.rs and kept it in c directory. In c.rs, I defined a function *C_func* as below. pub fn *c_func*() { io::println("I am in c"); } I called the function c_func in file test_orig.rs which is in example directory. As per the tutorial, I can create c.rs file and c directory both, but nothing is mentioned about the location of c.rs with respect to c directory i.e. whether c.rs will be kept inside c directory or outside of it at the same level as c directory inside example directory. I tried both and got the below error in each case when compiled: *test_orig.rs:8:0: 8:15 error: unresolved name: orig::c::c_func test_orig.rs:8 orig::c::c_func();* Tar file of the code is attached.Please suggest a solution to this. thanks Ranvijay -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: example.tar Type: application/x-tar Size: 30720 bytes Desc: not available URL: From fernandezpablo85 at gmail.com Fri Feb 1 14:13:02 2013 From: fernandezpablo85 at gmail.com (pablo fernandez) Date: Fri, 1 Feb 2013 19:13:02 -0300 Subject: [rust-dev] idea for Rust playground - seeking comments In-Reply-To: References: Message-ID: Is that the same syntax highlighter that github uses for their gists? Pablo On Fri, Feb 1, 2013 at 7:02 PM, Marijn Haverbeke wrote: > See also http://codemirror.net/mode/rust/ . Unfortunately, the syntax > has changed massively since I wrote that highlighting mode. On the > bright side, I believe the syntax became somewhat more regular, so > (though I'm not sure about this) a lot of the complexity in the > highlighter (and believe me, it is complex) might no longer be needed. > > Best, > Marijn > > On Fri, Feb 1, 2013 at 10:51 PM, Dean Thompson > wrote: > > Rust Dev, > > > > Pablo Fernandez and I are planning to build a simple "Rust playground" > -- a > > site where people can try running small Rust programs and then record > > examples of working or broken Rust code. We wrote down our current > strawman > > approach at https://github.com/rusthub/rustpad . We would greatly value > > feedback from this group before we begin. > > > > Dean > > > > _______________________________________________ > > 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 Fri Feb 1 15:14:31 2013 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 01 Feb 2013 15:14:31 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> Message-ID: <510C4C57.5090906@mozilla.com> On 02/01/2013 09:23 AM, Matthieu Monrocq wrote: > > > On Fri, Feb 1, 2013 at 12:09 PM, Michael Neumann > wrote: > > Am 31.01.2013 23:37, schrieb Patrick Walton: > > Hi everyone, > > With the revamp of the scheduler underway, I'd like to propose > a change to the way C functions work. > > Currently, we generate a shim and a stack switch for every > function call from Rust to C and likewise from C to Rust, > except for functions annotated with `#[rust_stack]`. These > wrappers result in a significant performance overhead. For > some workloads this performance overhead is acceptable in > order to maintain small stacks. For some workloads the > performance overhead is undesirable. > > For instance, the DOM in Servo requires lots of very small > calls from JavaScript to Rust. The overhead of stack switching > swamps most of the time here. Popular Web benchmarks will do > things like `someElement.clientX;` over and over, which > require calls from JavaScript to Rust to retrieve a cached > value. So we must carefully consider every CPU cycle spent in > the C-to-Rust transition. > > To address these issues I would like to propose a somewhat > radical change: don't have the compiler generate stack > switching stubs at all. Instead, the scheduler can expose a > primitive that generates the stack switch, and it's the > programmer's responsibility to perform the stack switch to > call out to C functions. To avoid the obvious footgun here, I > propose a lint pass, on by default, that ensures that > functions not annotated with `#[rust_stack]` are called inside > a stack switching helper. > > The rationale here is as follows: > > 1. It should be possible to group many C calls under a single > stack switching operation. For example: > > do stackswitch { > c_function_1(); > c_function_2(); > c_function_3(); > } > > > wouldn't it be possible for this case to just do: > > extern mod lib_c { > #[rust_stack] > fn c_function_1(); > > #[rust_stack] > fn c_function_2(); > > #[rust_stack] > fn c_function_3(); > } > > and then calling it like above with *one* "do stackswitch"? > > The default would still be to do a stack switch. If you need to > call c_function_1 sometimes with a stack switch, and sometimes > in a group of other functions (with just one stack switch for that > group), we could have something like this: > > extern mod lib_c { > > // This is the default > fn c_function_1(); > > #[rust_stack] > fn c_function_1() as rs_c_function1(); > > } > > Then use lib_c::c_function_1() when you want a stack switch, or > rs_c_function1() without. One could go further > and auto generate for mod lib_c a sub module called "rs" (for rust > stack), where each function has a #[rust_stack] > directive in front of it, so you don't have to declare it twice. > > This woudl give use: lib_c::c_function_1() and > lib_c::rs::c_function_1(). > > Regards, > > Michael > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > I would have a stupid proposal: what if the C function declaration was > annotated not with #[rust_stack] but with #[stack 5k] instead. That > is, instead of having a single blunt tool, let the programmer declare > how much stack is necessary for the C function and let the compiler > reason about it to guarantee that enough stack is available. > > extern mod lib_c { > #[stack 4k] > fn c_function_1(); > > #[stack unlimited] > fn c_function_2(); > > #[stack 16k] > fn c_function_3(); > } I do imagine we will eventually want precise control to declare how much stack we need. I originally wanted this for optimizations in core, but as more of core is written in Rust this probably isn't going to matter much. There is an issue open on this subject: https://github.com/mozilla/rust/issues/4481 > > > Then when the compiler sees a bunch of C functions: > > fn func(x: int) { > c_function_1(); > c_function_1(); > c_function_1(); > c_function_3(); > } > > > => if one is marked as "unlimited", then it performs stack switching > (once); this can deferred to the branch the function is called in if > judged "better". > => otherwise, it evaluates the maximum amount of stack needed and > prepares it at the beginning of the function, as usual This sounds like it requires the compiler to have yet more knowledge about stack switching, and a goal of pcwalton's proposal is to get the stack switching logic out of the compiler (into a syntax extension). > > > Advantages: > + Code is not invalidated, only the function declarations are, and > it's easy enough to do a bulk replace #[rust_stack] -> #[stack 4k] > + The information can bubble up at "func" automatically, so that > caller of "func" can perform the switch/reservation themselves if it's > judged profitable. > > Disadvantages: > - Myth of the sufficiently smart compiler spotted. > > > -- Matthieu > > > _______________________________________________ > 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 a.stavonin at gmail.com Fri Feb 1 15:49:30 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Sat, 2 Feb 2013 08:49:30 +0900 Subject: [rust-dev] trait and lifetime In-Reply-To: <510BD35B.2040203@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> Message-ID: Thank you! But I still can not compile it: 1 pub trait TupleVal { 2 pub pure fn _1(&self) -> &self/T; 3 pub pure fn _2(&self) -> &self/T; 4 } 5 6 impl (T, T): TupleVal { 7 pure fn _1(&self) -> &self/T { 8 let (a, _) = self; 9 a 10 } 11 pure fn _2(&self) -> &self/T { 12 let (_, b) = self; 13 b 14 } 15 } test.rs:8:12: 8:18 error: mismatched types: expected `&self/('a,'a)`, found tuple test.rs:8 let (a, _) = self; ^~~~~~ On Feb 1, 2013, at 11:38 PM, Niko Matsakis wrote: > What you want is something like this (and corresponding changes to the impl): > > pub trait TupleVal { > pub pure fn _1(&self) -> &self/T; > pub pure fn _2(&self) -> &self/T; > } > > The `&self` declaration is called an "explicit self" declaration. What you have currently written is called "implicit self" and is deprecated. Explicit self also tells the compiler what sort of pointer you expect: in this case, a borrowed pointer to the receiver. The lifetime of this borrowed pointer is always called "self". Therefore, the return type `&self/T` says: "a pointer with the same lifetime as the receiver to T". > > Note that this syntax is likely to change in the future, although the precise form is not yet finalized. I suspect it will be something like: > > pub trait TupleVal { > pub pure fn _1(&'v self) -> &'v T; > pub pure fn _2(&'v self) -> &'v T; > } > > which makes the connection between the lifetime of the self pointer and the lifetime of the return value more explicit. > > > Niko From niko at alum.mit.edu Fri Feb 1 16:08:06 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 01 Feb 2013 16:08:06 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: References: <510BD35B.2040203@alum.mit.edu> Message-ID: <510C58E6.8020909@alum.mit.edu> You need "let (a, _) = *self" or "let &(a, _) = self". self is a pointer to a tuple, not a tuple. Niko Alexander Stavonin wrote: > Thank you! But I still can not compile it: > > > 1 pub trait TupleVal { > 2 pub pure fn _1(&self) -> &self/T; > 3 pub pure fn _2(&self) -> &self/T; > 4 } > 5 > 6 impl(T, T): TupleVal { > 7 pure fn _1(&self) -> &self/T { > 8 let (a, _) = self; > 9 a > 10 } > 11 pure fn _2(&self) -> &self/T { > 12 let (_, b) = self; > 13 b > 14 } > 15 } > > test.rs:8:12: 8:18 error: mismatched types: expected `&self/('a,'a)`, found tuple > test.rs:8 let (a, _) = self; > ^~~~~~ > > > On Feb 1, 2013, at 11:38 PM, Niko Matsakis wrote: > >> What you want is something like this (and corresponding changes to the impl): >> >> pub trait TupleVal { >> pub pure fn _1(&self) -> &self/T; >> pub pure fn _2(&self) -> &self/T; >> } >> >> The `&self` declaration is called an "explicit self" declaration. What you have currently written is called "implicit self" and is deprecated. Explicit self also tells the compiler what sort of pointer you expect: in this case, a borrowed pointer to the receiver. The lifetime of this borrowed pointer is always called "self". Therefore, the return type `&self/T` says: "a pointer with the same lifetime as the receiver to T". >> >> Note that this syntax is likely to change in the future, although the precise form is not yet finalized. I suspect it will be something like: >> >> pub trait TupleVal { >> pub pure fn _1(&'v self) -> &'v T; >> pub pure fn _2(&'v self) -> &'v T; >> } >> >> which makes the connection between the lifetime of the self pointer and the lifetime of the return value more explicit. >> >> >> Niko > -------------- next part -------------- An HTML attachment was scrubbed... URL: From a.stavonin at gmail.com Fri Feb 1 16:17:48 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Sat, 2 Feb 2013 09:17:48 +0900 Subject: [rust-dev] trait and lifetime In-Reply-To: <510C58E6.8020909@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> Message-ID: Thank you very much! I guess had better extend your "Borrowed pointers" tutorial with information about traits. At least for me it's unclear from the tutorial. On Feb 2, 2013, at 9:08 AM, Niko Matsakis wrote: > You need "let (a, _) = *self" or "let &(a, _) = self". self is a pointer to a tuple, not a tuple. > > > Niko > > Alexander Stavonin wrote: >> >> Thank you! But I still can not compile it: >> >> >> 1 pub trait TupleVal { >> 2 pub pure fn _1(&self) -> &self/T; >> 3 pub pure fn _2(&self) -> &self/T; >> 4 } >> 5 >> 6 impl (T, T): TupleVal { >> 7 pure fn _1(&self) -> &self/T { >> 8 let (a, _) = self; >> 9 a >> 10 } >> 11 pure fn _2(&self) -> &self/T { >> 12 let (_, b) = self; >> 13 b >> 14 } >> 15 } >> >> test.rs:8:12: 8:18 error: mismatched types: expected `&self/('a,'a)`, found tuple >> test.rs:8 let (a, _) = self; >> ^~~~~~ From a.stavonin at gmail.com Fri Feb 1 17:33:04 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Sat, 2 Feb 2013 10:33:04 +0900 Subject: [rust-dev] trait and lifetime In-Reply-To: <510C58E6.8020909@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> Message-ID: <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> I made changes as you told me: 1 pub trait TupleVal { 2 pub pure fn _1(&self) -> &self/T; 3 /*pub pure fn _2(&self) -> &self/T;*/ 4 } 5 6 impl (T, T): TupleVal { 7 pure fn _1(&self) -> &self/T { 8 let &(a, _) = self; 9 &a 10 } 11 /*pure fn _2(&self) -> &self/T {*/ 12 /*let &(_, b) = self;*/ 13 /*&b*/ 14 /*}*/ 15 } 16 17 fn main() { 18 let pair = (1, 2); 19 let left = *pair._1(); 20 io::println(fmt!("pair left: %u", left)); 21 /*let r = pair._2();*/ 22 } But: test.rs:9:9: 9:10 error: illegal borrow: borrowed value does not live long enough test.rs:9 &a ^ test.rs:7:33: 10:5 note: borrowed pointer must be valid for the lifetime &self as defined on the block at 7:33... test.rs:7 pure fn _1(&self) -> &self/T { test.rs:8 let &(a, _) = self; test.rs:9 &a test.rs:10 } test.rs:7:33: 10:5 note: ...but borrowed value is only valid for the block at 7:33 test.rs:7 pure fn _1(&self) -> &self/T { test.rs:8 let &(a, _) = self; test.rs:9 &a test.rs:10 } error: aborting due to previous error Did I miss something? On Feb 2, 2013, at 9:08 AM, Niko Matsakis wrote: > You need "let (a, _) = *self" or "let &(a, _) = self". self is a pointer to a tuple, not a tuple. > > > Niko > > Alexander Stavonin wrote: >> >> Thank you! But I still can not compile it: >> >> >> 1 pub trait TupleVal { >> 2 pub pure fn _1(&self) -> &self/T; >> 3 pub pure fn _2(&self) -> &self/T; >> 4 } >> 5 >> 6 impl (T, T): TupleVal { >> 7 pure fn _1(&self) -> &self/T { >> 8 let (a, _) = self; >> 9 a >> 10 } >> 11 pure fn _2(&self) -> &self/T { >> 12 let (_, b) = self; >> 13 b >> 14 } >> 15 } >> >> test.rs:8:12: 8:18 error: mismatched types: expected `&self/('a,'a)`, found tuple >> test.rs:8 let (a, _) = self; >> ^~~~~~ From ben.striegel at gmail.com Fri Feb 1 19:13:35 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Fri, 1 Feb 2013 22:13:35 -0500 Subject: [rust-dev] idea for Rust playground - seeking comments In-Reply-To: References: Message-ID: > Is that the same syntax highlighter that github uses for their gists? No, Github uses Pygments for their syntax highlighting. And though there exists a Rust highlighter in Pygments, it's a newer version of Pygments that Github's Ruby-based Pygments wrapper doesn't yet support. Though note that Marijn's CodeMirror plugin is 100% Javascript, and is in fact designed to be embedded in web pages. It's quite a lovely client-side code editor. On Fri, Feb 1, 2013 at 5:13 PM, pablo fernandez wrote: > Is that the same syntax highlighter that github uses for their gists? > > Pablo > > > On Fri, Feb 1, 2013 at 7:02 PM, Marijn Haverbeke wrote: > >> See also http://codemirror.net/mode/rust/ . Unfortunately, the syntax >> has changed massively since I wrote that highlighting mode. On the >> bright side, I believe the syntax became somewhat more regular, so >> (though I'm not sure about this) a lot of the complexity in the >> highlighter (and believe me, it is complex) might no longer be needed. >> >> Best, >> Marijn >> >> On Fri, Feb 1, 2013 at 10:51 PM, Dean Thompson >> wrote: >> > Rust Dev, >> > >> > Pablo Fernandez and I are planning to build a simple "Rust playground" >> -- a >> > site where people can try running small Rust programs and then record >> > examples of working or broken Rust code. We wrote down our current >> strawman >> > approach at https://github.com/rusthub/rustpad . We would greatly value >> > feedback from this group before we begin. >> > >> > Dean >> > >> > _______________________________________________ >> > 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 Fri Feb 1 19:47:16 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 01 Feb 2013 19:47:16 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> Message-ID: <510C8C44.7000905@alum.mit.edu> Sorry, I told you wrong. When you write: let &(a, _) = self; &a You are actually copying the value out of `self` and into the stack variable `a`. The error message is telling you that you are returning a pointer into your stack frame, which is of course unsafe. What you actually want is this: let &(ref a, _) = self; a The `ref` keyword indicates that the `a` variable should be a pointer into the value being matched (here, `self`) and not copied out. Niko Alexander Stavonin wrote: > I made changes as you told me: > > 1 pub trait TupleVal { > 2 pub pure fn _1(&self) -> &self/T; > 3 /*pub pure fn _2(&self) -> &self/T;*/ > 4 } > 5 > 6 impl(T, T): TupleVal { > 7 pure fn _1(&self) -> &self/T { > 8 let&(a, _) = self; > 9&a > 10 } > 11 /*pure fn _2(&self) -> &self/T {*/ > 12 /*let&(_, b) = self;*/ > 13 /*&b*/ > 14 /*}*/ > 15 } > 16 > 17 fn main() { > 18 let pair = (1, 2); > 19 let left = *pair._1(); > 20 io::println(fmt!("pair left: %u", left)); > 21 /*let r = pair._2();*/ > 22 } > > But: > > test.rs:9:9: 9:10 error: illegal borrow: borrowed value does not live long enough > test.rs:9&a > ^ > test.rs:7:33: 10:5 note: borrowed pointer must be valid for the lifetime&self as defined on the block at 7:33... > test.rs:7 pure fn _1(&self) -> &self/T { > test.rs:8 let&(a, _) = self; > test.rs:9&a > test.rs:10 } > test.rs:7:33: 10:5 note: ...but borrowed value is only valid for the block at 7:33 > test.rs:7 pure fn _1(&self) -> &self/T { > test.rs:8 let&(a, _) = self; > test.rs:9&a > test.rs:10 } > error: aborting due to previous error > > Did I miss something? > > On Feb 2, 2013, at 9:08 AM, Niko Matsakis wrote: > >> You need "let (a, _) = *self" or "let&(a, _) = self". self is a pointer to a tuple, not a tuple. >> >> >> Niko >> >> Alexander Stavonin wrote: >>> Thank you! But I still can not compile it: >>> >>> >>> 1 pub trait TupleVal { >>> 2 pub pure fn _1(&self) -> &self/T; >>> 3 pub pure fn _2(&self) -> &self/T; >>> 4 } >>> 5 >>> 6 impl(T, T): TupleVal { >>> 7 pure fn _1(&self) -> &self/T { >>> 8 let (a, _) = self; >>> 9 a >>> 10 } >>> 11 pure fn _2(&self) -> &self/T { >>> 12 let (_, b) = self; >>> 13 b >>> 14 } >>> 15 } >>> >>> test.rs:8:12: 8:18 error: mismatched types: expected `&self/('a,'a)`, found tuple >>> test.rs:8 let (a, _) = self; >>> ^~~~~~ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From a.stavonin at gmail.com Fri Feb 1 20:13:09 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Sat, 2 Feb 2013 13:13:09 +0900 Subject: [rust-dev] trait and lifetime In-Reply-To: <510C8C44.7000905@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> <510C8C44.7000905@alum.mit.edu> Message-ID: Looks like I'd like to do something extremely difficult %) 7 impl (T, T): TupleVal { 8 fn _1(&self) -> &self/T { 9 let &(ref a, _) = self; 10 a 11 } Assertion failed: (getOperand(0)->getType() == cast(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file /Volumes/Home/astavonin/Projects/rust/src/llvm/lib/VMCore/Instructions.cpp, line 1062. zsh: abort rustc test.rs On Feb 2, 2013, at 12:47 PM, Niko Matsakis wrote: > Sorry, I told you wrong. When you write: > > let &(a, _) = self; > &a > > You are actually copying the value out of `self` and into the stack variable `a`. The error message is telling you that you are returning a pointer into your stack frame, which is of course unsafe. > > What you actually want is this: > > let &(ref a, _) = self; > a > > The `ref` keyword indicates that the `a` variable should be a pointer into the value being matched (here, `self`) and not copied out. > > > Niko From erick.tryzelaar at gmail.com Fri Feb 1 21:26:24 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Fri, 1 Feb 2013 21:26:24 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> <510C8C44.7000905@alum.mit.edu> Message-ID: That's definitely a bug. I filed a bug report it about it for you here: https://github.com/mozilla/rust/issues/4760 On Fri, Feb 1, 2013 at 8:13 PM, Alexander Stavonin wrote: > Looks like I'd like to do something extremely difficult %) > > 7 impl (T, T): TupleVal { > 8 fn _1(&self) -> &self/T { > 9 let &(ref a, _) = self; > 10 a > 11 } > > > Assertion failed: (getOperand(0)->getType() == > cast(getOperand(1)->getType())->getElementType() && "Ptr must > be a pointer to Val type!"), function AssertOK, file > /Volumes/Home/astavonin/Projects/rust/src/llvm/lib/VMCore/Instructions.cpp, > line 1062. > zsh: abort rustc test.rs > > > On Feb 2, 2013, at 12:47 PM, Niko Matsakis wrote: > > > Sorry, I told you wrong. When you write: > > > > let &(a, _) = self; > > &a > > > > You are actually copying the value out of `self` and into the stack > variable `a`. The error message is telling you that you are returning a > pointer into your stack frame, which is of course unsafe. > > > > What you actually want is this: > > > > let &(ref a, _) = self; > > a > > > > The `ref` keyword indicates that the `a` variable should be a pointer > into the value being matched (here, `self`) and not copied out. > > > > > > Niko > > _______________________________________________ > 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 Fri Feb 1 23:02:21 2013 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 01 Feb 2013 23:02:21 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510C4C57.5090906@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> Message-ID: <510CB9FD.60605@mozilla.com> On 02/01/2013 03:14 PM, Brian Anderson wrote: > On 02/01/2013 09:23 AM, Matthieu Monrocq wrote: >> >> >> On Fri, Feb 1, 2013 at 12:09 PM, Michael Neumann > > wrote: >> >> Am 31.01.2013 23:37, schrieb Patrick Walton: >> >> Hi everyone, >> >> With the revamp of the scheduler underway, I'd like to >> propose a change to the way C functions work. >> >> Currently, we generate a shim and a stack switch for every >> function call from Rust to C and likewise from C to Rust, >> except for functions annotated with `#[rust_stack]`. These >> wrappers result in a significant performance overhead. For >> some workloads this performance overhead is acceptable in >> order to maintain small stacks. For some workloads the >> performance overhead is undesirable. >> >> For instance, the DOM in Servo requires lots of very small >> calls from JavaScript to Rust. The overhead of stack >> switching swamps most of the time here. Popular Web >> benchmarks will do things like `someElement.clientX;` over >> and over, which require calls from JavaScript to Rust to >> retrieve a cached value. So we must carefully consider every >> CPU cycle spent in the C-to-Rust transition. >> >> To address these issues I would like to propose a somewhat >> radical change: don't have the compiler generate stack >> switching stubs at all. Instead, the scheduler can expose a >> primitive that generates the stack switch, and it's the >> programmer's responsibility to perform the stack switch to >> call out to C functions. To avoid the obvious footgun here, I >> propose a lint pass, on by default, that ensures that >> functions not annotated with `#[rust_stack]` are called >> inside a stack switching helper. >> >> The rationale here is as follows: >> >> 1. It should be possible to group many C calls under a single >> stack switching operation. For example: >> >> do stackswitch { >> c_function_1(); >> c_function_2(); >> c_function_3(); >> } >> >> >> wouldn't it be possible for this case to just do: >> >> extern mod lib_c { >> #[rust_stack] >> fn c_function_1(); >> >> #[rust_stack] >> fn c_function_2(); >> >> #[rust_stack] >> fn c_function_3(); >> } >> >> and then calling it like above with *one* "do stackswitch"? >> >> The default would still be to do a stack switch. If you need to >> call c_function_1 sometimes with a stack switch, and sometimes >> in a group of other functions (with just one stack switch for >> that group), we could have something like this: >> >> extern mod lib_c { >> >> // This is the default >> fn c_function_1(); >> >> #[rust_stack] >> fn c_function_1() as rs_c_function1(); >> >> } >> >> Then use lib_c::c_function_1() when you want a stack switch, or >> rs_c_function1() without. One could go further >> and auto generate for mod lib_c a sub module called "rs" (for >> rust stack), where each function has a #[rust_stack] >> directive in front of it, so you don't have to declare it twice. >> >> This woudl give use: lib_c::c_function_1() and >> lib_c::rs::c_function_1(). >> >> Regards, >> >> Michael >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> >> I would have a stupid proposal: what if the C function declaration >> was annotated not with #[rust_stack] but with #[stack 5k] instead. >> That is, instead of having a single blunt tool, let the programmer >> declare how much stack is necessary for the C function and let the >> compiler reason about it to guarantee that enough stack is available. >> >> extern mod lib_c { >> #[stack 4k] >> fn c_function_1(); >> >> #[stack unlimited] >> fn c_function_2(); >> >> #[stack 16k] >> fn c_function_3(); >> } > > I do imagine we will eventually want precise control to declare how > much stack we need. I originally wanted this for optimizations in > core, but as more of core is written in Rust this probably isn't going > to matter much. There is an issue open on this subject: > https://github.com/mozilla/rust/issues/4481 After thinking about this more, I like this direction and think it will matter for core because core should entirely be able to avoid big stack switches once the runtime is rewritten. I want to stop thinking about this as 'stack switching' and instead as 'reserving stack'. At some point I intend to remove the distinction between the C stack and Rust stack segments, and they will be cached in a pool on the scheduler. It will be considerably simpler than the current arrangement that employs two very different strategies for creating and caching stacks. I am thinking a two-pronged approach of library functions plus syntax extensions. extern-ABI functions don't switch stacks by default. In the library we add this sort of function that simply guarantee that the closure has some amount of stack available. do reserve_stack(Standard) { rust_task_fail(); } do reserve_stack(Tiny) {... } do reserve_stack(Large) { } do reserve_stack(Size(4096)) { } Then a decorating syntax extension that automatically wraps a declaration. extern { #[reserve_stack] fn rust_task_fail(); #[reserve_stack(Tiny)] fn rust_get_task() -> *rust_task; } Or even #[reserve_stack] extern { ... } -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Fri Feb 1 23:08:14 2013 From: banderson at mozilla.com (Brian Anderson) Date: Fri, 01 Feb 2013 23:08:14 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CB9FD.60605@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> Message-ID: <510CBB5E.7010705@mozilla.com> On 02/01/2013 11:02 PM, Brian Anderson wrote: > On 02/01/2013 03:14 PM, Brian Anderson wrote: >> On 02/01/2013 09:23 AM, Matthieu Monrocq wrote: >> > > do reserve_stack(Standard) { rust_task_fail(); } Of course that's do reserve_stack(Standard) { unsafe { rust_task_fail(); } } -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sat Feb 2 01:16:09 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 02 Feb 2013 01:16:09 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CB9FD.60605@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> Message-ID: <510CD959.4050702@mozilla.com> On 2/1/13 11:02 PM, Brian Anderson wrote: > In the library we add this sort of function that simply guarantee that > the closure has some amount of stack available. > > do reserve_stack(Standard) { rust_task_fail(); } > do reserve_stack(Tiny) {... } > do reserve_stack(Large) { } > do reserve_stack(Size(4096)) { } My main worry about this is that it's always guesswork. Determining how much stack a C function needs is really hard and involves doing a lot of non-local reasoning. Getting it wrong can result in exploitable security vulnerabilities. From a safety POV, it seems that you always really want as big a stack as possible, unless the function is something trivial like floor(). Patrick From banderson at mozilla.com Sat Feb 2 01:49:11 2013 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 02 Feb 2013 01:49:11 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CD959.4050702@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> Message-ID: <510CE117.30100@mozilla.com> On 02/02/2013 01:16 AM, Patrick Walton wrote: > On 2/1/13 11:02 PM, Brian Anderson wrote: >> In the library we add this sort of function that simply guarantee that >> the closure has some amount of stack available. >> >> do reserve_stack(Standard) { rust_task_fail(); } >> do reserve_stack(Tiny) {... } >> do reserve_stack(Large) { } >> do reserve_stack(Size(4096)) { } > > My main worry about this is that it's always guesswork. Determining > how much stack a C function needs is really hard and involves doing a > lot of non-local reasoning. Getting it wrong can result in exploitable > security vulnerabilities. From a safety POV, it seems that you always > really want as big a stack as possible, unless the function is > something trivial like floor(). It's true that it's guesswork, but so is #[rust_stack], and #[rust_stack] isn't even asking for _any_ stack, it is asking to run off the end of the stack. Instead we could ask for a very small amount of stack, and we would almost always get it, and nothing would be running in the red zone (hopefully). From banderson at mozilla.com Sat Feb 2 01:54:04 2013 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 02 Feb 2013 01:54:04 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CE117.30100@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510CE117.30100@mozilla.com> Message-ID: <510CE23C.7010505@mozilla.com> On 02/02/2013 01:49 AM, Brian Anderson wrote: > On 02/02/2013 01:16 AM, Patrick Walton wrote: >> On 2/1/13 11:02 PM, Brian Anderson wrote: >>> In the library we add this sort of function that simply guarantee that >>> the closure has some amount of stack available. >>> >>> do reserve_stack(Standard) { rust_task_fail(); } >>> do reserve_stack(Tiny) {... } >>> do reserve_stack(Large) { } >>> do reserve_stack(Size(4096)) { } >> >> My main worry about this is that it's always guesswork. Determining >> how much stack a C function needs is really hard and involves doing a >> lot of non-local reasoning. Getting it wrong can result in >> exploitable security vulnerabilities. From a safety POV, it seems >> that you always really want as big a stack as possible, unless the >> function is something trivial like floor(). > > It's true that it's guesswork, but so is #[rust_stack], and > #[rust_stack] isn't even asking for _any_ stack, it is asking to run > off the end of the stack. Instead we could ask for a very small amount > of stack, and we would almost always get it, and nothing would be > running in the red zone (hopefully). Also guesswork: finding the stack red zone size. From banderson at mozilla.com Sat Feb 2 02:00:40 2013 From: banderson at mozilla.com (Brian Anderson) Date: Sat, 02 Feb 2013 02:00:40 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CD959.4050702@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> Message-ID: <510CE3C8.9000806@mozilla.com> On 02/02/2013 01:16 AM, Patrick Walton wrote: > On 2/1/13 11:02 PM, Brian Anderson wrote: >> In the library we add this sort of function that simply guarantee that >> the closure has some amount of stack available. >> >> do reserve_stack(Standard) { rust_task_fail(); } >> do reserve_stack(Tiny) {... } >> do reserve_stack(Large) { } >> do reserve_stack(Size(4096)) { } > > My main worry about this is that it's always guesswork. Determining > how much stack a C function needs is really hard and involves doing a > lot of non-local reasoning. Getting it wrong can result in exploitable > security vulnerabilities. From a safety POV, it seems that you always > really want as big a stack as possible, unless the function is > something trivial like floor(). Perhaps the API is wrong then. I do think this capability is desirable for core and superior to running code in the red zone. Maybe the primary interface is a nullary function and there are alternate ways to control the segment size. From mneumann at ntecs.de Sat Feb 2 04:50:36 2013 From: mneumann at ntecs.de (Michael Neumann) Date: Sat, 02 Feb 2013 13:50:36 +0100 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510CD959.4050702@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> Message-ID: <510D0B9C.3020007@ntecs.de> Am 02.02.2013 10:16, schrieb Patrick Walton: > On 2/1/13 11:02 PM, Brian Anderson wrote: >> In the library we add this sort of function that simply guarantee that >> the closure has some amount of stack available. >> >> do reserve_stack(Standard) { rust_task_fail(); } >> do reserve_stack(Tiny) {... } >> do reserve_stack(Large) { } >> do reserve_stack(Size(4096)) { } > > My main worry about this is that it's always guesswork. Determining > how much stack a C function needs is really hard and involves doing a > lot of non-local reasoning. Getting it wrong can result in exploitable > security vulnerabilities. From a safety POV, it seems that you always > really want as big a stack as possible, unless the function is > something trivial like floor(). Ultimately we never often want a stack to be increased in size as this seems to be a quite expensive operation. Calling a function that crosses stack space boundaries (i.e. when it has to alloc new stack space) inside a loop might severly affect performance. "do reserve_stack" could be used to prevent that, but the programmer need to be aware of that. At least theoretical it should be possible to calculate how much stack space a given function needs including all the space that all called functions need. Recursive functions would result in "unlimited stack space", just because we cannot analyse the depths of the calls. But for most of the code, we would know the maximum stack space used. We could use this when we start new tasks to allocate a contiguous stack large enough to hold the whole computation of that task without the need to resize (in which case we could optimize away the checks in front of each function). Most functions called by FFI should have a pretty flat call hierarchy. At least functions in lib_c do have. Ideally there is information at link time how much space a given function consumes (I read something about this topic on LLVM segmented stacks). If not, then it is always a guess and it might be better to perform those calls only inside a special task and make sure this task has enough space and that it is protected against stack overflowing (don't have native threads a guard page after the stack segment?). Michael From pwalton at mozilla.com Sat Feb 2 06:01:40 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 02 Feb 2013 06:01:40 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510D0B9C.3020007@ntecs.de> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510D0B9C.3020007@ntecs.de> Message-ID: <510D1C44.3090407@mozilla.com> On 2/2/13 4:50 AM, Michael Neumann wrote: > Ultimately we never often want a stack to be increased in size as this > seems to be a quite expensive operation. Calling a function that crosses > stack space > boundaries (i.e. when it has to alloc new stack space) inside a loop > might severly affect performance. "do reserve_stack" could be used to > prevent that, but > the programmer need to be aware of that. At least theoretical it should > be possible to calculate how much stack space a given function needs > including > all the space that all called functions need. Recursive functions would > result in "unlimited stack space", just because we cannot analyse the > depths of > the calls. But for most of the code, we would know the maximum stack > space used. We could use this when we start new tasks to allocate a > contiguous > stack large enough to hold the whole computation of that task without > the need to resize (in which case we could optimize away the checks in > front > of each function). You have a good point here, and this is a use case I hadn't considered. It's often desirable to have a task allocate a large amount of stack up front and use it for all FFI calls: in fact, this corresponds directly to the JavaScript task in Servo. In some sense this is a generalization of the use case I posted earlier, in which multiple FFI calls would be grouped under the same `reserve_stack` call. So I suppose `reserve_stack` would simply check to see whether there's enough stack space at runtime and turn into a no-op if there is. The safe interfaces to functions would always use `reserve_stack`. (We would enforce this with a lint pass, as earlier.) Thus, in general, if you see `__morestack` high in your profiles, you can fix the thrashing by simply adding a call to `reserve_stack` high in the call chain. This all sounds very attractive to me now. Patrick From niko at alum.mit.edu Sat Feb 2 06:21:01 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Feb 2013 06:21:01 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> <510C8C44.7000905@alum.mit.edu> Message-ID: <510D20CD.80600@alum.mit.edu> Interesting! I'm surprised to see that... anyway, try this: ``` let (ref a, _) = *self; a ``` That's how we normally write it. It might workaround the bug (if not, I'd like to know!) Niko Alexander Stavonin wrote: > Looks like I'd like to do something extremely difficult %) > > 7 impl(T, T): TupleVal { > 8 fn _1(&self) -> &self/T { > 9 let&(ref a, _) = self; > 10 a > 11 } > > > Assertion failed: (getOperand(0)->getType() == cast(getOperand(1)->getType())->getElementType()&& "Ptr must be a pointer to Val type!"), function AssertOK, file /Volumes/Home/astavonin/Projects/rust/src/llvm/lib/VMCore/Instructions.cpp, line 1062. > zsh: abort rustc test.rs > > > On Feb 2, 2013, at 12:47 PM, Niko Matsakis wrote: > >> Sorry, I told you wrong. When you write: >> >> let&(a, _) = self; >> &a >> >> You are actually copying the value out of `self` and into the stack variable `a`. The error message is telling you that you are returning a pointer into your stack frame, which is of course unsafe. >> >> What you actually want is this: >> >> let&(ref a, _) = self; >> a >> >> The `ref` keyword indicates that the `a` variable should be a pointer into the value being matched (here, `self`) and not copied out. >> >> >> Niko > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sat Feb 2 06:39:49 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Feb 2013 06:39:49 -0800 Subject: [rust-dev] Container framework? In-Reply-To: References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> <510C1D85.3010500@mozilla.com> Message-ID: <510D2535.7040609@alum.mit.edu> Erick Tryzelaar wrote: > Well, we need the MutableMap-style traits, but we could fold the > ImmutableMap-style "insert into a copy" methods to Map. I don't think > we can rely on "&mut self" helping us out because it could be a source > of bugs. For example, if w forget a hashmap is currently immutable and > do "m.remove(x);" nothing actually happened. One idea regarding remove and friends would be to structure the traits something like this. First there would be your basic `Map` trait that assumes operations take effect "in-place": trait Map { fn add(&mut self, k: K, v: V); fn remove(&mut self, k: &K); ... } In a persistent map, there must be some other operation that returns a new map, let's call them plus and minus: trait PersistentMap : Map { fn plus(&self, k: K, v: V) -> self; fn minus(&self, k: &K) -> self; ... } In that case, add and remove can be implemented in terms of plus and minus fairly easily: trait PersistentMap : Map { ... fn add(&mut self, k: K, v: V) { *self = self.plus(k, v); } fn minus(&mut self, k: &K) { *self = self.minus(k); } } Here I am assuming an impl something like: impl PersistentMap for @PersistentHashMap { ... } Note that `@` sign in the impl. I think this would be required for this scheme to work out. The neat thing about this is that persistent maps can be used anywhere a "normal" map is expected. In fact, you'll note that *persistent maps* and *freezable maps* work pretty similarly. That is, if I have a function like this: fn do_something>(m: M) { ... } If `m` is a freezable map, like send_map, then `m` is *consumed* by `do_something()` and thus the caller of `do_something()` can never see the changes that `do_something()` made. If `m` is a persistent map, the same is true, except that the caller may hold on to its original copy of `m`---but in any case the caller cannot see what `do_something()` has done. If `do_something()` wants its changes to be visible to the caller, it should be declared with a borrowed pointer: fn do_something>(m: &mut M) { ... } Basically what I'm getting at here is that both *freezable* and *persistent* maps share the property that they *act like immutable values*. This is true *even though* freezable maps are modified in-place, because *at the time of modification* no aliases exist, so who's to say you didn't swap in a new map? Niko From niko at alum.mit.edu Sat Feb 2 06:51:18 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Feb 2013 06:51:18 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510D2535.7040609@alum.mit.edu> References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> <510C1D85.3010500@mozilla.com> <510D2535.7040609@alum.mit.edu> Message-ID: <510D27E6.3050805@alum.mit.edu> Niko Matsakis wrote: > Basically what I'm getting at here is that both *freezable* and > *persistent* maps share the property that they *act like immutable > values*. This is true *even though* freezable maps are modified > in-place, because *at the time of modification* no aliases exist, so > who's to say you didn't swap in a new map? Taking this idea a little further, you could almost just have one interface: trait Map { fn add(&mut self, k: K, v: V); fn remove(&mut self, k: &K); fn plus(&self, k: K, v: V) -> self; fn minus(&self, k: &K) -> self; } In the case of a persistent map, `add()` and `remove()` are impl'd in terms of `plus()` and `minus()`, but for an in-place, freezable map---which I will call an imperative map---it's the other way around: trait ImperativeMap : Map { fn add(&mut self, k: K, v: V); fn remove(&mut self, k: &K); fn plus(&self, k: K, v: V) -> self { let mut m = *self; // Problem: requires that K and V be copyable. m.add(k, v); return m; } fn minus(&self, k: &K) -> self { ... } } As I wrote this, though, I realize the flaw: K and V would have to be declared copyable, which we do not want to require. Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From erick.tryzelaar at gmail.com Sat Feb 2 09:31:12 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Sat, 2 Feb 2013 09:31:12 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: <510D20CD.80600@alum.mit.edu> References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> <510C8C44.7000905@alum.mit.edu> <510D20CD.80600@alum.mit.edu> Message-ID: That doesn't work. It triggers this error: test2.rs:8:25: 8:30 error: moving out of dereference of immutable & pointer test2.rs:8 let (ref a, _) = *self; ^~~~~ On Sat, Feb 2, 2013 at 6:21 AM, Niko Matsakis wrote: > Interesting! I'm surprised to see that... anyway, try this: > > ``` > let (ref a, _) = *self; > a > ``` > > That's how we normally write it. It might workaround the bug (if not, I'd > like to know!) > > > Niko > > > Alexander Stavonin wrote: > > Looks like I'd like to do something extremely difficult %) > > 7 impl (T, T): TupleVal { > 8 fn _1(&self) -> &self/T { > 9 let &(ref a, _) = self; > 10 a > 11 } > > > Assertion failed: (getOperand(0)->getType() == cast(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file /Volumes/Home/astavonin/Projects/rust/src/llvm/lib/VMCore/Instructions.cpp, line 1062. > zsh: abort rustc test.rs > > > On Feb 2, 2013, at 12:47 PM, Niko Matsakis wrote: > > > Sorry, I told you wrong. When you write: > > let &(a, _) = self; > &a > > You are actually copying the value out of `self` and into the stack variable `a`. The error message is telling you that you are returning a pointer into your stack frame, which is of course unsafe. > > What you actually want is this: > > let &(ref a, _) = self; > a > > The `ref` keyword indicates that the `a` variable should be a pointer into the value being matched (here, `self`) and not copied out. > > > Niko > > > _______________________________________________ > 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 mcguire at crsr.net Sat Feb 2 12:49:39 2013 From: mcguire at crsr.net (Tommy M. McGuire) Date: Sat, 02 Feb 2013 14:49:39 -0600 Subject: [rust-dev] First program? Message-ID: <510D7BE3.70204@crsr.net> Is this a good place to request comments on a (really horrible) first Rust program? https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict.rs For inspiration (and because I have no actual creativity of my own), I picked up http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/, which is basically an anagram solution generator; this first program generates a text dictionary of letter sequences to words, one mapping per line. I'm using Rust 0.5. * I used std::map::HashMap, although I have since read that LinerMap is more idiomatic? * I saw a suggestion to use @~str since ~str's seem to be better supported, library-wise, and I saw a suggestion to use @~str to avoid the copying warnings for bare ~str's. * After playing some more, I think read_lines is kind of silly. * For no readily apparent reason, I used @[] quite a bit. Should there be any special preferences for ~[]? Thanks in advance for any comments on correctness, style, idiom. -- Tommy M. McGuire mcguire at crsr.net From niko at alum.mit.edu Sat Feb 2 13:02:58 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Feb 2013 13:02:58 -0800 Subject: [rust-dev] trait and lifetime In-Reply-To: References: <510BD35B.2040203@alum.mit.edu> <510C58E6.8020909@alum.mit.edu> <9FBB3A62-7DD4-44F1-AD79-6FB82999F52F@gmail.com> <510C8C44.7000905@alum.mit.edu> <510D20CD.80600@alum.mit.edu> Message-ID: <510D7F02.6070503@alum.mit.edu> Wow, interesting. Another bug! Actually, I just remembered that `ref` bindings in `let` are still broken...I have a pending patch to fix that, maybe I should go dust if off and see if I can finish it up. The way we would *really* write this today is as follows: match *self { (ref a, _) => a } Niko Erick Tryzelaar wrote: > That doesn't work. It triggers this error: > > test2.rs:8:25: 8:30 error: moving out of dereference of immutable & > pointer > test2.rs:8 let (ref a, _) = *self; > ^~~~~ > > > On Sat, Feb 2, 2013 at 6:21 AM, Niko Matsakis > wrote: > > Interesting! I'm surprised to see that... anyway, try this: > > ``` > let (ref a, _) = *self; > a > ``` > > That's how we normally write it. It might workaround the bug (if > not, I'd like to know!) > > > Niko > > > Alexander Stavonin wrote: >> Looks like I'd like to do something extremely difficult %) >> >> 7 impl(T, T): TupleVal { >> 8 fn _1(&self) -> &self/T { >> 9 let&(ref a, _) = self; >> 10 a >> 11 } >> >> >> Assertion failed: (getOperand(0)->getType() == cast(getOperand(1)->getType())->getElementType()&& "Ptr must be a pointer to Val type!"), function AssertOK, file /Volumes/Home/astavonin/Projects/rust/src/llvm/lib/VMCore/Instructions.cpp, line 1062. >> zsh: abort rustctest.rs >> >> >> On Feb 2, 2013, at 12:47 PM, Niko Matsakis wrote: >> >>> Sorry, I told you wrong. When you write: >>> >>> let&(a, _) = self; >>> &a >>> >>> You are actually copying the value out of `self` and into the stack variable `a`. The error message is telling you that you are returning a pointer into your stack frame, which is of course unsafe. >>> >>> What you actually want is this: >>> >>> let&(ref a, _) = self; >>> a >>> >>> The `ref` keyword indicates that the `a` variable should be a pointer into the value being matched (here, `self`) and not copied out. >>> >>> >>> Niko > > _______________________________________________ > 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 a.stavonin at gmail.com Sat Feb 2 22:36:38 2013 From: a.stavonin at gmail.com (Alexander Stavonin) Date: Sun, 3 Feb 2013 15:36:38 +0900 Subject: [rust-dev] Sorting & generics Message-ID: <01364D07-EF8B-4B74-8EAA-A4B3A733029F@gmail.com> Hi, I'm not sure it is an defect or failure to fully understand from my side. I'd like to sort an array. Unfortunately, it is not easy to understand which sort function should be used, but looks like quick_sort3 is good enough. Than: 1 extern mod std; 2 use std::sort::*; 3 4 fn foo_generic(data : &[T]) { 5 let part = data.slice(0, data.len()/2); 6 quick_sort3(part); 7 io::println(part.to_str()); 8 } 9 10 fn foo(data : &[int]) { 11 let mut part = data.slice(0, data.len()/2); 12 quick_sort3(part); 13 io::println(part.to_str()); 14 } 15 fn main() { 16 let data = ~[1, 3, 5, 2, 4, 6]; 17 foo(data); 18 foo_generic(data); 19 } test.rs:6:4: 6:15 error: failed to find an implementation of trait @core::cmp::Ord for test.rs:6 quick_sort3(part); ^~~~~~~~~~~ Is the foo_generic correct function? Regards, From gwillen at nerdnet.org Sat Feb 2 23:30:34 2013 From: gwillen at nerdnet.org (Glenn Willen) Date: Sat, 2 Feb 2013 23:30:34 -0800 Subject: [rust-dev] Sorting & generics In-Reply-To: <01364D07-EF8B-4B74-8EAA-A4B3A733029F@gmail.com> References: <01364D07-EF8B-4B74-8EAA-A4B3A733029F@gmail.com> Message-ID: <9EF0FDC2-3C6D-4C42-99DD-06DF2640A9D7@nerdnet.org> I believe you need to specify, when declaring foo_generic, that your type T has the Ord trait (i.e. that objects of type T can be ordered, which is necessary in order for them to be sorted.) I think the way to do that is fn foo_generic... When I test this, I have to 'use cmp::Ord;' in order to get Ord in scope. Then I get a similar error about the Eq trait, but I have not yet figured out how to convince rust that my type T also has Eq. The seemingly-obvious thing of "T: Ord, Eq", combined with 'use cmp::Eq;' does not work. /tmp/foo.rs:8:4: 8:15 error: failed to find an implementation of trait core::cmp::Eq for /tmp/foo.rs:8 quick_sort3(part); (Although the error spells it core::cmp::Eq, using that doesn't help.) Note that I am using rustc 0.5 -- I think the syntax for this may have changed since then, confusing things further. Glenn On Feb 2, 2013, at 10:36 PM, Alexander Stavonin wrote: > Hi, > > I'm not sure it is an defect or failure to fully understand from my side. I'd like to sort an array. Unfortunately, it is not easy to understand which sort function should be used, but looks like quick_sort3 is good enough. > > Than: > > 1 extern mod std; > 2 use std::sort::*; > 3 > 4 fn foo_generic(data : &[T]) { > 5 let part = data.slice(0, data.len()/2); > 6 quick_sort3(part); > 7 io::println(part.to_str()); > 8 } > 9 > 10 fn foo(data : &[int]) { > 11 let mut part = data.slice(0, data.len()/2); > 12 quick_sort3(part); > 13 io::println(part.to_str()); > 14 } > 15 fn main() { > 16 let data = ~[1, 3, 5, 2, 4, 6]; > 17 foo(data); > 18 foo_generic(data); > 19 } > > > test.rs:6:4: 6:15 error: failed to find an implementation of trait @core::cmp::Ord for > test.rs:6 quick_sort3(part); > ^~~~~~~~~~~ > > Is the foo_generic correct function? > > Regards, > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > !DSPAM:510e0ce6261275098973934! > From gwillen at nerdnet.org Sun Feb 3 00:24:00 2013 From: gwillen at nerdnet.org (Glenn Willen) Date: Sun, 3 Feb 2013 00:24:00 -0800 Subject: [rust-dev] Sorting & generics In-Reply-To: <9EF0FDC2-3C6D-4C42-99DD-06DF2640A9D7@nerdnet.org> References: <01364D07-EF8B-4B74-8EAA-A4B3A733029F@gmail.com> <9EF0FDC2-3C6D-4C42-99DD-06DF2640A9D7@nerdnet.org> Message-ID: <8679A855-EA2E-4346-9FB6-8CEFCE9A9869@nerdnet.org> Okay, at least in 0.5, multiple traits are spelled with a space, not a comma, oops. So it should be, after fixing most of the errors: use cmp::{Ord, Eq}; ... fn foo_generic... There is one error left that I haven't figured out: /tmp/foo.rs:7:16: 7:20 error: illegal borrow: creating mutable alias to dereference of immutable ~ pointer /tmp/foo.rs:7 quick_sort3(part); ^~~~ I find it weird that this manifests only in the generic version; I don't really understand slices, so I'm not sure how to go about diagnosing it. Glenn On Feb 2, 2013, at 11:30 PM, Glenn Willen wrote: > I believe you need to specify, when declaring foo_generic, that your type T has the Ord trait (i.e. that objects of type T can be ordered, which is necessary in order for them to be sorted.) I think the way to do that is > > fn foo_generic... > > When I test this, I have to 'use cmp::Ord;' in order to get Ord in scope. Then I get a similar error about the Eq trait, but I have not yet figured out how to convince rust that my type T also has Eq. The seemingly-obvious thing of "T: Ord, Eq", combined with 'use cmp::Eq;' does not work. > > /tmp/foo.rs:8:4: 8:15 error: failed to find an implementation of trait core::cmp::Eq for > /tmp/foo.rs:8 quick_sort3(part); > > (Although the error spells it core::cmp::Eq, using that doesn't help.) > > Note that I am using rustc 0.5 -- I think the syntax for this may have changed since then, confusing things further. > > Glenn > > On Feb 2, 2013, at 10:36 PM, Alexander Stavonin wrote: > >> Hi, >> >> I'm not sure it is an defect or failure to fully understand from my side. I'd like to sort an array. Unfortunately, it is not easy to understand which sort function should be used, but looks like quick_sort3 is good enough. >> >> Than: >> >> 1 extern mod std; >> 2 use std::sort::*; >> 3 >> 4 fn foo_generic(data : &[T]) { >> 5 let part = data.slice(0, data.len()/2); >> 6 quick_sort3(part); >> 7 io::println(part.to_str()); >> 8 } >> 9 >> 10 fn foo(data : &[int]) { >> 11 let mut part = data.slice(0, data.len()/2); >> 12 quick_sort3(part); >> 13 io::println(part.to_str()); >> 14 } >> 15 fn main() { >> 16 let data = ~[1, 3, 5, 2, 4, 6]; >> 17 foo(data); >> 18 foo_generic(data); >> 19 } >> >> >> test.rs:6:4: 6:15 error: failed to find an implementation of trait @core::cmp::Ord for >> test.rs:6 quick_sort3(part); >> ^~~~~~~~~~~ >> >> Is the foo_generic correct function? >> >> Regards, >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> >> >> !DSPAM:510e0ce6261275098973934! >> > From gwillen at nerdnet.org Sun Feb 3 00:27:35 2013 From: gwillen at nerdnet.org (Glenn Willen) Date: Sun, 3 Feb 2013 00:27:35 -0800 Subject: [rust-dev] Sorting & generics In-Reply-To: <8679A855-EA2E-4346-9FB6-8CEFCE9A9869@nerdnet.org> References: <01364D07-EF8B-4B74-8EAA-A4B3A733029F@gmail.com> <9EF0FDC2-3C6D-4C42-99DD-06DF2640A9D7@nerdnet.org> <8679A855-EA2E-4346-9FB6-8CEFCE9A9869@nerdnet.org> Message-ID: Oh, final reply to myself: I didn't notice that, in the original code, you did 'let part' instead of 'let mut part', in the generic function. After fixing that, the code works. Glenn On Feb 3, 2013, at 12:24 AM, Glenn Willen wrote: > Okay, at least in 0.5, multiple traits are spelled with a space, not a comma, oops. > > So it should be, after fixing most of the errors: > > use cmp::{Ord, Eq}; > ... > fn foo_generic... > > There is one error left that I haven't figured out: > > /tmp/foo.rs:7:16: 7:20 error: illegal borrow: creating mutable alias to dereference of immutable ~ pointer > /tmp/foo.rs:7 quick_sort3(part); > ^~~~ > > I find it weird that this manifests only in the generic version; I don't really understand slices, so I'm not sure how to go about diagnosing it. > > Glenn > > On Feb 2, 2013, at 11:30 PM, Glenn Willen wrote: > >> I believe you need to specify, when declaring foo_generic, that your type T has the Ord trait (i.e. that objects of type T can be ordered, which is necessary in order for them to be sorted.) I think the way to do that is >> >> fn foo_generic... >> >> When I test this, I have to 'use cmp::Ord;' in order to get Ord in scope. Then I get a similar error about the Eq trait, but I have not yet figured out how to convince rust that my type T also has Eq. The seemingly-obvious thing of "T: Ord, Eq", combined with 'use cmp::Eq;' does not work. >> >> /tmp/foo.rs:8:4: 8:15 error: failed to find an implementation of trait core::cmp::Eq for >> /tmp/foo.rs:8 quick_sort3(part); >> >> (Although the error spells it core::cmp::Eq, using that doesn't help.) >> >> Note that I am using rustc 0.5 -- I think the syntax for this may have changed since then, confusing things further. >> >> Glenn >> >> On Feb 2, 2013, at 10:36 PM, Alexander Stavonin wrote: >> >>> Hi, >>> >>> I'm not sure it is an defect or failure to fully understand from my side. I'd like to sort an array. Unfortunately, it is not easy to understand which sort function should be used, but looks like quick_sort3 is good enough. >>> >>> Than: >>> >>> 1 extern mod std; >>> 2 use std::sort::*; >>> 3 >>> 4 fn foo_generic(data : &[T]) { >>> 5 let part = data.slice(0, data.len()/2); >>> 6 quick_sort3(part); >>> 7 io::println(part.to_str()); >>> 8 } >>> 9 >>> 10 fn foo(data : &[int]) { >>> 11 let mut part = data.slice(0, data.len()/2); >>> 12 quick_sort3(part); >>> 13 io::println(part.to_str()); >>> 14 } >>> 15 fn main() { >>> 16 let data = ~[1, 3, 5, 2, 4, 6]; >>> 17 foo(data); >>> 18 foo_generic(data); >>> 19 } >>> >>> >>> test.rs:6:4: 6:15 error: failed to find an implementation of trait @core::cmp::Ord for >>> test.rs:6 quick_sort3(part); >>> ^~~~~~~~~~~ >>> >>> Is the foo_generic correct function? >>> >>> Regards, >>> _______________________________________________ >>> Rust-dev mailing list >>> Rust-dev at mozilla.org >>> https://mail.mozilla.org/listinfo/rust-dev >>> >>> >>> !DSPAM:510e0ce6261275098973934! >>> >> > From hatahet at gmail.com Sun Feb 3 07:22:26 2013 From: hatahet at gmail.com (Ziad Hatahet) Date: Sun, 3 Feb 2013 07:22:26 -0800 Subject: [rust-dev] Questions about pointers Message-ID: Hi all, I was playing around with the different pointer types in Rust, and I have the following program: https://gist.github.com/4702154 My questions/comments are listed in lines 16, 23, 27, and 29. As a side note, I believe that there is still work being done on having mutability depend on the containing slot, could that be a source of some of the issues in the code? Thanks -- Ziad -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Sun Feb 3 08:32:32 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Sun, 3 Feb 2013 08:32:32 -0800 Subject: [rust-dev] Questions about pointers In-Reply-To: References: Message-ID: On Sun, Feb 3, 2013 at 7:22 AM, Ziad Hatahet wrote: > Hi all, > > I was playing around with the different pointer types in Rust, and I have > the following program: https://gist.github.com/4702154 > > My questions/comments are listed in lines 16, 23, 27, and 29. > Line 16: The recent "move based on type" changes mean that when you refer to a variable that has a non-implicitly-copyable type -- `c`, which is mutable and has type `~int` in this case -- writing `c` means `move c`. So that means if you use `c` again in a place where a previous use of `c` may have occurred, you get an error because `c` has already been moved out of and zeroed out. The answer here is to either write `copy c` instead of c, or pass `c` by reference. Line 23: `c` isn't incremented because you passed a new pointer to a copy of the contents of `c` in the previous call to `inc`. Line 27: Likewise, modify doesn't do what I think you expect, for the same reason as in Line 23. Here's some C code (that probably won't compile), that shows the basic premise: void inc(int *x) { (*x)++; } void main() { int y = 3; int *z = &y; inc(z); printf("%d\n", *z); int *w = malloc(sizeof(int)); *w = *z; inc(w); printf("%d\n", *z); } You wouldn't expect the second printf to print out 5, right? Line 29: Same issue as with Line 16. Hope this helps! > As a side note, I believe that there is still work being done on having > mutability depend on the containing slot, could that be a source of some of > the issues in the code? No, not in this case. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From catamorphism at gmail.com Sun Feb 3 08:54:08 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Sun, 3 Feb 2013 08:54:08 -0800 Subject: [rust-dev] First program? In-Reply-To: <510D7BE3.70204@crsr.net> References: <510D7BE3.70204@crsr.net> Message-ID: On Sat, Feb 2, 2013 at 12:49 PM, Tommy M. McGuire wrote: > Is this a good place to request comments on a (really horrible) first > Rust program? > Certainly! > https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict.rs > > For inspiration (and because I have no actual creativity of my own), I > picked up > http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/, > which is basically an anagram solution generator; this first program > generates a text dictionary of letter sequences to words, one mapping > per line. > > I'm using Rust 0.5. > > * I used std::map::HashMap, although I have since read that LinerMap is > more idiomatic? I wouldn't worry about that at first while learning. HashMap will be removed eventually, though (I think). > > * I saw a suggestion to use @~str since ~str's seem to be better > supported, library-wise, and I saw a suggestion to use @~str to avoid > the copying warnings for bare ~str's. I guess that's probably the best you can do right now, yes. Though as an exercise, it might be fun to see if you can change the @~strs to ~strs now that your code works. On the other hand, storing strings in a map is probably one of those cases where not using @strs will be painful. As you alluded to, though, some library functions only work with ~str so @~str may be easier than @str right now. We really need to work on that... (this part certainly isn't your fault!) > > * After playing some more, I think read_lines is kind of silly. > > * For no readily apparent reason, I used @[] quite a bit. Should there > be any special preferences for ~[]? > No, at least not until you're writing code with multiple tasks or where you care about performance. It's fine to start with @[] and then change to ~[] as needed. As with @str, there's less library support for @[], but that's another thing we need to work on. There are a few places where you call a function like str::len(**line), where line.len() would be more idiomatic (and because of auto-dereference, you're saved from writing the asterisks). I'll let others point out other nits :-) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From erick.tryzelaar at gmail.com Sun Feb 3 14:10:21 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Sun, 3 Feb 2013 14:10:21 -0800 Subject: [rust-dev] Container framework? In-Reply-To: <510D27E6.3050805@alum.mit.edu> References: <510C0B1B.5040005@mozilla.com> <510C167C.3070202@mozilla.com> <510C1D85.3010500@mozilla.com> <510D2535.7040609@alum.mit.edu> <510D27E6.3050805@alum.mit.edu> Message-ID: On Sat, Feb 2, 2013 at 6:51 AM, Niko Matsakis wrote: > > > Niko Matsakis wrote: > > Basically what I'm getting at here is that both **freezable** and ** > persistent** maps share the property that they *act like immutable > values*. This is true **even though** freezable maps are modified > in-place, because **at the time of modification** no aliases exist, so > who's to say you didn't swap in a new map? > > > Taking this idea a little further, you could almost just have one > interface: > > [snip] > > As I wrote this, though, I realize the flaw: K and V would have to be > declared copyable, which we do not want to require. > How big do we want to make the container interfaces? If we have a full interface like Haskell: http://www.haskell.org/ghc/docs/6.12.2/html/libraries/containers-0.3.0.0/Data-Map.html Then we probably should just add a suffix to each form, like "_imm", since I can't think up good names to distinguish all those functions from each other. I do find that a bit ugly though. On the other hand, if we wanted just a small interface like Scala, we could probably get away with a coming up with names like insert/remove vs plus/minus: http://www.scala-lang.org/docu/files/collections-api/collections_10.html Or we could just have two interfaces that share the same names, but have different interfaces. I can't decide. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pnkfelix at mozilla.com Mon Feb 4 04:52:22 2013 From: pnkfelix at mozilla.com (Felix S Klock II) Date: Mon, 04 Feb 2013 13:52:22 +0100 Subject: [rust-dev] Compilation Error in Rust in Nesting of Modules In-Reply-To: References: Message-ID: <510FAF06.9050203@mozilla.com> Ranvijay (cc'ing rust-dev)- Since you put your source code in the file c/c.rs, that code belongs to a module named `c` *inside* of the `c` module you have already put into your orig.rs crate. You can see the "git diff" invocation in the transcript below to see how I fixed your code. Cheers, -Felix % rustc --version rustc 0.5 (09bb07b 2012-12-24 18:29:02 -0800) host: x86_64-apple-darwin % git diff diff --git a/orig.rs b/orig.rs index 8a81117..decb7fe 100644 --- a/orig.rs +++ b/orig.rs @@ -7,6 +7,9 @@ pub mod a ; pub mod b ; pub mod c { pub mod inner_mod ; + + // Fixed code: + pub mod c; } diff --git a/test_orig.rs b/test_orig.rs index 9b0bd63..babf26f 100644 --- a/test_orig.rs +++ b/test_orig.rs @@ -5,7 +5,12 @@ orig::c::inner_mod::inner_mod(); orig::dummy(); orig::a::a_func(); orig::b::b_func(); -orig::c::c_func(); + +// // Original code: +// orig::c::c_func(); +// +// // Fixed Code: +orig::c::c::c_func(); //parserutils::utils::inner_mod::inner_mod(); } % rustc orig.rs && rustc -L. test_orig.rs warning: no debug symbols in executable (-arch x86_64) warning: no debug symbols in executable (-arch x86_64) % ./test_orig i am in inner_mod i am in dummy i am in a i am in b i am in c On Fri Feb 1 12:29:44 2013, Ranvijay Singh wrote: > > Hi, > I am getting compilation error while implementing the nesting of > modules as per the Rust Language tutorial. > Below is the description of my code structure. > > Inside example directory,I created a file orig.rs and > declared 3 modules a, b and c inside it. Inside module c, I declared > another module inner_mod. I created 3 files a.rs , b.rs > and c.rs and one directory c, all inside > the example directory.Also, I created another file inner_mod.rs > and kept it in c directory. In c.rs > , I defined a function *C_func* as below. > > pub fn *c_func*() { > io::println("I am in c"); > } > I called the function c_func in file test_orig.rs > which is in example directory. > As per the tutorial, I can create c.rs file and c > directory both, but nothing is mentioned about the location of c.rs > with respect to c directory i.e. whether c.rs > will be kept inside c directory or outside of it at the > same level as c directory inside example directory. I tried both and > got the below error in each case when compiled: > > *test_orig.rs:8:0: 8:15 error: unresolved name: orig::c::c_func > test_orig.rs:8 orig::c::c_func();* > > Tar file of the code is attached.Please suggest a solution to this. > > > thanks > Ranvijay > > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- irc: pnkfelix on irc.mozilla.org email: {fklock, pnkfelix}@mozilla.org From vadimcn at gmail.com Mon Feb 4 11:34:33 2013 From: vadimcn at gmail.com (Vadim) Date: Mon, 4 Feb 2013 11:34:33 -0800 Subject: [rust-dev] Iterators in Rust Message-ID: Hi, I saw a postby Patrick Walton last week on Reddit in which he implied that it is possible to convert Rust enumerator function into a Java-style iterator by applying some magic transformer function to it. Am I reading this right? Are there any examples of doing this in Rust? I can't fathom how that'd be possible without Rust supporting co-routines or, possibly, lazy evaluation, or something like that... -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Feb 4 12:15:52 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 04 Feb 2013 12:15:52 -0800 Subject: [rust-dev] Iterators in Rust In-Reply-To: References: Message-ID: <511016F8.3090906@mozilla.com> On 2/4/13 11:34 AM, Vadim wrote: > Hi, > I saw a post > > by Patrick Walton last week on Reddit in which he implied that it is > possible to convert Rust enumerator function into a Java-style iterator > by applying some magic transformer function to it. Am I reading this > right? Are there any examples of doing this in Rust? I can't fathom > how that'd be possible without Rust supporting co-routines or, possibly, > lazy evaluation, or something like that... Sorry, I didn't mean to imply that. It's not really possible, except by farming out the iteration to a task and sending messages over a channel. Patrick From cpeterson at mozilla.com Mon Feb 4 12:49:26 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Mon, 04 Feb 2013 12:49:26 -0800 Subject: [rust-dev] Question about lifetime names Message-ID: <51101ED6.9000408@mozilla.com> After reading the recent discussions about lifetime notation, I was wondering why lifetimes need their own names. Lifetimes refer to variables that already have names. For example, given this fn from the borrowed pointers tutorial: fn select(shape: &Shape, threshold: float, a: &r/T, b: &r/T) -> &r/T { if compute_area(shape) > threshold {a} else {b} } What does lifetime `r` actually need a name? The return type is referring to the lifetime of the `a` and `b` parameters. Those parameters already have names. Is it possible to declare a type that references a lifetime name that is not in scope? Could the return type refer to those names (`a` or `b`)? For example: fn select(shape: &Shape, threshold: float, a: &T, b: &T) -> &a/T { if compute_area(shape) > threshold {a} else {b} } Regarding syntax, since the lifetime is annotating a type, would a lifetime suffix be feasible? For example, &T is a "pointer to T" and &T'lt could be a "pointer to type T with a lifetime of lt" chris From vadimcn at gmail.com Mon Feb 4 12:57:37 2013 From: vadimcn at gmail.com (Vadim) Date: Mon, 4 Feb 2013 12:57:37 -0800 Subject: [rust-dev] Iterators in Rust In-Reply-To: <511016F8.3090906@mozilla.com> References: <511016F8.3090906@mozilla.com> Message-ID: So right now there is no way to implement, say, lock-step iteration of two containers, without first copying contents of one of them into a vector? On Mon, Feb 4, 2013 at 12:15 PM, Patrick Walton wrote: > On 2/4/13 11:34 AM, Vadim wrote: > >> Hi, >> I saw a post >> > little_bit_rusty_practical_**approach_on_rust/c86xyor >> > >> by Patrick Walton last week on Reddit in which he implied that it is >> possible to convert Rust enumerator function into a Java-style iterator >> by applying some magic transformer function to it. Am I reading this >> right? Are there any examples of doing this in Rust? I can't fathom >> how that'd be possible without Rust supporting co-routines or, possibly, >> lazy evaluation, or something like that... >> > > Sorry, I didn't mean to imply that. It's not really possible, except by > farming out the iteration to a task and sending messages over a channel. > > 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 Feb 4 12:59:26 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 04 Feb 2013 12:59:26 -0800 Subject: [rust-dev] Iterators in Rust In-Reply-To: References: <511016F8.3090906@mozilla.com> Message-ID: <5110212E.60507@mozilla.com> On 2/4/13 12:57 PM, Vadim wrote: > So right now there is no way to implement, say, lock-step iteration of > two containers, without first copying contents of one of them into a vector? Not using the normal iteration protocol. Some containers (for example, treemap, IIRC) have methods that will produce iterator objects though. Patrick From rexlen at gmail.com Mon Feb 4 14:29:59 2013 From: rexlen at gmail.com (Renato Lenzi) Date: Mon, 4 Feb 2013 23:29:59 +0100 Subject: [rust-dev] Simple question Message-ID: Hi there. How can i use power operator? that is: let x1 = 7; let x2 = 8; let mut x3; x3 = x1 ** x2; ? it seems this doesn't work.... thx. From simon.sapin at exyr.org Mon Feb 4 15:29:04 2013 From: simon.sapin at exyr.org (Simon Sapin) Date: Mon, 04 Feb 2013 16:29:04 -0700 Subject: [rust-dev] Simple question In-Reply-To: References: Message-ID: <51104440.5020002@exyr.org> Le 04/02/2013 15:29, Renato Lenzi a ?crit : > Hi there. How can i use power operator? > that is: > > let x1 = 7; > let x2 = 8; > let mut x3; > x3 = x1 ** x2; ? it seems this doesn't work.... Hi, AFAIK there is no operator for this, but libcore has a float::pow_with_uint function: http://static.rust-lang.org/doc/core/float.html#function-pow_with_uint For a float power, I find traces of a f64::pow function but it?s undocumented? -- Simon Sapin From samuel at framond.fr Mon Feb 4 21:08:45 2013 From: samuel at framond.fr (Samuel de Framond) Date: Tue, 05 Feb 2013 13:08:45 +0800 Subject: [rust-dev] Question about lifetime names In-Reply-To: <51101ED6.9000408@mozilla.com> References: <51101ED6.9000408@mozilla.com> Message-ID: <511093DD.5030802@framond.fr> On 02/05/2013 04:49 AM, Chris Peterson wrote: > After reading the recent discussions about lifetime notation, I was > wondering why lifetimes need their own names. Lifetimes refer to > variables that already have names. For example, given this fn from the > borrowed pointers tutorial: This is not always true. Consider a function that takes a function as parameter: struct Foo { f: int } fn takes_foo(v : </Foo) -> </int { &v.f } fn foobar(v: </Foo, f: fn(</Foo) -> </int) -> </int{ f(v) } fn main() { let a = Foo {f: 1}; let f = foobar(&a, takes_foo); io::println(fmt!("%?", f)); } In this example, the type of the function `f` passed to `foobar` (which is `fn(</Foo) -> </int`) must have a lifetime annotation to compile but has no variable name. > Regarding syntax, since the lifetime is annotating a type, would a > lifetime suffix be feasible? For example, &T is a "pointer to T" and > &T'lt could be a "pointer to type T with a lifetime of lt" I don't know :/ -- Samuel de Framond P: +86 135 8556 8964 M: samuel at framond.fr -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Feb 4 21:10:49 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 04 Feb 2013 21:10:49 -0800 Subject: [rust-dev] Question about lifetime names In-Reply-To: <511093DD.5030802@framond.fr> References: <51101ED6.9000408@mozilla.com> <511093DD.5030802@framond.fr> Message-ID: <51109459.8070300@mozilla.com> On 2/4/13 9:08 PM, Samuel de Framond wrote: >> Regarding syntax, since the lifetime is annotating a type, would a >> lifetime suffix be feasible? For example, &T is a "pointer to T" and >> &T'lt could be a "pointer to type T with a lifetime of lt" > I don't know :/ This was covered earlier. Suffixes tend to cause ambiguity when combined with prefixes in the type grammar. (Consider as a simple example &&T'lt -- which & does that lifetime belong to?) Patrick From gnucash at brinckerhoff.org Mon Feb 4 21:10:52 2013 From: gnucash at brinckerhoff.org (John Clements) Date: Mon, 4 Feb 2013 21:10:52 -0800 Subject: [rust-dev] bors last-commit approval lost on updates Message-ID: <84360CE4-DADF-4956-9ADD-CE86FC5CF82A@brinckerhoff.org> I'm guessing this was deliberate, but I thought I'd check. The bors bot (IIUC) looks for an r+ attached to the final commit of a pull request in order to start auto-merging. When a pull request becomes non-automatically-mergeable (as mine did a few hours ago: jbclements:demodeing-and-deGCing), my understanding is that it's a kindness to force-push to the given branch to make it automatically mergeable (as I just did). Since the approval message appears on the last commit and the last commit is renamed, though, that approval is lost. Is it the intent of the system to have people re-approve the pull requests in situations like this? Thanks! John From samuel at framond.fr Tue Feb 5 07:57:02 2013 From: samuel at framond.fr (Samuel de Framond) Date: Tue, 05 Feb 2013 23:57:02 +0800 Subject: [rust-dev] Question about lifetime names In-Reply-To: <511093DD.5030802@framond.fr> References: <51101ED6.9000408@mozilla.com> <511093DD.5030802@framond.fr> Message-ID: <51112BCE.4030404@framond.fr> Thinking of this again, it seems possible to avoid naming lifetimes if we allow an optional parameter name when specifying types. The example I gave before would become (with the current slash syntax): struct Foo { f: int } // We refer to v's lifetime with &v/... fn takes_foo(v : Foo) -> &v/int { &v.f } ///////////////////////////// // We give the name `toto` to the parameter of the function `f`. // This name is only used to refer to this value's lifetime, never to the value itself. //////////////////////////// fn foobar(v: &Foo, f: fn(toto: &Foo) -> &toto/int) -> &toto/int{ f(v) } My feeling is that it would make the simple case more intuitive while keeping the difficult case as difficult as before. Does it make sense? Samuel On 02/05/2013 01:08 PM, Samuel de Framond wrote: > > On 02/05/2013 04:49 AM, Chris Peterson wrote: >> After reading the recent discussions about lifetime notation, I was >> wondering why lifetimes need their own names. Lifetimes refer to >> variables that already have names. For example, given this fn from >> the borrowed pointers tutorial: > This is not always true. Consider a function that takes a function as > parameter: > > struct Foo { f: int } > > fn takes_foo(v : </Foo) -> </int { > &v.f > } > > fn foobar(v: </Foo, f: fn(</Foo) -> </int) -> </int{ > f(v) > } > > fn main() { > let a = Foo {f: 1}; > let f = foobar(&a, takes_foo); > io::println(fmt!("%?", f)); > } > -- Samuel de Framond P: +86 135 8556 8964 M: samuel at framond.fr -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Tue Feb 5 10:38:09 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 10:38:09 -0800 Subject: [rust-dev] bors last-commit approval lost on updates In-Reply-To: <84360CE4-DADF-4956-9ADD-CE86FC5CF82A@brinckerhoff.org> References: <84360CE4-DADF-4956-9ADD-CE86FC5CF82A@brinckerhoff.org> Message-ID: <51115191.8080503@mozilla.com> On 02/04/2013 09:10 PM, John Clements wrote: > I'm guessing this was deliberate, but I thought I'd check. The bors bot (IIUC) looks for an r+ attached to the final commit of a pull request in order to start auto-merging. When a pull request becomes non-automatically-mergeable (as mine did a few hours ago: jbclements:demodeing-and-deGCing), my understanding is that it's a kindness to force-push to the given branch to make it automatically mergeable (as I just did). Since the approval message appears on the last commit and the last commit is renamed, though, that approval is lost. > > Is it the intent of the system to have people re-approve the pull requests in situations like this? > > Thanks! Yes, I believe it is intended that rebased pull requests require re-approval. From banderson at mozilla.com Tue Feb 5 10:50:19 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 10:50:19 -0800 Subject: [rust-dev] GitHub label maintenance Message-ID: <5111546B.4060604@mozilla.com> Greetings, folks, There was some discussion about bug triage in the meeting today so I went to do some and was reminded of how frustrated I get by our labels: there are a lot of them and I usually can't find an `A-` label that matches the bug. I have some proposals here to remove a lot of them and add a few. Any objections? Add: A-parser A-tools A-concurrency - replaces A-comm/A-parallel A-infrastructure Remove: A-classes - obsolete A-comm - use A-concurrency A-frontend - catchall - existing issues have no obvious relationship. use A-parser, A-syntaxext instead, A-driver instead A-editors - use A-tools A-infer - not used much - use A-typesystem A-kindchk - obsolete A-linearity - use A-typesystem A-liveness - use A-typesystem A-packaging - use A-tools A-parallel - use A-concurrency A-servo - not many issues A-typestate A-unsafe A-unwind A-versioning A-website - use A-infrastructure A-rustbot - use A-infrastructure A-cyclecollector A-github From niko at alum.mit.edu Tue Feb 5 10:50:54 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 05 Feb 2013 10:50:54 -0800 Subject: [rust-dev] lifetime syntax Message-ID: <5111548E.8090205@alum.mit.edu> We are reaching a degree of consensus on the new lifetime syntax. The general idea is as follows. # Lifetime names and borrowed pointers First, `'lt` is the new lexical class for lifetime names. A borrowed pointer has the (fully specified) form `&'lt mq Type`, where `'lt` is the lifetime and `mq` is the mutability (for slices, the syntax is `&'lt mq [T]` and `&'lt str`). As today, `mq` can be `mut` for mutable or nothing for immutable (I believe `const` for read-only is deprecated and hopefully going away). So some examples: &'lt int &'lt mut int In some cases, the lifetime may be omitted: - In a function declaration: `&int` is short for a fresh lifetime name (meaning a different name from all the other names in scope) - In a function body: `&int` is short for an inferred lifetime # Lifetime parameters and fn/struct declarations When you define a function or type, it can be lifetime parameterized. Lifetime parameters are declared within `<>` just like type parameters. If there are both lifetime and type parameters, lifetime parameters must appear first. For example, here is a simple iterator type that iterates over a slice. I have written all lifetime parameters in full, later we will see that not all of them are necessary. (This example compiles today, albeit with different syntax) struct Iterator<'lt, T> { source: &'lt [T], index: uint } fn has_next<'a, 'b, T>(iter: &'a Iterator<'b, T>) -> bool { iter.index + 1 < iter.source.len() } fn next<'a, 'b, T>(iter: &'a mut Iterator<'b, T>) -> Option<&'b T> { iter.index += 1; if iter.index < iter.source.len() { Some(&iter.source[iter.index]) } else { None } } When defining a type, all lifetime parameters must be specified in full (as shown). When defining a function, lifetime parameters may be omitted if you simply with to use a fresh lifetime. The fn `has_next()`, for example, can be simplified to: fn has_next(iter: &Iterator) -> bool { /* same as before */ } This is exactly equivalent. Note that we omitted both the lifetime `'a` that defined the lifetime of the pointer `iter` and the lifetime `'b` which defined the lifetime of `iter.source`. Because this is part of a fn signature, the default for omitted lifetimes is to substitute fresh lifetimes. If we had written the type `&Iterator` inside the fn body, the default would be to infer appropriate lifetimes. Anywhere else where we might write that type, for example as part of a struct or type declaration, there are no defaults and everything must be specified in full. The fn `next()` can be simplified as well, but not *quite* as much: fn next<'b, T>(iter: &mut Iterator<'b, T>) -> Option<&'b T> { /* same as before */ } Here the named lifetime parameter `'b` must remain. This is because it is needed to link the lifetime parameter of the input iterator to the returned option. Note that the lifetime of the pointer `iter` itself is not important: the only important thing is the lifetime of the vector `iter.source`, which is `'b`. # Lifetime parameters andimpls This is what we were discussing in the method but we were cut off. If we wanted to convert the two iterator functions to an impl, we could so as follows (again, we begin with the *fully explicit* form): impl<'b, T> Iterator<'b, T> { fn has_next<'a, T>(&'a self) { /* same as before */ } fn next<'a, T>(&'a mut self) -> Option<&'b T> { /* same as before */ } } As before, lifetimes can be omitted in method declarations if they are not used anywhere else, so this can be simplified to: impl<'b, T> Iterator<'b, T> { fn has_next(&self) { /* same as before */ } fn next(&mut self) -> Option<&'b T> { /* same as before */ } } This is *slightly* different than today. This is because, today, `&self` is equivalent to a self type of `&'b Iterator<'b, T>` rather than using a fresh lifetime (like `&'a Iterator<'a, T>`). The current system causes various issues in real-life examples, including this specific iterator example. # Multiple lifetime parameters Note that this proposal easily permits having multiple lifetime parameters on a given struct. One unclear point is whether you should be able to specify only one of many lifetime parameters. I am inclined to say no, it's all or nothing. For example, given this struct: struct Foo<'a, 'b> You can write `Foo` or `Foo<'lt1, 'lt2>` but not `Foo<'lt1>`. # Labeling blocks and expressions Looking to the future, I personally would like to, further out, support lifetime names as labels on blocks or expressions, so that you could write something like: 'a: { let x: &'a T = ...; } Here `'a` would be a name for the block and it could be used as a lifetime in type annotations and so forth within the method. This would help in allowing users to write explicit annotations. It also helps for breaking/looping in named loops etc: 'a: while cond1 { 'b: while cond2 { ... break 'a; } } Niko From catamorphism at gmail.com Tue Feb 5 10:52:52 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Tue, 5 Feb 2013 10:52:52 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <5111546B.4060604@mozilla.com> References: <5111546B.4060604@mozilla.com> Message-ID: On Tue, Feb 5, 2013 at 10:50 AM, Brian Anderson wrote: > Greetings, folks, > > There was some discussion about bug triage in the meeting today so I went to > do some and was reminded of how frustrated I get by our labels: there are a > lot of them and I usually can't find an `A-` label that matches the bug. I > have some proposals here to remove a lot of them and add a few. Any > objections? Yes, please! > > Add: > > A-parser > A-tools > A-concurrency - replaces A-comm/A-parallel > A-infrastructure > > Remove: > > A-classes - obsolete > A-comm - use A-concurrency > A-frontend - catchall - existing issues have no obvious relationship. use > A-parser, A-syntaxext instead, A-driver instead > A-editors - use A-tools > A-infer - not used much - use A-typesystem > A-kindchk - obsolete > A-linearity - use A-typesystem > A-liveness - use A-typesystem > A-packaging - use A-tools > A-parallel - use A-concurrency > A-servo - not many issues > A-typestate > A-unsafe > A-unwind > A-versioning > A-website - use A-infrastructure > A-rustbot - use A-infrastructure > A-cyclecollector > A-github I actually support breaking up the A-typesystem label into fewer labels. I find myself using typesystem a lot when I want something more specific, actually. Sounds good otherwise. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From catamorphism at gmail.com Tue Feb 5 10:53:11 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Tue, 5 Feb 2013 10:53:11 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: References: <5111546B.4060604@mozilla.com> Message-ID: On Tue, Feb 5, 2013 at 10:52 AM, Tim Chevalier wrote: > On Tue, Feb 5, 2013 at 10:50 AM, Brian Anderson wrote: >> Greetings, folks, >> >> There was some discussion about bug triage in the meeting today so I went to >> do some and was reminded of how frustrated I get by our labels: there are a >> lot of them and I usually can't find an `A-` label that matches the bug. I >> have some proposals here to remove a lot of them and add a few. Any >> objections? > > Yes, please! > >> >> Add: >> >> A-parser >> A-tools >> A-concurrency - replaces A-comm/A-parallel >> A-infrastructure >> >> Remove: >> >> A-classes - obsolete >> A-comm - use A-concurrency >> A-frontend - catchall - existing issues have no obvious relationship. use >> A-parser, A-syntaxext instead, A-driver instead >> A-editors - use A-tools >> A-infer - not used much - use A-typesystem >> A-kindchk - obsolete >> A-linearity - use A-typesystem >> A-liveness - use A-typesystem >> A-packaging - use A-tools >> A-parallel - use A-concurrency >> A-servo - not many issues >> A-typestate >> A-unsafe >> A-unwind >> A-versioning >> A-website - use A-infrastructure >> A-rustbot - use A-infrastructure >> A-cyclecollector >> A-github > > I actually support breaking up the A-typesystem label into fewer > labels. I find myself using typesystem a lot when I want something > more specific, actually. > Er, I meant "more labels". Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From banderson at mozilla.com Tue Feb 5 10:59:01 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 10:59:01 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: References: <5111546B.4060604@mozilla.com> Message-ID: <51115675.4080900@mozilla.com> On 02/05/2013 10:53 AM, Tim Chevalier wrote: > On Tue, Feb 5, 2013 at 10:52 AM, Tim Chevalier wrote: >> On Tue, Feb 5, 2013 at 10:50 AM, Brian Anderson wrote: >>> Greetings, folks, >>> >>> There was some discussion about bug triage in the meeting today so I went to >>> do some and was reminded of how frustrated I get by our labels: there are a >>> lot of them and I usually can't find an `A-` label that matches the bug. I >>> have some proposals here to remove a lot of them and add a few. Any >>> objections? >> Yes, please! >> >>> Add: >>> >>> A-parser >>> A-tools >>> A-concurrency - replaces A-comm/A-parallel >>> A-infrastructure >>> >>> Remove: >>> >>> A-classes - obsolete >>> A-comm - use A-concurrency >>> A-frontend - catchall - existing issues have no obvious relationship. use >>> A-parser, A-syntaxext instead, A-driver instead >>> A-editors - use A-tools >>> A-infer - not used much - use A-typesystem >>> A-kindchk - obsolete >>> A-linearity - use A-typesystem >>> A-liveness - use A-typesystem >>> A-packaging - use A-tools >>> A-parallel - use A-concurrency >>> A-servo - not many issues >>> A-typestate >>> A-unsafe >>> A-unwind >>> A-versioning >>> A-website - use A-infrastructure >>> A-rustbot - use A-infrastructure >>> A-cyclecollector >>> A-github >> I actually support breaking up the A-typesystem label into fewer >> labels. I find myself using typesystem a lot when I want something >> more specific, actually. >> > Er, I meant "more labels". I suggested removing a few that weren't being used much (classes, infer, kindchk, linearity, typestate). Is the division here just wrong? After removing those I suggest it looks like just A-typesystem and A-regions remain. Are there hot areas in the type system that we're missing labels for? From pwalton at mozilla.com Tue Feb 5 10:59:56 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 05 Feb 2013 10:59:56 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <51115675.4080900@mozilla.com> References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> Message-ID: <511156AC.2060901@mozilla.com> On 2/5/13 10:59 AM, Brian Anderson wrote: > I suggested removing a few that weren't being used much (classes, infer, > kindchk, linearity, typestate). Is the division here just wrong? After > removing those I suggest it looks like just A-typesystem and A-regions > remain. Are there hot areas in the type system that we're missing labels > for? Borrow checking. Patrick From banderson at mozilla.com Tue Feb 5 11:03:15 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 11:03:15 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <511156AC.2060901@mozilla.com> References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> <511156AC.2060901@mozilla.com> Message-ID: <51115773.5010902@mozilla.com> On 02/05/2013 10:59 AM, Patrick Walton wrote: > On 2/5/13 10:59 AM, Brian Anderson wrote: >> I suggested removing a few that weren't being used much (classes, infer, >> kindchk, linearity, typestate). Is the division here just wrong? After >> removing those I suggest it looks like just A-typesystem and A-regions >> remain. Are there hot areas in the type system that we're missing labels >> for? > > Borrow checking. Is this different from A-regions? Should A-regions be renamed A-borrowck? From graydon at mozilla.com Tue Feb 5 11:14:22 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 05 Feb 2013 11:14:22 -0800 Subject: [rust-dev] bors last-commit approval lost on updates In-Reply-To: <84360CE4-DADF-4956-9ADD-CE86FC5CF82A@brinckerhoff.org> References: <84360CE4-DADF-4956-9ADD-CE86FC5CF82A@brinckerhoff.org> Message-ID: <51115A0E.3030904@mozilla.com> On 13-02-04 09:10 PM, John Clements wrote: > I'm guessing this was deliberate, but I thought I'd check. The bors bot (IIUC) looks for an r+ attached to the final commit of a pull request in order to start auto-merging. When a pull request becomes non-automatically-mergeable (as mine did a few hours ago: jbclements:demodeing-and-deGCing), my understanding is that it's a kindness to force-push to the given branch to make it automatically mergeable (as I just did). Since the approval message appears on the last commit and the last commit is renamed, though, that approval is lost. > > Is it the intent of the system to have people re-approve the pull requests in situations like this? Yeah. Because bors really has no ability to judge the "mostly-sameness" of a re-submitted chunk of code, if its bits differ. If it didn't work this way, you could get approval on X and then "resubmit" completely-different-code Y and have bors land it. This was, in my estimate, not a desirable behavior for a robot with commit rights. -Graydon From graydon at mozilla.com Tue Feb 5 11:17:19 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 05 Feb 2013 11:17:19 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <51115773.5010902@mozilla.com> References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> <511156AC.2060901@mozilla.com> <51115773.5010902@mozilla.com> Message-ID: <51115ABF.9060208@mozilla.com> On 13-02-05 11:03 AM, Brian Anderson wrote: > On 02/05/2013 10:59 AM, Patrick Walton wrote: >> On 2/5/13 10:59 AM, Brian Anderson wrote: >>> I suggested removing a few that weren't being used much (classes, infer, >>> kindchk, linearity, typestate). Is the division here just wrong? After >>> removing those I suggest it looks like just A-typesystem and A-regions >>> remain. Are there hot areas in the type system that we're missing labels >>> for? >> >> Borrow checking. > > Is this different from A-regions? Should A-regions be renamed A-borrowck? I think so, yes. Thanks for bringing this up. We didn't get to discussing triage at the meeting in much detail, but we definitely need to think/talk/act a bit more about it. I'll try to organize thoughts and post more here shortly. -Graydon From banderson at mozilla.com Tue Feb 5 11:26:08 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 11:26:08 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <51115ABF.9060208@mozilla.com> References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> <511156AC.2060901@mozilla.com> <51115773.5010902@mozilla.com> <51115ABF.9060208@mozilla.com> Message-ID: <51115CD0.30204@mozilla.com> On 02/05/2013 11:17 AM, Graydon Hoare wrote: > On 13-02-05 11:03 AM, Brian Anderson wrote: >> On 02/05/2013 10:59 AM, Patrick Walton wrote: >>> On 2/5/13 10:59 AM, Brian Anderson wrote: >>>> I suggested removing a few that weren't being used much (classes, infer, >>>> kindchk, linearity, typestate). Is the division here just wrong? After >>>> removing those I suggest it looks like just A-typesystem and A-regions >>>> remain. Are there hot areas in the type system that we're missing labels >>>> for? >>> Borrow checking. >> Is this different from A-regions? Should A-regions be renamed A-borrowck? > I think so, yes. > > Thanks for bringing this up. We didn't get to discussing triage at the > meeting in much detail, but we definitely need to think/talk/act a bit > more about it. I'll try to organize thoughts and post more here shortly. > > -Graydon > Also I want to add `A-ui` - error messages, etc. seems to be one of the things that `A-frontend` is useful for. From catamorphism at gmail.com Tue Feb 5 11:27:57 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Tue, 5 Feb 2013 11:27:57 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: <51115CD0.30204@mozilla.com> References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> <511156AC.2060901@mozilla.com> <51115773.5010902@mozilla.com> <51115ABF.9060208@mozilla.com> <51115CD0.30204@mozilla.com> Message-ID: On Tue, Feb 5, 2013 at 11:26 AM, Brian Anderson wrote: > On 02/05/2013 11:17 AM, Graydon Hoare wrote: >> >> On 13-02-05 11:03 AM, Brian Anderson wrote: >>> >>> On 02/05/2013 10:59 AM, Patrick Walton wrote: >>>> >>>> On 2/5/13 10:59 AM, Brian Anderson wrote: >>>>> >>>>> I suggested removing a few that weren't being used much (classes, >>>>> infer, >>>>> kindchk, linearity, typestate). Is the division here just wrong? After >>>>> removing those I suggest it looks like just A-typesystem and A-regions >>>>> remain. Are there hot areas in the type system that we're missing >>>>> labels >>>>> for? >>>> >>>> Borrow checking. >>> >>> Is this different from A-regions? Should A-regions be renamed A-borrowck? >> >> I think so, yes. >> >> Thanks for bringing this up. We didn't get to discussing triage at the >> meeting in much detail, but we definitely need to think/talk/act a bit >> more about it. I'll try to organize thoughts and post more here shortly. >> >> -Graydon >> > > Also I want to add `A-ui` - error messages, etc. seems to be one of the > things that `A-frontend` is useful for. > Don't we have A-diagnostics already for that, though? Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From banderson at mozilla.com Tue Feb 5 11:29:46 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 11:29:46 -0800 Subject: [rust-dev] GitHub label maintenance In-Reply-To: References: <5111546B.4060604@mozilla.com> <51115675.4080900@mozilla.com> <511156AC.2060901@mozilla.com> <51115773.5010902@mozilla.com> <51115ABF.9060208@mozilla.com> <51115CD0.30204@mozilla.com> Message-ID: <51115DAA.80100@mozilla.com> On 02/05/2013 11:27 AM, Tim Chevalier wrote: > On Tue, Feb 5, 2013 at 11:26 AM, Brian Anderson wrote: >> On 02/05/2013 11:17 AM, Graydon Hoare wrote: >>> On 13-02-05 11:03 AM, Brian Anderson wrote: >>>> On 02/05/2013 10:59 AM, Patrick Walton wrote: >>>>> On 2/5/13 10:59 AM, Brian Anderson wrote: >>>>>> I suggested removing a few that weren't being used much (classes, >>>>>> infer, >>>>>> kindchk, linearity, typestate). Is the division here just wrong? After >>>>>> removing those I suggest it looks like just A-typesystem and A-regions >>>>>> remain. Are there hot areas in the type system that we're missing >>>>>> labels >>>>>> for? >>>>> Borrow checking. >>>> Is this different from A-regions? Should A-regions be renamed A-borrowck? >>> I think so, yes. >>> >>> Thanks for bringing this up. We didn't get to discussing triage at the >>> meeting in much detail, but we definitely need to think/talk/act a bit >>> more about it. I'll try to organize thoughts and post more here shortly. >>> >>> -Graydon >>> >> Also I want to add `A-ui` - error messages, etc. seems to be one of the >> things that `A-frontend` is useful for. >> > Don't we have A-diagnostics already for that, though? > > Cheers, > Tim > > Ah, yes. Can we possibly rename it? 'diagnostics' is pretty narrow and we're going to have more UI concerns as we build tools. From graydon at mozilla.com Tue Feb 5 16:23:42 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 05 Feb 2013 16:23:42 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <510D1C44.3090407@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510D0B9C.3020007@ntecs.de> <510D1C44.3090407@mozilla.com> Message-ID: <5111A28E.7070101@mozilla.com> On 13-02-02 06:01 AM, Patrick Walton wrote: > So I suppose `reserve_stack` would simply check to see whether there's > enough stack space at runtime and turn into a no-op if there is. The > safe interfaces to functions would always use `reserve_stack`. (We would > enforce this with a lint pass, as earlier.) Thus, in general, if you see > `__morestack` high in your profiles, you can fix the thrashing by simply > adding a call to `reserve_stack` high in the call chain. > > This all sounds very attractive to me now. I feel like there are (or may be) two very different topics going on here. Can those reading fill me on whether each of these two points is the goal? (1) avoiding _crossings_ of rust-stack-segment-boundaries at performance-inconvenient places. (2) asking that a block of code run placing a chunk of code "back on the C stack" for some sort of "stack affinity" reason (the way certain actions have to run on particular threads at an OS level) (3) asking that a block of code be run _uninterrupted_, regardless of stack, in the sense of not being suspended mid-block by the scheduler. These all seem like .. potentially separate concerns, and potentially all valid for different reasons. I'd like to know which we're talking about. -Graydon From graydon at mozilla.com Tue Feb 5 16:24:19 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 05 Feb 2013 16:24:19 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <5111A28E.7070101@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510D0B9C.3020007@ntecs.de> <510D1C44.3090407@mozilla.com> <5111A28E.7070101@mozilla.com> Message-ID: <5111A2B3.50008@mozilla.com> On 13-02-05 04:23 PM, Graydon Hoare wrote: > I feel like there are (or may be) two And by "two" of course I mean "three". -Graydon From pwalton at mozilla.com Tue Feb 5 16:29:06 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 05 Feb 2013 16:29:06 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <5111A28E.7070101@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510D0B9C.3020007@ntecs.de> <510D1C44.3090407@mozilla.com> <5111A28E.7070101@mozilla.com> Message-ID: <5111A3D2.9000007@mozilla.com> On 2/5/13 4:23 PM, Graydon Hoare wrote: > I feel like there are (or may be) two very different topics going on > here. Can those reading fill me on whether each of these two points is > the goal? > > (1) avoiding _crossings_ of rust-stack-segment-boundaries at > performance-inconvenient places. Yes, this is a goal. > > (2) asking that a block of code run placing a chunk of code "back on > the C stack" for some sort of "stack affinity" reason (the way > certain actions have to run on particular threads at an OS level) Sort of. We would like to be able to run Rust code directly on the C stack, both for performance reasons (e.g. DOM bindings) and for correctness reasons (e.g. early initialization of the scheduler). But much of this thread is questioning whether the division into "Rust" segments and "C" segments even makes sense, given that all C really cares about is having a large stack segment to work with. > (3) asking that a block of code be run _uninterrupted_, regardless of > stack, in the sense of not being suspended mid-block by the > scheduler. Not a goal, as far as I see it. Patrick From graydon at mozilla.com Tue Feb 5 17:09:58 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 05 Feb 2013 17:09:58 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: <5111548E.8090205@alum.mit.edu> References: <5111548E.8090205@alum.mit.edu> Message-ID: <5111AD66.7020405@mozilla.com> On 13-02-05 10:50 AM, Niko Matsakis wrote: > We are reaching a degree of consensus on the new lifetime syntax. Yeah, I think at this point I'm willing to (again) bust out the BDFL hat and say that, absent _incoherence or ambiguity_ in this proposal, it's no longer time for fiddling with the sigils and brackets. We have to move ahead on this. If it works, let's go with it. If something terrible is lurking in the usability, we'll discover it in the future. > # Lifetime names and borrowed pointers All of this section, agree 100%. > # Lifetime parameters and fn/struct declarations Likewise, A-ok here. > # Lifetime parameters and impls > > ... > > This is *slightly* different than today. This is because, today, > `&self` is equivalent to a self type of `&'b Iterator<'b, T>` rather > than using a fresh lifetime (like `&'a Iterator<'a, T>`). The current > system causes various issues in real-life examples, including this > specific iterator example. I do not entirely understand what the failure mode is. Are you saying that today, an omitted lifetime parameter in an impl method signature gets its default provided from the underlying type's lifetime parameter, whereas in the new regime it will get a fresh parameter provided? If so, I don't know the exact way it goes wrong (or really see it in the example here), but it works better, I trust you know why, that's fine. If you mean something else, I'd like a little more illumination. I _almost_ understand what's going on here :) > # Multiple lifetime parameters > ... > You can write `Foo` or `Foo<'lt1, 'lt2>` but not `Foo<'lt1>`. Yes. All or none. > # Labeling blocks and expressions Compatible and future-concern, defer. (Thanks for the tireless care to get this all worked out.) -Graydon From banderson at mozilla.com Tue Feb 5 18:43:41 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 05 Feb 2013 18:43:41 -0800 Subject: [rust-dev] RFC: Explicit stack switching In-Reply-To: <5111A28E.7070101@mozilla.com> References: <510AF22D.3040509@mozilla.com> <510BA277.6070701@ntecs.de> <510C4C57.5090906@mozilla.com> <510CB9FD.60605@mozilla.com> <510CD959.4050702@mozilla.com> <510D0B9C.3020007@ntecs.de> <510D1C44.3090407@mozilla.com> <5111A28E.7070101@mozilla.com> Message-ID: <5111C35D.80306@mozilla.com> On 02/05/2013 04:23 PM, Graydon Hoare wrote: > On 13-02-02 06:01 AM, Patrick Walton wrote: > >> So I suppose `reserve_stack` would simply check to see whether there's >> enough stack space at runtime and turn into a no-op if there is. The >> safe interfaces to functions would always use `reserve_stack`. (We would >> enforce this with a lint pass, as earlier.) Thus, in general, if you see >> `__morestack` high in your profiles, you can fix the thrashing by simply >> adding a call to `reserve_stack` high in the call chain. >> >> This all sounds very attractive to me now. > I feel like there are (or may be) two very different topics going on > here. Can those reading fill me on whether each of these two points is > the goal? > > (1) avoiding _crossings_ of rust-stack-segment-boundaries at > performance-inconvenient places. This is a major motivation, at the moment particularly for SpiderMonkey and core (though they care about this for different reasons - SpiderMonkey cares about calls from C to Rust and core cares about the other direction). > > (2) asking that a block of code run placing a chunk of code "back on > the C stack" for some sort of "stack affinity" reason (the way > certain actions have to run on particular threads at an OS level) I'm not aware of this use case. > > (3) asking that a block of code be run _uninterrupted_, regardless of > stack, in the sense of not being suspended mid-block by the > scheduler. > This isn't a motivation here and I think this use case isn't that related to stack management and the FFI. The task has some runtime calls used by core for this type of thing, some of which will fail dynamically if you do the wrong thing while trying to avoid being descheduled. In general the only time a task will be descheduled is when using pipes or other synchronization code. This could change if we ever put yields on loop edges, etc. but I'm not sure we want to. If somebody does want to run without interference from the scheduler then they could do it in a raw thread. Aside from the aforementioned performance considerations, my major concern is that our stack management model is more complex than it should be (with the distinction between stack growth and stack switching), and the way we manage stacks is reflected in the FFI. From niko at alum.mit.edu Tue Feb 5 20:02:55 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 05 Feb 2013 20:02:55 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: <5111AD66.7020405@mozilla.com> References: <5111548E.8090205@alum.mit.edu> <5111AD66.7020405@mozilla.com> Message-ID: <5111D5EF.30909@alum.mit.edu> Graydon Hoare wrote: >> # Lifetime parameters and impls >> >> ... >> >> This is *slightly* different than today. This is because, today, >> `&self` is equivalent to a self type of `&'b Iterator<'b, T>` rather >> than using a fresh lifetime (like `&'a Iterator<'a, T>`). The current >> system causes various issues in real-life examples, including this >> specific iterator example. > > I do not entirely understand what the failure mode is. Are you saying > that today, an omitted lifetime parameter in an impl method signature > gets its default provided from the underlying type's lifetime parameter, > whereas in the new regime it will get a fresh parameter provided? More or less, yes. > If so, I don't know the exact way it goes wrong (or really see it in the > example here), but it works better, I trust you know why, that's fine. This is indeed what I mean and yes it can go wrong. Let me spell out what happens with the Iterator example, it's a bit involved and took me some time to fully appreciate. To begin, today you have the following annotations on the `next()` method, effectively: impl<'b, T> Iterator<'b, T> { fn next(&'b mut self) -> Option<&'b T> { /* same as before */ } } As you can see, both the lifetime of the `&mut self` pointer and the lifetime of the contents are `'b`. Now let's have an example of some code that invokes `next()`. This is the standard `find()` function for vectors, expressed with an iterator. It iterates down the list and returns the first item that matches some predicate `pred`. I have included all possible annotations and made all borrows explicit. Key lines are numbered in comments. fn find(v: &'lt [T], pred: &fn(&'lt T) -> bool) -> Option<&'lt T> { let iterator = Iterator(v); loop { let result: Option<&'lt T> = /* [1] */ (&'lt mut iterator).next(); /* [2] */ match result { None => { return None; } Some(r) => { if pred(r) { return Some(r); /* [3] */ } else { return None; } } } } } The lifetime of the input vector is 'lt. The signature promises to invoke the predicate function with data in the vector (and hence with the same lifetime) and to return an element of the vector (and hence with the same lifetime). The first important point is that, when we call `next()`, the lifetime of the resulting pointer must also be 'lt (as indicated in the type annotation [1]). This is because we are going to be returning this result if it matches the predicate ([3]). Now, because the lifetime of the pointer to the iterator and the lifetime of the iteratee are specified as the same ('b), this means that the lifetime of the borrow must be the same [2]. So, as a result of the above rules, the iterator is borrowed mutably for the full lifetime 'lt. This makes the borrow checker unhappy because it is only supposed to allow one mutable alias to iterator at a time, but the scope of the first mutable borrow outlives the enclosing loop (in fact, it outlives the entire `find()` function), and thus it seems to the borrow checker that you are creating new mutable aliases while the old ones still exist. Thus you get errors. These problems go away when you don't artificially conflate the lifetime attached to the `&self` pointer with the lifetime of the stuff it points at. In general, I prefer this model anyhow because it treats `self` more like the other parameters to the function, which I think is somewhat less surprising and well simplify the specification and implementation. > Compatible and future-concern, defer. Yes, adding label syntax is compatible and not something I particularly want to nail down now. The main reason that I mention it is that, with regard to pcwalton's desire for backwards-compatible language support, I would rather not be locked in to the current labeled loop system we have now. regards, Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Tue Feb 5 22:13:10 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Wed, 6 Feb 2013 01:13:10 -0500 Subject: [rust-dev] lifetime syntax In-Reply-To: <5111D5EF.30909@alum.mit.edu> References: <5111548E.8090205@alum.mit.edu> <5111AD66.7020405@mozilla.com> <5111D5EF.30909@alum.mit.edu> Message-ID: Can you clarify the syntax for function types with lifetime parameters? I saw this in the meeting transcript: &fn<'a>(f: &fn(&'a T)) > &fn(f: &fn<'a>(&'a T)) I think I've filled in blanks that were left correctly. I'm guessing the that the first case forces the lifetime 'a to be known when you call the function, and the second case allows the lifetime 'a to be determined inside the body of the function as needed on each call to f. I'm pretty sure that the <'a> in both cases is new syntax, since I don't think you can put type parameters on function values. Is this correct? On Tuesday, February 5, 2013, Niko Matsakis wrote: > > > Graydon Hoare wrote: > > # Lifetime parameters and impls > > ... > > This is *slightly* different than today. This is because, today, > `&self` is equivalent to a self type of `&'b Iterator<'b, T>` rather > than using a fresh lifetime (like `&'a Iterator<'a, T>`). The current > system causes various issues in real-life examples, including this > specific iterator example. > > I do not entirely understand what the failure mode is. Are you saying > that today, an omitted lifetime parameter in an impl method signature > gets its default provided from the underlying type's lifetime parameter, > whereas in the new regime it will get a fresh parameter provided? > > > More or less, yes. > > If so, I don't know the exact way it goes wrong (or really see it in the > example here), but it works better, I trust you know why, that's fine. > > > This is indeed what I mean and yes it can go wrong. Let me spell out what > happens with the Iterator example, it's a bit involved and took me some > time to fully appreciate. To begin, today you have the following > annotations on the `next()` method, effectively: > > impl<'b, T> Iterator<'b, T> { > fn next(&'b mut self) -> Option<&'b T> { /* same as before */ } > } > > As you can see, both the lifetime of the `&mut self` pointer and the > lifetime of the contents are `'b`. Now let's have an example of some code > that invokes `next()`. This is the standard `find()` function for vectors, > expressed with an iterator. It iterates down the list and returns the > first item that matches some predicate `pred`. I have included all > possible annotations and made all borrows explicit. Key lines are numbered > in comments. > > fn find(v: &'lt [T], pred: &fn(&'lt T) -> bool) -> Option<&'lt T> { > let iterator = Iterator(v); > loop { > let result: Option<&'lt T> = /* [1] */ > (&'lt mut iterator).next(); /* [2] */ > match result { > None => { return None; } > Some(r) => { > if pred(r) { > return Some(r); /* [3] */ > } else { > return None; > } > } > } > } > } > > The lifetime of the input vector is 'lt. The signature promises to invoke > the predicate function with data in the vector (and hence with the same > lifetime) and to return an element of the vector (and hence with the same > lifetime). The first important point is that, when we call `next()`, the > lifetime of the resulting pointer must also be 'lt (as indicated in the > type annotation [1]). This is because we are going to be returning this > result if it matches the predicate ([3]). Now, because the lifetime of the > pointer to the iterator and the lifetime of the iteratee are specified as > the same ('b), this means that the lifetime of the borrow must be the same > [2]. > > So, as a result of the above rules, the iterator is borrowed mutably for > the full lifetime 'lt. This makes the borrow checker unhappy because it is > only supposed to allow one mutable alias to iterator at a time, but the > scope of the first mutable borrow outlives the enclosing loop (in fact, it > outlives the entire `find()` function), and thus it seems to the borrow > checker that you are creating new mutable aliases while the old ones still > exist. Thus you get errors. These problems go away when you don't > artificially conflate the lifetime attached to the `&self` pointer with the > lifetime of the stuff it points at. > > In general, I prefer this model anyhow because it treats `self` more like > the other parameters to the function, which I think is somewhat less > surprising and well simplify the specification and implementation. > > Compatible and future-concern, defer. > > > Yes, adding label syntax is compatible and not something I particularly > want to nail down now. The main reason that I mention it is that, with > regard to pcwalton's desire for backwards-compatible language support, I > would rather not be locked in to the current labeled loop system we have > now. > > > regards, > Niko > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Wed Feb 6 06:37:06 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 06 Feb 2013 06:37:06 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: References: <5111548E.8090205@alum.mit.edu> <5111AD66.7020405@mozilla.com> <5111D5EF.30909@alum.mit.edu> Message-ID: <51126A92.1020508@alum.mit.edu> Steven Blenkinsop wrote: > Can you clarify the syntax for function types with lifetime > parameters? I saw this in the meeting transcript: > > &fn<'a>(f: &fn(&'a T)) > &fn(f: &fn<'a>(&'a T)) > > > I think I've filled in blanks that were left correctly. I'm guessing > the that the first case forces the lifetime 'a to be known when you > call the function, and the second case allows the lifetime 'a to be > determined inside the body of the function as needed on each call to > f. I'm pretty sure that the <'a> in both cases is new syntax, since I > don't think you can put type parameters on function values. Is this > correct? This is exactly correct and yes <'a> would be new syntax. The first form (with 'a bound on the outer fn) is pretty close to useless, I imagine, because the outer fn has no way to know what the lifetime 'a is and moreover it has no pointers with that lifetime. This implies that it could invoke its argument `f` with pointers whose lifetime is 'static. So the first function is, for all intents and purposes, equivalent to &fn(f: &fn(&'static T)) I am not 100% sure if this pattern arises in other cases where it might be more important, but I can't imagine what such a case would be. Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From isaac.aggrey at gmail.com Wed Feb 6 10:33:37 2013 From: isaac.aggrey at gmail.com (Isaac Aggrey) Date: Wed, 6 Feb 2013 12:33:37 -0600 Subject: [rust-dev] lifetime syntax Message-ID: I realize the Rust community is beginning to settle on the `'lt` as the syntax to rule them all, but is using any sort of suffix for lifetime syntax a non-starter? If it is, ignore everything below, and instead I'll suggest another sigil: What about using `#` instead of `'`? It's a bit more visually significant and doesn't overload any operators I can think of. The inherent numerical meaning often associated with the symbol (since we're talking about life*times*) is also helpful. If lifetime as a suffix is a possibility, keep reading: I find it harder to read this code: &'lt int &'lt mut int over something like: &int#lt // or if unambiguous, preferably: &int #lt &mut int#lt // `` : &mut int #lt The latter example reads as "a borrowed pointer to an integer with a lifetime lt" versus the former as "a borrowed pointer with a lifetime lt to an integer". It is more accurate to say the pointer has the lifetime, but it seems more immediately useful to emphasize it is a "pointer to an integer" with the lifetime as a modifier on "pointer to an integer". This subjective clarity also carries over to generic functions to reduce noise in the type parameter such as: fn has_next#a#b(iter: &Iterator#a) -> bool { iter.index + 1 < iter.source.len() } // reads as a function called has_next over type T with lifetimes a and b vs the current style of: fn has_next<'a, 'b, T>(iter: &'a Iterator<'b, T>) -> bool { iter.index + 1 < iter.source.len() } // reads as a function called has_next with lifetimes a and b over type T I'm not sure if the `#` symbol was ever discussed or if it's even viable, but to my newbie eyes it seems like it's at least clearer with my eye compiler. Despite having a very poor understanding of lifetimes and likely butchering the original intent in the lifetime syntax below, I've attempted to suffixify some of the examples taken from Niko's opening post: struct Iterator { source: &[T]#lt, index: uint } fn has_next#a#b(iter: &Iterator#a) -> bool { iter.index + 1 < iter.source.len() } fn next#a#b(iter: &mut Iterator#a) -> Option<&T#b> { iter.index += 1; if iter.index < iter.source.len() { Some(&iter.source[iter.index]) } else { None } } impl Iterator { fn has_next(&self#a) { /* same as before */ } fn next(&mut self#a) -> Option<&T#b> { /* same as before */ } } struct Foo<#a#b> // or struct Foo<#a #b> if unambiguous From graydon at mozilla.com Wed Feb 6 10:52:42 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 06 Feb 2013 10:52:42 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: References: Message-ID: <5112A67A.8010907@mozilla.com> On 13-02-06 10:33 AM, Isaac Aggrey wrote: > I realize the Rust community is beginning to settle on the `'lt` as the syntax > to rule them all, but is using any sort of suffix for lifetime syntax a > non-starter? Yeah, sorry, this horse* is dead. -Graydon (* no actual horses were harmed in the discussion of this feature) From mcguire at crsr.net Wed Feb 6 13:45:13 2013 From: mcguire at crsr.net (Tommy M. McGuire) Date: Wed, 06 Feb 2013 15:45:13 -0600 Subject: [rust-dev] First program? In-Reply-To: References: <510D7BE3.70204@crsr.net> Message-ID: <5112CEE9.7060205@crsr.net> Thanks for your comments! On 02/03/2013 10:54 AM, Tim Chevalier wrote: > On Sat, Feb 2, 2013 at 12:49 PM, Tommy M. McGuire wrote: >> https://github.com/tmmcguire/rust-toys/blob/master/mk_anadict.rs >> >> For inspiration (and because I have no actual creativity of my own), I >> picked up >> http://www.jeffknupp.com/blog/2013/01/04/creating-and-optimizing-a-letterpress-cheating-program-in-python/, >> which is basically an anagram solution generator; this first program >> generates a text dictionary of letter sequences to words, one mapping >> per line. >> >> I'm using Rust 0.5. >> ... >> * For no readily apparent reason, I used @[] quite a bit. Should there >> be any special preferences for ~[]? >> > > No, at least not until you're writing code with multiple tasks or > where you care about performance. It's fine to start with @[] and then > change to ~[] as needed. As with @str, there's less library support > for @[], but that's another thing we need to work on. Actually, performance was going to be my next question. mk_anadict started out as a direct translation of the Python code and it produces (nearly) the same output. Unfortunately, it currently takes approximately 3x as long. The one major change I made was in producing the output; the Python version does a single write, joining all of the lines produced individually in an array. That, in Rust, was even slower than the current code. There seems to be a lot of memcpy's going on, but I don't see why and I'm not sure that would explain the difference. Is there anything obvious? (I've just started playing with perf, as well.) > There are a few places where you call a function like > str::len(**line), where line.len() would be more idiomatic (and > because of auto-dereference, you're saved from writing the asterisks). > I'll let others point out other nits :-) > > Cheers, > Tim > -- Tommy M. McGuire mcguire at crsr.net From clements at brinckerhoff.org Thu Feb 7 09:45:15 2013 From: clements at brinckerhoff.org (John Clements) Date: Thu, 7 Feb 2013 09:45:15 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: <5111D5EF.30909@alum.mit.edu> References: <5111548E.8090205@alum.mit.edu> <5111AD66.7020405@mozilla.com> <5111D5EF.30909@alum.mit.edu> Message-ID: <6720360B-4AF2-4769-AB3A-D65BDB220C0C@brinckerhoff.org> On Feb 5, 2013, at 8:02 PM, Niko Matsakis wrote: > This is indeed what I mean and yes it can go wrong. Let me spell out what happens with the Iterator example, it's a bit involved and took me some time to fully appreciate. To begin, today you have the following annotations on the `next()` method, effectively: > > impl<'b, T> Iterator<'b, T> { > fn next(&'b mut self) -> Option<&'b T> { /* same as before */ } > } > > As you can see, both the lifetime of the `&mut self` pointer and the lifetime of the contents are `'b`. Now let's have an example of some code that invokes `next()`. This is the standard `find()` function for vectors, expressed with an iterator. It iterates down the list and returns the first item that matches some predicate `pred`. I have included all possible annotations and made all borrows explicit. Key lines are numbered in comments. > > fn find(v: &'lt [T], pred: &fn(&'lt T) -> bool) -> Option<&'lt T> { > let iterator = Iterator(v); > loop { > let result: Option<&'lt T> = /* [1] */ > (&'lt mut iterator).next(); /* [2] */ > match result { > None => { return None; } > Some(r) => { > if pred(r) { > return Some(r); /* [3] */ > } else { > return None; > } > } > } > } > } > > The lifetime of the input vector is 'lt. The signature promises to invoke the predicate function with data in the vector (and hence with the same lifetime) and to return an element of the vector (and hence with the same lifetime). The first important point is that, when we call `next()`, the lifetime of the resulting pointer must also be 'lt (as indicated in the type annotation [1]). This is because we are going to be returning this result if it matches the predicate ([3]). Now, because the lifetime of the pointer to the iterator and the lifetime of the iteratee are specified as the same ('b), this means that the lifetime of the borrow must be the same [2]. > > So, as a result of the above rules, the iterator is borrowed mutably for the full lifetime 'lt. This makes the borrow checker unhappy because it is only supposed to allow one mutable alias to iterator at a time, but the scope of the first mutable borrow outlives the enclosing loop (in fact, it outlives the entire `find()` function), and thus it seems to the borrow checker that you are creating new mutable aliases while the old ones still exist. Thus you get errors. These problems go away when you don't artificially conflate the lifetime attached to the `&self` pointer with the lifetime of the stuff it points at. Nice example. Just to make things completely absolutely clear: IIUC, you're saying that changing the (&'b mut self) argument to the next function into, e.g., (&'c mut self) --that is, a "free" lifetime (and I forget whether a binding site is required for this)--makes the code run correctly? John From niko at alum.mit.edu Thu Feb 7 12:53:54 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 07 Feb 2013 12:53:54 -0800 Subject: [rust-dev] lifetime syntax In-Reply-To: <6720360B-4AF2-4769-AB3A-D65BDB220C0C@brinckerhoff.org> References: <5111548E.8090205@alum.mit.edu> <5111AD66.7020405@mozilla.com> <5111D5EF.30909@alum.mit.edu> <6720360B-4AF2-4769-AB3A-D65BDB220C0C@brinckerhoff.org> Message-ID: <51141462.7020405@alum.mit.edu> John Clements wrote: > Nice example. Just to make things completely absolutely clear: IIUC, you're saying that changing the (&'b mut self) argument to the next function into, e.g., (&'c mut self) --that is, a "free" lifetime (and I forget whether a binding site is required for this)--makes the code run correctly? Yes. Niko From graydon at mozilla.com Thu Feb 7 19:00:41 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 07 Feb 2013 19:00:41 -0800 Subject: [rust-dev] bors Message-ID: <51146A59.1010108@mozilla.com> Hi, Many on the IRC channel (or those watching the commit stream) will have noticed we've recently enabled an "auto-merge" robot (named "bors"[1]). This slightly changes the path for merging code into our repository. For the most part no changes are required to people submitting pull requests: keep doing what you've been doing, and when a reviewer signs off on one of your commits by writing "r+" in a comment on the final commit of a pull req, bors will automatically: - Form a new merge node based on your pull + incoming - Wait for results from that to come back from buildbot - If successful, advance incoming to that node - Otherwise report how the change failed The only thing you're likely to notice is a certain degree of chatter from bors as it steps through its automation. It makes comments, such as in this pull request: https://github.com/mozilla/rust/pull/4832 This is just automation of a somewhat tedious merge-making and testsuite-watching behavior that we were previously doing manually (and spending a lot of time at, and occasionally skipping steps of). Automating it frees up time, lets the robot do useful work overnight when reviewers are asleep, and ensures that we never skip running tests "optimistically". Incoming only ever advances to merge nodes that are _exactly_ the bits that tested OK. It retries if you move incoming while it's working, so tends to behave "mostly gracefully" with respect to disruption around it. If it misbehaves, it can be provoked to retry a commit with a comment from a reviewer saying "@bors: retry". It ignores comments by non-reviewers. It also does not merge "updates" to a pull req. It considers comments on commits only, not pull reqs; if you update a pull req to contain new commits, they need to be reviewed anew. While we were testing it, it only considered pull requests with the word "auto: " in the title, so this is what those strings mean in recent pull requests. I've now opened it up to processing all pull requests; you do not need to put "auto: " on the title anymore. If you have feature requests or want it to behave differently, please let me know. I'll be conducting a brief security review with some mozilla folks and open-sourcing it soon for others who want to apply similar behavior to their own repositories. It's a very small, simple script. I'll also be posting a new URL soon that will hold a regularly-refreshing description of bors' work queue so folks can monitor what it's doing and planning-to-do (and ignoring) without having to re-read the state of all the pull reqs. -Graydon [1] It was hard to find a non-annoying robot name that isn't already taken on github; settled on this one: en.wikipedia.org/wiki/The_Last_of_the_Masters#The_last_government From steve at steveklabnik.com Thu Feb 7 20:51:11 2013 From: steve at steveklabnik.com (Steve Klabnik) Date: Thu, 7 Feb 2013 21:51:11 -0700 Subject: [rust-dev] bors In-Reply-To: <51146A59.1010108@mozilla.com> References: <51146A59.1010108@mozilla.com> Message-ID: Neat! I'm assuming this is based on how Mozilla works internally, yes? You may be interested in integrating it with the commit status API, like Travis has: https://github.com/blog/1227-commit-status-api From sh4.seo at samsung.com Thu Feb 7 20:57:50 2013 From: sh4.seo at samsung.com (Sanghyeon Seo) Date: Fri, 08 Feb 2013 04:57:50 +0000 (GMT) Subject: [rust-dev] bors Message-ID: <2819721.403441360299470722.JavaMail.weblogic@epv6ml07> > Neat! I'm assuming this is based on how Mozilla works internally, yes? > > You may be interested in integrating it with the commit status API, > like Travis has: https://github.com/blog/1227-commit-status-api In case you missed, it already does. From graydon at mozilla.com Thu Feb 7 21:02:34 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 07 Feb 2013 21:02:34 -0800 Subject: [rust-dev] bors In-Reply-To: References: <51146A59.1010108@mozilla.com> Message-ID: <511486EA.1050502@mozilla.com> On 07/02/2013 8:51 PM, Steve Klabnik wrote: > Neat! I'm assuming this is based on how Mozilla works internally, yes? No, just for rust. Much of mozilla runs off mercurial and bugzilla; some projects are on github, some use their own testing bots, some just manual testing. The tools vary from group to group. > You may be interested in integrating it with the commit status API, > like Travis has: https://github.com/blog/1227-commit-status-api Yeah, it sets those status markers; that's how it keeps track of the minor amount of "state" is has between runs, that can't be directly inferred from the git graph structure. If you take a look at the example pull I pointed to, you'll see it's set the "success" status, which is why you get the little green bar with the checkmark. -Graydon From cpeterson at mozilla.com Fri Feb 8 09:53:55 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Fri, 08 Feb 2013 09:53:55 -0800 Subject: [rust-dev] bors In-Reply-To: <51146A59.1010108@mozilla.com> References: <51146A59.1010108@mozilla.com> Message-ID: <51153BB3.70902@mozilla.com> On 2/7/13 7:00 PM, Graydon Hoare wrote: > Automating it frees up time, lets the robot do useful work overnight > when reviewers are asleep, and ensures that we never skip running tests > "optimistically". Incoming only ever advances to merge nodes that are > _exactly_ the bits that tested OK. Since bors is more patient than a human, it would be interesting if bors ran the testsuite for all optimization levels: --opt-level 0, 1, 2 and 3. This might help find bugs in rustc's code generator or optimizer. chris From clements at brinckerhoff.org Fri Feb 8 10:39:34 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 8 Feb 2013 10:39:34 -0800 Subject: [rust-dev] bus error on test case failures in libstd Message-ID: <7607737F-76E6-49DB-8050-95411F356D6F@brinckerhoff.org> I just added some test cases to libstd; I'm being a good TDD-fanboy, so I added the tests before implementing the desired behavior, so I expected the tests to fail. What I didn't expect was a bus error: ... test uv_ll::test::test_uv_ll_struct_size_uv_tcp_t ... ok test uv_ll::test::test_uv_ll_struct_size_uv_buf_t ... ok test sync::tests::test_rwlock_cond_broadcast ... ok test timer::test::test_gl_timer_sleep_stress2 ... ok failures: json::tests::test_write_none json::tests::test_write_some result: FAILED. 334 passed; 2 failed; 7 ignored rust: task failed at 'Some tests failed', :15 rust: domain main @0x7ff671015e10 root task failed rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 rust: task failed at 'killed', :15 zsh: bus error /tmp/t jclements-09740:~/tryrust/src/libstd clements> Is this something we already know about? John From mcguire at crsr.net Fri Feb 8 11:08:20 2013 From: mcguire at crsr.net (Tommy M. McGuire) Date: Fri, 08 Feb 2013 13:08:20 -0600 Subject: [rust-dev] Faster vec::each_permutation implementation, again Message-ID: <51154D24.9000209@crsr.net> I was working on the silly anagram program and needed something like Python's itertools.combinations. While I was working on it[1], I saw each_permutation and the same comment that Ben Alpert mentioned, so I took a pass at it: https://gist.github.com/tmmcguire/4741058 I'd like to say that I'm really liking the lifetime variables. Then, I saw Ben and Niko's thread from January[2]. This version seems to be somewhat faster than the one there. I'd appreciate any comments, and if anyone's interested, I'll try to figure out how to create a pull request. :-) [1] https://github.com/tmmcguire/rust-toys/blob/master/combinations.rs [2] https://mail.mozilla.org/pipermail/rust-dev/2013-January/002857.html -- Tommy M. McGuire mcguire at crsr.net From graydon at mozilla.com Fri Feb 8 11:36:28 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 08 Feb 2013 11:36:28 -0800 Subject: [rust-dev] bus error on test case failures in libstd In-Reply-To: <7607737F-76E6-49DB-8050-95411F356D6F@brinckerhoff.org> References: <7607737F-76E6-49DB-8050-95411F356D6F@brinckerhoff.org> Message-ID: <511553BC.10501@mozilla.com> On 13-02-08 10:39 AM, John Clements wrote: > zsh: bus error /tmp/t > jclements-09740:~/tryrust/src/libstd clements> > > > Is this something we already know about? Possibly. Failure-unwinding is currently a little unstable; but we're also seeing a sporadic race / deadlock / some-other-kind of memory corruption in the bots, even when succeeding, which is even more worrying. -Graydon From graydon at mozilla.com Fri Feb 8 14:16:50 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 08 Feb 2013 14:16:50 -0800 Subject: [rust-dev] bors In-Reply-To: <51146A59.1010108@mozilla.com> References: <51146A59.1010108@mozilla.com> Message-ID: <51157952.9090103@mozilla.com> On 13-02-07 07:00 PM, Graydon Hoare wrote: > I'll also be posting a new URL soon that will hold a > regularly-refreshing description of bors' work queue so folks can > monitor what it's doing and planning-to-do (and ignoring) without having > to re-read the state of all the pull reqs. http://buildbot.rust-lang.org/bors/bors.html ^^ that is the status URL. Should refresh every couple minutes. -Graydon From clements at brinckerhoff.org Fri Feb 8 18:08:24 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 8 Feb 2013 18:08:24 -0800 Subject: [rust-dev] use of partially moved value Message-ID: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> I'm trying to figure out a clean way to juggle ownership to rearrange the parts of a mutable structure. Specifically, in the example below, I want to take a field containing an owned pointer and mutate it to point to a different structure that contains the original value. After the move, the pointer is again owned by the same structure, but the borrow checker is unhappy with me. I've tried a bunch of variations using intermediate variables and 'match'ing, but none of them have worked. Actually, it seems like I need an atomic operation like the one described by Tucker Taft, where I move and simultaneously set-to-null?. Is there some way to make this happen?[*] // a list that uses owned pointers pub enum IntList { MT, Cons(int,~IntList) } // a structure containing a list pub struct HasList { a : ~str, l : ~IntList } // add a '3' at the head of the contained list fn extendH(v: &mut HasList) { v.l = ~Cons(3,v.l); } #[test] fn t1() { let h = ~mut HasList {a:~"bogus",l:~MT}; extendH(h); } ==> rustc --test foo.rs Running /usr/local/bin/rustc: foo.rs:13:4: 13:5 error: use of partially moved value: `v` foo.rs:13 v.l = ~Cons(3,v.l); ^ foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type ~IntList, which is moved by default (use `copy` to override) foo.rs:13 v.l = ~Cons(3,v.l); ^~~ foo.rs:13:4: 13:5 error: use of partially moved value: `v` foo.rs:13 v.l = ~Cons(3,v.l); ^ foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type ~IntList, which is moved by default (use `copy` to override) foo.rs:13 v.l = ~Cons(3,v.l); ^~~ error: aborting due to 2 previous errors John [*] Naturally, I could just use a vector rather than the cons-pair representation; I'm not looking for that answer. From zackcorr95 at gmail.com Sat Feb 9 04:54:08 2013 From: zackcorr95 at gmail.com (Zack Corr) Date: Sat, 9 Feb 2013 22:54:08 +1000 Subject: [rust-dev] Exporting a glob of items results in unresolved exports: bug or am I doing it wrong? Message-ID: I have this crate file and an error: https://gist.github.com/z0w0/4745195 It only happens when I try to re-export all the pub items in a module in the crate using `pub use some_mod::*;` - the only way to do it successfully is to explicitly use all the items in each module which is a horrible alternative considering in one module I need to rexport over 200 variants of a key symbol enum. Am I doing this wrong or is this a bug? I've mentioned this on IRC before but I don't remember getting an answer. -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sat Feb 9 08:08:11 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 09 Feb 2013 08:08:11 -0800 Subject: [rust-dev] use of partially moved value In-Reply-To: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> Message-ID: <5116746B.4090306@alum.mit.edu> Today I think the only way you could do this is like so: fn extendH(v:&mut HasList) { let w = util::replace(&mut v.l, ~MT); v.l = ~Cons(3, w); } Or, written using the swap operator: fn extendH(v:&mut HasList) { let mut w = ~MT; v.l<-> w; v.l = ~Cons(3, w); } This unfortunately requires a temporary allocation of ~MT to "plug into" v.l in the interim before you have updated its value. You could avoid this by using an Option type, which at least wouldn't require allocation. However, I think we could also add a helper like `util::replace()` that updates the value "in-place", as you originally wanted. I imagine something like this: fn update(v: &mut T, f: &fn(T) -> T) { unsafe { ... } } and then you would write: fn extendH(v:&mut HasList) { util::update(&mut v.l, |l| ~Cons(3, l)); } Niko John Clements wrote: > I'm trying to figure out a clean way to juggle ownership to rearrange the parts of a mutable structure. Specifically, in the example below, I want to take a field containing an owned pointer and mutate it to point to a different structure that contains the original value. After the move, the pointer is again owned by the same structure, but the borrow checker is unhappy with me. > > I've tried a bunch of variations using intermediate variables and 'match'ing, but none of them have worked. Actually, it seems like I need an atomic operation like the one described by Tucker Taft, where I move and simultaneously set-to-null?. > > Is there some way to make this happen?[*] > > > // a list that uses owned pointers > pub enum IntList { > MT, > Cons(int,~IntList) > } > > // a structure containing a list > pub struct HasList { > a : ~str, > l : ~IntList > } > > // add a '3' at the head of the contained list > fn extendH(v:&mut HasList) { > v.l = ~Cons(3,v.l); > } > > #[test] fn t1() { > let h = ~mut HasList {a:~"bogus",l:~MT}; > extendH(h); > } > > ==> > > rustc --test foo.rs > Running /usr/local/bin/rustc: > foo.rs:13:4: 13:5 error: use of partially moved value: `v` > foo.rs:13 v.l = ~Cons(3,v.l); > ^ > foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type ~IntList, which is moved by default (use `copy` to override) > foo.rs:13 v.l = ~Cons(3,v.l); > ^~~ > foo.rs:13:4: 13:5 error: use of partially moved value: `v` > foo.rs:13 v.l = ~Cons(3,v.l); > ^ > foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type ~IntList, which is moved by default (use `copy` to override) > foo.rs:13 v.l = ~Cons(3,v.l); > ^~~ > error: aborting due to 2 previous errors > > > > John > > > [*] Naturally, I could just use a vector rather than the cons-pair representation; I'm not looking for that answer. > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From niko at alum.mit.edu Sat Feb 9 08:48:00 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 09 Feb 2013 08:48:00 -0800 Subject: [rust-dev] Is Bors active? Message-ID: <51167DC0.1000609@alum.mit.edu> It seems like http://buildbot.rust-lang.org/bors/bors.html hasn't change in a while. NIko From steven099 at gmail.com Sat Feb 9 12:16:52 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Sat, 9 Feb 2013 15:16:52 -0500 Subject: [rust-dev] use of partially moved value In-Reply-To: <5116746B.4090306@alum.mit.edu> References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> <5116746B.4090306@alum.mit.edu> Message-ID: Under the new borrowing rules, if &const were removed, wouldn't it be safe to temporarily deinitialize a mutably borrowed value as long as it can be statically guaranteed that you reinitialize it before the next use? On Saturday, 9 February 2013, Niko Matsakis wrote: > Today I think the only way you could do this is like so: > > fn extendH(v:&mut HasList) { > let w = util::replace(&mut v.l, ~MT); > v.l = ~Cons(3, w); > } > > Or, written using the swap operator: > > fn extendH(v:&mut HasList) { > let mut w = ~MT; > v.l<-> w; > v.l = ~Cons(3, w); > } > > This unfortunately requires a temporary allocation of ~MT to "plug into" > v.l in the interim before you have updated its value. You could avoid this > by using an Option type, which at least wouldn't require allocation. > However, I think we could also add a helper like `util::replace()` that > updates the value "in-place", as you originally wanted. I imagine > something like this: > > fn update(v: &mut T, f: &fn(T) -> T) { unsafe { ... } } > > and then you would write: > > fn extendH(v:&mut HasList) { > util::update(&mut v.l, |l| ~Cons(3, l)); > } > > > > > Niko > > John Clements wrote: > >> I'm trying to figure out a clean way to juggle ownership to rearrange the >> parts of a mutable structure. Specifically, in the example below, I want >> to take a field containing an owned pointer and mutate it to point to a >> different structure that contains the original value. After the move, the >> pointer is again owned by the same structure, but the borrow checker is >> unhappy with me. >> >> I've tried a bunch of variations using intermediate variables and >> 'match'ing, but none of them have worked. Actually, it seems like I need an >> atomic operation like the one described by Tucker Taft, where I move and >> simultaneously set-to-null?. >> >> Is there some way to make this happen?[*] >> >> >> // a list that uses owned pointers >> pub enum IntList { >> MT, >> Cons(int,~IntList) >> } >> >> // a structure containing a list >> pub struct HasList { >> a : ~str, >> l : ~IntList >> } >> >> // add a '3' at the head of the contained list >> fn extendH(v:&mut HasList) { >> v.l = ~Cons(3,v.l); >> } >> >> #[test] fn t1() { >> let h = ~mut HasList {a:~"bogus",l:~MT}; >> extendH(h); >> } >> >> ==> >> >> rustc --test foo.rs >> Running /usr/local/bin/rustc: >> foo.rs:13:4: 13:5 error: use of partially moved value: `v` >> foo.rs:13 v.l = ~Cons(3,v.l); >> ^ >> foo.rs:13:18: 13:21 note: field of `v` moved here because the field has >> type ~IntList, which is moved by default (use `copy` to override) >> foo.rs:13 v.l = ~Cons(3,v.l); >> ^~~ >> foo.rs:13:4: 13:5 error: use of partially moved value: `v` >> foo.rs:13 v.l = ~Cons(3,v.l); >> ^ >> foo.rs:13:18: 13:21 note: field of `v` moved here because the field has >> type ~IntList, which is moved by default (use `copy` to override) >> foo.rs:13 v.l = ~Cons(3,v.l); >> ^~~ >> error: aborting due to 2 previous errors >> >> >> >> John >> >> >> [*] Naturally, I could just use a vector rather than the cons-pair >> representation; I'm not looking for that answer. >> >> ______________________________**_________________ >> 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 Sat Feb 9 13:07:40 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 09 Feb 2013 13:07:40 -0800 Subject: [rust-dev] use of partially moved value In-Reply-To: References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> <5116746B.4090306@alum.mit.edu> Message-ID: <5116BA9C.3090102@alum.mit.edu> Steven Blenkinsop wrote: > Under the new borrowing rules, if &const were removed, wouldn't it be > safe to temporarily deinitialize a mutably borrowed value as long as > it can be statically guaranteed that you reinitialize it before the > next use? Perhaps. Right now we only track this at the resolution of local variables, but it would be possible to extend it to something finer-grained. In this case, though, the value was accessed through an `&mut`, which means we'd have to be extra careful, particularly around function calls, as there may be other ways to read the value than what we can immediately see. Niko From steven099 at gmail.com Sat Feb 9 14:03:11 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Sat, 9 Feb 2013 17:03:11 -0500 Subject: [rust-dev] use of partially moved value In-Reply-To: <5116BA9C.3090102@alum.mit.edu> References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> <5116746B.4090306@alum.mit.edu> <5116BA9C.3090102@alum.mit.edu> Message-ID: On Sat, Feb 9, 2013 at 4:07 PM, Niko Matsakis wrote: > > Perhaps. Right now we only track this at the resolution of local > variables, but it would be possible to extend it to something > finer-grained. In this case, though, the value was accessed through an > `&mut`, which means we'd have to be extra careful, particularly around > function calls, as there may be other ways to read the value than what we > can immediately see. The only other ways to read a value pointed to by an &mut that I can think of are through an &const and potentially though an @mut, if you can read from the @mut while there's an &mut into it. If either of these is the case, then the update/replace function wouldn't be safe either, since f could read v.l indirectly after v.l has been moved into f, breaking uniqueness guarantees. The only other thing I can think of is to make moving lazy, such that when you move a value from p to q, p is only deinitialized when q might be used. That way, moving v.l into the ~Cons would be effectively delayed so that it happens simultaneously with moving the ~Cons into v.l. -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Sat Feb 9 15:26:43 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Sat, 09 Feb 2013 15:26:43 -0800 Subject: [rust-dev] Is Bors active? In-Reply-To: <51167DC0.1000609@alum.mit.edu> References: <51167DC0.1000609@alum.mit.edu> Message-ID: <5116DB33.5010600@mozilla.com> On 09/02/2013 8:48 AM, Niko Matsakis wrote: > It seems like > > http://buildbot.rust-lang.org/bors/bors.html > > hasn't change in a while. Not sure. It's certainly running now. It does look like there were some truncated runs overnight, but I didn't get exception traces from them. Will poke at that some next week. I put the timestamp on it so you can see when it last updated its status. -Graydon From catamorphism at gmail.com Sat Feb 9 15:27:45 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 9 Feb 2013 15:27:45 -0800 Subject: [rust-dev] Exporting a glob of items results in unresolved exports: bug or am I doing it wrong? In-Reply-To: References: Message-ID: Globs don't always work well / predictably right now. The most common reason why something wouldn't work is a cyclic import. If you can minimize this at all, reporting an issue would be great! Thanks! Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From niko at alum.mit.edu Sat Feb 9 21:22:26 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 09 Feb 2013 21:22:26 -0800 Subject: [rust-dev] use of partially moved value In-Reply-To: References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> <5116746B.4090306@alum.mit.edu> <5116BA9C.3090102@alum.mit.edu> Message-ID: <51172E92.5060200@alum.mit.edu> Steven Blenkinsop wrote: > If either of these is the case, then the update/replace function > wouldn't be safe either, since f could read v.l indirectly after v.l > has been moved into f, breaking uniqueness guarantees. There are other ways to have aliases as well, for example as part of a closure. But you're correct, the function I proposed wouldn't be safe. Not sure what I was thinking. In any case, the other technique I mentioned works just fine (swapping with None or what have you). Niko From zackcorr95 at gmail.com Sat Feb 9 23:09:39 2013 From: zackcorr95 at gmail.com (Zack Corr) Date: Sun, 10 Feb 2013 17:09:39 +1000 Subject: [rust-dev] Exporting a glob of items results in unresolved exports: bug or am I doing it wrong? In-Reply-To: References: Message-ID: I managed to narrow down a test case, here's the reported issue for anyone that's interested: https://github.com/mozilla/rust/issues/4865 -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Sun Feb 10 10:39:53 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Sun, 10 Feb 2013 13:39:53 -0500 Subject: [rust-dev] use of partially moved value In-Reply-To: <51172E92.5060200@alum.mit.edu> References: <03386E3E-914B-46CA-9025-D3B235B920D0@brinckerhoff.org> <5116746B.4090306@alum.mit.edu> <5116BA9C.3090102@alum.mit.edu> <51172E92.5060200@alum.mit.edu> Message-ID: On Sun, Feb 10, 2013 at 12:22 AM, Niko Matsakis wrote: > > > Steven Blenkinsop wrote: > >> If either of these is the case, then the update/replace function wouldn't >> be safe either, since f could read v.l indirectly after v.l has been moved >> into f, breaking uniqueness guarantees. >> > > There are other ways to have aliases as well, for example as part of a > closure. But you're correct, the function I proposed wouldn't be safe. > Not sure what I was thinking. In any case, the other technique I > mentioned works just fine (swapping with None or what have you) Sure. And you can get rid of the allocation by moving the ~ into Cons, so that MT variants don't require allocation: extern mod std; // a list that uses owned pointers pub enum IntList { MT, Cons(~(int, IntList)) } // a structure containing a list pub struct HasList { a : ~str, l : IntList } // add a '3' at the head of the contained list fn extendH(v: &mut HasList) { let w = util::replace(&mut v.l, MT); v.l = Cons(~(3, w)); } #[test] fn t1() { let h = ~mut HasList {a: ~"bogus", l: MT}; extendH(h); } -------------- next part -------------- An HTML attachment was scrubbed... URL: From brandon at mintern.net Sun Feb 10 14:51:04 2013 From: brandon at mintern.net (Brandon Mintern) Date: Sun, 10 Feb 2013 14:51:04 -0800 Subject: [rust-dev] Adding allocation-free library functions Message-ID: I recently decided to start contributing to Rust, and to that end, I grabbed the code and grepped for FIXME. One of the issues I came across was #4423: "Make a version of char::escape_unicode that doesn't allocate" ( https://github.com/mozilla/rust/issues/4423). Of course, we could add a one-off fix to ensure that repr doesn't allocate, but that would involve duplicating a lot of logic that currently lives in char, num, and uint-template. Instead, it seems that we need a suitable replacement for all library functions that return ~str, so that an allocation-conscious caller can avoid allocating. One approach would be to instead pass in a fn(char) that is called for each resulting character in order. Thus, escaping unicode code point 256 would call fn('\\'), fn('u'), fn('0'), fn('1'), fn('0'), fn('0'). Another approach would be for the functions that return ~str to instead accept an argument for some general object (like Writer) on which write_char could be called repeatedly. Then the function would return () instead. I'm partial to the fn approach, as the usage in repr would then look something like: do with_escaped_unicode_chars(ch) |c| { self.write_char(c); } Any thoughts on this? p.s. I'm very new to Rust development and might not understand the prevalent paradigms, so anything about this suggestion is off-base, I'd appreciate a nudge in the right direction. Also, wouldn't it make sense to have some kind of core-lang docs? Or have I just now looked hard enough? -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Sun Feb 10 15:21:10 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 10 Feb 2013 15:21:10 -0800 Subject: [rust-dev] Adding allocation-free library functions In-Reply-To: References: Message-ID: <51182B66.3060205@mozilla.com> On 2/10/13 2:51 PM, Brandon Mintern wrote: > I recently decided to start contributing to Rust, and to that end, I > grabbed the code and grepped for FIXME. One of the issues I came across > was #4423: "Make a version of char::escape_unicode that doesn't > allocate" (https://github.com/mozilla/rust/issues/4423). I've given this some thought lately, and I think you're generally on the right track. I very much want to make readers and writers not allocate. Now that we have &Trait, this should be doable. Something like this was what I had in mind: fn with_str_writer(s: &mut ~str, f: &fn(&Writer) -> R) -> R { let writer = StringWriter::new(s) as &Writer; f(writer) } struct StringWriter<'lt> { buf: &mut 'lt ~str } impl<'lt> Writer for StringWriter<'lt> { fn write(&self, bytes: &[u8]) { self.buf.append_bytes(bytes); } } Then the functions like `escape_unicode` could become something like this: fn write_escaped_unicode(writer: &Writer, ch: char) { ... } Then if you wanted the string you could write: let mut s = ~""; with_str_writer(&mut s, |w| write_escaped_unicode(w, '\u1F63B')) Of course, that's pretty verbose. So we have a number of options: (1) For every `write_foo` function, also define a `foo` function. Maybe we could use a macro to autogenerate these, or use one of the combinator functions below as a helper. Then you could write: let smiley = escaped_unicode('\u1F63B'); (2) Define a macro so we could write it this way: let smiley = write_string!(write_escaped_unicode('\u1F63B')); (3) Define a few combinator functions that take arguments. Unfortunately we can't do just one due to the lack of tupling of arguments in Rust. fn write_string_1(&fn(&Writer,A), A) -> ~str { ? } fn write_string_2(&fn(&Writer,A,B), A, B) -> ~str { ? } fn write_string_3(&fn(&Writer,A,B,C), A, B, C) -> ~str { ? } let smiley = write_string_1(write_escaped_unicode, '\u1F63B'); (4) Define a combinator function that takes a thunk. fn write_string(&fn(&Writer)) -> ~str { ? } let smiley = write_string(|w| write_escaped_unicode(w, '\u1F63B')); Note that if we had something like Scala's pseudo-currying form with '_' we could shorten that to: let smiley = write_string(write_escaped_unicode(_, '\u1F63B')) But that's probably not a 1.0 feature at this point. I lean toward (1) myself as a worse-is-better solution, but I don't really feel strongly one way or another. By the way, once we revamp writers in this way, we should be able to make fmt!() much more efficient, solving the performance problem that Chris Leary noted a while back... Patrick From someone at mearie.org Mon Feb 11 21:22:57 2013 From: someone at mearie.org (Kang Seonghoon) Date: Tue, 12 Feb 2013 14:22:57 +0900 Subject: [rust-dev] [RFC] Functions/methods with generated names Message-ID: Hello, I tried to make a prototype of syntactic sugar for bit-fields. My initial design is something like this: declare_bitfields!(MipsOpR: u32 { opcode: 6, rs: 5, rt: 5, rd: 5, shamt: 5, funct: 6 }) ...which should expand to something like this: enum MipsOpR = u32; impl MipsOpR { pure fn opcode(self) -> u32 { let MipsOpR(__val) = self; __val & 0xf } // this may go to ~MipsOpR etc. fn set_opcode(&mut self, __new: u32) { let MipsOpR(__val) = *self; let __mask = (1<<6)-1, __shift = 5+5+5+6; *self = MipsOpR((__val & !(__mask << __shift)) | ((__new & __mask) << __shift)); } // ...snip... } The rules required for declare_bitfields!() are straightforward, but I have encountered two problems while prototyping this: - Multiple items are not allowed. (Issue #4375) - concat_idents!() does not work for field/method names. (Issue #4365) The first problem is more or less a matter of internal representations, but the second problem is more severe because concat_idents!() is thought to be made for exactly this situation. I personally prefer to have macros work on the ident position, but there are several alternatives if this makes the macro system more difficult: - Add a set of built-in macros for generated names. e.g. `declare_fn!(foo { ... })` where `foo` is actually an expr (so concat_idents!() work) but declare_fn!() checks for expanded exprs which are not idents. - Make concat_idents!() occur during the expansion. So for example, we will have something like `set_$+$e` (check for $e being an ident is done when the macro is defined). Then concat_idents!() will be rewritten in terms of $+ I think. ...Any thoughts? -- -- Kang Seonghoon | Software Engineer, iPlateia Inc. | http://mearie.org/ -- Opinions expressed in this email do not necessarily represent the views of my employer. -- From ben.striegel at gmail.com Tue Feb 12 06:07:59 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Tue, 12 Feb 2013 09:07:59 -0500 Subject: [rust-dev] Google Summer of Code Message-ID: GSoC is starting up soon: http://www.google-melange.com/gsoc/homepage/google/gsoc2013 Does anyone want to get Rust in on this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Tue Feb 12 10:04:23 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Tue, 12 Feb 2013 10:04:23 -0800 Subject: [rust-dev] Google Summer of Code In-Reply-To: References: Message-ID: On Tue, Feb 12, 2013 at 6:07 AM, Benjamin Striegel wrote: > GSoC is starting up soon: > > http://www.google-melange.com/gsoc/homepage/google/gsoc2013 > > Does anyone want to get Rust in on this? The feeling among the core team is that at least this year, we don't have the energy/resources to (as part of Mozilla) start a Summer of Code project ourselves. Since it's the summer, we will have interns to supervise and additional mentoring is just going to be too much. If a very motivated community member wanted to coordinate a project and recruit mentors from the community, there's a possibility (I can't promise anything) that we could put our name on it, as Mozilla. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From illissius at gmail.com Wed Feb 13 03:04:51 2013 From: illissius at gmail.com (=?ISO-8859-1?Q?G=E1bor_Lehel?=) Date: Wed, 13 Feb 2013 12:04:51 +0100 Subject: [rust-dev] lifetime syntax In-Reply-To: <5112A67A.8010907@mozilla.com> References: <5112A67A.8010907@mozilla.com> Message-ID: On Wed, Feb 6, 2013 at 7:52 PM, Graydon Hoare wrote: > On 13-02-06 10:33 AM, Isaac Aggrey wrote: >> I realize the Rust community is beginning to settle on the `'lt` as the syntax >> to rule them all, but is using any sort of suffix for lifetime syntax a >> non-starter? > > Yeah, sorry, this horse* is dead. > > -Graydon > > (* no actual horses were harmed in the discussion of this feature) > Apologies, I've just spotted another horse whose lifetime I couldn't quite infer, though it is probably dead: What about just having types be uppercase and lifetimes be lowercase? I was reading the weekly meeting, specifically the example ~'task Reader, when I thought "why not just ~task Reader -- oh, right, lifetimes need the sigil", which lead me to the present horse. Unless my memory has been corrupted, in every example I've seen so far, probably not by conscious design but also not by accident, the types have been uppercase and the lifetimes lowercase. Why not codify it? I don't know if there are serious philosophical agreements about the idea of case being significant. But in any case, it would eliminate a lot of punctuation, and I think code would be a lot more pleasant to look at. ...I was wrong, types are not all uppercase, the primitive ones like bool, int, etc. are not. That probably doesn't help the prognosis. But if lifetime parameters need to be explicitly introduced, maybe it doesn't lead to actual ambiguity? If it was introduced as a parameter then lowercase -> lifetime, uppercase -> type, otherwise if it's a predefined lifetime name -> it's a lifetime, otherwise -> it's a type. But maybe that wouldn't play well with the future-idea of labelling blocks with lifetimes. Or the primitive type names could be special cased, but I guess that's not appealing. Iunno. Sorry again for bringing this up after the matter's already been decided. -- Your ship was destroyed in a monadic eruption. From vince.raiken at gmail.com Wed Feb 13 08:26:35 2013 From: vince.raiken at gmail.com (vince.raiken at gmail.com) Date: Wed, 13 Feb 2013 16:26:35 -0000 Subject: [rust-dev] Managing "global" state with callback functions Message-ID: I'm currently working with GLUT bindings in Rust (or I can use GLFW, doesn't matter to me), and one of the main ways that GLUT (and GLFW) manage things such as key presses is with callback functions. Getting a Rust function to act as a callback function for GLUT is easy enough, but I'm currently stuck at figuring out how I'm supposed to manipulate the world state when input happens, or when a frame "ticks", etc. Due to the nature of Rust, just throwing an anonymous function into the callback doesn't work by itself, because impure functions might be used with an @WorldState (thus it doesn't compile), or moving a ~WorldState can only work once, and not into the 5+ callbacks I need to setup. How can I properly work with GLUT such that each callback can manipulate the WorldState in some way? (preferably safely) -------------- next part -------------- An HTML attachment was scrubbed... URL: From gwillen at nerdnet.org Wed Feb 13 10:04:40 2013 From: gwillen at nerdnet.org (Glenn Willen) Date: Wed, 13 Feb 2013 10:04:40 -0800 Subject: [rust-dev] Managing "global" state with callback functions In-Reply-To: References: Message-ID: I'd say the first thing to try -- if I'm understanding the problem right -- is having one task maintain the state, and having the callbacks communicate with that task through channels. Does that sound feasible for what you need to accomplish? Glenn On Feb 13, 2013, at 8:26 AM, vince.raiken at gmail.com wrote: > I'm currently working with GLUT bindings in Rust (or I can use GLFW, doesn't matter to me), and one of the main ways that GLUT (and GLFW) manage things such as key presses is with callback functions. Getting a Rust function to act as a callback function for GLUT is easy enough, but I'm currently stuck at figuring out how I'm supposed to manipulate the world state when input happens, or when a frame "ticks", etc. > > Due to the nature of Rust, just throwing an anonymous function into the callback doesn't work by itself, because impure functions might be used with an @WorldState (thus it doesn't compile), or moving a ~WorldState can only work once, and not into the 5+ callbacks I need to setup. > > How can I properly work with GLUT such that each callback can manipulate the WorldState in some way? (preferably safely) > > > !DSPAM:511bbebe36705315134984! > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > > !DSPAM:511bbebe36705315134984! From vince.raiken at gmail.com Wed Feb 13 12:01:58 2013 From: vince.raiken at gmail.com (vince.raiken at gmail.com) Date: Wed, 13 Feb 2013 20:01:58 -0000 Subject: [rust-dev] Cannot determine a type for this expression: unconstrained type Message-ID: I'm trying to create a function which initializes a generic structure with a generic value. However, rustc is giving me the error that is the subject. I have no idea why this is happening. Anyone have any tips? Code here: http://pastebin.com/6LiciGeX -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Wed Feb 13 12:06:10 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 13 Feb 2013 12:06:10 -0800 Subject: [rust-dev] Managing "global" state with callback functions In-Reply-To: References: Message-ID: <511BF232.4090704@mozilla.com> On 02/13/2013 10:04 AM, Glenn Willen wrote: > I'd say the first thing to try -- if I'm understanding the problem right -- is having one task maintain the state, and having the callbacks communicate with that task through channels. Does that sound feasible for what you need to accomplish? > I don't quite understand the problem, but I agree that it is good policy to keep the world state off the thread that is doing graphics. One can start with message passing and if that's to slow maybe put the bits of mutable state that are needed for rendering into a RWARC or MutexARC. I haven't used it personally but GLUT is notorious for it's callback-based API that doesn't provide a custom data pointer like every other sane, thread-safe, callback-based API. I believe what servo does in this situation is stuff a value into task-local storage (core::task::local_storage) immediately before the call, then pull it out after. The condition API is perfect for this (core::condition). Interested people might want to look at or use https://github.com/mozilla-servo/rust-glut. From niko at alum.mit.edu Wed Feb 13 14:27:26 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 13 Feb 2013 14:27:26 -0800 Subject: [rust-dev] Cannot determine a type for this expression: unconstrained type In-Reply-To: References: Message-ID: <511C134E.9040503@alum.mit.edu> That is somewhat surprising to me. In some cases you do need type annotations but I wouldn't expect one to be required on that line. Can you give a larger snippet, including perhaps the body of the function you are calling? Also, you can try an explicit annotation: glut::init(~1, |glut_s: GLUT|) { ... } Niko vince.raiken at gmail.com wrote: > > I'm trying to create a function which initializes a generic structure > with a generic value. However, rustc is giving me the error that is > the subject. I have no idea why this is happening. Anyone have any tips? > > Code here: http://pastebin.com/6LiciGeX > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From nik9000 at gmail.com Wed Feb 13 16:32:56 2013 From: nik9000 at gmail.com (Nikolas Everett) Date: Wed, 13 Feb 2013 19:32:56 -0500 Subject: [rust-dev] Just found yesterday and impressed and I have a question Message-ID: I found rust last night and am pretty impressed by what I've read so far but I have a question. In the tutorial you seem to switch between pointer types quite a bit when I don't _think_ it is relevant. Here is an example: fn draw_all(shapes: ~[T]) { for shapes.each |shape| { shape.draw(); } } becomes fn draw_all(shapes: &[@Drawable]) { for shapes.each |shape| { shape.draw(); } } Is it relevant that shapes is owned above and borrowed below? If I read the section above right then it is best to declare everything as borrowed unless you need to do otherwise. Also, now that I think about it, is it possible to define shapes as &[&Drawable] and then call draw_all with a &[@Drawable]? I'm trying to wrap my head around all this but intuitively I think of pointers as downgrade-able. Is that right? Nik -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Wed Feb 13 17:29:27 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 13 Feb 2013 17:29:27 -0800 Subject: [rust-dev] Just found yesterday and impressed and I have a question In-Reply-To: References: Message-ID: <511C3DF7.10804@mozilla.com> On 02/13/2013 04:32 PM, Nikolas Everett wrote: > I found rust last night and am pretty impressed by what I've read so > far but I have a question. In the tutorial you seem to switch between > pointer types quite a bit when I don't _think_ it is relevant. Here > is an example: > fn draw_all(shapes:~[T]) { > for shapes.each |shape| {shape.draw(); } > } > becomes > fn draw_all(shapes: &[@Drawable]) { > for shapes.each |shape| {shape.draw(); } > } > Is it relevant that shapes is owned above and borrowed below? If I > read the section above right then it is best to declare everything as > borrowed unless you need to do otherwise. > It is not relevant. Here @Drawable is a managed object (a boxed type cast to a trait), and at the time the tutorial was written @Object was the only form of this that worked. Even now ~Drawable does not work. This example is as written because of language deficiencies and if I were to redo these examples (and the compiler worked as expected) I would use the same sigil in both. > Also, now that I think about it, is it possible to define shapes as > &[&Drawable] and then call draw_all with a &[@Drawable]? I'm trying > to wrap my head around all this but intuitively I think of pointers as > downgrade-able. Is that right? No. The conversion from @ and ~ to & is a specific type of coercion called 'borrowing' and it applies to the 'outer' pointer. Treating &[@Drawable] as &[&Drawable] would require more complex subtyping, of which there is very little in Rust. -------------- next part -------------- An HTML attachment was scrubbed... URL: From vince.raiken at gmail.com Wed Feb 13 18:33:02 2013 From: vince.raiken at gmail.com (vince.raiken at gmail.com) Date: Thu, 14 Feb 2013 02:33:02 -0000 Subject: [rust-dev] Cannot determine a type for this expression: unconstrained type In-Reply-To: <511C134E.9040503@alum.mit.edu> References: <511C134E.9040503@alum.mit.edu> Message-ID: <52vvKqzXAVv3IZNO_EmeMKgUhfwXPz-RjwT-5QX7PbmwNDHGI@smtp.gmail.com> Sorry if it wasn't clear, but the body of glut::init is included in the pastebin snippet I posted. Line 15: pub fn init(?) I tried adding the GLUT annotation to the function, and got the same error: main.rs:10:4: 10:14 error: cannot determine a type for this expression: unconstrained type main.rs:10 glut::init(move initial, |glut_s: GLUT| { Niko Matsakis wrote: That is somewhat surprising to me. In some cases you do need type annotations but I wouldn't expect one to be required on that line. Can you give a larger snippet, including perhaps the body of the function you are calling? Also, you can try an explicit annotation: glut::init(~1, |glut_s: GLUT|) { ... } Niko vince.raiken at gmail.com wrote: I'm trying to create a function which initializes a generic structure with a generic value. However, rustc is giving me the error that is the subject. I have no idea why this is happening. Anyone have any tips? Code here: http://pastebin.com/6LiciGeX _______________________________________________ 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 Wed Feb 13 19:10:45 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Wed, 13 Feb 2013 22:10:45 -0500 Subject: [rust-dev] Cannot determine a type for this expression: unconstrained type In-Reply-To: <52vvKqzXAVv3IZNO_EmeMKgUhfwXPz-RjwT-5QX7PbmwNDHGI@smtp.gmail.com> References: <511C134E.9040503@alum.mit.edu> <52vvKqzXAVv3IZNO_EmeMKgUhfwXPz-RjwT-5QX7PbmwNDHGI@smtp.gmail.com> Message-ID: You shouldn't have a comma between Copy and Send. It thinks Send is a type parameter, and it can't infer a type argument since Send doesn't appear in the signature. On Wed, Feb 13, 2013 at 9:33 PM, wrote: > Sorry if it wasn't clear, but the body of glut::init is included in the > pastebin snippet I posted. Line 15: pub fn init(?) > > > > I tried adding the GLUT annotation to the function, and got the same > error: > > > > > main.rs:10:4: 10:14 error: cannot determine a type for this expression: > unconstrained type > main.rs:10 glut::init(move initial, |glut_s: GLUT| { > > > Niko Matsakis wrote: > > That is somewhat surprising to me. In some cases you do need type > annotations but I wouldn't expect one to be required on that line. Can you > give a larger snippet, including perhaps the body of the function you are > calling? > > > > Also, you can try an explicit annotation: > > > > glut::init(~1, |glut_s: GLUT|) { ... } > > > > > > Niko > > > > vince.raiken at gmail.com wrote: > > > > I'm trying to create a function which initializes a generic structure with > a generic value. However, rustc is giving me the error that is the subject. > I have no idea why this is happening. Anyone have any tips? > > > > Code here: http://pastebin.com/6LiciGeX > > > > _______________________________________________ > > 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 thomas at codesourcery.com Thu Feb 14 03:03:58 2013 From: thomas at codesourcery.com (Thomas Schwinge) Date: Thu, 14 Feb 2013 12:03:58 +0100 Subject: [rust-dev] [Google Summer of Code 2013] - Mozilla Rust language bindings In-Reply-To: <005201ce0a5a$c05f0470$411d0d50$@2ndnature.co.nz> References: <005201ce0a5a$c05f0470$411d0d50$@2ndnature.co.nz> Message-ID: <877gmbnom9.fsf@kepler.schwinge.homeip.net> Hi! On Thu, 14 Feb 2013 15:26:46 +1300, "Nolan Tunnicliffe" wrote: > http://www.reddit.com/r/rust/comments/18dfd6/gsoc_2013_started_any_rust_project_ideas/ Thanks for this proposal (the very first we (GNU Hurd) get this year)! Looks like a good project to me. As you posted it on , I'll assume you'd like it discussed there. I'd also be fine posting/subscribing to a Rust mailing list. [Well, in fact I simply cross-posted the email there (and tried subscribing, which currently doesn't seem to work, though); please keep everyone in copy.] Reddit would be an unusual place (for us, at least) to discuss technical topics. Many of my following questions may already be answered in the regular Rust documentation -- which I have not yet had the chance to chase up. Of course it is fine to simply give pointers that answer my questions. > Rust is a language sponsored by Mozilla who are using it to write a next > generation web browser engine. It is low level hardware access capable, > making it a potential replacement for C and C++ for writing device drivers. Please verify (or ask us to help looking at the Rust sources if you're unsure): it does have a functional x86 (that is, 32-bit) GNU/Linux port, which generally is implemented on top of the usual Unix/POSIX as well as glibc APIs (?#define _GNU_SOURCE?), and makes little or no use of direct Linux kernel syscalls (such as futex, for example). > From http://www.rust-lang.org/ : > > Rust is a curly-brace, block-structured expression language. It visually > resembles the C language family, but differs significantly in syntactic and > semantic details. Its design is oriented toward concerns of "programming in > the large", that is, of creating and maintaining boundaries - both abstract > and operational - that preserve large-system integrity, availability and > concurrency. > > It supports a mixture of imperative procedural, concurrent actor, > object-oriented and pure functional styles. Rust also supports generic > programming and metaprogramming, in both static and dynamic styles. Look, it has *all of it*! ;-) > Memory safety > > no null or dangling pointers, no buffer overflows How is this implemented? Internal reference counting, or garbage collection? If the latter, which engine? > Concurrency > > lightweight tasks with message passing, no shared memory How implemented? Standard pthread interfaces or some internal thing (using which kernel interface)? > Exception handling > > unrecoverable unwinding with task isolation Requiring run-time/operating system support, or based on standard DWARF? > Memory model > > optional task-local GC, safe pointer types with region analysis Aha, garbage collection. How implemented/which engine? (Boehm?) > Compilation model > > ahead-of-time, C/C++ compatible More specifically, how do you get from Rust source code to executing machine code? What is your expertise as a Rust programmer (using Rust), Rust developer (developing Rust itself), and programming language implementation generally, focussing not on the copmuter science part of it ;-) but on the actual implementation, host system interfaces, and so on? In the following the terminology is sometimes unclear (maybe this simply is "new ground" for you?), for example, often when you say ?kernel? that should -- in our terminology -- be ?operating system?; by kernel we normally understand the GNU Mach microkernel, the base of the operating system. What experience do you have with operating system implementation? (These questions, by the way, are just so that we get a feeling about what we can roughly expect you to know, and what we first have to teach you -- but no problem with that, of course!) > For the Google Summer of Code 2013, Port the Mozilla Rust > http://www.rust-lang.org/ programming language to GNU Hurd, Mach based > operating system microkernel. GNU Hurd microkernel allows any language that > can RPC Remote Procedure Call http://www.gnu.org/software/hurd/hurd/rpc.html > to write kernel 'servers' ie. components of the kernel that in Mach's case > run in User mode as opposed to Kernel mode. Allowing an existing modern > functioning kernel to be written, extended and potentially parts rewritten > in Rust. Kernel writers would use a modern low level capable language, Rust, > to extend a functioning kernel and components in a language that was > designed to preserve large-system integrity, availability and concurrency, > some of the same goals of GNU Hurd project itself. This in fact is a separate project, which first requires a general port of the Rust programming environment to GNU/Hurd, which I cannot judge yet how difficult it will be. But of course it (enabling Hurd interfaces (RPCs) in Rust) is a very desirable follow-on project! > GNU Hurd allows runtime installation of user mode, and most are, kernel > components that do not require root access or a reboot to install and if > they crash do not bring the whole kernel down. Unlike most UNIX's, GNU Hurd > is designed to be modified and extended through system hooks. The kernel can > be developed and progress at a potentially different pace compared to Linux. > A lot of functionality is implemented as file system interfaces > 'translators' which may be another way of providing further features to Rust > without reprioritizing language features such as httpfs virtual filesystem > and netio http://www.gnu.org/software/hurd/hurd/translator.html . Perhaps > Hurd translators or Rust library features can be written with a layer such > that you can add the feature to a GNU Hurd virtual file system 'translator' > AND Rust library with a single implementation. Work on either is work on > both. > Potentially this could mean that one missing aspect of GNU Hurd, drivers, > could be written in Rust with the advantage that they are written in a > modern language, for making the sacrifice of having to rewrite drivers to > work on this kernel as opposed to sticking with existing drivers written in > 'C' and Linux. Turning the disadvantage in the lack of drivers currently > written for Hurd into an advantage that they could now be written in a new > language, Rust. Making the assumption that hardware device drivers can > currently be written for GNU Hurd in any language that can RPC and has low > level hardware access capability. I believe the project to make userspace > drivers exists if not yet fully realized. Yes, the DDE project, . Implementing device drivers in Rust is yet another project. Generally (due to the complexity and sheer number of drivers), the tendency has been in "use" another operating system's drivers (such as Linux') by implementing some sort of glue-code to embed and run them. But of course, once the RPC interfaces are available in the Rust language/libraries, it would be possible to implement device drivers, too. > Even if having the majority of drivers written in Rust is optimistic the > above two paragraphs still suggest the advantages of Rust language bindings > for GNU Hurd such as being able to write a currently functioning microkernel > in the Rust language with all the benefits that implies for both Rust > programmers and the GNU Hurd microkernel. Again, you don't want to rewrite the GNU Mach microkernel in Rust, but rather implement operating system components in Rust, that make use of the microkernel's interfaces. (Of course, the microkernel could be rewritten, too, but that is yet another project, and much bigger one. Gr??e, Thomas -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 489 bytes Desc: not available URL: From thomas at codesourcery.com Thu Feb 14 03:03:09 2013 From: thomas at codesourcery.com (Thomas Schwinge) Date: Thu, 14 Feb 2013 12:03:09 +0100 Subject: [rust-dev] [Google Summer of Code 2013] - Mozilla Rust language bindings In-Reply-To: <005201ce0a5a$c05f0470$411d0d50$@2ndnature.co.nz> References: <005201ce0a5a$c05f0470$411d0d50$@2ndnature.co.nz> Message-ID: <878v6rnonm.fsf@kepler.schwinge.homeip.net> Hi! On Thu, 14 Feb 2013 15:26:46 +1300, "Nolan Tunnicliffe" wrote: > http://www.reddit.com/r/rust/comments/18dfd6/gsoc_2013_started_any_rust_project_ideas/ Thanks for this proposal (the very first we (GNU Hurd) get this year)! Looks like a good project to me. As you posted it on , I'll assume you'd like it discussed there. I'd also be fine posting/subscribing to a Rust mailing list. [Well, in fact I simply cross-posted the email there (and tried subscribing, which currently doesn't seem to work, though); please keep everyone in copy.] Reddit would be an unusual place (for us, at least) to discuss technical topics. Many of my following questions may already be answered in the regular Rust documentation -- which I have not yet had the chance to chase up. Of course it is fine to simply give pointers that answer my questions. > Rust is a language sponsored by Mozilla who are using it to write a next > generation web browser engine. It is low level hardware access capable, > making it a potential replacement for C and C++ for writing device drivers. Please verify (or ask us to help looking at the Rust sources if you're unsure): it does have a functional x86 (that is, 32-bit) GNU/Linux port, which generally is implemented on top of the usual Unix/POSIX as well as glibc APIs (?#define _GNU_SOURCE?), and makes little or no use of direct Linux kernel syscalls (such as futex, for example). > From http://www.rust-lang.org/ : > > Rust is a curly-brace, block-structured expression language. It visually > resembles the C language family, but differs significantly in syntactic and > semantic details. Its design is oriented toward concerns of "programming in > the large", that is, of creating and maintaining boundaries - both abstract > and operational - that preserve large-system integrity, availability and > concurrency. > > It supports a mixture of imperative procedural, concurrent actor, > object-oriented and pure functional styles. Rust also supports generic > programming and metaprogramming, in both static and dynamic styles. Look, it has *all of it*! ;-) > Memory safety > > no null or dangling pointers, no buffer overflows How is this implemented? Internal reference counting, or garbage collection? If the latter, which engine? > Concurrency > > lightweight tasks with message passing, no shared memory How implemented? Standard pthread interfaces or some internal thing (using which kernel interface)? > Exception handling > > unrecoverable unwinding with task isolation Requiring run-time/operating system support, or based on standard DWARF? > Memory model > > optional task-local GC, safe pointer types with region analysis Aha, garbage collection. How implemented/which engine? (Boehm?) > Compilation model > > ahead-of-time, C/C++ compatible More specifically, how do you get from Rust source code to executing machine code? What is your expertise as a Rust programmer (using Rust), Rust developer (developing Rust itself), and programming language implementation generally, focussing not on the copmuter science part of it ;-) but on the actual implementation, host system interfaces, and so on? In the following the terminology is sometimes unclear (maybe this simply is "new ground" for you?), for example, often when you say ?kernel? that should -- in our terminology -- be ?operating system?; by kernel we normally understand the GNU Mach microkernel, the base of the operating system. What experience do you have with operating system implementation? (These questions, by the way, are just so that we get a feeling about what we can roughly expect you to know, and what we first have to teach you -- but no problem with that, of course!) > For the Google Summer of Code 2013, Port the Mozilla Rust > http://www.rust-lang.org/ programming language to GNU Hurd, Mach based > operating system microkernel. GNU Hurd microkernel allows any language that > can RPC Remote Procedure Call http://www.gnu.org/software/hurd/hurd/rpc.html > to write kernel 'servers' ie. components of the kernel that in Mach's case > run in User mode as opposed to Kernel mode. Allowing an existing modern > functioning kernel to be written, extended and potentially parts rewritten > in Rust. Kernel writers would use a modern low level capable language, Rust, > to extend a functioning kernel and components in a language that was > designed to preserve large-system integrity, availability and concurrency, > some of the same goals of GNU Hurd project itself. This in fact is a separate project, which first requires a general port of the Rust programming environment to GNU/Hurd, which I cannot judge yet how difficult it will be. But of course it (enabling Hurd interfaces (RPCs) in Rust) is a very desirable follow-on project! > GNU Hurd allows runtime installation of user mode, and most are, kernel > components that do not require root access or a reboot to install and if > they crash do not bring the whole kernel down. Unlike most UNIX's, GNU Hurd > is designed to be modified and extended through system hooks. The kernel can > be developed and progress at a potentially different pace compared to Linux. > A lot of functionality is implemented as file system interfaces > 'translators' which may be another way of providing further features to Rust > without reprioritizing language features such as httpfs virtual filesystem > and netio http://www.gnu.org/software/hurd/hurd/translator.html . Perhaps > Hurd translators or Rust library features can be written with a layer such > that you can add the feature to a GNU Hurd virtual file system 'translator' > AND Rust library with a single implementation. Work on either is work on > both. > Potentially this could mean that one missing aspect of GNU Hurd, drivers, > could be written in Rust with the advantage that they are written in a > modern language, for making the sacrifice of having to rewrite drivers to > work on this kernel as opposed to sticking with existing drivers written in > 'C' and Linux. Turning the disadvantage in the lack of drivers currently > written for Hurd into an advantage that they could now be written in a new > language, Rust. Making the assumption that hardware device drivers can > currently be written for GNU Hurd in any language that can RPC and has low > level hardware access capability. I believe the project to make userspace > drivers exists if not yet fully realized. Yes, the DDE project, . Implementing device drivers in Rust is yet another project. Generally (due to the complexity and sheer number of drivers), the tendency has been in "use" another operating system's drivers (such as Linux') by implementing some sort of glue-code to embed and run them. But of course, once the RPC interfaces are available in the Rust language/libraries, it would be possible to implement device drivers, too. > Even if having the majority of drivers written in Rust is optimistic the > above two paragraphs still suggest the advantages of Rust language bindings > for GNU Hurd such as being able to write a currently functioning microkernel > in the Rust language with all the benefits that implies for both Rust > programmers and the GNU Hurd microkernel. Again, you don't want to rewrite the GNU Mach microkernel in Rust, but rather implement operating system components in Rust, that make use of the microkernel's interfaces. (Of course, the microkernel could be rewritten, too, but that is yet another project, and much bigger one. Gr??e, Thomas -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 489 bytes Desc: not available URL: From vince.raiken at gmail.com Thu Feb 14 14:40:12 2013 From: vince.raiken at gmail.com (vince.raiken at gmail.com) Date: Thu, 14 Feb 2013 22:40:12 -0000 Subject: [rust-dev] Port/Chan problem "type parameter with incompatible type" Message-ID: I'm trying to write some code where a task does something and sends a struct through a Chan to the function that created the task, and it's giving me some serious issues with not letting me actually send it. The full error is: glfw.rs:135:8: 135:12 error: not a sendable value glfw.rs:135 chan.send(first_glfw); ^~~~ glfw.rs:135:8: 135:30 error: instantiating a type parameter with an incompatible type (needs `owned`, got `copy durable`, missing `owned`) glfw.rs:135 chan.send(first_glfw); ^~~~~~~~~~~~~~~~~~~~~~ >From the code: http://pastebin.com/f3XFxBuQ (this is at line 80 of the pastebin code). I asked IRC about this as well, and someone suggested changing "let first_glfw = GLFW" to "let first_glfw = ~GLFW" but that didn't change the error. Any help getting this worked out would be seriously appreciated. -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Feb 14 15:03:13 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 14 Feb 2013 15:03:13 -0800 Subject: [rust-dev] Cannot determine a type for this expression: unconstrained type In-Reply-To: References: <511C134E.9040503@alum.mit.edu> <52vvKqzXAVv3IZNO_EmeMKgUhfwXPz-RjwT-5QX7PbmwNDHGI@smtp.gmail.com> Message-ID: <511D6D31.8090404@alum.mit.edu> Ah indeed. In fact the current syntax is: pub fn init(...) Steven Blenkinsop wrote: > You shouldn't have a comma between Copy and Send. It thinks Send is a > type parameter, and it can't infer a type argument since Send doesn't > appear in the signature. > > On Wed, Feb 13, 2013 at 9:33 PM, > wrote: > > Sorry if it wasn't clear, but the body of glut::init is included > in the pastebin snippet I posted. Line 15: pub fn init Send>(?) > > I tried adding the GLUT annotation to the function, and got > the same error: > > main.rs:10:4: 10:14 error: cannot determine a type for this > expression: unconstrained type > main.rs:10 glut::init(move initial, > |glut_s: GLUT| { > Niko Matsakis wrote: > > That is somewhat surprising to me. In some cases you do need type > annotations but I wouldn't expect one to be required on that line. > Can you give a larger snippet, including perhaps the body of the > function you are calling? > > Also, you can try an explicit annotation: > > glut::init(~1, |glut_s: GLUT|) { ... } > > Niko > > vince.raiken at gmail.com wrote: > > I'm trying to create a function which initializes a generic > structure with a generic value. However, rustc is giving me > the error that is the subject. I have no idea why this is > happening. Anyone have any tips? > > Code here: http://pastebin.com/6LiciGeX > > _______________________________________________ > > 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 banderson at mozilla.com Thu Feb 14 15:03:36 2013 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 14 Feb 2013 15:03:36 -0800 Subject: [rust-dev] Port/Chan problem "type parameter with incompatible type" In-Reply-To: References: Message-ID: <511D6D48.1030401@mozilla.com> On 02/14/2013 02:40 PM, vince.raiken at gmail.com wrote: > > I'm trying to write some code where a task does something and sends a > struct through a Chan to the function that created the task, and it's > giving me some serious issues with not letting me actually send it. > The full error is: > > glfw.rs:135:8: 135:12 error: not a sendable value > glfw.rs:135 chan.send(first_glfw); > ^~~~ > glfw.rs:135:8: 135:30 error: instantiating a type parameter with an > incompatible type (needs `owned`, got `copy durable`, missing `owned`) > glfw.rs:135 chan.send(first_glfw); > ^~~~~~~~~~~~~~~~~~~~~~ > From the code: http://pastebin.com/f3XFxBuQ (this is at line 80 of the > pastebin code). I asked IRC about this as well, and someone suggested > changing "let first_glfw = GLFW" to "let first_glfw = ~GLFW" but that > didn't change the error. Any help getting this worked out would be > seriously appreciated. > > That's vexing. It's suspicious that the error is pointing to `chan` and not `first_glfw`, but maybe it just imprecise. GLFW<~T> looks owned to me, though I'll note that `impl GLFW: Owned` is incorrect (as is the impl of `Copy`) - `Owned` and `Copy` are not supposed to be implementable by user code. Taking those out could maybe disconfuse rustc. You may also try changing the `stream` call to mention the type and see if that stirs up any different errors, `stream::>()`. Is it possible that this code is using a bogus definition of the `Owned' trait and not the one from core? That could explain why everything looks owned but the compiler can't see it, and also why rustc isn't complaining about the impl of `Owned`. Which version of rustc are you using? From paul.stansifer at gmail.com Fri Feb 15 08:09:19 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Fri, 15 Feb 2013 11:09:19 -0500 Subject: [rust-dev] [RFC] Functions/methods with generated names In-Reply-To: References: Message-ID: Your analysis is solid; those are the main options, as far as I can tell. TL;DR: Advantages and disadvantages! Implementation concerns! Smurfs! Third option somewhat preferred by me! - I agree that macros-in-identifier-position is appealing linguistically, but it's a bit tricky for internal reasons: the representation of identifiers would need to be changed. The most natural choice is an `enum { literal_ident(...), macro_invocation(...) }`, but this change would probably have a pretty big surface area (it wouldn't touch *everything*, the way interning identifiers originally did, and the lookup-the-actual-name-or-fail could be folded into changes that hygiene requires anyways). An easier-to-implement strategy would be to add an Option to all identifiers, and have the macro system examine and expand this during expand.rs, as if it were an actual node in the AST. That would be quite easy to implement, but wouldn't be very clean. Either way, the result looks would be used like: macro_rules! define_smurfy_fn( ($name:id, $arg:id, $body:expr) => ( fn concat_idents!(smurf_, $name) ($arg:uint) -> uint { $body } ) ) - I think that there's a modification of your second option that'll be a bit more general, and could be implemented as a single, ordinary syntax extension. Replace `concat_idents!(...)` with `invoke_with_concatted_idents!(...)` (taking a macro name as its first argument, and a `+`-separated sequence of identifiers as its second, and an arbitrary number of arguments to be passed through afterwards), to be used as follows: macro_rules! define_smurfy_fn_internal( ($smurf_name:id, $arg:id, $body:expr) => ( fn $smurf_name($arg:uint) -> uint { $body } ) ) macro_rules! define_smurfy_fn( ($name:id, $arg:id, $body:expr) => ( invoke_with_concatted_idents!( define_smurfy_fn_internal, smurf_ + $name, $body) ) ) It's like continuation-passing-style! As portrayed in a horror movie about functional programming! Actually, aside from the verbosity, it's not too bad, and the implementation of `invoke_with_concatted_idents!` would be neatly contained within one file. - Building identifier concatenation into the macro system wouldn't be too bad. It has one particular advantage: it might make it easier to automatically do the Right Thing hygienically when concatenating identifiers. For example, if you write (using prefix notation, which I think might be more readable for this) `$+(smurf_, $name)`, the resulting identifier Ought To have the marks from $name. (I *think* that `$+($name_left, _, $name_right)` ought to have the union of the marks from both names, but I'm not sure.) I don't think that the previous two options could do this (to make `concat_idents!(...)` hygienic, the programmer would have to pass an additional argument indicating where to get the marks from, e.g. `concat_idents!(smurf_, $name <~~ $name)`). The expander could magically inform the appropriate macro which identifiers are literal and which ones aren't, but that would be awfully sad. The big disadvantage of this is that it doesn't naturally extend to other operations on names. But I think that concatenation ought to be enough for anybody. (`subidentifier!(...)`? `join_idents!(...)`? `disemvowel!(...)`?). Implementation-wise, I think that this is not bad: just another case in transcribe.rs, ast.rs, and parser.rs. On the whole, now that I've written this all, I think that the third option is the most appealing, unless we expect non-concatenation-operations-on-identifiers to be something we want. Otherwise, I think identifier-position-macros are a one-syntax-extension pony, so we might as well make concatenation a special operation, and keep the second option on the shelf for when someone wants something truly strange. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From clements at brinckerhoff.org Fri Feb 15 16:55:13 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 15 Feb 2013 16:55:13 -0800 Subject: [rust-dev] parser bug? Message-ID: <85869259-FC10-402A-A6BA-E448B637F17C@brinckerhoff.org> This program: pub trait MyTrait { /// doc comment with nothing after it... } ...signals the error: oiseau:/tmp clements> rustc --test bar.rs bar.rs:3:0: 3:1 error: unexpected token: `}` bar.rs:3 } ^ This looks ilke a parser bug to me, but maybe it's deliberately illegal to have a doc comment with nothing after it ? John -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4370 bytes Desc: not available URL: From clements at brinckerhoff.org Fri Feb 15 17:12:41 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 15 Feb 2013 17:12:41 -0800 Subject: [rust-dev] ptr to trait with fun that returns borrowed ptr can't be put in another struct? Message-ID: It appears that if a trait has a function that returns a borrowed pointer with lifetime self (e.g. Map), then pointers to values with that trait can't be stored in other structures. Here's the example I'm thinking of: pub trait MyMap { fn find(&self) -> &self/uint; } type MyTy = MyMap; pub struct AStruct { a : ~MyTy } pub fn new(init: ~MyTy) -> AStruct { AStruct {a:init} } this signals the error(s): oiseau:/tmp clements> rustc --test foo.rs foo.rs:19:4: 19:11 error: cannot infer an appropriate lifetime due to conflicting requirements foo.rs:19 AStruct {a:init} ^~~~~~~ foo.rs:18:35: 20:1 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 18:35... foo.rs:18 pub fn new(init: ~MyTy) -> AStruct { foo.rs:19 AStruct {a:init} foo.rs:20 } foo.rs:19:15: 19:19 note: ...due to the following expression foo.rs:19 AStruct {a:init} ^~~~ foo.rs:18:35: 20:1 note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the block at 18:35... foo.rs:18 pub fn new(init: ~MyTy) -> AStruct { foo.rs:19 AStruct {a:init} foo.rs:20 } foo.rs:19:4: 19:11 note: ...due to the following expression foo.rs:19 AStruct {a:init} ^~~~~~~ error: aborting due to previous error Changing the return type of find() to be simply 'uint' makes the problem go away. Is this correct behavior? If so, is there an obvious workaround? Without understanding the problem, it's hard to see what the workaround would be. Thanks! John -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4370 bytes Desc: not available URL: From niko at alum.mit.edu Sat Feb 16 09:23:50 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 16 Feb 2013 12:23:50 -0500 Subject: [rust-dev] ptr to trait with fun that returns borrowed ptr can't be put in another struct? Message-ID: I think there is a bug in the region parameterization inference that causes it to mistakenly infer that the trait map (in this case) is region parametrized. I've seen such bugs before but since the plan is to remove region parameterization inference in favor of explicit declarations I haven't bothered to isolate it. By the way I do hope to land those changes soon. If this is blocking you let me know and I'm sure we can come up with a work around.? Niko (Sent from a cramped, unreliable keyboard) -------- Original message -------- Subject: [rust-dev] ptr to trait with fun that returns borrowed ptr can't be put in another struct? From: John Clements To: rust-dev at mozilla.org CC: It appears that if a trait has a function that returns a borrowed pointer with lifetime self (e.g. Map), then pointers to values with that trait can't be stored in other structures. Here's the example I'm thinking of: pub trait MyMap { ??? fn find(&self) -> &self/uint; } type MyTy = MyMap; pub struct AStruct { a : ~MyTy } pub fn new(init: ~MyTy) -> AStruct { ??? AStruct {a:init} } this signals the error(s): oiseau:/tmp clements> rustc --test foo.rs foo.rs:19:4: 19:11 error: cannot infer an appropriate lifetime due to conflicting requirements foo.rs:19???? AStruct {a:init} ????????????? ^~~~~~~ foo.rs:18:35: 20:1 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 18:35... foo.rs:18 pub fn new(init: ~MyTy) -> AStruct { foo.rs:19???? AStruct {a:init} foo.rs:20 } foo.rs:19:15: 19:19 note: ...due to the following expression foo.rs:19???? AStruct {a:init} ???????????????????????? ^~~~ foo.rs:18:35: 20:1 note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the block at 18:35... foo.rs:18 pub fn new(init: ~MyTy) -> AStruct { foo.rs:19???? AStruct {a:init} foo.rs:20 } foo.rs:19:4: 19:11 note: ...due to the following expression foo.rs:19???? AStruct {a:init} ????????????? ^~~~~~~ error: aborting due to previous error Changing the return type of find() to be simply 'uint' makes the problem go away. Is this correct behavior? If so, is there an obvious workaround? Without understanding the problem, it's hard to see what the workaround would be. Thanks! John _______________________________________________ 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 Sat Feb 16 09:24:58 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 16 Feb 2013 12:24:58 -0500 Subject: [rust-dev] parser bug? Message-ID: Doc comments that are not attached to items do yield a parse error. There is an open issue on this point though personally I find it to be a feature and not a bug. Niko (Sent from a cramped, unreliable keyboard) -------- Original message -------- Subject: [rust-dev] parser bug? From: John Clements To: rust-dev at mozilla.org CC: This program: pub trait MyTrait { ??? /// doc comment with nothing after it... } ...signals the error: oiseau:/tmp clements> rustc --test bar.rs bar.rs:3:0: 3:1 error: unexpected token: `}` bar.rs:3 } ???????? ^ This looks ilke a parser bug to me, but maybe it's deliberately illegal to have a doc comment with nothing after it ? John _______________________________________________ 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 cpeterson at mozilla.com Sat Feb 16 15:38:08 2013 From: cpeterson at mozilla.com (Chris Peterson) Date: Sat, 16 Feb 2013 15:38:08 -0800 (PST) Subject: [rust-dev] no warnings about variable redeclarations: feature or bug? In-Reply-To: <1888728283.3133957.1361057079023.JavaMail.root@mozilla.com> Message-ID: <1084702705.3134405.1361057888464.JavaMail.root@mozilla.com> The following code snippet does not emit any compilation warnings about redeclaring variable names or types: fn x(y: int) -> ~str { let y = y + 1; let x = y == 2; let x = x.to_str(); x } Is this a feature or a bug? The Rust manual has no comment. This behavior was surprising, but I actually it. I use a similar pattern in Python when transforming a variable to a different type. I don't want to make up a new (and uglier) name when I no longer care about referencing the old value. chris From pwalton at mozilla.com Sat Feb 16 15:40:33 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 16 Feb 2013 15:40:33 -0800 Subject: [rust-dev] no warnings about variable redeclarations: feature or bug? In-Reply-To: <1084702705.3134405.1361057888464.JavaMail.root@mozilla.com> References: <1084702705.3134405.1361057888464.JavaMail.root@mozilla.com> Message-ID: <512018F1.2090309@mozilla.com> On 2/16/13 3:38 PM, Chris Peterson wrote: > Is this a feature or a bug? The Rust manual has no comment. This behavior was surprising, but I actually it. I use a similar pattern in Python when transforming a variable to a different type. I don't want to make up a new (and uglier) name when I no longer care about referencing the old value. I like this pattern a lot. In fact I often intentionally shadow variables if I want to make sure that they can't be used again (for example, if I'm moving the variable somewhere else, or I'm casting a numeric and want to make sure I never use the old value). I believe it's a common functional programming idiom. At least I started using the pattern a lot when I got into OCaml. Patrick From catamorphism at gmail.com Sat Feb 16 15:41:21 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 16 Feb 2013 15:41:21 -0800 Subject: [rust-dev] no warnings about variable redeclarations: feature or bug? In-Reply-To: <1084702705.3134405.1361057888464.JavaMail.root@mozilla.com> References: <1888728283.3133957.1361057079023.JavaMail.root@mozilla.com> <1084702705.3134405.1361057888464.JavaMail.root@mozilla.com> Message-ID: This is a feature. The Rust compiler uses name shadowing a fair amount. It's imaginable to have a lint pass about it that's off by default, though I don't think we have a lint pass like that now. (In Haskell, for example, name shadowing is allowed but GHC has an optional warning flag that will warn you about it.) Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From catamorphism at gmail.com Sat Feb 16 17:34:45 2013 From: catamorphism at gmail.com (Tim Chevalier) Date: Sat, 16 Feb 2013 17:34:45 -0800 Subject: [rust-dev] Proposed tutorial talk on Rust at Open Source Bridge Message-ID: Hi all -- I submitted a proposal to the Open Source Bridge conference to do a tutorial on Rust. I'm still able to edit the proposal until the deadline (March 2), so if anyone is interested in reading it over, I'd welcome any suggestions! http://opensourcebridge.org/proposals/970 Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Too much to carry, too much to let go Time goes fast, learning goes slow." -- Bruce Cockburn From erick.tryzelaar at gmail.com Sat Feb 16 21:23:59 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Sat, 16 Feb 2013 21:23:59 -0800 Subject: [rust-dev] Rust support in the Ragel State Machine Compiler Message-ID: I have a fork of Ragel that supports Rust, which you can find here: https://github.com/erickt/ragel. I just updated it to support rust incoming. It performs pretty well too, the url example can parse urls roughly 2-3 times faster than the hand written parser in the standard library. I'll try to push my ragel patches upstream one rust 0.6 lands. For those of you that haven't heard of Ragel, it's part way between regular expressions and a full parser generator. It builds state machines, and allows you to manipulate state transitions to parse more complex grammars. It's pretty neat. For example, here is a simple reverse polish notation calculator: https://github.com/erickt/ragel/blob/rust/examples/rust/rpn.rl %% machine rpn; %% write data; fn rpn(data: &str) -> Result { let mut cs = 0; let mut p = 0; let mut pe = data.len(); let mut mark = 0; let mut st = ~[]; %%{ action mark { mark = p; } action push { let s = data.slice(mark, p); match int::from_str(s) { None => return Err(fmt!("invalid integer %s", s)), Some(i) => st.push(i), } } action add { let y = st.pop(); let x = st.pop(); st.push(x + y); } action sub { let y = st.pop(); let x = st.pop(); st.push(x - y); } action mul { let y = st.pop(); let x = st.pop(); st.push(x * y); } action div { let y = st.pop(); let x = st.pop(); st.push(x / y); } action abs { let x = st.pop(); st.push(int::abs(x)); } action abba { st.push(666); } stuff = digit+ >mark %push | '+' @add | '-' @sub | '*' @mul | '/' @div | 'abs' %abs | 'add' %add | 'abba' %abba ; main := ( space | stuff space )* ; write init; write exec; }%% if cs < rpn_first_final { if p == pe { Err(~"unexpected eof") } else { Err(fmt!("error at position %u", p)) } } else if st.is_empty() { Err(~"rpn stack empty on result") } else { Ok(st.pop()) } } -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Sun Feb 17 21:02:38 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Mon, 18 Feb 2013 00:02:38 -0500 Subject: [rust-dev] Pattern macros? Message-ID: I was fiddling around with macros when I noticed that they don't work in a pattern position (such as on the LHS of => in a match). Just for curiosity's sake, I was wondering whether there was a particular reason for this, or if it just hadn't been implemented / wasn't worth implementing. The motivating case was creating intuitive constructors for a `struct List(Option<~(T, List)>);` while maintaining compatibility with `Option`, since `List(Some(~(v, next))` doesn't read quite as well as `Cons!(v, next)`. -------------- next part -------------- An HTML attachment was scrubbed... URL: From paul.stansifer at gmail.com Mon Feb 18 06:23:20 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Mon, 18 Feb 2013 09:23:20 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: It's just a matter of not having implemented it yet. Each new macro invocation location unfortunately requires modifying the AST, which affects all the code that is interested in that part of the AST. It's not a huge amount of work, but it does inflict lots of "can't happen" error cases on unrelated code, which is kinda sad. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From steve at steveklabnik.com Mon Feb 18 09:03:51 2013 From: steve at steveklabnik.com (Steve Klabnik) Date: Mon, 18 Feb 2013 09:03:51 -0800 Subject: [rust-dev] Rust support in the Ragel State Machine Compiler In-Reply-To: References: Message-ID: I tried to get you some publicity: http://thechangelog.com/a-rust-backend-for-ragel/ If anyone's projects have releases, let me know. Trying to get more attention for Rust via linking to new code all the time. :) From pwalton at mozilla.com Mon Feb 18 10:22:34 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 18 Feb 2013 10:22:34 -0800 Subject: [rust-dev] RFC: Prelude extension Message-ID: <5122716A.9010206@mozilla.com> Hi everyone, When writing functions that interoperate with C code, I tend to find myself importing the same few functions over and over. I'd like to see how everyone feels about a few extensions to the prelude: * c_int, c_long, c_void, etc. * ptr::null(). * cast::transmute(). I feel like these are relatively harmless extensions to the prelude, given Rust's systems focus. Thoughts? Patrick From jfredett at gmail.com Mon Feb 18 12:42:08 2013 From: jfredett at gmail.com (Joe Fredette) Date: Mon, 18 Feb 2013 15:42:08 -0500 Subject: [rust-dev] Rust support in the Ragel State Machine Compiler In-Reply-To: References: Message-ID: <306F35AE-89EE-4650-AC48-2EBB63239C46@gmail.com> Erick: This is fantastic, just the other day I was hunting for a parser library (generator or combinator, I was (and am) of little preference) and now here you provide one out of the box for me. Steve: OT: Nice to see another rubyist who's name I recognize. :) On Feb 18, 2013, at 12:03 PM, Steve Klabnik wrote: > I tried to get you some publicity: > http://thechangelog.com/a-rust-backend-for-ragel/ > > If anyone's projects have releases, let me know. Trying to get more > attention for Rust via linking to new code all the time. :) > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From erick.tryzelaar at gmail.com Mon Feb 18 12:53:05 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Mon, 18 Feb 2013 12:53:05 -0800 Subject: [rust-dev] Rust support in the Ragel State Machine Compiler In-Reply-To: <306F35AE-89EE-4650-AC48-2EBB63239C46@gmail.com> References: <306F35AE-89EE-4650-AC48-2EBB63239C46@gmail.com> Message-ID: Thanks Joe, I hope it works for you. Let me know if you have any trouble. Also, in case you are also looking for a parser combinator library, Jesse Jones wrote one, which you can find here: https://github.com/jesse99/rparse On Mon, Feb 18, 2013 at 12:42 PM, Joe Fredette wrote: > Erick: > > This is fantastic, just the other day I was hunting for a parser library > (generator or combinator, I was (and am) of little preference) and now here > you provide one out of the box for me. > > Steve: > > OT: Nice to see another rubyist who's name I recognize. :) > > On Feb 18, 2013, at 12:03 PM, Steve Klabnik > wrote: > > > I tried to get you some publicity: > > http://thechangelog.com/a-rust-backend-for-ragel/ > > > > If anyone's projects have releases, let me know. Trying to get more > > attention for Rust via linking to new code all the time. :) > > _______________________________________________ > > 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 danoctavian91 at gmail.com Mon Feb 18 13:22:15 2013 From: danoctavian91 at gmail.com (Dan Cristian Octavian) Date: Mon, 18 Feb 2013 21:22:15 +0000 Subject: [rust-dev] possible bug in net_tcp upon socket reading Message-ID: Hi, Is this a bug or am i doing something wrong? i am calling net_tcp::listen with the following callback for new_connect_cb, and when sending data from the client through the socket, i get a ***stack smashing detected*** error. |newConn, kill_chan| { debug!("new conn"); task::spawn_sched (task::ManualThreads(1u), || { debug!("this is the spawned task running"); let mut acceptRes = net_tcp::accept(newConn); match acceptRes { result::Ok(tcpSocket) => { let socketBuf = net_tcp::socket_buf(tcpSocket); debug!("accepted connection"); socketBuf.read_byte(); debug!("read byte"); socketBuf.write(str::to_bytes("yellow")); debug!("wrote to socket"); } result::Err(_) => error!("failed to accept socket connection") }; }; What couid be the problem? Thank you. D -------------- next part -------------- An HTML attachment was scrubbed... URL: From dave at davbo.org Mon Feb 18 15:05:08 2013 From: dave at davbo.org (Dave King) Date: Mon, 18 Feb 2013 23:05:08 +0000 Subject: [rust-dev] Linking against an updated linenoise Message-ID: Hi rust folks, First up, thanks for all the work on rust I'm really enjoying getting to grips with it. I've been toying with the idea writing a simple shell in Rust and rather than link against readline I was trying out linenoise (a much smaller library) which seems to already be bundled with rust in src/rt/linenoise. I've got my rust bindings here: https://github.com/davbo/rust-linenoise/blob/master/linenoise.rs As you can see I'm getting away with using "nolink" I'm guessing that's because of the included version of linenoise. However I would like to compile against a newer version of linenoise (or at least be capable of doing so). I don't have much experience with this stuff but it feels like I'm just missing a compiler option. As you can see I'm feeling a little lost, what might my next steps be? Thanks again, -- - Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Mon Feb 18 17:47:54 2013 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 18 Feb 2013 17:47:54 -0800 Subject: [rust-dev] Misc questions In-Reply-To: <5103BDD3.9000401@ntecs.de> References: <5101C9FD.7030204@ntecs.de> <5101D3E6.7070902@mozilla.com> <5101F572.3090202@mozilla.com> <5103BDD3.9000401@ntecs.de> Message-ID: <5122D9CA.40101@mozilla.com> On 01/26/2013 03:28 AM, Michael Neumann wrote: > Am 25.01.2013 04:01, schrieb Brian Anderson: >> On 01/24/2013 04:37 PM, Patrick Walton wrote: >>> On 1/24/13 3:55 PM, Michael Neumann wrote: >>> >>>> * I don't like the way libuv is currently integrated into the >>>> system. It I've posted a pull request with a proposed redesign of the Rust scheduler that integrates the uv event loop directly: https://github.com/mozilla/rust/pull/5022 From marcianx at gmail.com Mon Feb 18 21:56:07 2013 From: marcianx at gmail.com (Ashish Myles) Date: Tue, 19 Feb 2013 00:56:07 -0500 Subject: [rust-dev] Parametrizing traits by integers (or equivalent behavior) Message-ID: Firstly, as this seems to be the only discussion mailing list for rust, I presumed that this might be a good place to ask newbie-ish questions. Please correct me if I am wrong. (I have previously played around with D, which has separate mailing lists for learners.) I am particularly interested in implementing and porting little utilities to try to get a better understanding of how well the type system supports (or gets in the way) of practical problems. I do understand rust is well in the alpha stage and I don't have any problems with rust modifications breaking my code. Secondly, I was wondering how one would go about writing a rust equivalent of the following C++ class for creating static-sized arrays interpreted as vectors. template class Vector { public: enum { N = _N }; private: T m_v[N]; }; As traits are not parametrized by integers, and macros don't seem to be the right tool for this, is there some other language feature that could help me get a similar effect? Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Mon Feb 18 22:10:24 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Mon, 18 Feb 2013 22:10:24 -0800 Subject: [rust-dev] Parametrizing traits by integers (or equivalent behavior) In-Reply-To: References: Message-ID: <51231750.3060501@mozilla.com> On 2/18/13 9:56 PM, Ashish Myles wrote: > As traits are not parametrized by integers, and macros don't seem to be > the right tool for this, is there some other language feature that could > help me get a similar effect? You need to use macros right now. There has been quite a bit of discussion of GHC-like type-level numeric literals (or just traits parameterized by constants) in the past, and that feature might make it in at some point. It's certainly a common feature request. Patrick From clements at brinckerhoff.org Tue Feb 19 11:05:12 2013 From: clements at brinckerhoff.org (John Clements) Date: Tue, 19 Feb 2013 11:05:12 -0800 Subject: [rust-dev] hygiene and module references Message-ID: <449979CE-5C58-4CCE-86F7-F5CAFD96090F@brinckerhoff.org> Okay, following up briefly on the hygiene / path discussion at the meeting. Niko asks about a macro that accepts a path element (or, more specifically, a prefix). Specifically, what about a macro that accepts the name of a module and then uses several functions defined in that module? So, for instance, suppose you want a macro that accepts the name of a module that includes map functions, and creates a new map where z is bound to 4. This may or may not work right now: macro_rules! map_z_to_4 ( ($MAPMODULE:ident) => (let new_map = $MAPMODULE::new(); $MAPMODULE::bind(~"z",4)) ) First off, I believe that currently, this will work if $MAPMODULE is a single alnum sequence, but not if it's something like "std::hashmap"? because that's not an identifier. In fact, that kind of makes my point right there :). In a solution where paths are treated as the basic hygiene element, I would expect to have to write something like this, depending on what the syntax for a capturing macro is: macro_rules! map_z_to_4 ( ($MAPMODULE:ident) => (let new_map = capture!($MAPMODULE::new()); capture!($MAPMODULE::bind)(~"z",4)) ) ? or you can imagine some other syntax. The word "capture" here may not be the right choice; the idea is that when we want to construct a reference artificially (in this case, by gluing together a module name and a variable name), that this would be explicitly called out. I should also add that in this situation, it seems like it would be more natural just to pass around an object or trait with methods, rather than using a macro at all. Does that make sense and/or seem desirable? John From banderson at mozilla.com Tue Feb 19 11:16:31 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 19 Feb 2013 11:16:31 -0800 Subject: [rust-dev] parser bug? In-Reply-To: <85869259-FC10-402A-A6BA-E448B637F17C@brinckerhoff.org> References: <85869259-FC10-402A-A6BA-E448B637F17C@brinckerhoff.org> Message-ID: <5123CF8F.70507@mozilla.com> On 02/15/2013 04:55 PM, John Clements wrote: > This program: > > pub trait MyTrait { > /// doc comment with nothing after it... > } > > ...signals the error: > > oiseau:/tmp clements> rustc --test bar.rs > bar.rs:3:0: 3:1 error: unexpected token: `}` > bar.rs:3 } > ^ > > This looks ilke a parser bug to me, but maybe it's deliberately illegal to have a doc comment with nothing after it ? > > John > It's a bit of both. It is deliberate that a doc comment (which desugars to an attribute) must precede something, but that results in crazy errors like this that confuse people. Here are some related issues about problems with doc comments: https://github.com/mozilla/rust/issues/2789 https://github.com/mozilla/rust/issues/4106 From banderson at mozilla.com Tue Feb 19 11:33:45 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 19 Feb 2013 11:33:45 -0800 Subject: [rust-dev] Linking against an updated linenoise In-Reply-To: References: Message-ID: <5123D399.80707@mozilla.com> On 02/18/2013 03:05 PM, Dave King wrote: > Hi rust folks, > > First up, thanks for all the work on rust I'm really enjoying getting > to grips with it. > > I've been toying with the idea writing a simple shell in Rust and > rather than link against readline I was trying out linenoise (a much > smaller library) which seems to already be bundled with rust in > src/rt/linenoise. > > I've got my rust bindings here: > https://github.com/davbo/rust-linenoise/blob/master/linenoise.rs > > As you can see I'm getting away with using "nolink" I'm guessing > that's because of the included version of linenoise. However I would > like to compile against a newer version of linenoise (or at least be > capable of doing so). > > I don't have much experience with this stuff but it feels like I'm > just missing a compiler option. As you can see I'm feeling a little > lost, what might my next steps be? > > Thanks again, I opened an issue about this: https://github.com/mozilla/rust/issues/5038. I don't know if there's a workaround or not. From clements at brinckerhoff.org Tue Feb 19 12:10:02 2013 From: clements at brinckerhoff.org (John Clements) Date: Tue, 19 Feb 2013 12:10:02 -0800 Subject: [rust-dev] is this a case where flow-sensitivity is needed? Message-ID: Here's the code I want to run: pub enum EnumTwo { A(uint), B(uint) } fn get_map(env: </mut EnumTwo) -> </mut uint { match *env { A (ref mut map_a) => map_a, B (ref mut map_b) => map_b } } This fails with this error: jclements-09740:/tmp clements> rustc --test ./zap.rs Running /usr/local/bin/rustc: ./zap.rs:13:11: 13:25 error: loan of enum content as mutable conflicts with prior loan ./zap.rs:13 B (ref mut map_b) => map_b ^~~~~~~~~~~~~~ ./zap.rs:12:11: 12:25 note: prior loan as mutable granted here ./zap.rs:12 A (ref mut map_a) => map_a, ^~~~~~~~~~~~~~ error: aborting due to previous error Patrick and I brainstormed on various moderately disgusting workarounds, but I couldn't find one that worked and returned a mutable borrowed pointer. I think I can see how to work around it by completely dismantling the abstraction that returns the mutable pointer. Am I missing anything ? John From zack at z0w0.me Tue Feb 19 14:13:04 2013 From: zack at z0w0.me (Zack Corr) Date: Wed, 20 Feb 2013 08:13:04 +1000 Subject: [rust-dev] Linking against an updated linenoise In-Reply-To: <5123D399.80707@mozilla.com> References: <5123D399.80707@mozilla.com> Message-ID: Isn't the solution just to not use nolink and dynamically link to a linenoise shared library? On 20/02/2013 5:33 AM, "Brian Anderson" wrote: > On 02/18/2013 03:05 PM, Dave King wrote: > >> Hi rust folks, >> >> First up, thanks for all the work on rust I'm really enjoying getting to >> grips with it. >> >> I've been toying with the idea writing a simple shell in Rust and rather >> than link against readline I was trying out linenoise (a much smaller >> library) which seems to already be bundled with rust in src/rt/linenoise. >> >> I've got my rust bindings here: https://github.com/davbo/rust-** >> linenoise/blob/master/**linenoise.rs >> >> As you can see I'm getting away with using "nolink" I'm guessing that's >> because of the included version of linenoise. However I would like to >> compile against a newer version of linenoise (or at least be capable of >> doing so). >> >> I don't have much experience with this stuff but it feels like I'm just >> missing a compiler option. As you can see I'm feeling a little lost, what >> might my next steps be? >> >> Thanks again, >> > > I opened an issue about this: https://github.com/mozilla/** > rust/issues/5038 . I don't > know if there's a workaround or not. > ______________________________**_________________ > 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 Tue Feb 19 15:13:11 2013 From: banderson at mozilla.com (Brian Anderson) Date: Tue, 19 Feb 2013 15:13:11 -0800 Subject: [rust-dev] Linking against an updated linenoise In-Reply-To: References: <5123D399.80707@mozilla.com> Message-ID: <51240707.7080406@mozilla.com> On 02/19/2013 02:13 PM, Zack Corr wrote: > > Isn't the solution just to not use nolink and dynamically link to a > linenoise shared library? > Oh. Maybe, in which case I guess you would add `#[link_args = "-llinenoise"]` to your extern block. From steven099 at gmail.com Tue Feb 19 15:18:56 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Tue, 19 Feb 2013 18:18:56 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: Okay, that makes sense. I figured it was probably just non-trivial to implement, but I figured I'd ask. Something else I was wondering about was the lack of alternation or option (0:1 repetition) syntax. I was writing a macro that would expand to a match, replacing short form patterns with their long forms, and ended up going with this: macro_rules! match_list ( ($value:expr : $( $(Cons!($v1:pat, $n1:pat) => $e1:expr)* $(MT!() => $e2:expr)* $(!$p:pat => $e3:expr)* ),* ) => (match $value { $( $(List(Some(~($v1, $n1))) => $e1)* $(List(None) => $e2)* $($p => $e3)* ),* }); ) Here I'm simulating alternation by concatenating 0:n repetitions. It happens to work in this case, since the macro will expand to a syntax error if it matches two or more arms that aren't separated by commas. Is there any plan to add alternation and option syntax to macro_rules in the future, or is simulating them with 0:n repetition seen as being sufficient? On Mon, Feb 18, 2013 at 9:23 AM, Paul Stansifer wrote: > It's just a matter of not having implemented it yet. Each new macro > invocation location unfortunately requires modifying the AST, which affects > all the code that is interested in that part of the AST. It's not a huge > amount of work, but it does inflict lots of "can't happen" error cases on > unrelated code, which is kinda sad. > > Paul > -------------- next part -------------- An HTML attachment was scrubbed... URL: From paul.stansifer at gmail.com Tue Feb 19 15:43:34 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Tue, 19 Feb 2013 18:43:34 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: Alternation already exists, at least at the outer level: macro_rules! alt_example( ( cons($e1:expr, $e2:expr) ) => ( ... ) ( mt() ) => ( ... ) ) Of course, making use of it for something other than a whole macro invocation requires the use of a helper macro, which can be tricky if the helper macro wants to be invoked somewhere that macro invocations can't yet go. There's generally some way around this sort of problem, typically involving continuation-passing-style at the macro level. Since you can't generate patterns, you'll want to generate a whole match (as you are doing), and since you want to process each arm on its own (in order to do pattern-matching), you'll want to process one at a time, accumulating your work into some sort of accumulator argument. Abusing repetition to get around this is probably equally legitimate. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From dave at davbo.org Tue Feb 19 16:28:30 2013 From: dave at davbo.org (Dave King) Date: Wed, 20 Feb 2013 00:28:30 +0000 Subject: [rust-dev] Linking against an updated linenoise In-Reply-To: <51240707.7080406@mozilla.com> References: <5123D399.80707@mozilla.com> <51240707.7080406@mozilla.com> Message-ID: Aha! That works, I added a Makefile[0] for creating the linenoise shared library and once I'd correctly set the LD_LIBRARY_PATH everything works. Clearly I must have slept through the lecture on dynamic loading and shared libraries :-) Thanks again chaps. [0] - https://github.com/davbo/rust-linenoise/blob/master/Makefile -- - Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Tue Feb 19 17:05:39 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 19 Feb 2013 17:05:39 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions Message-ID: <51242163.4040100@mozilla.com> Hi, We've recently replaced the cargo package manager with a new (very young) tool called rustpkg; in the process it's (temporarily) broken most of the packages installable through cargo, but we'll be fixing this up before the next release. The main new feature of rustpkg is that it permits writing custom build logic (and custom build tasks) in rust itself, as an escape hatch: if there's a file called pkg.rs in a package repository it is compiled, linked against rustpkg itself and run for various tasks. That's a nice feature and all, but we don't want to force (or even _suggest_) use of the escape hatch by default. We'd like rustpkg to do most things by inferring-sensible-defaults when looking at a repository. In particular, building all the most obvious / findable binary and library crates contained therein, based on simple rules. Preferably rules that don't require parsing all the files in the repo and sorting them into a module-graph just to figure out the targets. There might be a lot of files (cf. src/test/run-pass/*.rs) The simplest rule I've come up with is based on a convention for chosen filenames and their immediately-containing dir names. Specifically the names "lib.rs" for libraries and "bin.rs" for binaries: foo/lib.rs ==> build libfoo-.so / .dll, a library foo/bin.rs ==> build foo / foo.exe, an executable This is a convention that'll require a certain amount of reorganization to existing code, but it permits multi-library / multi-binary packages in a single source repo, which is an important use-case. Lots of time people want >1 crate in the same git tree. Moreover it makes for a pretty simple naming heuristic that can be derived directly from URL-path-fragment package identifiers, such that: extern mod foo (id = "github.com/graydon/foo"); will pick up a single-library package, assuming there's a single file lib.rs in that repo, and give it the name libfoo-.so, because 'foo' is the immediate parent-dir of the lib.rs file. Whereas: extern mod foo (id = "github.com/graydon/foo/thing"); will look for a thing/lib.rs dir-and-stem inside the github.com/graydon/foo repo, and build-and-link _that_ into libthing-.so. This should also permit mapping such identifiers to filesystem paths in GOPATH-like workspaces, permitting local workspaces overlaid on global ones and branching (via your VCS -- it does versions!) inside local workspaces and whatnot. In case it's not clear from the sketch here, it's very similar to what Go does -- I think they did a very tidy job and I'm interested in copying its good parts. It feels like we didn't quite hit the mark with cargo and this is an important thing to get right. That said, I'm interested in some feedback before we get too far into it, to make sure we aren't making serious mistakes or missing issues that people feel are unpleasant about URL-centric schemes. Any thoughts? Notes on other failure modes in package managers? Requests for ponies? I'd prefer specificity in response, if you can manage it. We all know package management is "generally miserable", but if you can describe _exactly_ how things go wrong in other systems and what we should be trying to avoid, or aiming for, that'd be good. Thanks, -Graydon From graydon at mozilla.com Tue Feb 19 17:11:28 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 19 Feb 2013 17:11:28 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <51242163.4040100@mozilla.com> References: <51242163.4040100@mozilla.com> Message-ID: <512422C0.5000004@mozilla.com> On 13-02-19 05:05 PM, Graydon Hoare wrote: > In particular, building all the most obvious / findable binary and > library crates contained therein, based on simple rules. Oh, I should also mention: we don't want to use the .rs / .rc distinction, rather we'd like to finish deprecating .rc as a suffix since that seems to have been a poor choice, colliding with several zillion lines of code in not-at-all-rust languages and making us fight over syntax highlighting modes and such. -Graydon From graydon at mozilla.com Tue Feb 19 18:09:48 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 19 Feb 2013 18:09:48 -0800 Subject: [rust-dev] Misc questions In-Reply-To: <5122D9CA.40101@mozilla.com> References: <5101C9FD.7030204@ntecs.de> <5101D3E6.7070902@mozilla.com> <5101F572.3090202@mozilla.com> <5103BDD3.9000401@ntecs.de> <5122D9CA.40101@mozilla.com> Message-ID: <5124306C.2070200@mozilla.com> On 18/02/2013 5:47 PM, Brian Anderson wrote: > I've posted a pull request with a proposed redesign of the Rust > scheduler that integrates the uv event loop directly: > https://github.com/mozilla/rust/pull/5022 This is fantastic. Thank you so much for taking the lead on this; it's obviously early code but it looks like it's headed in a very positive direction. (Huge smile reading initialize_call_frame in rust. Whee!) -Graydon From steven099 at gmail.com Tue Feb 19 21:58:46 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Wed, 20 Feb 2013 00:58:46 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: On Tue, Feb 19, 2013 at 6:43 PM, Paul Stansifer wrote: > Alternation already exists, at least at the outer level: > > macro_rules! alt_example( > ( cons($e1:expr, $e2:expr) ) => ( ... ) > ( mt() ) => ( ... ) > ) > > Of course, making use of it for something other than a whole macro > invocation requires the use of a helper macro, which can be tricky if the > helper macro wants to be invoked somewhere that macro invocations can't yet > go. > > There's generally some way around this sort of problem, typically > involving continuation-passing-style at the macro level. Since you can't > generate patterns, you'll want to generate a whole match (as you are > doing), and since you want to process each arm on its own (in order to do > pattern-matching), you'll want to process one at a time, accumulating your > work into some sort of accumulator argument. > One thing this does is force all the alternatives to follow the same form so that they can be matched by the same matcher, which isn't always desirable. Also, I ran into something I can't explain trying to use this approach. This works: macro_rules! make_vec( ($($n:ident),*) => (make_vec_rec!($($n),* :)); ) macro_rules! make_vec_rec( (a $(,$n1:ident)* : $($n2:expr),*) => (make_vec_rec!($($n1),* : $($n2,)* 1)); (b $(,$n1:ident)* : $($n2:expr),*) => (make_vec_rec!($($n1),* : $($n2,)* 2)); (: $($n2:expr),*) => ([$($n2),*]); ) But this is ambiguous: macro_rules! make_vec( ($($n:ident),*) => (make_vec_rec!(($($n),*)())); ) macro_rules! make_vec_rec( ((a $(,$n1:ident)*)($($n2:expr),*)) => (make_vec_rec!(($($n1),*)($($n2,)* 1))); ((b $(,$n1:ident)*)($($n2:expr),*)) => (make_vec_rec!(($($n1),*)($($n2,)* 2))); (()($($n2:expr),*)) => ([$($n2),*]); ) Documents/test.rs:85:45: 85:46 error: Local ambiguity: multiple parsing options: built-in NTs expr (' n2') or 1 other options. Documents/test.rs:85 ($($n:ident),*) => (make_vec_rec!(($($n),*)())); (`^` pointing at `()`) Any idea why? () could be considered an expression, but it's not in an expression position, and a lot of things could be considered expressions and don't do this. Abusing repetition to get around this is probably equally legitimate > My only concern would be whether there are cases where this abuse causes unexpected behaviour rather than a syntax error when given incorrect input, though I can't think of any off the top of my head. -------------- next part -------------- An HTML attachment was scrubbed... URL: From sh4.seo at samsung.com Wed Feb 20 01:15:29 2013 From: sh4.seo at samsung.com (Sanghyeon Seo) Date: Wed, 20 Feb 2013 09:15:29 +0000 (GMT) Subject: [rust-dev] RFC: Bless mod.rs Message-ID: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> rustc.rc has: #[path = "metadata/mod.rs"] pub mod metadata; #[path = "driver/mod.rs"] pub mod driver; I think this should be the default. "mod" is a keyword anyway. What do you think? From zack at z0w0.me Wed Feb 20 01:53:07 2013 From: zack at z0w0.me (Zack Corr) Date: Wed, 20 Feb 2013 19:53:07 +1000 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <512422C0.5000004@mozilla.com> References: <51242163.4040100@mozilla.com> <512422C0.5000004@mozilla.com> Message-ID: I agree with pretty much everything you've said. The bin.rs/lib.rs thing sounds good to me - would it walk into all sub directories to find crates, with inner crates being built first? Also IMO, as the person that chose the name pkg.rs for the build script file, I think you should change it to something like build.rs. I chose pkg.rs because it would always be required to define a package - this new scheme will not require a central metadata file. The awesome thing about the new scheme is it still works as a purely functional package manager - library crates already work like that and we can continue to use the same logic that the current rustpkg scheme does to create a unique hash for binaries - just parse their link attribute and generate a unique name in the exact same fashion as libraries. This new scheme will simplify things greatly, which is awesome. For example, packages will be a word we never need to say again (sans the title "package manager" of course) as this will just make installing from a location just install a set of crates. Preferring and other functionality will now act on the installed crates themselves rather than the packages as a unit. I think we should try and figure out a way to remove the declarative API from the pkg.rs file. If we can just make the pkg.rs have the imperative API, that would simplify things even further. All that we need to move in that direction is a way to declare configuration to both about-to-be-built crates, and dependencies of crates. Currently (N.B. you can't actually do this yet, it was a planned patch) you declare configuration of dependencies like `#[pkg_dep(url = "git://github.com/brson/rust-sdl", cfg = "image mixer")];`. However, that only declares configuration to the pkg.rs script and not the crate files themselves. I think if we make `rustpkg build --cfg hello` pass the config flag to all crates being built (excluding their dependencies), `extern mod sdl(id = "github.com/brson/rust-sdl", cfg = "image mixer");` pass config flags to the dependency (N.B. the preferred way to do this would of course have a separate image and mixer crates in the same repo - a cool new capability - but it's just for example purposes) then we can make pkg.rs (or build.rs) only be needed for imperative things, such as compiling C code. The closer we can get to the build.rs being a real source file that can be compiled and run straight using rustc the better - that'll make Brian happy. Also, I'd like to start working on this. Is that OK or are you already looking into this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From deansherthompson at gmail.com Wed Feb 20 05:50:06 2013 From: deansherthompson at gmail.com (Dean Thompson) Date: Wed, 20 Feb 2013 05:50:06 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <51242163.4040100@mozilla.com> Message-ID: After using sbt (http://www.scala-sbt.org/) extensively, I have become quite uncomfortable with compiled languages that use themselves as their build automation language. Sbt is the primary Scala build tool, and uses Scala as its build automation language. The appeal is obvious: Rust is the only language we know for certain is available on the machine, and also the only language we know that the programmer knows and can presume they like. However, in my experience with sbt, I have seen many problems with this model. (Perhaps others on this list know recursive-build environments where these problems have been avoided?) ** How is the build automation code compiled? If (as envisioned here so far) it can only be compiled using the default compilation rules, that is a huge simplification. However, over time it likely will not suffice. Builds can become legitimately complex (such as source generation tools, multiple languages, and preprocessed resources). Over time, many off-the-shelf build automation components are created (for example, here's a list of Ant tasks: https://ant.apache.org/manual/tasksoverview.html). If a project's build automation is too complex to be compiled with the default compilation rules, then what? Sbt's approach (perhaps inevitable) is to allow a subproject containing the build automation for compiling the build automation. And, of course, you might need a sub-subproject for compiling that. As the sbt documentation puts it, "the turtles go all the way down" (http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html). In my experience with sbt, even having the initial build-automation subproject becomes a brain-twister when problems occur. ** How are errors in the build automation reported and diagnosed? One characteristic I have often seen with sbt is that, when you make a mistake coding your build automation, the build system can't function well enough to give you good diagnostics. For example, sbt often can't display a dependency tree until you straighten out your dependencies. ** What is the interactive experience? It is extremely useful in a build system to be able to poke around by hand -- manually executing tasks and inspecting state. Sbt has a very well-developed, and in many ways quite nice, interactive environment for this. However, that environment has an uneasy relationship with the Scala code that is the true underlying build automation, since it isn't natural to type Scala code interactively. ** Is the target language really a natural build automation language? In Scala's case, having spent much time with sbt, I don't feel Scala is the language I would choose for writing build automation. Although I am a fan of statically typed languages for many purposes, they don't seem to come into their own in short scripts that are centered around manipulating text and the filesystem. * Alternative suggestion Here's what I said was appealing about using Rust as its own build automation language: "Rust is the only language we know for certain is available on the machine, and also the only language we know that the programmer knows and can presume they like." How close can we come to these benefits without using Rust as its own build automation language? We could address the first issue, "Rust is the only language we know for certain is available on the machine", either by choosing a language with a compact enough interpreter for us to embed in the Rust tooling, or at least by choosing a language that is almost universally available. We could mitigate the second issue, "the only language we know that the programmer knows and can presume they like", by trying to pick a language that is generally popular among frustrated C++ programmers, and at least that is easy to learn. At any rate, we would want to pick a language that is very convenient and comfortable for manipulating the filesystem. Also, we would like one that is natural to use interactively. My suggestion: Python. Dean On 2/19/13 5:05 PM, "Graydon Hoare" wrote: >Hi, > >We've recently replaced the cargo package manager with a new (very >young) tool called rustpkg; in the process it's (temporarily) broken >most of the packages installable through cargo, but we'll be fixing this >up before the next release. > >The main new feature of rustpkg is that it permits writing custom build >logic (and custom build tasks) in rust itself, as an escape hatch: if >there's a file called pkg.rs in a package repository it is compiled, >linked against rustpkg itself and run for various tasks. > >That's a nice feature and all, but we don't want to force (or even >_suggest_) use of the escape hatch by default. We'd like rustpkg to do >most things by inferring-sensible-defaults when looking at a repository. >In particular, building all the most obvious / findable binary and >library crates contained therein, based on simple rules. Preferably >rules that don't require parsing all the files in the repo and sorting >them into a module-graph just to figure out the targets. There might be >a lot of files (cf. src/test/run-pass/*.rs) > >The simplest rule I've come up with is based on a convention for chosen >filenames and their immediately-containing dir names. Specifically the >names "lib.rs" for libraries and "bin.rs" for binaries: > > foo/lib.rs ==> build libfoo-.so / .dll, a library > foo/bin.rs ==> build foo / foo.exe, an executable > >This is a convention that'll require a certain amount of reorganization >to existing code, but it permits multi-library / multi-binary packages >in a single source repo, which is an important use-case. Lots of time >people want >1 crate in the same git tree. Moreover it makes for a >pretty simple naming heuristic that can be derived directly from >URL-path-fragment package identifiers, such that: > > extern mod foo (id = "github.com/graydon/foo"); > >will pick up a single-library package, assuming there's a single file >lib.rs in that repo, and give it the name libfoo-.so, because >'foo' is the immediate parent-dir of the lib.rs file. Whereas: > > extern mod foo (id = "github.com/graydon/foo/thing"); > >will look for a thing/lib.rs dir-and-stem inside the >github.com/graydon/foo repo, and build-and-link _that_ into >libthing-.so. > >This should also permit mapping such identifiers to filesystem paths in >GOPATH-like workspaces, permitting local workspaces overlaid on global >ones and branching (via your VCS -- it does versions!) inside local >workspaces and whatnot. In case it's not clear from the sketch here, >it's very similar to what Go does -- I think they did a very tidy job >and I'm interested in copying its good parts. It feels like we didn't >quite hit the mark with cargo and this is an important thing to get right. > >That said, I'm interested in some feedback before we get too far into >it, to make sure we aren't making serious mistakes or missing issues >that people feel are unpleasant about URL-centric schemes. > >Any thoughts? Notes on other failure modes in package managers? Requests >for ponies? I'd prefer specificity in response, if you can manage it. We >all know package management is "generally miserable", but if you can >describe _exactly_ how things go wrong in other systems and what we >should be trying to avoid, or aiming for, that'd be good. > >Thanks, > >-Graydon >_______________________________________________ >Rust-dev mailing list >Rust-dev at mozilla.org >https://mail.mozilla.org/listinfo/rust-dev From dpc at ucore.info Wed Feb 20 07:31:08 2013 From: dpc at ucore.info (dpc at ucore.info) Date: Wed, 20 Feb 2013 16:31:08 +0100 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: References: <51242163.4040100@mozilla.com> Message-ID: On Wed, Feb 20, 2013 at 2:50 PM, Dean Thompson wrote: > > My suggestion: Python. > Please. Not Python. Everything but not this. I admit: I hate Python with passion, so I may be biased. I hate not so much the language itself but all it's tooling and constant problems with it and people constantly putting it everywhere because the only language they grasp or assume everyone else should know it to. (No intention to offend the original poster, it's just a fact of life that Python is quite easy to learn and university courses often pick it and ,,when hammer is all you got, everything looks like a nail''. In 2011, I've spent 2 weeks rewritting (removing or decoupling, really) the `scons`-based build system that was meant to be "flexible, powerful, fast, easy to use, with interactive features, etc.". An in reality it was unmaintenable, complex, big and slow and the 3rd-party components used to build it were becoming abandoned. Python : * Is not designed for handling dependencies from groundup like eg. `make`. So it needs some custom foundation code to handle it, probably with 3rd party dependencies. * Is not really efficient for gluing external tools like shell scripts are. * Is not solid (things break in runtime, and many times just because newer minor Python version came out). * It's not providing support for ancient tools like autotools, neither Rust needs this, as there will be no legacy software using Rust yet. Besides I don't understand why normal projects in Rust would require anything more to be built other than: rustc main.rs or something similarly simple. As long as Rust building system support the mentioned "escape hatch", with complex project people will be able to build using any complex logic they like, written in any language, using any 3rd-party software they choose. For 99.9% mainstream projects though any simple solution will be fine, and the less potential problems and dependencies it introduces, the best for all of us. Imagine the scenario: "Why did this Rust package failed to build? Some weird Python error... . Should I use different version of Python? Which one: 1.x, 2.5, 2.6, 2.7, 3.x, 4.x, 5.x ? Because programs breaks randomly (in runtime!) between Python versions. Must I use `virtualenv` (or what's the current/best version of this idea ATM)? Are all the pips installed and configured correctly? Maybe one of these many funny python environment varibles is wrong for some reason... ?" So let's not import Pythons problems into Rust world. Regards, -- Dawid Ci??arkiewicz From deansherthompson at gmail.com Wed Feb 20 07:46:46 2013 From: deansherthompson at gmail.com (Dean Thompson) Date: Wed, 20 Feb 2013 07:46:46 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: Message-ID: :-) Ok -- that's quite a convincing argument against Python! My experience with it is casual. However, I still believe the following: - Rust should have a standard build tool that is able to handle complex cases. - This build tool needs a programming language. - This programming language should not be Rust (to avoid the complexity of recursive builds) and indeed should be interpreted. Any similarly convincing arguments against those beliefs? Dean On 2/20/13 7:31 AM, "dpc at ucore.info" wrote: >On Wed, Feb 20, 2013 at 2:50 PM, Dean Thompson > wrote: >> >> My suggestion: Python. >> > >Please. Not Python. Everything but not this. > >I admit: I hate Python with passion, so I may be biased. I hate not so >much the language itself but all it's tooling and constant problems >with it and people constantly putting it everywhere because the only >language they grasp or assume everyone else should know it to. (No >intention to offend the original poster, it's just a fact of life that >Python is quite easy to learn and university courses often pick it and >,,when hammer is all you got, everything looks like a nail''. > >In 2011, I've spent 2 weeks rewritting (removing or decoupling, >really) the `scons`-based build system that was meant to be "flexible, >powerful, fast, easy to use, with interactive features, etc.". An in >reality it was unmaintenable, complex, big and slow and the 3rd-party >components used to build it were becoming abandoned. > >Python : > >* Is not designed for handling dependencies from groundup like eg. >`make`. So it needs some custom foundation code to handle it, probably >with 3rd party dependencies. >* Is not really efficient for gluing external tools like shell scripts >are. >* Is not solid (things break in runtime, and many times just because >newer minor Python version came out). >* It's not providing support for ancient tools like autotools, neither >Rust needs this, as there will be no legacy software using Rust yet. > > >Besides I don't understand why normal projects in Rust would require >anything more to be built other than: > >rustc main.rs > >or something similarly simple. > >As long as Rust building system support the mentioned "escape hatch", >with complex project people will be able to build using any complex >logic they like, written in any language, using any 3rd-party software >they choose. For 99.9% mainstream projects though any simple solution >will be fine, and the less potential problems and dependencies it >introduces, the best for all of us. > >Imagine the scenario: > >"Why did this Rust package failed to build? Some weird Python error... >. Should I use different version of Python? Which one: 1.x, 2.5, 2.6, >2.7, 3.x, 4.x, 5.x ? Because programs breaks randomly (in runtime!) >between Python versions. Must I use `virtualenv` (or what's the >current/best version of this idea ATM)? Are all the pips installed and >configured correctly? Maybe one of these many funny python environment >varibles is wrong for some reason... ?" > >So let's not import Pythons problems into Rust world. > >Regards, >-- >Dawid Ci??arkiewicz From benoit.j.girard at agaguk.net Wed Feb 20 08:20:13 2013 From: benoit.j.girard at agaguk.net (Benoit Jauvin-Girard) Date: Wed, 20 Feb 2013 11:20:13 -0500 Subject: [rust-dev] Dynamic loading and unloading of crates. In-Reply-To: References: Message-ID: Greetings all, Is there any word on wether Rust will support the dynamic loading and unloading of crates at runtime? If so, any documentation as to what's planned? I could not find anything concrete in the rust-dev archives or in the manual. If I missed some existing document, please just point me in the right direction. -- Benoit. From jack at metajack.im Wed Feb 20 08:39:33 2013 From: jack at metajack.im (Jack Moffitt) Date: Wed, 20 Feb 2013 09:39:33 -0700 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: References: Message-ID: > - This build tool needs a programming language. > > - This programming language should not be Rust (to avoid the complexity of > recursive builds) and indeed should be interpreted. > > Any similarly convincing arguments against those beliefs? I haven't used the go tool much, but I have used both Leiningen and Rebar (Clojure and Erlang build tools respectively), and they are two of the more pleasant things I've ever used. Neither of them supports direct programming like scons, but both are extensible through easy to write simple plugins. Rebar especially works pretty much out of the box with no special configuration needed for the large majority of Erlang projects. Both rebar and lein also work reasonably well building platform code (Java in lein's case or C in rebar's). I think this is an existence proof that you don't need full language power in the majority of cases, even moderately complicated ones. Also, in those build systems, it is quite common for complicated builds to drop to something else. For example, for building non-OTP apps in Erlang, many people use regular makefiles. In Clojure-land, using maven is also common. It sounds like rustpkg will work similarly, and if anything really complex is required, it's easy to switch to make or cmake, etc. I've seen pretty much nothing but praise for the go toolchain, so I think rustpkg is on the right track. I would like to mention that JARs in clojure-land are very useful. Erlang also has ez packages, but these are a bit restrictive in the types of data they contain, so aren't quite as nice. This makes shipping around and deploying things really simple. Specifically, it is often useful to include non-code resources in these artifacts which are easily accessible from the library consumer. Clojure has clojure.java.io/resource to pick these up, and Erlang has a slightly more verbose but similar way to do the same. Perhaps it would be possible to incorporate something similar into Rust's build tooling. jack. From lucab at debian.org Wed Feb 20 09:04:07 2013 From: lucab at debian.org (Luca BRUNO) Date: Wed, 20 Feb 2013 18:04:07 +0100 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <51242163.4040100@mozilla.com> References: <51242163.4040100@mozilla.com> Message-ID: <20130220180407.19b69b15@debian.org> Graydon Hoare scrisse: > This should also permit mapping such identifiers to filesystem paths > in GOPATH-like workspaces, permitting local workspaces overlaid on > global ones and branching (via your VCS -- it does versions!) inside > local workspaces and whatnot. In case it's not clear from the sketch > here, it's very similar to what Go does -- I think they did a very > tidy job and I'm interested in copying its good parts. It feels like > we didn't quite hit the mark with cargo and this is an important > thing to get right. > > That said, I'm interested in some feedback before we get too far into > it, to make sure we aren't making serious mistakes or missing issues > that people feel are unpleasant about URL-centric schemes. > > Any thoughts? Notes on other failure modes in package managers? > Requests for ponies? I'd prefer specificity in response, if you can > manage it. We all know package management is "generally miserable", > but if you can describe _exactly_ how things go wrong in other > systems and what we should be trying to avoid, or aiming for, that'd > be good. There are many good points in this proposal, the sensible-defaults and the plugin escape-hatch are the foremost. However, there are some (to my eyes) pitfalls here and more notably in the GO way that are not really comfortable for me, so I'd like to chime in. As we are talking about a package manager, I'd like to have it more focused on building system-integrated overlays over than replacing common package management. Having to handle N local big-workspaces vs. a central system plus minimal overlays may be cumbersome, eg. in a typical high-rush security push. System package managers also handles many subtitles (like enforcing signatures and checksums checks, handling conflicts, managing inter-languages/FFI dependencies, running privileged triggers, update system-wide caches) which I'd like to retain and not re-implement, side-by-side with local rustpkg overlay handling. With your URL-proposal and Zack's related mail, I got some taste of "screw versioning and API/ABI contracts" or "let's deploy everything locally out of github", which I fear may hurt in the long term on the manageability, maintenance and scaling side. I clearly see the benefits for devs of this proposed model, but I hope long-term ops won't be sacrificed for that. I may be biased and may have missed some rust-peculiar points, but I feel more confident with a model where package archives and package managers are not too coupled and can gracefully cohabit alongside with system-wide packages, over a "let's keep everything local and static" ?-la GO. Cheers, Luca -- .''`. | ~<[ Luca BRUNO ~ (kaeso) ]>~ : :' : | Email: lucab (AT) debian.org ~ Debian Developer `. `'` | GPG Key ID: 0x3BFB9FB3 ~ Free Software supporter `- | HAM-radio callsign: IZ1WGT ~ Networking sorcerer -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From paul.stansifer at gmail.com Wed Feb 20 09:08:20 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Wed, 20 Feb 2013 12:08:20 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: > Any idea why? () could be considered an expression, but it's not in an > expression position, and a lot of things could be considered expressions > and don't do this. > The local ambiguity errors exist for the internal reason that the Rust parser `fail`s (I guess now it `die!`s) when it gets a parse error. Therefore, the macro system refuses to start parsing a nonterminal (in this case, expr), unless it can conclusively rule out all other options (in this case, I think, the token ")", which occurs if there are 0 exprs in that sequence), using one character of lookahead. And it isn't aware what nonterminals can and can't start with, so the fact that ")" isn't the beginning of an expression isn't useful to it (hm. It'd be a bit of a hack, since we'd need to manually generate a table of acceptable start tokens, but maybe adding that feature would make macro writing easier.). The general solution is to make sure that the first thing inside a `$(...)*` isn't a `$name:nt`. I think the macro tutorial (or possible the reference guide) may have more information. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.striegel at gmail.com Wed Feb 20 09:25:15 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Wed, 20 Feb 2013 12:25:15 -0500 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: References: <51242163.4040100@mozilla.com> Message-ID: I think it would be useful to address all of these points with real examples and see if we can come up with solutions if Rust is currently falling short. For instance, in the imperative API, running external programs is *really* hideously ugly right now (by the end of the day I'll have submitted a pull request to try and address this). On Wed, Feb 20, 2013 at 8:50 AM, Dean Thompson wrote: > After using sbt (http://www.scala-sbt.org/) extensively, I have become > quite uncomfortable with compiled languages that use themselves as their > build automation language. Sbt is the primary Scala build tool, and uses > Scala as its build automation language. > > The appeal is obvious: Rust is the only language we know for certain is > available on the machine, and also the only language we know that the > programmer knows and can presume they like. > > However, in my experience with sbt, I have seen many problems with this > model. (Perhaps others on this list know recursive-build environments > where these problems have been avoided?) > > ** How is the build automation code compiled? > > If (as envisioned here so far) it can only be compiled using the default > compilation rules, that is a huge simplification. However, over time it > likely will not suffice. Builds can become legitimately complex (such as > source generation tools, multiple languages, and preprocessed resources). > Over time, many off-the-shelf build automation components are created (for > example, here's a list of Ant tasks: > https://ant.apache.org/manual/tasksoverview.html). > > If a project's build automation is too complex to be compiled with the > default compilation rules, then what? Sbt's approach (perhaps inevitable) > is to allow a subproject containing the build automation for compiling the > build automation. And, of course, you might need a sub-subproject for > compiling that. As the sbt documentation puts it, "the turtles go all the > way down" > (http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html). In > my experience with sbt, even having the initial build-automation > subproject becomes a brain-twister when problems occur. > > ** How are errors in the build automation reported and diagnosed? > > One characteristic I have often seen with sbt is that, when you make a > mistake coding your build automation, the build system can't function well > enough to give you good diagnostics. For example, sbt often can't display > a dependency tree until you straighten out your dependencies. > > ** What is the interactive experience? > > It is extremely useful in a build system to be able to poke around by hand > -- manually executing tasks and inspecting state. Sbt has a very > well-developed, and in many ways quite nice, interactive environment for > this. However, that environment has an uneasy relationship with the Scala > code that is the true underlying build automation, since it isn't natural > to type Scala code interactively. > > ** Is the target language really a natural build automation language? > > In Scala's case, having spent much time with sbt, I don't feel Scala is > the language I would choose for writing build automation. Although I am a > fan of statically typed languages for many purposes, they don't seem to > come into their own in short scripts that are centered around manipulating > text and the filesystem. > > * Alternative suggestion > > Here's what I said was appealing about using Rust as its own build > automation language: "Rust is the only language we know for certain is > available on the machine, and also the only language we know that the > programmer knows and can presume they like." How close can we come to > these benefits without using Rust as its own build automation language? > > We could address the first issue, "Rust is the only language we know for > certain is available on the machine", either by choosing a language with a > compact enough interpreter for us to embed in the Rust tooling, or at > least by choosing a language that is almost universally available. > > We could mitigate the second issue, "the only language we know that the > programmer knows and can presume they like", by trying to pick a language > that is generally popular among frustrated C++ programmers, and at least > that is easy to learn. > > At any rate, we would want to pick a language that is very convenient and > comfortable for manipulating the filesystem. Also, we would like one that > is natural to use interactively. > > My suggestion: Python. > > Dean > > > On 2/19/13 5:05 PM, "Graydon Hoare" wrote: > > >Hi, > > > >We've recently replaced the cargo package manager with a new (very > >young) tool called rustpkg; in the process it's (temporarily) broken > >most of the packages installable through cargo, but we'll be fixing this > >up before the next release. > > > >The main new feature of rustpkg is that it permits writing custom build > >logic (and custom build tasks) in rust itself, as an escape hatch: if > >there's a file called pkg.rs in a package repository it is compiled, > >linked against rustpkg itself and run for various tasks. > > > >That's a nice feature and all, but we don't want to force (or even > >_suggest_) use of the escape hatch by default. We'd like rustpkg to do > >most things by inferring-sensible-defaults when looking at a repository. > >In particular, building all the most obvious / findable binary and > >library crates contained therein, based on simple rules. Preferably > >rules that don't require parsing all the files in the repo and sorting > >them into a module-graph just to figure out the targets. There might be > >a lot of files (cf. src/test/run-pass/*.rs) > > > >The simplest rule I've come up with is based on a convention for chosen > >filenames and their immediately-containing dir names. Specifically the > >names "lib.rs" for libraries and "bin.rs" for binaries: > > > > foo/lib.rs ==> build libfoo-.so / .dll, a library > > foo/bin.rs ==> build foo / foo.exe, an executable > > > >This is a convention that'll require a certain amount of reorganization > >to existing code, but it permits multi-library / multi-binary packages > >in a single source repo, which is an important use-case. Lots of time > >people want >1 crate in the same git tree. Moreover it makes for a > >pretty simple naming heuristic that can be derived directly from > >URL-path-fragment package identifiers, such that: > > > > extern mod foo (id = "github.com/graydon/foo"); > > > >will pick up a single-library package, assuming there's a single file > >lib.rs in that repo, and give it the name libfoo-.so, because > >'foo' is the immediate parent-dir of the lib.rs file. Whereas: > > > > extern mod foo (id = "github.com/graydon/foo/thing"); > > > >will look for a thing/lib.rs dir-and-stem inside the > >github.com/graydon/foo repo, and build-and-link _that_ into > >libthing-.so. > > > >This should also permit mapping such identifiers to filesystem paths in > >GOPATH-like workspaces, permitting local workspaces overlaid on global > >ones and branching (via your VCS -- it does versions!) inside local > >workspaces and whatnot. In case it's not clear from the sketch here, > >it's very similar to what Go does -- I think they did a very tidy job > >and I'm interested in copying its good parts. It feels like we didn't > >quite hit the mark with cargo and this is an important thing to get right. > > > >That said, I'm interested in some feedback before we get too far into > >it, to make sure we aren't making serious mistakes or missing issues > >that people feel are unpleasant about URL-centric schemes. > > > >Any thoughts? Notes on other failure modes in package managers? Requests > >for ponies? I'd prefer specificity in response, if you can manage it. We > >all know package management is "generally miserable", but if you can > >describe _exactly_ how things go wrong in other systems and what we > >should be trying to avoid, or aiming for, that'd be good. > > > >Thanks, > > > >-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 graydon at mozilla.com Wed Feb 20 10:15:38 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 20 Feb 2013 10:15:38 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: References: Message-ID: <512512CA.9090400@mozilla.com> On 20/02/2013 5:50 AM, Dean Thompson wrote: > The appeal is obvious: Rust is the only language we know for certain is > available on the machine, and also the only language we know that the > programmer knows and can presume they like. Hm. Ok, I didn't really want to turn this into a language discussion, but if it's going that way: I don't especially care if users _like_ it as a build language. Writing "build logic" code is always an unpleasant concession. The argument for "use rust" is merely that it's sufficiently powerful, under our control, and we know we have the tool at hand. Adding another tool adds another very complex moving part (under some other party's control) to a delicate process we're trying to standardize and simplify. Keep in mind, this is for escape-hatch-use only. We have a rule in tooling rustc that "any command-line flag you have to pass to make something compile should be expressible in-source as an attribute". Most crates should compile most of the time as "rustc .rs". That's currently often true and we're aiming to make it more commonly true as we flesh out the dependency logic. I want the same sort of rule to apply here: most packages should build by inference-rules 99% of the time; pkg.rs is the 'unsafe { ... }' block of build automation. We'll try to discourage its use however possible (maybe only offer auto-build service to people who don't use it?) > However, in my experience with sbt, I have seen many problems with this > model. (Perhaps others on this list know recursive-build environments > where these problems have been avoided?) > > ** How is the build automation code compiled? > > If (as envisioned here so far) it can only be compiled using the default > compilation rules, that is a huge simplification. I think you're conflating issues. If the "default compilation rules" involve "potentially resolving extern-mod and syntax-extension dependencies of pkg.rs itself", then it's no simplification at all. It's exactly the "turtles all the way down" scenario you describe in sbt. Which, while undesirable as a general occurrence -- I will probably cry a bit the first time I see it happen -- is (as far as I can see) the _simplest_ form of escape-hatch-within-an-escape-hatch possible. Which I hope to be a 1% sub-case within the 1% we're already discussing. The other recursive escape hatch, if you want to go sideways, is: run::run_command(["python", "my_pythonic_stack_of_turtles.py"]) but good luck diagnosing the virtualenv, pip, easy_install, distribute and such errors emerging from that, mid-build. Python's versioning and packaging problems are worse than ours; they have a legacy of incompatible attempts to fight. We at least have few enough past experiments that we can clean them all up and pretend we're at a blank slate. IMO there's no real easy way out from an over-complex build aside from "don't make over-complex builds". We should do everything we can to discourage byzantine build logic: make things work via less-expressive but automatic defaults whenever possible, and factor anything we see cropping up in "custom rules" into default inferrable behavior. We added pkg.rs only because people are currently writing make-and-sh logic and git submodule forests, which is worse, and harder to factor. (I do agree we should be providing a better repl and shell-library experience out of the box in rust. I don't think that's an argument to change languages though. Fixing those problems is far less work.) -Graydon From deansherthompson at gmail.com Wed Feb 20 10:59:29 2013 From: deansherthompson at gmail.com (Dean Thompson) Date: Wed, 20 Feb 2013 10:59:29 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <512512CA.9090400@mozilla.com> Message-ID: Ok -- makes sense. Having been through the sbt pain of Scala-built-by-Scala, I'll watch as Rust's tooling evolves and try to be alert in mentioning patterns that went badly in sbt. Hopefully others have positive experiences with Xyz-built-by-Xyz, and can mention patterns that help. Dean On 2/20/13 10:15 AM, "Graydon Hoare" wrote: >On 20/02/2013 5:50 AM, Dean Thompson wrote: >> The appeal is obvious: Rust is the only language we know for certain is >> available on the machine, and also the only language we know that the >> programmer knows and can presume they like. > >Hm. Ok, I didn't really want to turn this into a language discussion, >but if it's going that way: I don't especially care if users _like_ it >as a build language. Writing "build logic" code is always an unpleasant >concession. The argument for "use rust" is merely that it's sufficiently >powerful, under our control, and we know we have the tool at hand. >Adding another tool adds another very complex moving part (under some >other party's control) to a delicate process we're trying to standardize >and simplify. > >Keep in mind, this is for escape-hatch-use only. We have a rule in >tooling rustc that "any command-line flag you have to pass to make >something compile should be expressible in-source as an attribute". Most >crates should compile most of the time as "rustc .rs". That's >currently often true and we're aiming to make it more commonly true as >we flesh out the dependency logic. > >I want the same sort of rule to apply here: most packages should build >by inference-rules 99% of the time; pkg.rs is the 'unsafe { ... }' block >of build automation. We'll try to discourage its use however possible >(maybe only offer auto-build service to people who don't use it?) > >> However, in my experience with sbt, I have seen many problems with this >> model. (Perhaps others on this list know recursive-build environments >> where these problems have been avoided?) >> >> ** How is the build automation code compiled? >> >> If (as envisioned here so far) it can only be compiled using the default >> compilation rules, that is a huge simplification. > >I think you're conflating issues. If the "default compilation rules" >involve "potentially resolving extern-mod and syntax-extension >dependencies of pkg.rs itself", then it's no simplification at all. It's >exactly the "turtles all the way down" scenario you describe in sbt. >Which, while undesirable as a general occurrence -- I will probably cry >a bit the first time I see it happen -- is (as far as I can see) the >_simplest_ form of escape-hatch-within-an-escape-hatch possible. Which I >hope to be a 1% sub-case within the 1% we're already discussing. > >The other recursive escape hatch, if you want to go sideways, is: > > run::run_command(["python", "my_pythonic_stack_of_turtles.py"]) > >but good luck diagnosing the virtualenv, pip, easy_install, distribute >and such errors emerging from that, mid-build. Python's versioning and >packaging problems are worse than ours; they have a legacy of >incompatible attempts to fight. We at least have few enough past >experiments that we can clean them all up and pretend we're at a blank >slate. > >IMO there's no real easy way out from an over-complex build aside from >"don't make over-complex builds". We should do everything we can to >discourage byzantine build logic: make things work via less-expressive >but automatic defaults whenever possible, and factor anything we see >cropping up in "custom rules" into default inferrable behavior. We added >pkg.rs only because people are currently writing make-and-sh logic and >git submodule forests, which is worse, and harder to factor. > >(I do agree we should be providing a better repl and shell-library >experience out of the box in rust. I don't think that's an argument to >change languages though. Fixing those problems is far less work.) > >-Graydon >_______________________________________________ >Rust-dev mailing list >Rust-dev at mozilla.org >https://mail.mozilla.org/listinfo/rust-dev From deansherthompson at gmail.com Wed Feb 20 11:40:41 2013 From: deansherthompson at gmail.com (Dean Thompson) Date: Wed, 20 Feb 2013 11:40:41 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: Message-ID: Here's a simplified example from how we build language bindings for RESTful APIs at LinkedIn. These APIs provide service-to-service communication internal to our service-oriented architecture. - Service implementor hand-codes the "resource implementation", writing source (would be Rust in this case) that contains annotations describing the REST resources. - "IDL generator tool" creates IDL files from the annotated "resource implementation" source. - "Client-binding generator tool" creates source code for a library (Rust, in this case) for using the RESTful API. - Client-binding library is published. - Client implementor writes code that depends on the client-binding library. In this scenario, I'd like to be able to publish the "IDL generator tool" and the "Client-binding generator tool" as easy-to-use plugins for the build process. Given rustpkg's direction, would I publish these as library crates that my pkg.rs (or build.rs, perhaps) would depend on? Would these library crates be able to influence the build process enough to control publication of the client-binding library? Is this kind of scenario even in scope for thinking about now? Dean From: Benjamin Striegel Date: Wednesday, February 20, 2013 9:25 AM Cc: "rust-dev at mozilla.org" Subject: Re: [rust-dev] rustpkg, package identifiers, filename conventions I think it would be useful to address all of these points with real examples and see if we can come up with solutions if Rust is currently falling short. For instance, in the imperative API, running external programs is *really* hideously ugly right now (by the end of the day I'll have submitted a pull request to try and address this). On Wed, Feb 20, 2013 at 8:50 AM, Dean Thompson wrote: > After using sbt (http://www.scala-sbt.org/) extensively, I have become > quite uncomfortable with compiled languages that use themselves as their > build automation language. Sbt is the primary Scala build tool, and uses > Scala as its build automation language. > > The appeal is obvious: Rust is the only language we know for certain is > available on the machine, and also the only language we know that the > programmer knows and can presume they like. > > However, in my experience with sbt, I have seen many problems with this > model. (Perhaps others on this list know recursive-build environments > where these problems have been avoided?) > > ** How is the build automation code compiled? > > If (as envisioned here so far) it can only be compiled using the default > compilation rules, that is a huge simplification. However, over time it > likely will not suffice. Builds can become legitimately complex (such as > source generation tools, multiple languages, and preprocessed resources). > Over time, many off-the-shelf build automation components are created (for > example, here's a list of Ant tasks: > https://ant.apache.org/manual/tasksoverview.html). > > If a project's build automation is too complex to be compiled with the > default compilation rules, then what? Sbt's approach (perhaps inevitable) > is to allow a subproject containing the build automation for compiling the > build automation. And, of course, you might need a sub-subproject for > compiling that. As the sbt documentation puts it, "the turtles go all the > way down" > (http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html). In > my experience with sbt, even having the initial build-automation > subproject becomes a brain-twister when problems occur. > > ** How are errors in the build automation reported and diagnosed? > > One characteristic I have often seen with sbt is that, when you make a > mistake coding your build automation, the build system can't function well > enough to give you good diagnostics. For example, sbt often can't display > a dependency tree until you straighten out your dependencies. > > ** What is the interactive experience? > > It is extremely useful in a build system to be able to poke around by hand > -- manually executing tasks and inspecting state. Sbt has a very > well-developed, and in many ways quite nice, interactive environment for > this. However, that environment has an uneasy relationship with the Scala > code that is the true underlying build automation, since it isn't natural > to type Scala code interactively. > > ** Is the target language really a natural build automation language? > > In Scala's case, having spent much time with sbt, I don't feel Scala is > the language I would choose for writing build automation. Although I am a > fan of statically typed languages for many purposes, they don't seem to > come into their own in short scripts that are centered around manipulating > text and the filesystem. > > * Alternative suggestion > > Here's what I said was appealing about using Rust as its own build > automation language: "Rust is the only language we know for certain is > available on the machine, and also the only language we know that the > programmer knows and can presume they like." How close can we come to > these benefits without using Rust as its own build automation language? > > We could address the first issue, "Rust is the only language we know for > certain is available on the machine", either by choosing a language with a > compact enough interpreter for us to embed in the Rust tooling, or at > least by choosing a language that is almost universally available. > > We could mitigate the second issue, "the only language we know that the > programmer knows and can presume they like", by trying to pick a language > that is generally popular among frustrated C++ programmers, and at least > that is easy to learn. > > At any rate, we would want to pick a language that is very convenient and > comfortable for manipulating the filesystem. Also, we would like one that > is natural to use interactively. > > My suggestion: Python. > > Dean > > > On 2/19/13 5:05 PM, "Graydon Hoare" wrote: > >> >Hi, >> > >> >We've recently replaced the cargo package manager with a new (very >> >young) tool called rustpkg; in the process it's (temporarily) broken >> >most of the packages installable through cargo, but we'll be fixing this >> >up before the next release. >> > >> >The main new feature of rustpkg is that it permits writing custom build >> >logic (and custom build tasks) in rust itself, as an escape hatch: if >> >there's a file called pkg.rs in a package repository it is >> compiled, >> >linked against rustpkg itself and run for various tasks. >> > >> >That's a nice feature and all, but we don't want to force (or even >> >_suggest_) use of the escape hatch by default. We'd like rustpkg to do >> >most things by inferring-sensible-defaults when looking at a repository. >> >In particular, building all the most obvious / findable binary and >> >library crates contained therein, based on simple rules. Preferably >> >rules that don't require parsing all the files in the repo and sorting >> >them into a module-graph just to figure out the targets. There might be >> >a lot of files (cf. src/test/run-pass/*.rs) >> > >> >The simplest rule I've come up with is based on a convention for chosen >> >filenames and their immediately-containing dir names. Specifically the >> >names "lib.rs " for libraries and "bin.rs " >> for binaries: >> > >> > foo/lib.rs ==> build libfoo-.so / .dll, a library >> > foo/bin.rs ==> build foo / foo.exe, an executable >> > >> >This is a convention that'll require a certain amount of reorganization >> >to existing code, but it permits multi-library / multi-binary packages >> >in a single source repo, which is an important use-case. Lots of time >> >people want >1 crate in the same git tree. Moreover it makes for a >> >pretty simple naming heuristic that can be derived directly from >> >URL-path-fragment package identifiers, such that: >> > >> > extern mod foo (id = "github.com/graydon/foo >> "); >> > >> >will pick up a single-library package, assuming there's a single file >> >lib.rs in that repo, and give it the name libfoo-.so, >> because >> >'foo' is the immediate parent-dir of the lib.rs file. >> Whereas: >> > >> > extern mod foo (id = "github.com/graydon/foo/thing >> "); >> > >> >will look for a thing/lib.rs dir-and-stem inside the >> >github.com/graydon/foo repo, and >> build-and-link _that_ into >> >libthing-.so. >> > >> >This should also permit mapping such identifiers to filesystem paths in >> >GOPATH-like workspaces, permitting local workspaces overlaid on global >> >ones and branching (via your VCS -- it does versions!) inside local >> >workspaces and whatnot. In case it's not clear from the sketch here, >> >it's very similar to what Go does -- I think they did a very tidy job >> >and I'm interested in copying its good parts. It feels like we didn't >> >quite hit the mark with cargo and this is an important thing to get right. >> > >> >That said, I'm interested in some feedback before we get too far into >> >it, to make sure we aren't making serious mistakes or missing issues >> >that people feel are unpleasant about URL-centric schemes. >> > >> >Any thoughts? Notes on other failure modes in package managers? Requests >> >for ponies? I'd prefer specificity in response, if you can manage it. We >> >all know package management is "generally miserable", but if you can >> >describe _exactly_ how things go wrong in other systems and what we >> >should be trying to avoid, or aiming for, that'd be good. >> > >> >Thanks, >> > >> >-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 _______________________________________________ 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 nmatsakis at mozilla.com Tue Feb 19 13:17:21 2013 From: nmatsakis at mozilla.com (Niko Matsakis) Date: Tue, 19 Feb 2013 16:17:21 -0500 Subject: [rust-dev] is this a case where flow-sensitivity is needed? In-Reply-To: References: Message-ID: <5123EBE1.3030302@mozilla.com> This is indeed the case where flow-sensitivity is truly needed (https://github.com/mozilla/rust/issues/4903). I don't think there's a good workaround for such cases. I am in the process of just implement flow sensitivity as part of some other changes. Niko John Clements wrote: > Here's the code I want to run: > > pub enum EnumTwo { > A(uint), > B(uint) > } > > fn get_map(env:</mut EnumTwo) -> </mut uint { > match *env { > A (ref mut map_a) => map_a, > B (ref mut map_b) => map_b > } > } > > > This fails with this error: > > jclements-09740:/tmp clements> rustc --test ./zap.rs > Running /usr/local/bin/rustc: > ./zap.rs:13:11: 13:25 error: loan of enum content as mutable conflicts with prior loan > ./zap.rs:13 B (ref mut map_b) => map_b > ^~~~~~~~~~~~~~ > ./zap.rs:12:11: 12:25 note: prior loan as mutable granted here > ./zap.rs:12 A (ref mut map_a) => map_a, > ^~~~~~~~~~~~~~ > error: aborting due to previous error > > > Patrick and I brainstormed on various moderately disgusting workarounds, but I couldn't find one that worked and returned a mutable borrowed pointer. I think I can see how to work around it by completely dismantling the abstraction that returns the mutable pointer. Am I missing anything ? > > John > From benoit.j.girard at agaguk.net Tue Feb 19 12:48:01 2013 From: benoit.j.girard at agaguk.net (Benoit Jauvin-Girard) Date: Tue, 19 Feb 2013 15:48:01 -0500 Subject: [rust-dev] Dynamic loading and unloading of crates. In-Reply-To: References: Message-ID: Greetings all, Is there any word on wether Rust will support the dynamic loading and unloading of crates at runtime? If so, any documentation as to what's planned? I could not find anything concrete in the rust-dev archives or in the manual. If I missed some existing document, please just point me in the right direction. -- Benoit. From martine at danga.com Wed Feb 20 12:16:27 2013 From: martine at danga.com (Evan Martin) Date: Wed, 20 Feb 2013 12:16:27 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <51242163.4040100@mozilla.com> References: <51242163.4040100@mozilla.com> Message-ID: On Tue, Feb 19, 2013 at 5:05 PM, Graydon Hoare wrote: > Any thoughts? Notes on other failure modes in package managers? Requests > for ponies? I'd prefer specificity in response, if you can manage it. We > all know package management is "generally miserable", but if you can > describe _exactly_ how things go wrong in other systems and what we > should be trying to avoid, or aiming for, that'd be good. > Two failure modes I ran into when using the Go build system, which this is similar to: 1) Is it still possible to build without using this system? Once my project had particular build requirements (I think I needed to shell out to a built program to generate more source code) I could no longer use the built-in "go build" command, and it turned out they'd grown dependencies between that and their unit-testing library -- that is, you couldn't use the built-in unit test library if you were running the compiler yourself, as "go build" had some codegen machinery in it required by the library! I guess this is another way of supporting Dean's point, that you need the escape hatch to be pretty wide to encompass all potential behaviors. 2) Where does a "configure" step fit into this? If you're linking against C headers or whatever you need a place to run extra code. The reason I bring it up is that you need the ability to run some steps before the other builds start, which means you need to express some sort of build-system-like dependency logic in between your pkg.rs steps. I guess that's inevitable though. This point might as well be the same thing as the first. :) -------------- next part -------------- An HTML attachment was scrubbed... URL: From martindemello at gmail.com Wed Feb 20 13:08:49 2013 From: martindemello at gmail.com (Martin DeMello) Date: Wed, 20 Feb 2013 13:08:49 -0800 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: <51242163.4040100@mozilla.com> References: <51242163.4040100@mozilla.com> Message-ID: If you're going to support go-style importing of external packages in git repos, it's worth reading kana's ideas concerning version tags. Pasting the relevant bit in: Plugins must follow the versioning pocilies of RubyGems and have "version" tags in their repositories. For example, if there is the version 1.2.3 of a plugin, its repository must have the tag 1.2.3, and the files of the version 1.2.3 can be checked out via the tag 1.2.3. In other words, plugins which do not have proper tags are not installable. This is an intentional design. Because: It's not possible to determine whether two versions are compatible or not without "version" tags. Compatibility is a big problem to resolve dependencies of plugins. For example, if plugin A requires plugin X 1.2.3 or later while plugin B requires plugin X 2.0 or later, it's not possible to use A and B at the same time. Such problems should be detected before installing plugins. Git mirrors by vim-scripts.org are tagged with version numbers. Some Git repositories might not have "version" tags. Such plugins are not ready to use for everyone. So that it should not be installable. https://www.relishapp.com/kana/vim-flavor/docs/philosophy martin On Tue, Feb 19, 2013 at 5:05 PM, Graydon Hoare wrote: > Hi, > > We've recently replaced the cargo package manager with a new (very > young) tool called rustpkg; in the process it's (temporarily) broken > most of the packages installable through cargo, but we'll be fixing this > up before the next release. > > The main new feature of rustpkg is that it permits writing custom build > logic (and custom build tasks) in rust itself, as an escape hatch: if > there's a file called pkg.rs in a package repository it is compiled, > linked against rustpkg itself and run for various tasks. > > That's a nice feature and all, but we don't want to force (or even > _suggest_) use of the escape hatch by default. We'd like rustpkg to do > most things by inferring-sensible-defaults when looking at a repository. > In particular, building all the most obvious / findable binary and > library crates contained therein, based on simple rules. Preferably > rules that don't require parsing all the files in the repo and sorting > them into a module-graph just to figure out the targets. There might be > a lot of files (cf. src/test/run-pass/*.rs) > > The simplest rule I've come up with is based on a convention for chosen > filenames and their immediately-containing dir names. Specifically the > names "lib.rs" for libraries and "bin.rs" for binaries: > > foo/lib.rs ==> build libfoo-.so / .dll, a library > foo/bin.rs ==> build foo / foo.exe, an executable > > This is a convention that'll require a certain amount of reorganization > to existing code, but it permits multi-library / multi-binary packages > in a single source repo, which is an important use-case. Lots of time > people want >1 crate in the same git tree. Moreover it makes for a > pretty simple naming heuristic that can be derived directly from > URL-path-fragment package identifiers, such that: > > extern mod foo (id = "github.com/graydon/foo"); > > will pick up a single-library package, assuming there's a single file > lib.rs in that repo, and give it the name libfoo-.so, because > 'foo' is the immediate parent-dir of the lib.rs file. Whereas: > > extern mod foo (id = "github.com/graydon/foo/thing"); > > will look for a thing/lib.rs dir-and-stem inside the > github.com/graydon/foo repo, and build-and-link _that_ into > libthing-.so. > > This should also permit mapping such identifiers to filesystem paths in > GOPATH-like workspaces, permitting local workspaces overlaid on global > ones and branching (via your VCS -- it does versions!) inside local > workspaces and whatnot. In case it's not clear from the sketch here, > it's very similar to what Go does -- I think they did a very tidy job > and I'm interested in copying its good parts. It feels like we didn't > quite hit the mark with cargo and this is an important thing to get right. > > That said, I'm interested in some feedback before we get too far into > it, to make sure we aren't making serious mistakes or missing issues > that people feel are unpleasant about URL-centric schemes. > > Any thoughts? Notes on other failure modes in package managers? Requests > for ponies? I'd prefer specificity in response, if you can manage it. We > all know package management is "generally miserable", but if you can > describe _exactly_ how things go wrong in other systems and what we > should be trying to avoid, or aiming for, that'd be good. > > Thanks, > > -Graydon > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From banderson at mozilla.com Wed Feb 20 16:41:46 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 20 Feb 2013 16:41:46 -0800 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> Message-ID: <51256D4A.6020701@mozilla.com> On 02/20/2013 01:15 AM, Sanghyeon Seo wrote: > rustc.rc has: > > #[path = "metadata/mod.rs"] > pub mod metadata; > #[path = "driver/mod.rs"] > pub mod driver; > > I think this should be the default. "mod" is a keyword anyway. > What do you think? > Because sometimes `mod driver;` means look in the current directory, and sometimes it means look in a subdirectory, doing this would require that, when the parser sees `pub mod driver;`: 1) look in the current directory for `driver.rs` 2) if that fails, look in the `driver` directory for `mod.rs` That's not necessarily bad, but it's a small bit of non-obvious behavior. I haven't been thrilled with the `mod.rs` convention (because my emacs buffers all have the same name) so I haven't been using it on new code, but I think if we go with the `lib.rs`/`bin.rs`/`pkg.rs` naming for crates in packages, then we should also settle on `mod.rs` for directory modules, in which case I think I'm fine with this change. From banderson at mozilla.com Wed Feb 20 16:56:23 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 20 Feb 2013 16:56:23 -0800 Subject: [rust-dev] Dynamic loading and unloading of crates. In-Reply-To: References: Message-ID: <512570B7.2050605@mozilla.com> On 02/19/2013 12:48 PM, Benoit Jauvin-Girard wrote: > Greetings all, > > Is there any word on wether Rust will support the dynamic loading and unloading of crates at runtime? If so, any documentation as to what's planned? > It will someday I hope, but nobody is working on it now. Simple bindings to dlopen etc., plus some name mangling code could be implemented quickly to create an unsafe dynamic loading system, but making dynamic loading safe (type-checked) is considerably harder. My current plan involves extracting metadata encoding and decoding, as well as a minimal set of type definitions from rustc to their own crate that depends only on libstd (maybe libsyntax). Then use that to do ... something, at runtime, to verify that loaded types match the expected types. There are also some unknowns about merging dynamically loaded crate maps (runtime crate metadata) into the current execution environment, but I think they are minor. This is a very worthy project, and even simple code for unsafe (cross-platform) dynamic loading would be warmly received I think. Relevant issues: * https://github.com/mozilla/rust/issues/458 - dynamic loading * https://github.com/mozilla/rust/issues/2213 - extracting metadata code from the compiler From zack at z0w0.me Wed Feb 20 18:19:20 2013 From: zack at z0w0.me (Zack Corr) Date: Thu, 21 Feb 2013 12:19:20 +1000 Subject: [rust-dev] rustpkg, package identifiers, filename conventions In-Reply-To: References: <51242163.4040100@mozilla.com> Message-ID: I think this is the best move right now. We should try and port the most notable Rust projects like Servo (or even Rust itself if someone is that ballsy) to Rustpkg and see how it works out. On Thu, Feb 21, 2013 at 3:25 AM, Benjamin Striegel wrote: > I think it would be useful to address all of these points with real > examples and see if we can come up with solutions if Rust is currently > falling short. For instance, in the imperative API, running external > programs is *really* hideously ugly right now (by the end of the day I'll > have submitted a pull request to try and address this). > > > On Wed, Feb 20, 2013 at 8:50 AM, Dean Thompson > wrote: > >> After using sbt (http://www.scala-sbt.org/) extensively, I have become >> quite uncomfortable with compiled languages that use themselves as their >> build automation language. Sbt is the primary Scala build tool, and uses >> Scala as its build automation language. >> >> The appeal is obvious: Rust is the only language we know for certain is >> available on the machine, and also the only language we know that the >> programmer knows and can presume they like. >> >> However, in my experience with sbt, I have seen many problems with this >> model. (Perhaps others on this list know recursive-build environments >> where these problems have been avoided?) >> >> ** How is the build automation code compiled? >> >> If (as envisioned here so far) it can only be compiled using the default >> compilation rules, that is a huge simplification. However, over time it >> likely will not suffice. Builds can become legitimately complex (such as >> source generation tools, multiple languages, and preprocessed resources). >> Over time, many off-the-shelf build automation components are created (for >> example, here's a list of Ant tasks: >> https://ant.apache.org/manual/tasksoverview.html). >> >> If a project's build automation is too complex to be compiled with the >> default compilation rules, then what? Sbt's approach (perhaps inevitable) >> is to allow a subproject containing the build automation for compiling the >> build automation. And, of course, you might need a sub-subproject for >> compiling that. As the sbt documentation puts it, "the turtles go all the >> way down" >> (http://www.scala-sbt.org/release/docs/Getting-Started/Full-Def.html). In >> my experience with sbt, even having the initial build-automation >> subproject becomes a brain-twister when problems occur. >> >> ** How are errors in the build automation reported and diagnosed? >> >> One characteristic I have often seen with sbt is that, when you make a >> mistake coding your build automation, the build system can't function well >> enough to give you good diagnostics. For example, sbt often can't display >> a dependency tree until you straighten out your dependencies. >> >> ** What is the interactive experience? >> >> It is extremely useful in a build system to be able to poke around by hand >> -- manually executing tasks and inspecting state. Sbt has a very >> well-developed, and in many ways quite nice, interactive environment for >> this. However, that environment has an uneasy relationship with the Scala >> code that is the true underlying build automation, since it isn't natural >> to type Scala code interactively. >> >> ** Is the target language really a natural build automation language? >> >> In Scala's case, having spent much time with sbt, I don't feel Scala is >> the language I would choose for writing build automation. Although I am a >> fan of statically typed languages for many purposes, they don't seem to >> come into their own in short scripts that are centered around manipulating >> text and the filesystem. >> >> * Alternative suggestion >> >> Here's what I said was appealing about using Rust as its own build >> automation language: "Rust is the only language we know for certain is >> available on the machine, and also the only language we know that the >> programmer knows and can presume they like." How close can we come to >> these benefits without using Rust as its own build automation language? >> >> We could address the first issue, "Rust is the only language we know for >> certain is available on the machine", either by choosing a language with a >> compact enough interpreter for us to embed in the Rust tooling, or at >> least by choosing a language that is almost universally available. >> >> We could mitigate the second issue, "the only language we know that the >> programmer knows and can presume they like", by trying to pick a language >> that is generally popular among frustrated C++ programmers, and at least >> that is easy to learn. >> >> At any rate, we would want to pick a language that is very convenient and >> comfortable for manipulating the filesystem. Also, we would like one that >> is natural to use interactively. >> >> My suggestion: Python. >> >> Dean >> >> >> On 2/19/13 5:05 PM, "Graydon Hoare" wrote: >> >> >Hi, >> > >> >We've recently replaced the cargo package manager with a new (very >> >young) tool called rustpkg; in the process it's (temporarily) broken >> >most of the packages installable through cargo, but we'll be fixing this >> >up before the next release. >> > >> >The main new feature of rustpkg is that it permits writing custom build >> >logic (and custom build tasks) in rust itself, as an escape hatch: if >> >there's a file called pkg.rs in a package repository it is compiled, >> >linked against rustpkg itself and run for various tasks. >> > >> >That's a nice feature and all, but we don't want to force (or even >> >_suggest_) use of the escape hatch by default. We'd like rustpkg to do >> >most things by inferring-sensible-defaults when looking at a repository. >> >In particular, building all the most obvious / findable binary and >> >library crates contained therein, based on simple rules. Preferably >> >rules that don't require parsing all the files in the repo and sorting >> >them into a module-graph just to figure out the targets. There might be >> >a lot of files (cf. src/test/run-pass/*.rs) >> > >> >The simplest rule I've come up with is based on a convention for chosen >> >filenames and their immediately-containing dir names. Specifically the >> >names "lib.rs" for libraries and "bin.rs" for binaries: >> > >> > foo/lib.rs ==> build libfoo-.so / .dll, a library >> > foo/bin.rs ==> build foo / foo.exe, an executable >> > >> >This is a convention that'll require a certain amount of reorganization >> >to existing code, but it permits multi-library / multi-binary packages >> >in a single source repo, which is an important use-case. Lots of time >> >people want >1 crate in the same git tree. Moreover it makes for a >> >pretty simple naming heuristic that can be derived directly from >> >URL-path-fragment package identifiers, such that: >> > >> > extern mod foo (id = "github.com/graydon/foo"); >> > >> >will pick up a single-library package, assuming there's a single file >> >lib.rs in that repo, and give it the name libfoo-.so, because >> >'foo' is the immediate parent-dir of the lib.rs file. Whereas: >> > >> > extern mod foo (id = "github.com/graydon/foo/thing"); >> > >> >will look for a thing/lib.rs dir-and-stem inside the >> >github.com/graydon/foo repo, and build-and-link _that_ into >> >libthing-.so. >> > >> >This should also permit mapping such identifiers to filesystem paths in >> >GOPATH-like workspaces, permitting local workspaces overlaid on global >> >ones and branching (via your VCS -- it does versions!) inside local >> >workspaces and whatnot. In case it's not clear from the sketch here, >> >it's very similar to what Go does -- I think they did a very tidy job >> >and I'm interested in copying its good parts. It feels like we didn't >> >quite hit the mark with cargo and this is an important thing to get >> right. >> > >> >That said, I'm interested in some feedback before we get too far into >> >it, to make sure we aren't making serious mistakes or missing issues >> >that people feel are unpleasant about URL-centric schemes. >> > >> >Any thoughts? Notes on other failure modes in package managers? Requests >> >for ponies? I'd prefer specificity in response, if you can manage it. We >> >all know package management is "generally miserable", but if you can >> >describe _exactly_ how things go wrong in other systems and what we >> >should be trying to avoid, or aiming for, that'd be good. >> > >> >Thanks, >> > >> >-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 >> > > > _______________________________________________ > 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 marcianx at gmail.com Wed Feb 20 18:38:48 2013 From: marcianx at gmail.com (Ashish Myles) Date: Wed, 20 Feb 2013 21:38:48 -0500 Subject: [rust-dev] Cloning managed memory between tasks? Message-ID: I didn't much previous discussion on this topic on google. Sorry if I missed something and re-starting an old discussion. Here is an example from the manual of a standard lisp-style list. enum List { Nil, Cons(T, @List) } If one wished to move such a list to another task, a copy to unique pointers would be needed. But it seems that this data structure doesn't support any way of unique-ifying it, it would have to be copied to a transferable data structure (like ~[T]) and reconstructed on the other side. As converting to another container might not be as optimal for, say a tree or more complex data type, is there another way to deal with such a use-case? I see a serialization/de-serialization approach was suggested here: https://github.com/mozilla/rust/issues/3836 Perhaps, a viable alternative would be to have a cloning procedure (given two tasks specified) that creates managed memory only on the receiving side while cloning? Something like a "copy to that task's heap and send it a pointer" functionality ? Ashish -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Wed Feb 20 19:21:19 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Wed, 20 Feb 2013 22:21:19 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: On Wednesday, 20 February 2013, Paul Stansifer wrote: > > Any idea why? () could be considered an expression, but it's not in an >> expression position, and a lot of things could be considered expressions >> and don't do this. >> > The local ambiguity errors exist for the internal reason that the Rust > parser `fail`s (I guess now it `die!`s) when it gets a parse error. > Therefore, the macro system refuses to start parsing a nonterminal (in this > case, expr), unless it can conclusively rule out all other options (in this > case, I think, the token ")", which occurs if there are 0 exprs in that > sequence), using one character of lookahead. And it isn't aware what > nonterminals can and can't start with, so the fact that ")" isn't the > beginning of an expression isn't useful to it (hm. It'd be a bit of a hack, > since we'd need to manually generate a table of acceptable start tokens, > but maybe adding that feature would make macro writing easier.). The > general solution is to make sure that the first thing inside a `$(...)*` > isn't a `$name:nt`. I think the macro tutorial (or possible the reference > guide) may have more information. > > Paul > > The tutorial example of ambiguity was so straightforward that I was lulled into complacency ;). I was misled by the apparent special treatment of delimiters, which is actually the result of the rust parser and not macro expansion*. Further complicating things is that identifiers, alone among non-terminals, can be matched against terminal symbols, which lets me do things with them that I can't do with patterns and expressions, which I didn't realize at first. * The delimiters have to be balanced so that the rust parser can find the outermost ones delimiting the input to the macro. The outermost delimiters behave differently from the nested ones since they don't actually form part of the input to the macro. -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcianx at gmail.com Wed Feb 20 19:54:58 2013 From: marcianx at gmail.com (Ashish Myles) Date: Wed, 20 Feb 2013 22:54:58 -0500 Subject: [rust-dev] Many little questions while writing a Vector class Message-ID: Lots of questions. 1. Is there an array string join function? I looked through possible pertinent vector- and string-related modules and I didn't see something equivalent. 2. Any particular reason to_str() for arrays (defined in in std::to_str) is defined only for unique arrays? i.e. impl ~[A]: ToStr { // ... } rather than for all array types via &? impl &[A]: ToStr { // ... } Modifying the definition seems to allow it to work for managed and static arrays. 3. What is the rust idiom for defining a constant value associated with a class? As an example, I defined N below for the vector class in C++ and immediately used it to define data members. struct Vector3 { enum { N = 3 }; T m_v[N]; }; In static contexts like above, especially when there may be multiple data members dependent on the constant, I just wanted to associate a name with them. I am already defining a len() method as below to return this value. struct Vector3 { priv m_v: [mut T * 3] } impl Vector3 { fn len(&self) -> uint { 3u; } } Rust does not seem to allow adding const definitions inside the struct. 4. How do I copy between mutable/immutable types and from dynamic to static array types? let a : ~[int] = ~[1,2,3]; // I know these are by design, but I don't know how to get the desired // effect. let b : [int * 3] = copy a; // fails due to storage mismatch let c : ~[mut int] = copy a; // fails due to mutability mismatch 5. Consistency of len/size: Each language seems to have its own standard for specifying container size. I thought Rust's convention was len from vector, dvec, list, etc, but deque uses size. Should that also be len? Or rather, as "size" is the more generic term (applies semantically to arbitrary containers like trees and maps), should "size" be the standard? Or, like ruby, perhaps both could be allowed. 6. Is there any way to get a number into a macro and splice it into a class name? i.e. Something like the intention behind the following. macro_rules! VectorT { // invoke it like VectorT ($name:ident, $n:expr) => ( struct Vector$n { priv m_v: [mut T * $n]; } ); } -------------- next part -------------- An HTML attachment was scrubbed... URL: From banderson at mozilla.com Wed Feb 20 19:56:17 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 20 Feb 2013 19:56:17 -0800 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: References: Message-ID: <51259AE1.4070701@mozilla.com> On 02/20/2013 06:38 PM, Ashish Myles wrote: > I didn't much previous discussion on this topic on google. Sorry if I > missed something and re-starting an old discussion. > > Here is an example from the manual of a standard lisp-style list. > enum List { > Nil, > Cons(T, @List) > } > If one wished to move such a list to another task, a copy to unique > pointers would be needed. But it seems that this data structure doesn't > support any way of unique-ifying it, it would have to be copied to > a transferable data structure (like ~[T]) > and reconstructed on the other side. As converting to another container > might not be as optimal for, say a tree or more complex data type, is > there another way to deal with such a use-case? > I see a serialization/de-serialization approach was suggested here: > https://github.com/mozilla/rust/issues/3836 > Perhaps, a viable alternative would be to have a cloning procedure (given > two tasks specified) that creates managed memory only on the receiving > side while cloning? Something like a "copy to that task's heap and send > it a pointer" functionality ? If you are ok with serialization (and want to implement it for `List`) then `std::flatpipes` should be able to send `List`. Without resorting to reflection, one thing we could possibly do is allow the current task to swap its heap with another, then just call the standard `.clone()` method, cloning into the new heap. At that point you could put that heap into another task. With some care such a thing could possibly by wrapped up into a safe interface, but it's kind of a scary notion to be swapping heaps. From jfredett at gmail.com Wed Feb 20 20:40:58 2013 From: jfredett at gmail.com (Joe Fredette) Date: Wed, 20 Feb 2013 23:40:58 -0500 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <51256D4A.6020701@mozilla.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> Message-ID: <18319AA8-479A-42D9-8337-B76EBC21B27C@gmail.com> (believe I missed reply-to-all the first time I tried this, apologies for the double-email, Brian) Speaking as a newb who struggled with how to do this not long ago. My expectation (which I knew was wholly unfounded) was that I could simply have `driver.rs` _and_ `driver/` for the various submodules of driver. In my case the goal was to distinguish different implementations of a common trait (namely, 'Command' which is a set of things which can be run). The intention was to have `command.rs` contain the trait definition and factory function, and then have the directory contain the various implemnentations (builtin, invocation, pipeline, etc). The eventual solution was somewhat confusing, and can be found (in a more abstract form) on my github at jfredett/rust_mod_test [1] on the 'fixed' branch. I won't go into what the solution was, my point was merely to offer that -- my assumption, at least, would be that there is simply a .rs and if I want a directory with submodules, I make that. The assumption derives from the Ruby convention of having `foo.rb` require all the necessary functionality out of `foo/`, and usually it contains cross-submodule functionality as well. [1] https://github.com/jfredett/rust_mod_test On Feb 20, 2013, at 7:41 PM, Brian Anderson wrote: > On 02/20/2013 01:15 AM, Sanghyeon Seo wrote: >> rustc.rc has: >> >> #[path = "metadata/mod.rs"] >> pub mod metadata; >> #[path = "driver/mod.rs"] >> pub mod driver; >> >> I think this should be the default. "mod" is a keyword anyway. >> What do you think? >> > > Because sometimes `mod driver;` means look in the current directory, and sometimes it means look in a subdirectory, doing this would require that, when the parser sees `pub mod driver;`: > > 1) look in the current directory for `driver.rs` > 2) if that fails, look in the `driver` directory for `mod.rs` > > That's not necessarily bad, but it's a small bit of non-obvious behavior. I haven't been thrilled with the `mod.rs` convention (because my emacs buffers all have the same name) so I haven't been using it on new code, but I think if we go with the `lib.rs`/`bin.rs`/`pkg.rs` naming for crates in packages, then we should also settle on `mod.rs` for directory modules, in which case I think I'm fine with this change. > _______________________________________________ > 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 pnkfelix at mozilla.com Wed Feb 20 23:25:17 2013 From: pnkfelix at mozilla.com (Felix S. Klock II) Date: Thu, 21 Feb 2013 08:25:17 +0100 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <51256D4A.6020701@mozilla.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> Message-ID: <5125CBDD.6040709@mozilla.com> > I haven't been thrilled with the `mod.rs` convention (because my emacs > buffers all have the same name) At this point this probably deserves an entry on the wiki or somewhere: https://www.google.com/search?q=emacs+uniquify I strongly recommend changing Emacs's default setting for this. Cheers, -Felix On 21/02/2013 01:41, Brian Anderson wrote: > On 02/20/2013 01:15 AM, Sanghyeon Seo wrote: >> rustc.rc has: >> >> #[path = "metadata/mod.rs"] >> pub mod metadata; >> #[path = "driver/mod.rs"] >> pub mod driver; >> >> I think this should be the default. "mod" is a keyword anyway. >> What do you think? >> > > Because sometimes `mod driver;` means look in the current directory, > and sometimes it means look in a subdirectory, doing this would > require that, when the parser sees `pub mod driver;`: > > 1) look in the current directory for `driver.rs` > 2) if that fails, look in the `driver` directory for `mod.rs` > > That's not necessarily bad, but it's a small bit of non-obvious > behavior. I haven't been thrilled with the `mod.rs` convention > (because my emacs buffers all have the same name) so I haven't been > using it on new code, but I think if we go with the > `lib.rs`/`bin.rs`/`pkg.rs` naming for crates in packages, then we > should also settle on `mod.rs` for directory modules, in which case I > think I'm fine with this change. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- irc: pnkfelix on irc.mozilla.org email: {fklock, pnkfelix}@mozilla.org From bruce at strapper.net Thu Feb 21 04:21:10 2013 From: bruce at strapper.net (Bruce M. Axtens) Date: Thu, 21 Feb 2013 20:21:10 +0800 Subject: [rust-dev] bundling gcc Message-ID: <51261136.7020701@strapper.net> Those who wander aimlessly about the internet may have noticed http://www.harbour-project.org . These folk distribute their preferred version of gcc in their installer. Is there any chance that Rust could do the same (for us folk who already have MinGW with a more recent version of gcc in it.) Kind regards, Bruce. From niko at alum.mit.edu Thu Feb 21 05:49:07 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 08:49:07 -0500 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <18319AA8-479A-42D9-8337-B76EBC21B27C@gmail.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> <18319AA8-479A-42D9-8337-B76EBC21B27C@gmail.com> Message-ID: <512625D3.6010806@alum.mit.edu> For what it's worth, this is how things used to work, but we changed it because it was annoying to have the "main code" for a module in a different directory from its submodules. Joe Fredette wrote: > (believe I missed reply-to-all the first time I tried this, apologies > for the double-email, Brian) > > Speaking as a newb who struggled with how to do this not long ago. My > expectation (which I knew was wholly unfounded) was that I could > simply have `driver.rs ` _and_ `driver/` for the > various submodules of driver. In my case the goal was to distinguish > different implementations of a common trait (namely, 'Command' which > is a set of things which can be run). The intention was to have > `command.rs ` contain the trait definition and > factory function, and then have the directory contain the various > implemnentations (builtin, invocation, pipeline, etc). > > The eventual solution was somewhat confusing, and can be found (in a > more abstract form) on my github at jfredett/rust_mod_test [1] on the > 'fixed' branch. I won't go into what the solution was, my point was > merely to offer that -- my assumption, at least, would be that there > is simply a .rs and if I want a directory with submodules, I > make that. The assumption derives from the Ruby convention of having > `foo.rb` require all the necessary functionality out of `foo/`, and > usually it contains cross-submodule functionality as well. > > > [1] https://github.com/jfredett/rust_mod_test > > > On Feb 20, 2013, at 7:41 PM, Brian Anderson > wrote: > >> On 02/20/2013 01:15 AM, Sanghyeon Seo wrote: >>> rustc.rc has: >>> >>> #[path = "metadata/mod.rs"] >>> pub mod metadata; >>> #[path = "driver/mod.rs"] >>> pub mod driver; >>> >>> I think this should be the default. "mod" is a keyword anyway. >>> What do you think? >>> >> >> Because sometimes `mod driver;` means look in the current directory, >> and sometimes it means look in a subdirectory, doing this would >> require that, when the parser sees `pub mod driver;`: >> >> 1) look in the current directory for `driver.rs` >> 2) if that fails, look in the `driver` directory for `mod.rs` >> >> That's not necessarily bad, but it's a small bit of non-obvious >> behavior. I haven't been thrilled with the `mod.rs` convention >> (because my emacs buffers all have the same name) so I haven't been >> using it on new code, but I think if we go with the >> `lib.rs`/`bin.rs`/`pkg.rs` naming for crates in packages, then we >> should also settle on `mod.rs` for directory modules, in which case I >> think I'm fine with this change. >> _______________________________________________ >> 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 Feb 21 05:50:17 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 08:50:17 -0500 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <51256D4A.6020701@mozilla.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> Message-ID: <51262619.9000401@alum.mit.edu> I think we should encode *something* as an intelligent default. The current system makes the common case harder than it ought to be, I think, though if you understand our annotations it's fine. But I feel like people should be able to make multi-directory Rust projects without having to know about the #[path] annotation. I am somewhat indifferent as to what convention we settle on, though I prefer `mod.rs` because it Brian Anderson wrote: > On 02/20/2013 01:15 AM, Sanghyeon Seo wrote: >> rustc.rc has: >> >> #[path = "metadata/mod.rs"] >> pub mod metadata; >> #[path = "driver/mod.rs"] >> pub mod driver; >> >> I think this should be the default. "mod" is a keyword anyway. >> What do you think? >> > > Because sometimes `mod driver;` means look in the current directory, > and sometimes it means look in a subdirectory, doing this would > require that, when the parser sees `pub mod driver;`: > > 1) look in the current directory for `driver.rs` > 2) if that fails, look in the `driver` directory for `mod.rs` > > That's not necessarily bad, but it's a small bit of non-obvious > behavior. I haven't been thrilled with the `mod.rs` convention > (because my emacs buffers all have the same name) so I haven't been > using it on new code, but I think if we go with the > `lib.rs`/`bin.rs`/`pkg.rs` naming for crates in packages, then we > should also settle on `mod.rs` for directory modules, in which case I > think I'm fine with this change. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From niko at alum.mit.edu Thu Feb 21 05:56:33 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 08:56:33 -0500 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <51262619.9000401@alum.mit.edu> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> <51262619.9000401@alum.mit.edu> Message-ID: <51262791.7020804@alum.mit.edu> Argh, there is some hot-key for send that is a bit too easy to press. Sorry about that. Here is the complete message I meant to write: I think we should encode *something* as an intelligent default. People should be able to make multi-directory Rust projects without having to know about the #[path] annotation as long as they're willing to follow our default convention. I am somewhat indifferent as to what convention we settle on. I have a slight preference for `mod.rs` because `mod` is a keyword and thus compatible with nested packages like `util::util::foo` (not that this is necessarily such a hot idea). Also both Python and Java solve this problem the same way (Python uses `__init__.py`, Java uses `package-info.java`), so there is certainly precedent, but I'm not sure what other languages do. The problem with emacs buffers is real but easily solved by adding `(toggle-uniquify-buffers)` to your .emacs file, which every emacs user should be doing anyway. The default configuration of emacs is annoying in general (why would you ever want `foo<2>` as a buffer name in place of `dir/foo`?) Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Feb 21 06:17:21 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 09:17:21 -0500 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: References: Message-ID: <51262C71.8020805@alum.mit.edu> Ashish Myles wrote: > Lots of questions. > > 1. Is there an array string join function? I looked through possible > pertinent vector- and string-related modules and I didn't see > something equivalent. vec::connect() will join a vector of strings into one string. > 2. Any particular reason to_str() for arrays (defined in in std::to_str) > is defined only for unique arrays? i.e. > impl ~[A]: ToStr { > // ... > } > rather than for all array types via &? > impl &[A]: ToStr { > // ... > } > Modifying the definition seems to allow it to work for managed and > static > arrays. I don't think there's a good reason for this. > 3. What is the rust idiom for defining a constant value associated with a > class? Declare a constant in the same module as the struct. Whereas C++ uses the class/struct as the primary organizing unit for code, Rust tends to use modules to group together related functions, types, constants, and so forth. Similarly, the Rust translation for a C++ class is a module containing a struct, impl, etc. > 4. How do I copy between mutable/immutable types and from dynamic to > static > array types? > let a : ~[int] = ~[1,2,3]; > // I know these are by design, but I don't know how to get the desired > // effect. > let b : [int * 3] = copy a; // fails due to storage mismatch Hmm, I don't know of a convenient way to do this. Obviously it would fail if the length of `a` were incorrect. You probably have to do something like the following: let mut b: [int*3] = [0, ..3]; // initialize with zeroes assert a.len() == 3; for uint::range(0, 3) |i| { b[i] = a[i]; } I imagine there is a "memcpy" like function for vectors that you could use to avoid the loop, but I don't know it's name off the top of my head. > let c : ~[mut int] = copy a; // fails due to mutability mismatch You should not be using a type like ~[mut int]. That is deprecated. Mutability is inherited through ~ pointers (indeed through any kind of ownership), so you can write: let mut c = a; // moves a by default, use `copy a` if you want to use `a` later c[0] += 1; // and so on... > 5. Consistency of len/size: > Each language seems to have its own standard for specifying container > size. I thought Rust's convention was len from vector, dvec, list, etc, > but deque uses size. Should that also be len? Or rather, as "size" is > the more generic term (applies semantically to arbitrary containers > like > trees and maps), should "size" be the standard? Or, like ruby, perhaps > both could be allowed. Good question. This is the sort of thing that we are going to be addressing as we cleanup the libraries. I agree we should settle on one. I don't personally care which it is. I'm personally not bothered by the semantic mismatch of a set having a length, but I guess `size()` would be the most broadly applicable and least likely to inspire later flame wars. > 6. Is there any way to get a number into a macro and splice it into a > class > name? i.e. Something like the intention behind the following. > macro_rules! VectorT { > // invoke it like VectorT > ($name:ident, $n:expr) => ( > struct Vector$n { > priv m_v: [mut T * $n]; > } > ); > } I don't know the answer to this. regards, Niko From niko at alum.mit.edu Thu Feb 21 06:21:31 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 09:21:31 -0500 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: References: Message-ID: <51262D6B.5040706@alum.mit.edu> The problem with allocating memory in another task is that it's kind of a "rendezvous" operation, since you must pause both tasks so that neither performs a GC etc during the time of the copy. Personally I think we should stick with serialization unless it becomes a true burden. We'll probably have to improve the serializer to handle cyclic data structures at some point though. If there is a true performance problem, we could build an API that allowed you to allocate arbitrary data structures in an arena that can then be sent to other tasks as a unit. In this way one could send an arbitrary graph in constant time. This takes a little bit of thought and care and maybe require some minor extensions to the type system. Niko Ashish Myles wrote: > I didn't much previous discussion on this topic on google. Sorry if I > missed something and re-starting an old discussion. > > Here is an example from the manual of a standard lisp-style list. > enum List { > Nil, > Cons(T, @List) > } > If one wished to move such a list to another task, a copy to unique > pointers would be needed. But it seems that this data structure doesn't > support any way of unique-ifying it, it would have to be copied to > a transferable data structure (like ~[T]) > and reconstructed on the other side. As converting to another container > might not be as optimal for, say a tree or more complex data type, is > there another way to deal with such a use-case? > I see a serialization/de-serialization approach was suggested here: > https://github.com/mozilla/rust/issues/3836 > Perhaps, a viable alternative would be to have a cloning procedure (given > two tasks specified) that creates managed memory only on the receiving > side while cloning? Something like a "copy to that task's heap and send > it a pointer" functionality ? > > Ashish > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From lucian.branescu at gmail.com Thu Feb 21 06:25:47 2013 From: lucian.branescu at gmail.com (Lucian Branescu) Date: Thu, 21 Feb 2013 14:25:47 +0000 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: <51262D6B.5040706@alum.mit.edu> References: <51262D6B.5040706@alum.mit.edu> Message-ID: A related problem is using a persistent data structure and a swap to allow several tasks to operate on the same immutable data structure and change the top-level reference atomically, basically transactions. Clojure operates this way and it works quite well, but I don't see how it would work in rust without copies. On 21 February 2013 14:21, Niko Matsakis wrote: > The problem with allocating memory in another task is that it's kind of a > "rendezvous" operation, since you must pause both tasks so that neither > performs a GC etc during the time of the copy. Personally I think we > should stick with serialization unless it becomes a true burden. We'll > probably have to improve the serializer to handle cyclic data structures at > some point though. > > If there is a true performance problem, we could build an API that allowed > you to allocate arbitrary data structures in an arena that can then be sent > to other tasks as a unit. In this way one could send an arbitrary graph in > constant time. This takes a little bit of thought and care and maybe > require some minor extensions to the type system. > > > Niko > > Ashish Myles wrote: > >> I didn't much previous discussion on this topic on google. Sorry if I >> missed something and re-starting an old discussion. >> >> Here is an example from the manual of a standard lisp-style list. >> enum List { >> Nil, >> Cons(T, @List) >> } >> If one wished to move such a list to another task, a copy to unique >> pointers would be needed. But it seems that this data structure doesn't >> support any way of unique-ifying it, it would have to be copied to >> a transferable data structure (like ~[T]) >> and reconstructed on the other side. As converting to another container >> might not be as optimal for, say a tree or more complex data type, is >> there another way to deal with such a use-case? >> I see a serialization/de-serialization approach was suggested here: >> https://github.com/mozilla/**rust/issues/3836 >> Perhaps, a viable alternative would be to have a cloning procedure (given >> two tasks specified) that creates managed memory only on the receiving >> side while cloning? Something like a "copy to that task's heap and send >> it a pointer" functionality ? >> >> Ashish >> >> ______________________________**_________________ >> 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 illissius at gmail.com Thu Feb 21 07:28:34 2013 From: illissius at gmail.com (=?ISO-8859-1?Q?G=E1bor_Lehel?=) Date: Thu, 21 Feb 2013 16:28:34 +0100 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: <51262C71.8020805@alum.mit.edu> References: <51262C71.8020805@alum.mit.edu> Message-ID: On Thu, Feb 21, 2013 at 3:17 PM, Niko Matsakis wrote: > > > Ashish Myles wrote: >> 5. Consistency of len/size: >> Each language seems to have its own standard for specifying container >> size. I thought Rust's convention was len from vector, dvec, list, etc, >> but deque uses size. Should that also be len? Or rather, as "size" is >> the more generic term (applies semantically to arbitrary containers >> like >> trees and maps), should "size" be the standard? Or, like ruby, perhaps >> both could be allowed. > > Good question. This is the sort of thing that we are going to be addressing > as we cleanup the libraries. I agree we should settle on one. I don't > personally care which it is. I'm personally not bothered by the semantic > mismatch of a set having a length, but I guess `size()` would be the most > broadly applicable and least likely to inspire later flame wars. FWIW Qt uses `count()`. (but also has size() for STL compatibility, and length() as well when it makes sense...) -- Your ship was destroyed in a monadic eruption. From jack at metajack.im Thu Feb 21 08:27:49 2013 From: jack at metajack.im (Jack Moffitt) Date: Thu, 21 Feb 2013 09:27:49 -0700 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: References: <51262C71.8020805@alum.mit.edu> Message-ID: > FWIW Qt uses `count()`. (but also has size() for STL compatibility, > and length() as well when it makes sense...) Clojure uses count as well. I'd prefer size or count, but I suppose another question is whether verbs or adjectives are preferred for this kind of thing. That should probably be consistent in the standard lib as well. jack. From stefan.plantikow at gmail.com Thu Feb 21 08:33:16 2013 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Thu, 21 Feb 2013 17:33:16 +0100 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: <51262D6B.5040706@alum.mit.edu> References: <51262D6B.5040706@alum.mit.edu> Message-ID: <836059FA-333F-4C2C-BA0A-B4857E6299DC@googlemail.com> Hi, Am 21.02.2013 um 15:21 schrieb Niko Matsakis : > The problem with allocating memory in another task is that it's kind of a "rendezvous" operation, since you must pause both tasks so that neither performs a GC etc during the time of the copy. Personally I think we should stick with serialization unless it becomes a true burden. We'll probably have to improve the serializer to handle cyclic data structures at some point though. > > If there is a true performance problem, we could build an API that allowed you to allocate arbitrary data structures in an arena that can then be sent to other tasks as a unit. In this way one could send an arbitrary graph in constant time. This takes a little bit of thought and care and maybe require some minor extensions to the type system. > I keep thinking about a feature like that in relationship to the Disruptor (factory line) concurrency pattern which is one of the fastest methods for CPU cache-conscious high-speed concurrent processing. Disruptor summary: A Disruptor is a ring buffer of event objects. The ring buffer keeps track of free event slot and events ready for consumption using two atomically incremented event slot pointers. Events get processed by different tasks/threads which read directly off the ring buffer and thus benefit massively from cache locality. Concurrency between tasks is managed by either ensuring that tasks work on different parts of the event or by ordering tasks that work on the same part of an event using atomic event slot pointers (i.e. task b only works on a field 'a' in an event after task a has worked on it). I've been wondering how to implement Disruptor in rust without resorting to using unsafe pointers. To make this convenient, I think it would be necessary to have partial transfer of ownership of data. For unique pointers, it should be possible to have that without needing cycle detecting GC by introducing a "split of" operation that transforms a unique into the original pointer with access removed to the sub-part (or replaced with a default value, like option::None), and a new unique pointer for the torn off sub-part. The second pointer could then be handed off to another task for parallel processing without incurring copying costs. The parent of such a "splittable pointer" would have to keep a reference count for the torn off part that gets incremented on "split" and decremented on "union". When the sub-part goes out of scope, it would automatically reunion with the parent. The parent can be freed, when its refcount is zero. There would be no cross-task cycles since all involved pointers would still be unique (only owned by a single task at a single point in time). The whole point of this would be to have good CPU cache locality, as the sub-pointer would live at a memory address close to its parent pointer. I guess what I am thinking about is /something/ like this: struct Event { partA: Splittable[A], partB: Splittable[B] } fn handleEvent(event: ~Event) { let (eventWithoutA, partA) = event.partA.split() // send unique partA somewhere for processing let (eventWithoutB, partB) = eventWithoutA.partB.split() // send unique partB somewhere for processing and retrieve it back let eventWithUpdatedB = eventWithB.partB.union(receivedPartB) // blocking union (?) let eventWithUpdatedA = eventWithUpdatedB.partA.blockingUnion() // continue } Is there a better way to achieve this in rust today? Cheers, Stefan From marcianx at gmail.com Thu Feb 21 08:33:33 2013 From: marcianx at gmail.com (Ashish Myles) Date: Thu, 21 Feb 2013 11:33:33 -0500 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: <51262C71.8020805@alum.mit.edu> References: <51262C71.8020805@alum.mit.edu> Message-ID: Thanks for all the answers. On Thu, Feb 21, 2013 at 9:17 AM, Niko Matsakis wrote: > > > Ashish Myles wrote: > >> Lots of questions. >> >> 1. Is there an array string join function? I looked through possible >> pertinent vector- and string-related modules and I didn't see >> something equivalent. >> > vec::connect() will join a vector of strings into one string. > > O wow, I don't know how I missed that. Coming from other languages, though "join" seem to be the common name for this. Even the following search does not bring up any reference to connect. http://www.google.com/search?q=site%3Astatic.rust-lang.org%2Fdoc%2F+join Perhaps a note could be made in the docs indicating that vec::connect() acts like a vector join with a string separator in various other languages? > 2. Any particular reason to_str() for arrays (defined in in std::to_str) >> is defined only for unique arrays? i.e. >> impl ~[A]: ToStr { >> // ... >> } >> rather than for all array types via &? >> impl &[A]: ToStr { >> // ... >> } >> Modifying the definition seems to allow it to work for managed and >> static >> arrays. >> > I don't think there's a good reason for this. > > 3. What is the rust idiom for defining a constant value associated with a >> class? >> > Declare a constant in the same module as the struct. Whereas C++ uses the > class/struct as the primary organizing unit for code, Rust tends to use > modules to group together related functions, types, constants, and so > forth. Similarly, the Rust translation for a C++ class is a module > containing a struct, impl, etc. > > C++ has both class- and namespace-level constants as they have different uses. In the example, I have a class/struct-level constant. For example struct Vector2 { enum { N = 2 }; T m_v[N]; }; struct Vector3 { enum { N = 3 }; T m_v[N]; }; Imagine also, as in my macro question below -- a vector struct is created based on some integer dimension value. So that dimension constant should logically be defined in the struct in that case as well. So, I am to presume from your answer that there is no way to create class-associated constants? Is this worth considering adding to Rust? > 6. Is there any way to get a number into a macro and splice it into a >> class >> name? i.e. Something like the intention behind the following. >> macro_rules! VectorT { >> // invoke it like VectorT >> ($name:ident, $n:expr) => ( >> struct Vector$n { >> priv m_v: [mut T * $n]; >> } >> ); >> } >> > I don't know the answer to this. > > I look forward to anyone else taking a stab at how one could accomplish something similar in Rust. One obvious but not very DRY way would be to send in all pre-concatenated identifiers. Like in this case, one could re-write the macro to be invoked as VectorT(Vector3, 3). If the macro creates multiple identifiers (including some associate with helper classes/functions) based on just concatenating the numeric value, then the invocation could get pretty ugly and would leak too much about the underlying implementation. Thanks, Ashish -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Thu Feb 21 08:43:34 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 21 Feb 2013 08:43:34 -0800 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: References: <51262C71.8020805@alum.mit.edu> Message-ID: <51264EB6.2080409@mozilla.com> On 2/21/13 8:33 AM, Ashish Myles wrote: > O wow, I don't know how I missed that. Coming from other languages, > though "join" seem to be the common name for this. Even the following > search does not bring up any reference to connect. > http://www.google.com/search?q=site%3Astatic.rust-lang.org%2Fdoc%2F+join > Perhaps a note could be made in the docs indicating that vec::connect() > acts like a vector join with a string separator in various other languages? We should probably just rename it to `join`. The reason why it's called `connect` is that in ancient versions of Rust `join` was a keyword (to join tasks). Patrick From niko at alum.mit.edu Thu Feb 21 09:25:45 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 12:25:45 -0500 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: References: <51262D6B.5040706@alum.mit.edu> Message-ID: <51265899.6050903@alum.mit.edu> This could be achieved by using a persistent data structure based on ARC. The tricky part is to write one generic shared data that can be used with both @ (single-task) and ARC (cross-task). This can probably be achieved, but it'll require some thought and maybe some bugfixes in the trait code. :) Niko Lucian Branescu wrote: > A related problem is using a persistent data structure and a swap to > allow several tasks to operate on the same immutable data structure > and change the top-level reference atomically, basically transactions. > > Clojure operates this way and it works quite well, but I don't see how > it would work in rust without copies. > > > On 21 February 2013 14:21, Niko Matsakis > wrote: > > The problem with allocating memory in another task is that it's > kind of a "rendezvous" operation, since you must pause both tasks > so that neither performs a GC etc during the time of the copy. > Personally I think we should stick with serialization unless it > becomes a true burden. We'll probably have to improve the > serializer to handle cyclic data structures at some point though. > > If there is a true performance problem, we could build an API that > allowed you to allocate arbitrary data structures in an arena that > can then be sent to other tasks as a unit. In this way one could > send an arbitrary graph in constant time. This takes a little bit > of thought and care and maybe require some minor extensions to the > type system. > > > Niko > > Ashish Myles wrote: > > I didn't much previous discussion on this topic on google. > Sorry if I missed something and re-starting an old discussion. > > Here is an example from the manual of a standard lisp-style list. > enum List { > Nil, > Cons(T, @List) > } > If one wished to move such a list to another task, a copy to > unique > pointers would be needed. But it seems that this data > structure doesn't > support any way of unique-ifying it, it would have to be copied to > a transferable data structure (like ~[T]) > and reconstructed on the other side. As converting to another > container > might not be as optimal for, say a tree or more complex data > type, is > there another way to deal with such a use-case? > I see a serialization/de-serialization approach was suggested > here: > https://github.com/mozilla/rust/issues/3836 > Perhaps, a viable alternative would be to have a cloning > procedure (given > two tasks specified) that creates managed memory only on the > receiving > side while cloning? Something like a "copy to that task's > heap and send > it a pointer" functionality ? > > Ashish > > _______________________________________________ > 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 Feb 21 09:28:20 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 12:28:20 -0500 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: <836059FA-333F-4C2C-BA0A-B4857E6299DC@googlemail.com> References: <51262D6B.5040706@alum.mit.edu> <836059FA-333F-4C2C-BA0A-B4857E6299DC@googlemail.com> Message-ID: <51265934.5040509@alum.mit.edu> I think this pattern as you described it could be written with Option types. What you call Splittable is basically just Option. To split off you can use the swap_unwrap() method of Option. You would then use futures or channels to receive back the result and simply assign it (e.g., `event.partA = Some(future.get())`). Niko Stefan Plantikow wrote: > Hi, > > > Am 21.02.2013 um 15:21 schrieb Niko Matsakis: > >> The problem with allocating memory in another task is that it's kind of a "rendezvous" operation, since you must pause both tasks so that neither performs a GC etc during the time of the copy. Personally I think we should stick with serialization unless it becomes a true burden. We'll probably have to improve the serializer to handle cyclic data structures at some point though. >> >> If there is a true performance problem, we could build an API that allowed you to allocate arbitrary data structures in an arena that can then be sent to other tasks as a unit. In this way one could send an arbitrary graph in constant time. This takes a little bit of thought and care and maybe require some minor extensions to the type system. >> > > > I keep thinking about a feature like that in relationship to the Disruptor (factory line) concurrency pattern which is one of the fastest methods for CPU cache-conscious high-speed concurrent processing. > > Disruptor summary: A Disruptor is a ring buffer of event objects. The ring buffer keeps track of free event slot and events ready for consumption using two atomically incremented event slot pointers. Events get processed by different tasks/threads which read directly off the ring buffer and thus benefit massively from cache locality. Concurrency between tasks is managed by either ensuring that tasks work on different parts of the event or by ordering tasks that work on the same part of an event using atomic event slot pointers (i.e. task b only works on a field 'a' in an event after task a has worked on it). > > I've been wondering how to implement Disruptor in rust without resorting to using unsafe pointers. To make this convenient, I think it would be necessary to have partial transfer of ownership of data. > For unique pointers, it should be possible to have that without needing cycle detecting GC by introducing a "split of" operation that transforms a unique into the original pointer with access removed to the sub-part (or replaced with a default value, like option::None), and a new unique pointer for the torn off sub-part. The second pointer could then be handed off to another task for parallel processing without incurring copying costs. The parent of such a "splittable pointer" would have to keep a reference count for the torn off part that gets incremented on "split" and decremented on "union". When the sub-part goes out of scope, it would automatically reunion with the parent. The parent can be freed, when its refcount is zero. There would be no cross-task cycles since all involved pointers would still be unique (only owned by a single task at a single point in time). > > The whole point of this would be to have good CPU cache locality, as the sub-pointer would live at a memory address close to its parent pointer. > > I guess what I am thinking about is /something/ like this: > > struct Event { > partA: Splittable[A], > partB: Splittable[B] > } > > fn handleEvent(event: ~Event) > { > let (eventWithoutA, partA) = event.partA.split() > > // send unique partA somewhere for processing > > let (eventWithoutB, partB) = eventWithoutA.partB.split() > > // send unique partB somewhere for processing and retrieve it back > > let eventWithUpdatedB = eventWithB.partB.union(receivedPartB) > > // blocking union (?) > > let eventWithUpdatedA = eventWithUpdatedB.partA.blockingUnion() > > // continue > } > > Is there a better way to achieve this in rust today? > > > Cheers, > > > Stefan > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Feb 21 09:37:37 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 12:37:37 -0500 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: References: <51262C71.8020805@alum.mit.edu> Message-ID: <51265B61.8030408@alum.mit.edu> Ashish Myles wrote: > So, I am to presume from your answer that there is no way to create > class-associated constants? Is this worth considering adding to Rust? Rust does not, in fact, have classes. However, what I think you are attempting to achieve is to have the ability to write generic code on some type T that is either Vector2 or Vector3, and then one could write T::len to reference the relevant constant. The way to do this in Rust would probably be with a trait and a static fn: trait VectorN { static fn len() -> uint; // Eventually: just fn len() -> uint } fn foo(v: &V) { /* In theory, V::len() would give the length */ } Problem is, you can't write static functions that do not reference `Self` today [1]. In any case what you *really* want is something like trait VectorN { const len: uint; } fn foo(v: &V) { /* Here, V::len is a constant */ } which certainly doesn't work today. There is some design work needed here. In general, this seems to be related to the desire for associated types [2]. We need to spend some time thinking about what we want to support. I imagine we'll wind up postponing some or all such features to after Rust 1.0. I guess the closest thing that does work today is something like: trait VectorN { fn len(&self) -> uint; } fn foo(v: &V) { /* v.len() gives the length */ This has the downside that it requires an instance of `V` to be used. Niko [1] I thought there was an issue on this, but I couldn't find it. [2] https://github.com/mozilla/rust/issues/5033 From illissius at gmail.com Thu Feb 21 11:25:01 2013 From: illissius at gmail.com (=?ISO-8859-1?Q?G=E1bor_Lehel?=) Date: Thu, 21 Feb 2013 20:25:01 +0100 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: <51265B61.8030408@alum.mit.edu> References: <51262C71.8020805@alum.mit.edu> <51265B61.8030408@alum.mit.edu> Message-ID: On Thu, Feb 21, 2013 at 6:37 PM, Niko Matsakis wrote: > There is some design work needed here. In general, this seems to be related > to the desire for associated types [2]. Coming from Haskell, they seem like separate things to me (or rather they're related only by them being extensions to the trait system). On the one hand there's the desire to have types/traits parameterized on things other than types: non-type template parameters in C++ parlance, or type-level literals in Haskell (or type-level things of kind other than * or k -> k, in a broader sense). And on the other hand there's the desire to have constants as members of a trait (type class). That's Haskell 98, no extensions required. E.g. you have `class Bounded a where minBound :: a; maxBound :: a`. (Haskell doesn't have a distinction between nullary functions and simple values, so there's no difference there between `static fn len() -> uint` and `const len: uint`.) But this is just a mapping from types to values, which is what type classes do. Associated types come into the picture when you want to map types to types. -- Your ship was destroyed in a monadic eruption. From niko at alum.mit.edu Thu Feb 21 12:19:16 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 15:19:16 -0500 Subject: [rust-dev] Many little questions while writing a Vector class In-Reply-To: References: <51262C71.8020805@alum.mit.edu> <51265B61.8030408@alum.mit.edu> Message-ID: <51268144.3070800@alum.mit.edu> You are correct that there is no deep relation. I merely meant that the surface syntax looks similar. Some of the same issues arise in both cases, but that has more to do with Rust's path resolution rules than anything else. Niko G?bor Lehel wrote: > On Thu, Feb 21, 2013 at 6:37 PM, Niko Matsakis wrote: >> There is some design work needed here. In general, this seems to be related >> to the desire for associated types [2]. > > Coming from Haskell, they seem like separate things to me (or rather > they're related only by them being extensions to the trait system). On > the one hand there's the desire to have types/traits parameterized on > things other than types: non-type template parameters in C++ parlance, > or type-level literals in Haskell (or type-level things of kind other > than * or k -> k, in a broader sense). And on the other hand there's > the desire to have constants as members of a trait (type class). > That's Haskell 98, no extensions required. E.g. you have `class > Bounded a where minBound :: a; maxBound :: a`. (Haskell doesn't have a > distinction between nullary functions and simple values, so there's no > difference there between `static fn len() -> uint` and `const len: > uint`.) But this is just a mapping from types to values, which is what > type classes do. Associated types come into the picture when you want > to map types to types. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From stefan.plantikow at gmail.com Thu Feb 21 14:26:54 2013 From: stefan.plantikow at gmail.com (Stefan Plantikow) Date: Thu, 21 Feb 2013 23:26:54 +0100 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: <51265934.5040509@alum.mit.edu> References: <51262D6B.5040706@alum.mit.edu> <836059FA-333F-4C2C-BA0A-B4857E6299DC@googlemail.com> <51265934.5040509@alum.mit.edu> Message-ID: <86128FB6-C87D-4340-B727-02F0DDE8D455@googlemail.com> Hi, Am 21.02.2013 um 18:28 schrieb Niko Matsakis : > I think this pattern as you described it could be written with Option types. What you call Splittable is basically just Option. To split off you can use the swap_unwrap() method of Option. You would then use futures or channels to receive back the result and simply assign it (e.g., `event.partA = Some(future.get())`). wasn't aware of all the goodies that have been added to Option since I last looked :) Just to be clear: Moving the data out of the Option will even work when the Option is embedded inside a uniquely owned struct without causing it to be copied? That would be awesome. Thanks, Stefan. > Stefan Plantikow wrote: >> >> Hi, >> >> >> Am 21.02.2013 um 15:21 schrieb Niko Matsakis : >> >>> The problem with allocating memory in another task is that it's kind of a "rendezvous" operation, since you must pause both tasks so that neither performs a GC etc during the time of the copy. Personally I think we should stick with serialization unless it becomes a true burden. We'll probably have to improve the serializer to handle cyclic data structures at some point though. >>> >>> If there is a true performance problem, we could build an API that allowed you to allocate arbitrary data structures in an arena that can then be sent to other tasks as a unit. In this way one could send an arbitrary graph in constant time. This takes a little bit of thought and care and maybe require some minor extensions to the type system. >>> >> >> >> I keep thinking about a feature like that in relationship to the Disruptor (factory line) concurrency pattern which is one of the fastest methods for CPU cache-conscious high-speed concurrent processing. >> >> Disruptor summary: A Disruptor is a ring buffer of event objects. The ring buffer keeps track of free event slot and events ready for consumption using two atomically incremented event slot pointers. Events get processed by different tasks/threads which read directly off the ring buffer and thus benefit massively from cache locality. Concurrency between tasks is managed by either ensuring that tasks work on different parts of the event or by ordering tasks that work on the same part of an event using atomic event slot pointers (i.e. task b only works on a field 'a' in an event after task a has worked on it). >> >> I've been wondering how to implement Disruptor in rust without resorting to using unsafe pointers. To make this convenient, I think it would be necessary to have partial transfer of ownership of data. >> For unique pointers, it should be possible to have that without needing cycle detecting GC by introducing a "split of" operation that transforms a unique into the original pointer with access removed to the sub-part (or replaced with a default value, like option::None), and a new unique pointer for the torn off sub-part. The second pointer could then be handed off to another task for parallel processing without incurring copying costs. The parent of such a "splittable pointer" would have to keep a reference count for the torn off part that gets incremented on "split" and decremented on "union". When the sub-part goes out of scope, it would automatically reunion with the parent. The parent can be freed, when its refcount is zero. There would be no cross-task cycles since all involved pointers would still be unique (only owned by a single task at a single point in time). >> >> The whole point of this would be to have good CPU cache locality, as the sub-pointer would live at a memory address close to its parent pointer. >> >> I guess what I am thinking about is /something/ like this: >> >> struct Event { >> partA: Splittable[A], >> partB: Splittable[B] >> } >> >> fn handleEvent(event: ~Event) >> { >> let (eventWithoutA, partA) = event.partA.split() >> >> // send unique partA somewhere for processing >> >> let (eventWithoutB, partB) = eventWithoutA.partB.split() >> >> // send unique partB somewhere for processing and retrieve it back >> >> let eventWithUpdatedB = eventWithB.partB.union(receivedPartB) >> >> // blocking union (?) >> >> let eventWithUpdatedA = eventWithUpdatedB.partA.blockingUnion() >> >> // continue >> } >> >> Is there a better way to achieve this in rust today? >> >> >> Cheers, >> >> >> Stefan >> >> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Thu Feb 21 16:53:30 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Feb 2013 19:53:30 -0500 Subject: [rust-dev] Cloning managed memory between tasks? In-Reply-To: <86128FB6-C87D-4340-B727-02F0DDE8D455@googlemail.com> References: <51262D6B.5040706@alum.mit.edu> <836059FA-333F-4C2C-BA0A-B4857E6299DC@googlemail.com> <51265934.5040509@alum.mit.edu> <86128FB6-C87D-4340-B727-02F0DDE8D455@googlemail.com> Message-ID: <5126C18A.3090905@alum.mit.edu> Stefan Plantikow wrote: > Just to be clear: Moving the data out of the Option will even work > when the Option is embedded inside a uniquely owned struct without > causing it to be copied? Yes, so long as the uniquely owned struct is in a mutable location (for example, stored in a mutable local variable). Niko From banderson at mozilla.com Thu Feb 21 18:34:25 2013 From: banderson at mozilla.com (Brian Anderson) Date: Thu, 21 Feb 2013 18:34:25 -0800 Subject: [rust-dev] Fwd: Re: Cloning managed memory between tasks? In-Reply-To: <5126C607.9080502@mozilla.com> References: <5126C607.9080502@mozilla.com> Message-ID: <5126D931.2070808@mozilla.com> Forgot to copy the list. -------- Original Message -------- Subject: Re: [rust-dev] Cloning managed memory between tasks? Date: Thu, 21 Feb 2013 17:12:39 -0800 From: Brian Anderson To: Ashish Myles On 02/20/2013 08:24 PM, Ashish Myles wrote: > On Wed, Feb 20, 2013 at 10:56 PM, Brian Anderson > > wrote: > > On 02/20/2013 06:38 PM, Ashish Myles wrote: > > I didn't much previous discussion on this topic on google. > Sorry if I missed something and re-starting an old discussion. > > Here is an example from the manual of a standard lisp-style list. > enum List { > Nil, > Cons(T, @List) > } > If one wished to move such a list to another task, a copy to > unique > pointers would be needed. But it seems that this data > structure doesn't > support any way of unique-ifying it, it would have to be copied to > a transferable data structure (like ~[T]) > and reconstructed on the other side. As converting to another > container > might not be as optimal for, say a tree or more complex data > type, is > there another way to deal with such a use-case? > I see a serialization/de-serialization approach was suggested > here: > https://github.com/mozilla/rust/issues/3836 > Perhaps, a viable alternative would be to have a cloning > procedure (given > two tasks specified) that creates managed memory only on the > receiving > side while cloning? Something like a "copy to that task's > heap and send > it a pointer" functionality ? > > > If you are ok with serialization (and want to implement it for > `List`) then `std::flatpipes` should be able to send `List`. > > Without resorting to reflection, one thing we could possibly do is > allow the current task to swap its heap with another, then just > call the standard `.clone()` method, cloning into the new heap. At > that point you could put that heap into another task. With some > care such a thing could possibly by wrapped up into a safe > interface, but it's kind of a scary notion to be swapping heaps. > > > As list was just an example (not needed for anything at the moment), I > was indeed hoping for something general-purpose. Perhaps one could > think in terms of accessing the receiving task's heap via some > antiseptic intermediate task rather than swapping heaps if it seems > scary. Task 2 would be blocked for the duration. > > Speaking conceptually, say task 1 wanted to clone into task 2's heap > and say they are connected by a channel chan. Assuming that chan has > meta-information (accessible only unsafely) about the tasks to which > it is connected, then one could invoke the following in task 1 > chan.send_clone(obj) > This would block both task 1 and task 2 until completed. It could > create an auxiliary task connected to the heap of task 2 and invokes a > deep_clone() on obj. This would, of course, mean that the deep_cone() > cannot access any globals. Optionally, a post-clone sweep through the > cloned object could be used ensure that no pointers point to task 1's > heap. > Something like you describe could be done, though I'm not sure how to implement deep_clone without either swapping the heaps or adding some kind of factory for creating boxes in a different heap. Rust doesn't have globals yet, and when it does they will require unsafe to mutate so I don't think there's a problem with globals. You do need to prevent `deep_clone` from mutating itself and storing a pointer to the wrong heap, which may be possible with the `Const` kind, depending on how it works with @ boxes. You also need to do the opposite and avoid putting pointers to your own boxes in the opposing heap, which I don't know how to do without, as you say, some introspection. -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcianx at gmail.com Thu Feb 21 19:50:42 2013 From: marcianx at gmail.com (Ashish Myles) Date: Thu, 21 Feb 2013 22:50:42 -0500 Subject: [rust-dev] Simple use of templates/generics compilation hassles Message-ID: Well, I eventually figured out how to get things compiling, but it was highly non-obvious. I would appreciate it if someone could shed some light on why things behave this way so that I may learn to visually "see" the error. Say we have the following struct pub struct Vector3 { priv mut m_v: [T * 3] } 1. The following fails because it says it can't find in the second line. pub pure fn foo() -> Vector3 { Vector3 { mut m_v: [Zero::zero(), Zero::zero(), Zero::zero()] } } Changing it to pub pure fn foo() -> Vector3 { Vector3 { mut m_v: [Zero::zero(), Zero::zero(), Zero::zero()] } } works. I had compared against core::DVec to avoid strange errors, but I seemed to have overlooked the lack of type in the constructor there. Why is the redundant inclusion of bad? If anything it would allow the compiler to point out an error if the types didn't come out to be as intended. 2. Most of my other issues were multiple cases of this error. The following invocation of the function above fails with "unresolved name: int" let v = foo(); Removing the explicit type specialization works, but requires an explicit type declaration to be unambiguous. let v : Vector3 = foo(); Why could I not be specific with the type parameter to the function? Is there an alternative meaning with which it clashed? Ashish -------------- next part -------------- An HTML attachment was scrubbed... URL: From laden at csclub.uwaterloo.ca Thu Feb 21 20:01:24 2013 From: laden at csclub.uwaterloo.ca (Luqman Aden) Date: Thu, 21 Feb 2013 20:01:24 -0800 Subject: [rust-dev] Simple use of templates/generics compilation hassles In-Reply-To: References: Message-ID: On Thu, Feb 21, 2013 at 7:50 PM, Ashish Myles wrote: > Well, I eventually figured out how to get things compiling, but it was > highly non-obvious. I would appreciate it if someone could shed some light > on why things behave this way so that I may learn to visually "see" the > error. > > Say we have the following struct > pub struct Vector3 { > priv mut m_v: [T * 3] > } > > 1. The following fails because it says it can't find in the second > line. > pub pure fn foo() -> Vector3 { > Vector3 { mut m_v: [Zero::zero(), Zero::zero(), Zero::zero()] } > } > Changing it to > pub pure fn foo() -> Vector3 { > Vector3 { mut m_v: [Zero::zero(), Zero::zero(), Zero::zero()] } > } > works. I had compared against core::DVec to avoid strange errors, but I > seemed to have overlooked the lack of type in the constructor there. Why > is the redundant inclusion of bad? If anything it would allow the > compiler to point out an error if the types didn't come out to be as > intended. > You need to write it as Vector3::. Most of the time you don't actually need to specify as it can be inferred. And actually, the error message is still the same when I tried with and without the :: for mismatched types. > > 2. Most of my other issues were multiple cases of this error. The > following invocation of the function above fails with "unresolved name: int" > let v = foo(); > Removing the explicit type specialization works, but requires an explicit > type declaration to be unambiguous. > let v : Vector3 = foo(); > Why could I not be specific with the type parameter to the function? Is > there an alternative meaning with which it clashed? Same as above, so you'd write: let v = foo::(); > > > Ashish > > > _______________________________________________ > 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 marcianx at gmail.com Thu Feb 21 20:26:04 2013 From: marcianx at gmail.com (Ashish Myles) Date: Thu, 21 Feb 2013 23:26:04 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? Message-ID: Thanks for all the corrections and feedback so far. Another strange one that has me stumped. This one gives me a strange error that reads like the e-mail subject. ---- macro_rules! VectorT { ($Vec:ident, $n:expr) => ( struct $Vec { priv mut m_v: [T * $n]; } ); } VectorT!(Vector3, 3) fn main() { } ---- The error I get is error: expected integral vector length but found `3` priv mut m_v: [T * $n]; ^ (the caret points to the "$n" part). I get the same error if I use 3u instead of 3. There is no other fragment specifier that I can use for $n, so I am stumped. Any clues? Thanks in advance, Ashish -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven099 at gmail.com Thu Feb 21 22:37:30 2013 From: steven099 at gmail.com (Steven Blenkinsop) Date: Fri, 22 Feb 2013 01:37:30 -0500 Subject: [rust-dev] Pattern macros? In-Reply-To: References: Message-ID: Okay, now that I have a better understanding of the limitations on macros, I have a couple more questions. First, the first limitation stated in the tutorial says that the parser is greedy. However, a lot of the ambiguities referred to in the second limitation would be eliminated if the parser were greedy in matching repetitions. As you said, the reason it doesn't do this is to cover up the internal limitation that attempting match a fragment against a $name:kind can cause the parser to die, potentially prematurely. However, the artificially imposed limitation is much stricter than the underlying limitation, and fails to cover up the underlying limitation completely, at least right now. For example, the following reports an ambiguity: macro_rules! map1 ( ($($e1:expr $e2:expr a)* $($p:pat $e3:expr b)*) => ($($e1+$e2)* $(let $p = $e3)*); ) While the following similar example does not: macro_rules! map2 ( ($e1:expr $e2:expr a) => ($e1 + $e2); ($p:pat $e:expr b) => (let $p = $e); ) It fails, however, if called as `map2!(_, 3);`, as a result of the internal limitation, since `_` doesn't parse as an expression. Would it be desirable for these two examples to have the same behaviour (repetition aside), and if so, which? Also, how likely is it that the internal limitation (dying on parse error) could be resolved in the future? Second, I noticed that once a series of tokens get matched to a $name:kind instance, they are outputted as a sort of meta-token which will only match against another $name:kind of the same kind in nested macro invocations and can't be decomposed. Why don't these meta-tokens get re-tokenized when you attempt to match them against literal tokens? -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Thu Feb 21 22:54:07 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 21 Feb 2013 22:54:07 -0800 Subject: [rust-dev] RFC: Merge Cell and Mut? Message-ID: <5127160F.9020402@mozilla.com> Hi everyone, Based on some discussions today, I'd like to float the idea of merging the Cell and Mut types into a single type called Cell. The reasoning here is basically that the two types are very similar in functionality, and the distinction between "lowercase-m mut" and "capital-M Mut" seems likely to be confusing to me. The resulting type, Cell, would have one byte of overhead over the enclosed type T (to support the empty/full/borrowed flags) and would support the following five basic operations: (1) `insert(&self, T)`: inserts a value of the appropriate type into an empty cell, failing if the cell is full; (2) `remove(&self) -> T`: removes a value from a full cell, failing if the cell is empty; (3) `with_imm_ref(&self, &fn(&T) -> R) -> R`: yields an immutable reference to the interior of the cell, failing if the cell is empty or is borrowed mutably; (4) `with_mut_ref(&self, &fn(&mut T) -> R) -> R`: yields a mutable reference to the interior of the cell, failing if the cell is empty or is borrowed immutably; (5) `status(&self) -> CellStatus`: returns the status of the cell, which is one of `Empty`, `Full`, `BorrowedImm`, or `BorrowedMut`. Under the hood, this would be implemented with unsafe code. The use cases here are: 1. As a friendlier replacement for mutable fields where you really want only a few fields of a structure to be mutable, and you don't want to have to use garbage collected `@mut` pointers. 2. Moving values out of closures that are not one-shot. I don't know how often this will occur in practice, but it seems prudent to have a story for the times when you actually need to do this. What I *don't* like about this scheme is that it means that the notion of a freezable data type is distinct once more from the notion of an owned data type. Not only does this result in added type system complexity, but it also means that Cells pollute data structures, making them non-ARCable. On the other hand, having the ability to make what essentially amounts to mutable fields without the borrowing problems that plagued mutable fields before is undeniably convenient. So I'm somewhat torn on this, and I'd be interested to hear what others think. Patrick From paul.stansifer at gmail.com Fri Feb 22 06:22:22 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Fri, 22 Feb 2013 09:22:22 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: References: Message-ID: Rust syntax expects a literal number in the `[T * n]` construct; from the parser's point of view, what it receives is an expression, without any information that it is a number. (There are internal reasons for this, but it also makes the behavior of `$` more consistent; for example, preventing Rust from having C's issue where everybody has to use lots of parentheses in macro definitions.) Implementing $n:integer in Rust is a possible solution, but not likely to happen very soon. Unfortunately, I can't think of a workaround that generates the same type. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Fri Feb 22 06:46:41 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 22 Feb 2013 09:46:41 -0500 Subject: [rust-dev] RFC: Merge Cell and Mut? In-Reply-To: <5127160F.9020402@mozilla.com> References: <5127160F.9020402@mozilla.com> Message-ID: <512784D1.2000807@alum.mit.edu> +1. I have been thinking for a while that freezability and constability will have to be separate anyhow. Oh well. It was nice while it lasted. On the topic of implementation strategies for internal types like Cell/ARC: At some point I was talking to brson about implementation strategies for things like Cells and Arcs. I was thinking that should allow you to label fields as `unsafe`, `unsafe mut`, and possibly also allow a volatile tag. In all cases, accesses to the field would require unsafe code. The unsafe flag serves as a warning that you will be mutating the field via transmuted pointers or other things. The mut declaration indicates whether the type should "appear as mutable" to the type system. In particular, ARCs have fields that are mutated when the ARC is copied or cloned, but the type itself should nonetheless appear immutable. Cells on the other hand have should not appear immutable. In both cases, to prevent incorrect LLVM optimization we need a way to indicate that this field may in fact be mutated in funny ways. This would ensure we don't supply LLVM incorrect alias/type information in the future. Similarly, it may or may not be worth adding some notion of volatile to warn LLVM that it must re-read from the value each time it is accessed; or perhaps we should just require that any value (like the ARC's ref count) which you suspect may be accessed across threads is only accessed by some intrinsics (we should probably just add an AtomicInteger type that enforces this, I guess). Niko Patrick Walton wrote: > Hi everyone, > > Based on some discussions today, I'd like to float the idea of merging > the Cell and Mut types into a single type called Cell. The reasoning > here is basically that the two types are very similar in > functionality, and the distinction between "lowercase-m mut" and > "capital-M Mut" seems likely to be confusing to me. > > The resulting type, Cell, would have one byte of overhead over the > enclosed type T (to support the empty/full/borrowed flags) and would > support the following five basic operations: > > (1) `insert(&self, T)`: inserts a value of the appropriate type into > an empty cell, failing if the cell is full; > > (2) `remove(&self) -> T`: removes a value from a full cell, failing if > the cell is empty; > > (3) `with_imm_ref(&self, &fn(&T) -> R) -> R`: yields an immutable > reference to the interior of the cell, failing if the cell is empty or > is borrowed mutably; > > (4) `with_mut_ref(&self, &fn(&mut T) -> R) -> R`: yields a mutable > reference to the interior of the cell, failing if the cell is empty or > is borrowed immutably; > > (5) `status(&self) -> CellStatus`: returns the status of the cell, > which is one of `Empty`, `Full`, `BorrowedImm`, or `BorrowedMut`. > > Under the hood, this would be implemented with unsafe code. > > The use cases here are: > > 1. As a friendlier replacement for mutable fields where you really > want only a few fields of a structure to be mutable, and you don't > want to have to use garbage collected `@mut` pointers. > > 2. Moving values out of closures that are not one-shot. I don't know > how often this will occur in practice, but it seems prudent to have a > story for the times when you actually need to do this. > > What I *don't* like about this scheme is that it means that the notion > of a freezable data type is distinct once more from the notion of an > owned data type. Not only does this result in added type system > complexity, but it also means that Cells pollute data structures, > making them non-ARCable. On the other hand, having the ability to make > what essentially amounts to mutable fields without the borrowing > problems that plagued mutable fields before is undeniably convenient. > > So I'm somewhat torn on this, and I'd be interested to hear what > others think. > > Patrick > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From clements at brinckerhoff.org Fri Feb 22 09:35:09 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 22 Feb 2013 09:35:09 -0800 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: References: Message-ID: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> On Feb 22, 2013, at 6:22 AM, Paul Stansifer wrote: > Rust syntax expects a literal number in the `[T * n]` construct; from the parser's point of view, what it receives is an expression, without any information that it is a number. (There are internal reasons for this, but it also makes the behavior of `$` more consistent; for example, preventing Rust from having C's issue where everybody has to use lots of parentheses in macro definitions.) Implementing $n:integer in Rust is a possible solution, but not likely to happen very soon. > > Unfortunately, I can't think of a workaround that generates the same type. More or less as a note to myself and Paul: I claim that this problem would be solved by a token-tree-based macro system. John From martindemello at gmail.com Fri Feb 22 09:44:23 2013 From: martindemello at gmail.com (Martin DeMello) Date: Fri, 22 Feb 2013 09:44:23 -0800 Subject: [rust-dev] RFC: Merge Cell and Mut? In-Reply-To: <5127160F.9020402@mozilla.com> References: <5127160F.9020402@mozilla.com> Message-ID: On Thu, Feb 21, 2013 at 10:54 PM, Patrick Walton wrote: > > (4) `with_mut_ref(&self, &fn(&mut T) -> R) -> R`: yields a mutable > reference to the interior of the cell, failing if the cell is empty or is > borrowed immutably; Does this mean you can borrow two mutable references to a cell's contents? martin From pwalton at mozilla.com Fri Feb 22 09:51:51 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Fri, 22 Feb 2013 09:51:51 -0800 Subject: [rust-dev] RFC: Merge Cell and Mut? In-Reply-To: References: <5127160F.9020402@mozilla.com> Message-ID: <5127B037.3040004@mozilla.com> On 2/22/13 9:44 AM, Martin DeMello wrote: > On Thu, Feb 21, 2013 at 10:54 PM, Patrick Walton wrote: >> >> (4) `with_mut_ref(&self, &fn(&mut T) -> R) -> R`: yields a mutable >> reference to the interior of the cell, failing if the cell is empty or is >> borrowed immutably; > > Does this mean you can borrow two mutable references to a cell's contents? No. Good catch :) Patrick From graydon at mozilla.com Fri Feb 22 10:51:21 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 22 Feb 2013 10:51:21 -0800 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <51256D4A.6020701@mozilla.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> Message-ID: <5127BE29.4090401@mozilla.com> On 13-02-20 04:41 PM, Brian Anderson wrote: > Because sometimes `mod driver;` means look in the current directory, and > sometimes it means look in a subdirectory, doing this would require > that, when the parser sees `pub mod driver;`: > > 1) look in the current directory for `driver.rs` > 2) if that fails, look in the `driver` directory for `mod.rs` > > That's not necessarily bad, but it's a small bit of non-obvious > behavior. I haven't been thrilled with the `mod.rs` convention (because > my emacs buffers all have the same name) so I haven't been using it on > new code, but I think if we go with the `lib.rs`/`bin.rs`/`pkg.rs` > naming for crates in packages, then we should also settle on `mod.rs` > for directory modules, in which case I think I'm fine with this change. Yeah. I was also thinking we should do this, and was considering the 2-step rule you describe above. I think it models the evolution of a library _reasonably_ well: you start by making foo.rs and then later it grows and you realize it's got submodules so change to foo/mod.rs and foo/otherstuff.rs etc. The rule above means most clients don't need to change as you refactor. It's convenient for developers and not entirely surprising for readers. (You'll probably want to double check that 1 and 2 are mutually exclusive though; that is, not-accept foo.rs when foo/mod.rs exists) -Graydon From niko at alum.mit.edu Fri Feb 22 12:05:43 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 22 Feb 2013 15:05:43 -0500 Subject: [rust-dev] RFC: Bless mod.rs In-Reply-To: <5127BE29.4090401@mozilla.com> References: <16807682.826701361351729631.JavaMail.weblogic@epv6ml04> <51256D4A.6020701@mozilla.com> <5127BE29.4090401@mozilla.com> Message-ID: <5127CF97.2040706@alum.mit.edu> +1 Graydon Hoare wrote: > On 13-02-20 04:41 PM, Brian Anderson wrote: > >> Because sometimes `mod driver;` means look in the current directory, and >> sometimes it means look in a subdirectory, doing this would require >> that, when the parser sees `pub mod driver;`: >> >> 1) look in the current directory for `driver.rs` >> 2) if that fails, look in the `driver` directory for `mod.rs` >> >> That's not necessarily bad, but it's a small bit of non-obvious >> behavior. I haven't been thrilled with the `mod.rs` convention (because >> my emacs buffers all have the same name) so I haven't been using it on >> new code, but I think if we go with the `lib.rs`/`bin.rs`/`pkg.rs` >> naming for crates in packages, then we should also settle on `mod.rs` >> for directory modules, in which case I think I'm fine with this change. > > Yeah. I was also thinking we should do this, and was considering the > 2-step rule you describe above. I think it models the evolution of a > library _reasonably_ well: you start by making foo.rs and then later it > grows and you realize it's got submodules so change to foo/mod.rs and > foo/otherstuff.rs etc. The rule above means most clients don't need to > change as you refactor. It's convenient for developers and not entirely > surprising for readers. > > (You'll probably want to double check that 1 and 2 are mutually > exclusive though; that is, not-accept foo.rs when foo/mod.rs exists) > > -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 graydon at mozilla.com Fri Feb 22 12:14:05 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 22 Feb 2013 12:14:05 -0800 Subject: [rust-dev] bundling gcc In-Reply-To: <51261136.7020701@strapper.net> References: <51261136.7020701@strapper.net> Message-ID: <5127D18D.7070401@mozilla.com> On 13-02-21 04:21 AM, Bruce M. Axtens wrote: > Those who wander aimlessly about the internet may have noticed > http://www.harbour-project.org . These folk distribute their preferred > version of gcc in their installer. Is there any chance that Rust could > do the same (for us folk who already have MinGW with a more recent > version of gcc in it.) It's possible but at this point would be quite an adventure in packaging. I think the effort would be better be spent on the other, related matters. Possibly the easiest route to diminishing the problems here would be to include _clang_ (which we already build while building LLVM) in our snapshots, and use the snapshot-clang to (re)build LLVM and the rest of the C/C++ bits of our runtime. Unfortunately even in that case clang still needs a platform linker for its final link -- lld isn't done yet -- but I don't think platform ld / gold / link.exe drift is nearly as likely to be a source of incompatibility as platform gcc drift. So long as clang can find _some_ platform linker, I think it's happy. We do eventually want to get away from building LLVM in-tree but we're committed-enough to needing-LLVM (and libclang for bindgen) that we're pretty much always going to have it around _somehow_. Might as well. -Graydon From graydon at mozilla.com Fri Feb 22 12:27:02 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 22 Feb 2013 12:27:02 -0800 Subject: [rust-dev] RFC: Merge Cell and Mut? In-Reply-To: <5127160F.9020402@mozilla.com> References: <5127160F.9020402@mozilla.com> Message-ID: <5127D496.8060702@mozilla.com> On 13-02-21 10:54 PM, Patrick Walton wrote: > Hi everyone, > > Based on some discussions today, I'd like to float the idea of merging > the Cell and Mut types into a single type called Cell. The reasoning > here is basically that the two types are very similar in functionality, > and the distinction between "lowercase-m mut" and "capital-M Mut" seems > likely to be confusing to me. I'm certainly keen on getting rid of Mut. But I talked briefly with Niko on IRC about this and got the impression that it might not be too zany to counter-propose removing Cell as well (at least once we h ave once functions). Which I shall now do: can we remove both? In particular, I feel like Cell (as presented here) is, much like the quickly-vanishing mut fields, a mechanism for breaking the type system, or for aspects of the type system we want to be true and have been pushing towards making-true, but aren't currently (as you say: the freezable == owned identity). I'd prefer we keep moving towards having one blessed-and-safe mechanism for this (@mut) and one unsafe mechanism (*mut) that you're responsible for wrapping up in an API that doesn't shoot yourself in the foot, and file down the remaining type system complexity so people can predict freeze/thaw, ARC-based sharing and such by reasoning about the rules, not worrying about the presence of a rule-breaking substructure. I realize this means you get a level of indirection when you use mutability inside a non-owned structure. This is a potential perf cost, but I don't know how common it'll be in practice. So far it seems like things that are perf sensitive are leaning towards Owned in most cases anyways (and if not due to only-using-~[], then using some unsafe bits that respect Owned semantics and are hidden inside a safe Owned API). I'm willing to bet this will not be an overriding perf sore spot, at this point. Also recognize that this requires us to get once functions working, and may not provide an answer for moving out of non-once closures. Not convinced this is a bad enough case to warrant Cell. Might be wrong. -Graydon From clements at brinckerhoff.org Fri Feb 22 13:47:44 2013 From: clements at brinckerhoff.org (John Clements) Date: Fri, 22 Feb 2013 13:47:44 -0800 Subject: [rust-dev] opinions about splicing macros / other items? Message-ID: <3BDF6059-C08D-4959-A256-32F29C2B117F@brinckerhoff.org> I've added scope to macros on my personal branch, and it immediately heightens the need for splicing item macros. Paul, I know you've thought about this a couple of times. I see two obvious solutions. 1) enrich "fold" to make it possible to return multiple items in some contexts. 2) add a "group" form--much like a block--that's silently flattened by the expander. I think I'm leaning toward #2, because it immediately works for pattern-based macros, rather than requiring a special "this is multiple forms" annotation. Thoughts? John From graydon at mozilla.com Fri Feb 22 14:01:53 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 22 Feb 2013 14:01:53 -0800 Subject: [rust-dev] opinions about splicing macros / other items? In-Reply-To: <3BDF6059-C08D-4959-A256-32F29C2B117F@brinckerhoff.org> References: <3BDF6059-C08D-4959-A256-32F29C2B117F@brinckerhoff.org> Message-ID: <5127EAD1.9070606@mozilla.com> On 13-02-22 01:47 PM, John Clements wrote: > I've added scope to macros on my personal branch, and it immediately heightens the need for splicing item macros. Paul, I know you've thought about this a couple of times. I see two obvious solutions. > > 1) enrich "fold" to make it possible to return multiple items in some contexts. > 2) add a "group" form--much like a block--that's silently flattened by the expander. > > I think I'm leaning toward #2, because it immediately works for pattern-based macros, rather than requiring a special "this is multiple forms" annotation. > > Thoughts? - I don't really understand #1. It's just the same idea but in fold, not expand? - #2 will vanish into thin air when/if results are token trees, yes? - the folder might, itself, also vanish someday, since expander is the main user and it might wind up expanding TTs, not ASTs, yes? -Graydon From graydon at mozilla.com Fri Feb 22 17:07:45 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 22 Feb 2013 17:07:45 -0800 Subject: [rust-dev] library editing Message-ID: <51281661.6030005@mozilla.com> Hi, After some consultation with the rest of the core rust developer group, I've posted some new guidelines concerning editing rust's libraries: https://github.com/mozilla/rust/wiki/Libs https://github.com/mozilla/rust/wiki/Library-editing In particular, the point of these is to _expedite library evolution_ by providing specific, objective (ish) criteria for library development, and introducing an additional project role ("library editors"), who are permitted to review conforming library work and have bors auto-merge it. These guidelines are mostly my own preferences, along with feedback from the other core developers; if you think these guidelines are bogus of course now is a good time to say so. My goal is to expand, in a controlled and predictable fashion, the set of people with ownership over our our libraries. Please let me know if you have any additional thoughts on the matter; I'm naturally a little uncertain about how to proceed here but I'm feeling like the core moco-employees are a bit of a bottleneck to library-evolution, and now that the language itself is stabilizing (ish) it might be a good time to invite more people to participate in the libraries. -Graydon From brandon at mintern.net Fri Feb 22 20:43:20 2013 From: brandon at mintern.net (Brandon Mintern) Date: Fri, 22 Feb 2013 20:43:20 -0800 Subject: [rust-dev] library editing In-Reply-To: <51281661.6030005@mozilla.com> References: <51281661.6030005@mozilla.com> Message-ID: As someone who is just getting into Rust development, I appreciate this documentation. Thanks! On Fri, Feb 22, 2013 at 5:07 PM, Graydon Hoare wrote: > Hi, > > After some consultation with the rest of the core rust developer group, > I've posted some new guidelines concerning editing rust's libraries: > > https://github.com/mozilla/rust/wiki/Libs > https://github.com/mozilla/rust/wiki/Library-editing > > In particular, the point of these is to _expedite library evolution_ by > providing specific, objective (ish) criteria for library development, > and introducing an additional project role ("library editors"), who are > permitted to review conforming library work and have bors auto-merge it. > > These guidelines are mostly my own preferences, along with feedback from > the other core developers; if you think these guidelines are bogus of > course now is a good time to say so. My goal is to expand, in a > controlled and predictable fashion, the set of people with ownership > over our our libraries. > > Please let me know if you have any additional thoughts on the matter; > I'm naturally a little uncertain about how to proceed here but I'm > feeling like the core moco-employees are a bit of a bottleneck to > library-evolution, and now that the language itself is stabilizing (ish) > it might be a good time to invite more people to participate in the > libraries. > > -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 marcianx at gmail.com Sat Feb 23 21:06:44 2013 From: marcianx at gmail.com (Ashish Myles) Date: Sun, 24 Feb 2013 00:06:44 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> References: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> Message-ID: On Fri, Feb 22, 2013 at 12:35 PM, John Clements wrote: > > On Feb 22, 2013, at 6:22 AM, Paul Stansifer wrote: > > > Rust syntax expects a literal number in the `[T * n]` construct; from the parser's point of view, what it receives is an expression, without any information that it is a number. (There are internal reasons for this, but it also makes the behavior of `$` more consistent; for example, preventing Rust from having C's issue where everybody has to use lots of parentheses in macro definitions.) Implementing $n:integer in Rust is a possible solution, but not likely to happen very soon. > > > > Unfortunately, I can't think of a workaround that generates the same type. > > More or less as a note to myself and Paul: I claim that this problem would be solved by a token-tree-based macro system. > > John > I just want to add for consideration: I hope the (eventually) implemented solution allows compile-time evaluable integer expressions for maximal expressivity. Same thing for $n:bool, etc, if implemented. Thanks, Ashish From marcianx at gmail.com Sun Feb 24 12:03:49 2013 From: marcianx at gmail.com (Ashish Myles) Date: Sun, 24 Feb 2013 15:03:49 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: References: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> Message-ID: On Sun, Feb 24, 2013 at 12:06 AM, Ashish Myles wrote: > On Fri, Feb 22, 2013 at 12:35 PM, John Clements > wrote: >> >> On Feb 22, 2013, at 6:22 AM, Paul Stansifer wrote: >> >> > Rust syntax expects a literal number in the `[T * n]` construct; from the parser's point of view, what it receives is an expression, without any information that it is a number. (There are internal reasons for this, but it also makes the behavior of `$` more consistent; for example, preventing Rust from having C's issue where everybody has to use lots of parentheses in macro definitions.) Implementing $n:integer in Rust is a possible solution, but not likely to happen very soon. >> > >> > Unfortunately, I can't think of a workaround that generates the same type. >> >> More or less as a note to myself and Paul: I claim that this problem would be solved by a token-tree-based macro system. >> >> John >> > > I just want to add for consideration: I hope the (eventually) > implemented solution allows compile-time evaluable integer expressions > for maximal expressivity. Same thing for $n:bool, etc, if implemented. > Wait a sec...I guess we are barking up the wrong tree. The problem is not that rust macros don't support $n:integer, but that static array initialization seem to require a raw integer literal (possibly at the parsing level). One can imagine designing a statically-allocated matrix for size C1 x C2 that would allocate similar to: const C1 : int = 2; const C2 : int = 2; let a : [int * (C1*C2)] = [1,2,3,4]; But the code above gives the following error error: expected integral vector length but found `(` If this misbehavior were fixed, I think the macro system would not need to accommodate ints and other types specially, keeping it fundamentally simpler. I would think that anything that requires a compile-time integer should be able to receive a compile-time evaluable integer expression. Ideally, it would be great if Rust went further to allow something like let a : [int * choose(C1, C2)]; or const C3 = choose(C1, C2); let a : [int * C3]; where choose is a pure function that returns n-choose-k. Any thoughts? Ashish From marcianx at gmail.com Sun Feb 24 12:06:49 2013 From: marcianx at gmail.com (Ashish Myles) Date: Sun, 24 Feb 2013 15:06:49 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: References: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> Message-ID: On Sun, Feb 24, 2013 at 3:03 PM, Ashish Myles wrote: > > Wait a sec...I guess we are barking up the wrong tree. The problem is > not that rust macros don't support $n:integer, but that static array > initialization seem to require a raw integer literal (possibly at the > parsing level). One can imagine designing a statically-allocated > matrix for size C1 x C2 that would allocate similar to: > const C1 : int = 2; > const C2 : int = 2; > let a : [int * (C1*C2)] = [1,2,3,4]; > But the code above gives the following error > error: expected integral vector length but found `(` > To slightly modify this example to be more realistic, I would do let a : [int * (C1*C2)] = [0, ..(C1*C2)]; so that the initializer expression should also be valid. Ashish > If this misbehavior were fixed, I think the macro system would not > need to accommodate ints and other types specially, keeping it > fundamentally simpler. I would think that anything that requires a > compile-time integer should be able to receive a compile-time > evaluable integer expression. Ideally, it would be great if Rust went > further to allow something like > let a : [int * choose(C1, C2)]; > or > const C3 = choose(C1, C2); > let a : [int * C3]; > where choose is a pure function that returns n-choose-k. > > Any thoughts? > Ashish From sh4.seo at samsung.com Sun Feb 24 21:48:18 2013 From: sh4.seo at samsung.com (Sanghyeon Seo) Date: Mon, 25 Feb 2013 05:48:18 +0000 (GMT) Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? Message-ID: <25551074.34121361771298153.JavaMail.weblogic@epml20> > Wait a sec...I guess we are barking up the wrong tree. The problem is > not that rust macros don't support $n:integer, but that static array > initialization seem to require a raw integer literal (possibly at the > parsing level). One can imagine designing a statically-allocated > matrix for size C1 x C2 that would allocate similar to: > const C1 : int = 2; > const C2 : int = 2; > let a : [int * (C1*C2)] = [1,2,3,4]; > But the code above gives the following error > error: expected integral vector length but found `(` This is issue #3469. https://github.com/mozilla/rust/issues/3469 From pauls at ccs.neu.edu Mon Feb 25 08:17:11 2013 From: pauls at ccs.neu.edu (Paul Stansifer) Date: Mon, 25 Feb 2013 11:17:11 -0500 Subject: [rust-dev] opinions about splicing macros / other items? In-Reply-To: <5127EAD1.9070606@mozilla.com> References: <3BDF6059-C08D-4959-A256-32F29C2B117F@brinckerhoff.org> <5127EAD1.9070606@mozilla.com> Message-ID: #2 had never occurred to me. I think I lean toward it, since it has the potential to be a simpler implementation. (And you could even use it to clean up the crufty can't-happen errors that I introduced when I made fold able to fold into zero items.) Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter.ronnquist at gmail.com Mon Feb 25 04:20:58 2013 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Mon, 25 Feb 2013 13:20:58 +0100 Subject: [rust-dev] troubles to use vec::filter() when pattern matching a vector Message-ID: I'm having troubles to use vec::filter() when pattern matching a vector: fn main() { let objs = ~[1, 3, 2]; fn isClose(a: int, b: int)-> bool { if (a-b <1) {true} else {false} } match objs { // Construct new integer vector that contains integers that are similar to the head. [head, ..tail] => vec::filter( tail, |obj| isClose(head, *obj)) , [] => ~[] }; } rustc tail_test.rs tail_test.rs:11:39: 11:43 error: mismatched types: expected `~[]` but found `&/[]` ([] storage differs: expected ~ but found &) tail_test.rs:11 [head, ..tail] => vec::filter( tail, |obj| isClose(head, *obj)) , ^~~~ $ rustc -v rustc 0.6 (b26d434 2013-02-24 10:57:16 -0800) host: x86_64-unknown-linux-gnu It seems like tail is a & type and not a ~ that I expected. Any thoughts on this? Thanks in advance, Peter From ben.striegel at gmail.com Mon Feb 25 12:03:55 2013 From: ben.striegel at gmail.com (Benjamin Striegel) Date: Mon, 25 Feb 2013 15:03:55 -0500 Subject: [rust-dev] troubles to use vec::filter() when pattern matching a vector In-Reply-To: References: Message-ID: I wonder if vec::filter ought to be rewritten to take &[] rather than ~[]. It's possible this decision was just a legacy one, but I'm not sure if there are technical obstacles. On Mon, Feb 25, 2013 at 7:20 AM, Peter Ronnquist wrote: > I'm having troubles to use vec::filter() when pattern matching a vector: > > fn main() { > > let objs = ~[1, 3, 2]; > > fn isClose(a: int, b: int)-> bool { > if (a-b <1) {true} else {false} > } > match objs { > // Construct new integer vector that contains integers that > are similar to the head. > [head, ..tail] => vec::filter( tail, |obj| isClose(head, *obj)) , > [] => ~[] > }; > } > > rustc tail_test.rs > tail_test.rs:11:39: 11:43 error: mismatched types: expected `~[]` > but found `&/[]` ([] storage differs: expected ~ but found &) > tail_test.rs:11 [head, ..tail] => vec::filter( tail, |obj| > isClose(head, *obj)) , > ^~~~ > $ rustc -v > rustc 0.6 (b26d434 2013-02-24 10:57:16 -0800) > host: x86_64-unknown-linux-gnu > > It seems like tail is a & type and not a ~ that I expected. > Any thoughts on this? > > Thanks in advance, > Peter > _______________________________________________ > 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 Tue Feb 26 02:56:12 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 26 Feb 2013 05:56:12 -0500 Subject: [rust-dev] troubles to use vec::filter() when pattern matching a vector In-Reply-To: References: Message-ID: <512C94CC.6060502@alum.mit.edu> Use vec::filtered(). vec::filter() works only on ~[T] and consumes its argument (so you cannot use it again) and vec::filtered() does not. This naming convention is probably too subtle and is also not entirely consistent across vec functions. Niko > Peter Ronnquist > February 25, 2013 7:20 AM > I'm having troubles to use vec::filter() when pattern matching a vector: > > fn main() { > > let objs = ~[1, 3, 2]; > > fn isClose(a: int, b: int)-> bool { > if (a-b <1) {true} else {false} > } > match objs { > // Construct new integer vector that contains integers that > are similar to the head. > [head, ..tail] => vec::filter( tail, |obj| isClose(head, *obj)) , > [] => ~[] > }; > } > > rustc tail_test.rs > tail_test.rs:11:39: 11:43 error: mismatched types: expected `~[]` > but found `&/[]` ([] storage differs: expected ~ but found &) > tail_test.rs:11 [head, ..tail] => vec::filter( tail, |obj| > isClose(head, *obj)) , > ^~~~ > $ rustc -v > rustc 0.6 (b26d434 2013-02-24 10:57:16 -0800) > host: x86_64-unknown-linux-gnu > > It seems like tail is a & type and not a ~ that I expected. > Any thoughts on this? > > Thanks in advance, > Peter > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From niko at alum.mit.edu Tue Feb 26 05:53:14 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 26 Feb 2013 08:53:14 -0500 Subject: [rust-dev] Warning: region syntax changes progressing Message-ID: <512CBE4A.8090606@alum.mit.edu> Hello, Once I finish up my latest pull request, the first non-backwards-compatible steps toward the new lifetime syntax will be in place. I'll try to send a mail for each change that requires modifying source code. Note: since the pull request hasn't landed yet, the changes I describe below are not yet mandatory, but they will still work even now. In particular: - you can now use the 'foo lifetime notation, though you don't have to (emacs users, if you update your emacs-mode the syntax highlighter will recognize 'foo. vi users, you're on your own). Once we do a snapshot, the 'foo notation will become mandatory. (Note: within the compiler, you should stick to &foo/Bar and Bar/&foo until we do a snapshot) - the defaults are changing. First, you can no longer use anonymous lifetime references outside of functions. Second, a type like &'a Foo where Foo contains borrowed pointers used to default to &'a Foo<'a>. You must now write that explicitly, otherwise it defaults to &'a Foo<'b>. That is, the lifetime parameter to Foo used to default to the same lifetime as the enclosing borrowed pointer, if any, but now all omitted lifetimes default to fresh lifetimes. So more concretely, a type definition like so: type MapUint = &fn(uint) -> uint; should be changed to: type MapUint<'self> = &'self fn(uint) -> uint; The `<'self>` declaration is currently inferred if you leave it off, but I have changes in place to disable that. For now, you *MUST* call the lifetime parameter `'self`. This too will change eventually. Similarly, a struct definition like: struct MyStruct { map_fn: MapUint, // same as above slice: &[uint] } should be changed to: struct MyStruct<'self> { map_fn: MapUint<'self>, slice: &'self [uint] } As before, for the moment, the `<'self>` definition is currently optional and the lifetime parameter must be called 'self, but this will change. Niko From sh4.seo at samsung.com Tue Feb 26 06:29:09 2013 From: sh4.seo at samsung.com (Sanghyeon Seo) Date: Tue, 26 Feb 2013 14:29:09 +0000 (GMT) Subject: [rust-dev] Warning: region syntax changes progressing Message-ID: <3084785.122631361888949454.JavaMail.weblogic@epml04> > - you can now use the 'foo lifetime notation, though you don't have to > (emacs users, if you update your emacs-mode the syntax highlighter will > recognize 'foo. vi users, you're on your own). Once we do a snapshot, > the 'foo notation will become mandatory. (Note: within the compiler, you > should stick to &foo/Bar and Bar/&foo until we do a snapshot) Vim users, FYI, updated Vim syntax highlighting is already in the Git master. From paul.stansifer at gmail.com Tue Feb 26 10:13:33 2013 From: paul.stansifer at gmail.com (Paul Stansifer) Date: Tue, 26 Feb 2013 13:13:33 -0500 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> References: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> Message-ID: > More or less as a note to myself and Paul: I claim that this problem > would be solved by a token-tree-based macro system. There's another consequence of a such a macro system related to this: You could write `[T * some_macro!(...)]`, but only on the right-hand side of a macro definition. It can't appear in plain code still, because it would need a place in the AST. Currently, the RHS of a macro definition is treated much more like "ordinary" code. Paul -------------- next part -------------- An HTML attachment was scrubbed... URL: From graydon at mozilla.com Tue Feb 26 14:10:03 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 26 Feb 2013 14:10:03 -0800 Subject: [rust-dev] I wanted a dollar but you gave me a ... dollar? In-Reply-To: References: <6804441E-5B2F-4CED-AC9C-1E05DC3205F3@brinckerhoff.org> Message-ID: <512D32BB.5020508@mozilla.com> On 13-02-24 12:06 PM, Ashish Myles wrote: > On Sun, Feb 24, 2013 at 3:03 PM, Ashish Myles wrote: >> >> Wait a sec...I guess we are barking up the wrong tree. The problem is >> not that rust macros don't support $n:integer, but that static array >> initialization seem to require a raw integer literal (possibly at the >> parsing level). One can imagine designing a statically-allocated >> matrix for size C1 x C2 that would allocate similar to: >> const C1 : int = 2; >> const C2 : int = 2; >> let a : [int * (C1*C2)] = [1,2,3,4]; >> But the code above gives the following error >> error: expected integral vector length but found `(` >> > > To slightly modify this example to be more realistic, I would do > let a : [int * (C1*C2)] = [0, ..(C1*C2)]; > so that the initializer expression should also be valid. Agreed. This has been open for a while: https://github.com/mozilla/rust/issues/3469 There's some discussion in there about intertwining const eval and typechecking. I'm still nervous about that, as I was back when I wrote this comment: https://github.com/mozilla/rust/issues/2317#issuecomment-5633079 but it seems we're sliding down the slippery slope I'm concerned about. We'll see how far down it goes. I hope not all the way to C++-ish constexpr. -Graydon From nathanfiedler at gmail.com Tue Feb 26 17:25:30 2013 From: nathanfiedler at gmail.com (Nathan Fiedler) Date: Tue, 26 Feb 2013 17:25:30 -0800 Subject: [rust-dev] Questions on language tutorial Message-ID: Hello all I was reading the language tutorial and had a couple of questions. I hope this is the appropriate forum for asking them. In section 4.1 the example has "return 0", seemingly as an expression. Is that correct usage? Should it not simply be "0" instead? Section 5.3 describes tuples and the ways in which you _cannot_ access the fields (i.e. not by name or dot notation). So I'm left wondering how one accesses the fields of a tuple. Must it always be through pattern matching? Thanks n -------------- next part -------------- An HTML attachment was scrubbed... URL: From pwalton at mozilla.com Tue Feb 26 17:30:43 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 26 Feb 2013 17:30:43 -0800 Subject: [rust-dev] Questions on language tutorial In-Reply-To: References: Message-ID: <512D61C3.7020308@mozilla.com> On 2/26/13 5:25 PM, Nathan Fiedler wrote: > Hello all > > I was reading the language tutorial and had a couple of questions. I > hope this is the appropriate forum for asking them. > > In section 4.1 the example has "return 0", seemingly as an expression. > Is that correct usage? Should it not simply be "0" instead? `return 0` is an expression in Rust. The typechecker considers the type of a `return` expression compatible with every other type. This is because the form causes the function to immediately exit, so the "result" of `return` is meaningless. > Section 5.3 describes tuples and the ways in which you _cannot_ access > the fields (i.e. not by name or dot notation). So I'm left wondering how > one accesses the fields of a tuple. Must it always be through pattern > matching? In the core language you have to use pattern matching. But there are methods in `core::tuple` that provide `.first()` and `.second()` convenience methods. Patrick From niko at alum.mit.edu Wed Feb 27 07:36:22 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 27 Feb 2013 10:36:22 -0500 Subject: [rust-dev] parsing, ambiguity, and empty structs Message-ID: <512E27F6.7060908@alum.mit.edu> A recent and very welcome pull request [1] pointed out Yet Another Ambiguity around struct syntax. If you have something like this: ... match x { ... is that "match (x {})", where `x` is the name of a struct literal, or `match x {` where `x` is the variable being matched and what follows are the arms? Before I go any further, I want to emphasize that I am not picking on the author of the pull request. As I said, it's excellent work and the author made a logical decision on how to proceed with the ambiguity. However, since it is dealing with our grammar, it seems like we should decide how to resolve this with more discussion than a review on a pull request, so I thought I'd write up an e-mail describing the issue and gather some feedback. Now, to some extent, you can resolve this if there are fields present because the code would look like: ... match x { field: ... However, this breaks down if you have empty structs, which didn't used to be allowed but currently are. Plus it requires more lookahead, clearly, though not an indeterminate amount. The pull request took the approach of parsing `match x {}` as an empty struct literal and thus to write a match with no arms (an admittedly bizarre thing to write) one must write `match (x) {}`. This is reasonable but I find it personally somewhat surprising that `match x { }` would not parse (...and then likely lead to an exhaustiveness checking failure). However, this same ambiguity arises in a lot of places: if/else-if expressions, match expressions, `do` and `for` expressions, and perhaps a few others. Currently I *think* we use lookahead for field names to resolve the ambiguity that arises with struct literals, but of course this doesn't work with empty structs. I'd like it if we could resolve this in a uniform way. I see various options: 1. Treat Foo {} as a struct literal, requiring parentheses to disambiguate in some cases (e.g., `if (x) {}`). This is what the pull request does. 2. Declare that `Foo { ... }` literals must always have at least one field, and use newtype structs for the empty struct case. 3. Place a parser restriction on those contexts where `{` terminates the expression and say that struct literals cannot appear there unless they are in parentheses. Some details follow. ### Treat `Foo {}` as a struct literal I don't have anything more to say about this approach. =) ### Treat empty structs the way we treat enum variants? Perhaps we should just not parse a declaration like: struct X {} instead one would write something like: struct X; or struct X(); Much as you write enum Foo { Y } This would be a "new-type" struct so X would also serve as a value, just like the constant `Y` in the enum case. This would mean that one never writes a struct literal `Foo {}` but instead just `Foo`. ### Restrict where struct literals can appear We could also just have a subclass of expressions which can appear in `if`, `do`, etc. This subclass would not permit struct literals. That means that `if Foo {x: 10}.is_true {}` or something would have to be written `if (Foo { x: 10 }.is_true()) { ... }`. This rule implies that very little lookahead is needed. Such rules can be a pain for the pretty printer, however. To some extent we already have a rule like this for `do` and `for`, since we will parse: ...for x.each |y... as a method call with one argument and not `(x.each | y)`. Since this rule would presumably not apply to `if` etc, there would actually be three classes of expressions, those that can appear in `if`, those that can appear in `do`/`for`, and full expressions. ### My personal opinion I started out preferring the final option, but I am now leaning towards option #2, which seems to simplify the grammar overall and still requires only fixed lookahead to disambiguate. Niko [1] https://github.com/mozilla/rust/pull/5137 From pwalton at mozilla.com Wed Feb 27 08:34:55 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 27 Feb 2013 08:34:55 -0800 Subject: [rust-dev] parsing, ambiguity, and empty structs In-Reply-To: <512E27F6.7060908@alum.mit.edu> References: <512E27F6.7060908@alum.mit.edu> Message-ID: <512E35AF.4050205@mozilla.com> On 2/27/13 7:36 AM, Niko Matsakis wrote: > ### Treat empty structs the way we treat enum variants? > > Perhaps we should just not parse a declaration like: > struct X {} > instead one would write something like: > struct X; > or > struct X(); > Much as you write > enum Foo { Y } > This would be a "new-type" struct so X would also serve as a value, just > like the constant `Y` in the enum case. This would mean that one never > writes a struct literal `Foo {}` but instead just `Foo`. `struct X;` already works today. I implemented it a few months ago. It's used in sprocketnes, and a couple of places in Servo IIRC. So I vote for disallowing `struct X {}` entirely. Patrick From graydon at mozilla.com Wed Feb 27 08:38:45 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 27 Feb 2013 08:38:45 -0800 Subject: [rust-dev] parsing, ambiguity, and empty structs In-Reply-To: <512E35AF.4050205@mozilla.com> References: <512E27F6.7060908@alum.mit.edu> <512E35AF.4050205@mozilla.com> Message-ID: <512E3695.2030806@mozilla.com> On 27/02/2013 8:34 AM, Patrick Walton wrote: > So I vote for disallowing `struct X {}` entirely. Yeah. This potential-ambiguity between brace-using values and control blocks is old; it existed under structural records as well and my feeling then as now was that the first label disambiguates, meaning there must be one label. -Graydon From peter.ronnquist at gmail.com Tue Feb 26 14:16:07 2013 From: peter.ronnquist at gmail.com (Peter Ronnquist) Date: Tue, 26 Feb 2013 23:16:07 +0100 Subject: [rust-dev] troubles to use vec::filter() when pattern matching a vector In-Reply-To: <512C94CC.6060502@alum.mit.edu> References: <512C94CC.6060502@alum.mit.edu> Message-ID: Thank you, I appreciate all the good feedback! On Tue, Feb 26, 2013 at 11:56 AM, Niko Matsakis wrote: > Use vec::filtered(). vec::filter() works only on ~[T] and consumes its > argument (so you cannot use it again) and vec::filtered() does not. This > naming convention is probably too subtle and is also not entirely > consistent across vec functions. > > > > Niko > > Peter Ronnquist > February 25, 2013 7:20 AM > I'm having troubles to use vec::filter() when pattern matching a vector: > > fn main() { > > let objs = ~[1, 3, 2]; > > fn isClose(a: int, b: int)-> bool { > if (a-b <1) {true} else {false} > } > match objs { > // Construct new integer vector that contains integers that > are similar to the head. > [head, ..tail] => vec::filter( tail, |obj| isClose(head, *obj)) , > [] => ~[] > }; > } > > rustc tail_test.rs > tail_test.rs:11:39: 11:43 error: mismatched types: expected `~[]` > but found `&/[]` ([] storage differs: expected ~ but found &) > tail_test.rs:11 [head, ..tail] => vec::filter( tail, |obj| > isClose(head, *obj)) , > ^~~~ > $ rustc -v > rustc 0.6 (b26d434 2013-02-24 10:57:16 -0800) > host: x86_64-unknown-linux-gnu > > It seems like tail is a & type and not a ~ that I expected. > Any thoughts on this? > > Thanks in advance, > Peter > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: From niko at alum.mit.edu Wed Feb 27 16:04:49 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 27 Feb 2013 19:04:49 -0500 Subject: [rust-dev] windows: error 101 Message-ID: <512E9F21.9070605@alum.mit.edu> All my recent pull requests (and those of many others, I suspect) have failed due to Windows Error 101 (e.g., [1]). I don't know what this is but I doubt it's related to my various changes. Anybody know what this error means? A brief Google search did not turn up anything. Niko [1] http://buildbot.rust-lang.org/builders/auto-win/builds/267/steps/compile/logs/stdio From pwalton at mozilla.com Wed Feb 27 16:05:46 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 27 Feb 2013 16:05:46 -0800 Subject: [rust-dev] windows: error 101 In-Reply-To: <512E9F21.9070605@alum.mit.edu> References: <512E9F21.9070605@alum.mit.edu> Message-ID: <512E9F5A.1000601@mozilla.com> On 2/27/13 4:04 PM, Niko Matsakis wrote: > All my recent pull requests (and those of many others, I suspect) have > failed due to Windows Error 101 (e.g., [1]). I don't know what this is > but I doubt it's related to my various changes. Anybody know what this > error means? A brief Google search did not turn up anything. I believe it's a segfault. Patrick From banderson at mozilla.com Wed Feb 27 16:51:56 2013 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 27 Feb 2013 16:51:56 -0800 Subject: [rust-dev] windows: error 101 In-Reply-To: <512E9F21.9070605@alum.mit.edu> References: <512E9F21.9070605@alum.mit.edu> Message-ID: <512EAA2C.6000306@mozilla.com> On 02/27/2013 04:04 PM, Niko Matsakis wrote: > All my recent pull requests (and those of many others, I suspect) have > failed due to Windows Error 101 (e.g., [1]). I don't know what this > is but I doubt it's related to my various changes. Anybody know what > this error means? A brief Google search did not turn up anything. > > > Niko > > [1] > http://buildbot.rust-lang.org/builders/auto-win/builds/267/steps/compile/logs/stdio > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev 101 is the default failure return code of the Rust runtime. From niko at alum.mit.edu Wed Feb 27 18:02:45 2013 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 27 Feb 2013 21:02:45 -0500 Subject: [rust-dev] windows: error 101 In-Reply-To: <512EAA2C.6000306@mozilla.com> References: <512E9F21.9070605@alum.mit.edu> <512EAA2C.6000306@mozilla.com> Message-ID: <512EBAC5.1080005@alum.mit.edu> Thanks. I was mistaken in saying that all of my pull requests failed the same way, I must have gotten my tabs confused. So it seems this failure is less widespread than I originally thought. Niko > Brian Anderson > February 27, 2013 7:51 PM > > > 101 is the default failure return code of the Rust runtime. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > Niko Matsakis > February 27, 2013 7:04 PM > All my recent pull requests (and those of many others, I suspect) have > failed due to Windows Error 101 (e.g., [1]). I don't know what this > is but I doubt it's related to my various changes. Anybody know what > this error means? A brief Google search did not turn up anything. > > > Niko > > [1] > http://buildbot.rust-lang.org/builders/auto-win/builds/267/steps/compile/logs/stdio > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: compose-unknown-contact.jpg Type: image/jpeg Size: 770 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: postbox-contact.jpg Type: image/jpeg Size: 1219 bytes Desc: not available URL: From ikadro+rust at gmail.com Wed Feb 27 22:38:19 2013 From: ikadro+rust at gmail.com (Cha, Hojeong) Date: Thu, 28 Feb 2013 15:38:19 +0900 Subject: [rust-dev] Internationalization of Rust Documents Message-ID: Hello everyone, I think many developers have an interest in learning Rust via tutorial. But the current tutorial is written in English, so it precludes many potential developers which English is not his/her native language. So I thought that it would be beneficial to internationalize Rust documents, or at least have a base-level work for internationalization. There would be many ways that such internationalization can be done, and I tried to find the tool which is familiar to the developers and able to update documents whenever the original document had changed; "gettext" came into my mind, so I lightly prototyped it (in my native tongue, Korean): https://gist.github.com/karipe/330d1ce1f0dbbf67abf0#file-tutorial_ko-md I would like to hear your opinions about this way of internationalization. Regards, Cha, Hojeong -------------- next part -------------- An HTML attachment was scrubbed... URL: From lucab at debian.org Thu Feb 28 00:00:48 2013 From: lucab at debian.org (Luca BRUNO) Date: Thu, 28 Feb 2013 09:00:48 +0100 Subject: [rust-dev] Internationalization of Rust Documents In-Reply-To: References: Message-ID: <20130228090048.1ec6af92@debian.org> Cha, Hojeong wrote: > So I thought that it would be beneficial to internationalize Rust > documents, or at least have a base-level work for > internationalization. > > https://gist.github.com/karipe/330d1ce1f0dbbf67abf0#file-tutorial_ko-md > > I would like to hear your opinions about this way of > internationalization. I'm not sure how you generated your initial .po, but if you plan to maintain it and track the evolution of the tutorial, you may consider po4a: http://po4a.alioth.debian.org/ Cheers, Luca -- .''`. | ~<[ Luca BRUNO ~ (kaeso) ]>~ : :' : | Email: lucab (AT) debian.org ~ Debian Developer `. `'` | GPG Key ID: 0x3BFB9FB3 ~ Free Software supporter `- | HAM-radio callsign: IZ1WGT ~ Networking sorcerer -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: not available URL: From ikadro+rust at gmail.com Thu Feb 28 01:45:03 2013 From: ikadro+rust at gmail.com (Cha, Hojeong) Date: Thu, 28 Feb 2013 18:45:03 +0900 Subject: [rust-dev] Internationalization of Rust Documents In-Reply-To: <20130228090048.1ec6af92@debian.org> References: <20130228090048.1ec6af92@debian.org> Message-ID: Thank you for pointing out. I didn't know po4a, so I made pomarkdown myself. I agree that po4a is more appropriate in this task. I do plan to maintain internationalized documents. Furthermore, I aim at the formal inclusion of internationalized documents in the build process if the community agrees on the document i18n. Regards, Cha, Hojeong 2013/2/28 Luca BRUNO > Cha, Hojeong wrote: > > > So I thought that it would be beneficial to internationalize Rust > > documents, or at least have a base-level work for > > internationalization. > > > > https://gist.github.com/karipe/330d1ce1f0dbbf67abf0#file-tutorial_ko-md > > > > I would like to hear your opinions about this way of > > internationalization. > > I'm not sure how you generated your initial .po, but if you plan to > maintain it and track the evolution of the tutorial, you may consider > po4a: http://po4a.alioth.debian.org/ > > Cheers, Luca > > -- > .''`. | ~<[ Luca BRUNO ~ (kaeso) ]>~ > : :' : | Email: lucab (AT) debian.org ~ Debian Developer > `. `'` | GPG Key ID: 0x3BFB9FB3 ~ Free Software supporter > `- | HAM-radio callsign: IZ1WGT ~ Networking sorcerer > > _______________________________________________ > 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 graydon at mozilla.com Thu Feb 28 08:13:43 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 28 Feb 2013 08:13:43 -0800 Subject: [rust-dev] Internationalization of Rust Documents In-Reply-To: References: Message-ID: <512F8237.9070503@mozilla.com> On 27/02/2013 10:38 PM, Cha, Hojeong wrote: > Hello everyone, > > I think many developers have an interest in learning Rust via tutorial. > But the current tutorial is written in English, so it precludes many > potential developers which English is not his/her native language. > > So I thought that it would be beneficial to internationalize Rust > documents, or at least have a base-level work for internationalization. Great! I'm sorry we've been negligent on this front so far; it's simply a matter of lack of available effort / small size of team. We'll absolutely work on improving our i18n/l10n support. We should probably build a gettext-like syntax extension into the compiler (to mimic the _(...) macro) and start moving our strings into .po files too. > There would be many ways that such internationalization can be done, and > I tried to find the tool which is familiar to the developers and able to > update documents whenever the original document had changed; "gettext" > came into my mind, so I lightly prototyped it (in my native tongue, Korean): > > https://gist.github.com/karipe/330d1ce1f0dbbf67abf0#file-tutorial_ko-md > > I would like to hear your opinions about this way of internationalization. Interesting. I am not familiar enough with the mechanisms mozilla generally uses for doc-translation vs. other strings (messages in programs etc.) but I will look into it and follow up. Suggestions welcome from anyone who's been on a translation team. I know we do use .po files and gettext for quite a lot of such things, and operate a pootle server for coordinating several teams. -Graydon From ikadro at gmail.com Thu Feb 28 01:43:12 2013 From: ikadro at gmail.com (=?EUC-KR?B?wvfIo8Gk?=) Date: Thu, 28 Feb 2013 18:43:12 +0900 Subject: [rust-dev] Internationalization of Rust Documents In-Reply-To: <20130228090048.1ec6af92@debian.org> References: <20130228090048.1ec6af92@debian.org> Message-ID: Thank you for pointing out. I didn't know po4a, so I made pomarkdown myself. I agree that po4a is more appropriate in this task. I do plan to maintain internationalized documents. Furthermore, I aim at the eventual inclusion of internationalized documents in the build process if the community agrees on the document i18n. Regards, Cha, Hojeong 2013/2/28 Luca BRUNO > Cha, Hojeong wrote: > > > So I thought that it would be beneficial to internationalize Rust > > documents, or at least have a base-level work for > > internationalization. > > > > https://gist.github.com/karipe/330d1ce1f0dbbf67abf0#file-tutorial_ko-md > > > > I would like to hear your opinions about this way of > > internationalization. > > I'm not sure how you generated your initial .po, but if you plan to > maintain it and track the evolution of the tutorial, you may consider > po4a: http://po4a.alioth.debian.org/ > > Cheers, Luca > > -- > .''`. | ~<[ Luca BRUNO ~ (kaeso) ]>~ > : :' : | Email: lucab (AT) debian.org ~ Debian Developer > `. `'` | GPG Key ID: 0x3BFB9FB3 ~ Free Software supporter > `- | HAM-radio callsign: IZ1WGT ~ Networking sorcerer > > _______________________________________________ > 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 mcguire at crsr.net Thu Feb 28 08:42:41 2013 From: mcguire at crsr.net (Tommy M. McGuire) Date: Thu, 28 Feb 2013 10:42:41 -0600 Subject: [rust-dev] library editing In-Reply-To: <51281661.6030005@mozilla.com> References: <51281661.6030005@mozilla.com> Message-ID: <512F8901.70508@crsr.net> On 02/22/2013 07:07 PM, Graydon Hoare wrote: > After some consultation with the rest of the core rust developer group, > I've posted some new guidelines concerning editing rust's libraries: > > https://github.com/mozilla/rust/wiki/Libs > https://github.com/mozilla/rust/wiki/Library-editing The process seems reasonable, and I like your module guidelines. But, what is the goal of Rust's standard/included libraries (which is what I think you're talking about there)? But I have a sort of philosophical question: is the goal to provide a core set of generic pieces like the C++ library or a "batteries included" approach like Python? I assume Rust will need a Big Bag o' Random Libraries, like Hackage or CPAN; do you have any ideas on what the dividing line between pointing at that and accepting something into the distribution would be? -- Tommy M. McGuire mcguire at crsr.net From erick.tryzelaar at gmail.com Thu Feb 28 09:43:05 2013 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Thu, 28 Feb 2013 09:43:05 -0800 Subject: [rust-dev] library editing In-Reply-To: <512F8901.70508@crsr.net> References: <51281661.6030005@mozilla.com> <512F8901.70508@crsr.net> Message-ID: Hello Tommy, I feel our process will ultimately be more along the lines of a small standard library that needs hooks into the compiler and runtime, and an extensive CPAN-esque repository for everything else. We'll have first party "blessed" packages for things like a web client, compression, and hashing algorithms. There is a lot of technical debt you have to pay with a "batteries included" approach. First off, you need to wait for each release before you can update standard libraries, even if those updates do not depend on changes for the compiler. Second, it forces the compiler team to maintain maintain old libraries for a long time. For example, according to this page (http://python3porting.com/stdlib.html), Python 2.x had to maintain 42 deprecated libraries for many years before they could be finally removed in Python 3. Once our new rustpkg is finished, it should make it really easy to work with external packages. On Thu, Feb 28, 2013 at 8:42 AM, Tommy M. McGuire wrote: > On 02/22/2013 07:07 PM, Graydon Hoare wrote: > > After some consultation with the rest of the core rust developer group, > > I've posted some new guidelines concerning editing rust's libraries: > > > > https://github.com/mozilla/rust/wiki/Libs > > https://github.com/mozilla/rust/wiki/Library-editing > > The process seems reasonable, and I like your module guidelines. But, > what is the goal of Rust's standard/included libraries (which is what I > think you're talking about there)? > > But I have a sort of philosophical question: is the goal to provide a > core set of generic pieces like the C++ library or a "batteries > included" approach like Python? > > I assume Rust will need a Big Bag o' Random Libraries, like Hackage or > CPAN; do you have any ideas on what the dividing line between pointing > at that and accepting something into the distribution would be? > > > > -- > Tommy M. McGuire > mcguire at crsr.net > _______________________________________________ > 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 graydon at mozilla.com Thu Feb 28 10:50:15 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 28 Feb 2013 10:50:15 -0800 Subject: [rust-dev] library editing In-Reply-To: References: <51281661.6030005@mozilla.com> <512F8901.70508@crsr.net> Message-ID: <512FA6E7.4060309@mozilla.com> On 28/02/2013 9:43 AM, Erick Tryzelaar wrote: > Hello Tommy, > > I feel our process will ultimately be more along the lines of a small > standard library that needs hooks into the compiler and runtime, and an > extensive CPAN-esque repository for everything else. We'll have first > party "blessed" packages for things like a web client, compression, and > hashing algorithms. This "blessed packages" approach to libstd is appealing in some ways but unappealing in others; it's something we discussed at the last weekly meeting and I'm curious to hear more perspectives on it. There are a bunch of tensions at work: - Terminology-wise, "standard library" as in "gets written into a standards document" suggests a very minimal libcore-like (or smaller) component. This is Stroustrup's philosophy[1] and it has a credible basis. You don't want to burden ISO translators with writing up the docs to your space invaders emulator[2]. - In terms of user convenience, tracking numerous library versions is a pain, as is tracking numerous "works on OS $foo" statuses. A standard-ish (or "common" if we want to avoid the word "standard") library is helpful in setting expectations about what a user can expect to be able to get working "on all reasonable installs", as well as which APIs will have long-term support and high levels of QA, documentation, integration testing, porting, etc. - Gating releases of a language on readiness-status of libraries and maintaining legacy APIs is a pain, true, but users often care much more about library APIs than they do about language features. "How do I write $foo in Rust" is very often an API question, not a language question, and the absence of a good API is equivalent to saying "go away". - Certain code idioms are mutually recursive. These need to be in the same crate for our purposes. In general my tendency is towards "batteries included" from the _user experience_ perspective when possible; this does leave some question about whether (and how) to approach a best-of-both-worlds situation as far as making the _developer experience_ also pleasant. I've been pushing around ideas about how to manage possibly re-exporting pinned versions of particular external libraries as part of the libstd namespace, as a way to mediate these tensions. Doing so would have possibly-weird, possibly-ok effects: - We might have to teach rustpkg to handle the idea of a mod directive resolving against a pkgid, the same way we're going to be teaching it to resolve extern mod directives. That is, we might need to be able to write 'mod foo = "github.com/user/foo";' and have it imply that the package manager check out that library but _build it into the referencing crate_ rather than as an extern. But I think that's ... possibly ok, and might even be pleasantly uniform in practice. - The libstd major-version might advance as the _maximum_ of advances in included libraries. It might bump with nearly every release, though I have a long-standing idea in mind to mitigate this: version attributes on module items. This is essentially a way to turn what _would_ be a major-version bump (API change) into a minor-version bump (API addition), since the items wind up qualified by separate version numbers. This might wind up weird or it might wind up quite practical. We haven't implemented it yet. Put concretely, we might get away with doing this (in libstd): #[vers="1.0.0"] pub mod foo = "github.com/user/foo#1.0"; #[vers="1.1.0"] pub mod foo = "github.com/user/foo#2.0"; which would "absorb" the major-version change between two versions of libfoo into a minor-version change to libstd, because we're "keeping the old API" of foo around qualified with std vers 1.0.0. Anyone who bound to "pkg.rust-lang.org/std#1.0.0" would get the old libfoo API they are expecting, but the package manager would be willing to provide it by downloading 1.0.0 or 1.1.0; in semver logic we literally are just "adding API" so are treated as such by version-reasoning tools. Moreover if a user wants to use a mixture of old and new APIs they can: extern mod std = "pkg.rust-lang.org/std#1.0.0"; std::foo::bar(1); // using foo::bar 1.0 API mod futuristic { // This module's been upgraded. extern mod std = "pkg.rust-lang.org/std#1.1.0"; std::foo::bar(1, true); // using foo::bar 2.0 API } of course if we got sick of maintaining foo 1.0 in libstd, we'd remove it and that would cause a major-version bump to libstd. Presumably we'd clear out a bunch of old re-exports at once in such a case -- anything that we're convinced is obsolete & unused, or causing undue maintenance pain. I'm interested to hear thoughts from others, as usual. This is tricky to get just right but it's important. API compatibility is the thing hardest to handle over time as they'll _always_ evolve, no matter how stable the language; having a strategy for thinking about backward compatibility might help us avoid the version tarpit that has happened to so many languages (inability to ship new APIs due to mismatches in users' willingness to upgrade, essentially). How we do this will have pretty major implications for how we work over time. -Graydon [1] https://en.wikipedia.org/wiki/Standard_library#Philosophies [2] http://docs.factorcode.org/content/article-handbook-library-reference.html From graydon at mozilla.com Thu Feb 28 11:46:33 2013 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 28 Feb 2013 11:46:33 -0800 Subject: [rust-dev] library editing In-Reply-To: <512FA6E7.4060309@mozilla.com> References: <51281661.6030005@mozilla.com> <512F8901.70508@crsr.net> <512FA6E7.4060309@mozilla.com> Message-ID: <512FB419.3010900@mozilla.com> On 28/02/2013 10:50 AM, Graydon Hoare wrote: > get away with doing this (in libstd): > > #[vers="1.0.0"] > pub mod foo = "github.com/user/foo#1.0"; > > #[vers="1.1.0"] > pub mod foo = "github.com/user/foo#2.0"; Also note: in case this sounds too terrifying in terms of hacking a new sub-dimension onto resolve, not to mention figuring out how to (automatically?) transform minor-version bumps in the 1.x and 2.x series of libfoo into corresponding minor-version bumps in libstd, this could equally be accomplished manually / by convention, in terms of: pub mod foo_v1 = "github.com/user/foo#1.0"; pub mod foo_v2 = "github.com/user/foo#2.0"; pub mod foo { pub use foo_v1::*; } or even possibly pub mod foo { pub mod v1 = "github.com/user/foo#1.0"; pub mod v2 = "github.com/user/foo#2.0"; pub use foo::v1::*; } assuming foo doesn't define names v1 and v2 itself (unlikely). Our module system is quite strong when it comes to rebinding names. Doing it this way just involves more legwork. But it might be desirable from a "minimizing cognitive load" perspective to make this explicit in the code and avoid having to reason about versions when thinking about what resolve is doing. -Graydon From pnathan at vandals.uidaho.edu Thu Feb 28 11:56:39 2013 From: pnathan at vandals.uidaho.edu (Paul Nathan) Date: Thu, 28 Feb 2013 11:56:39 -0800 Subject: [rust-dev] library editing In-Reply-To: <8158C096-CC19-4762-BD2A-49B4F43B8D09@vandals.uidaho.edu> References: <51281661.6030005@mozilla.com> <512F8901.70508@crsr.net> <512FA6E7.4060309@mozilla.com> <8158C096-CC19-4762-BD2A-49B4F43B8D09@vandals.uidaho.edu> Message-ID: Forgot to reply-all. d'oh! Regards, Paul Nathan Sent from my iPhone On Feb 28, 2013, at 11:01 AM, Paul Nathan wrote: > I would suggest a three-ring strategy. > > 1. Compiler and minimal libs, much like C. This is the sacred system maintained by rust devs. This is just what would be needed for writing embedded systems and other minimal lib situations. > > 2. Blessed ring: moves faster and is collected periodically. C.f. Haskell platform. It represents common programming tasks and 'batteries'. Not standardized.( no iso document) > > 3. Rust-cpan. Free for all. Yahoos. Whatever. Popular packages might make into the platform. > > N. b. - Version locking can be problematic and a hassle; see in the case of Haskell/cabal. > > Well, those are my 2c. :) > > Regards, > Paul Nathan > > Sent from my iPhone > > On Feb 28, 2013, at 10:50 AM, Graydon Hoare wrote: > >> On 28/02/2013 9:43 AM, Erick Tryzelaar wrote: >>> Hello Tommy, >>> >>> I feel our process will ultimately be more along the lines of a small >>> standard library that needs hooks into the compiler and runtime, and an >>> extensive CPAN-esque repository for everything else. We'll have first >>> party "blessed" packages for things like a web client, compression, and >>> hashing algorithms. >> >> This "blessed packages" approach to libstd is appealing in some ways but >> unappealing in others; it's something we discussed at the last weekly >> meeting and I'm curious to hear more perspectives on it. There are a >> bunch of tensions at work: >> >> - Terminology-wise, "standard library" as in "gets written into a >> standards document" suggests a very minimal libcore-like (or >> smaller) component. This is Stroustrup's philosophy[1] and it has >> a credible basis. You don't want to burden ISO translators with >> writing up the docs to your space invaders emulator[2]. >> >> - In terms of user convenience, tracking numerous library versions >> is a pain, as is tracking numerous "works on OS $foo" statuses. >> A standard-ish (or "common" if we want to avoid the word "standard") >> library is helpful in setting expectations about what a user can >> expect to be able to get working "on all reasonable installs", >> as well as which APIs will have long-term support and high levels >> of QA, documentation, integration testing, porting, etc. >> >> - Gating releases of a language on readiness-status of libraries and >> maintaining legacy APIs is a pain, true, but users often care much >> more about library APIs than they do about language features. "How >> do I write $foo in Rust" is very often an API question, not a >> language question, and the absence of a good API is equivalent >> to saying "go away". >> >> - Certain code idioms are mutually recursive. These need to be in the >> same crate for our purposes. >> >> In general my tendency is towards "batteries included" from the _user >> experience_ perspective when possible; this does leave some question >> about whether (and how) to approach a best-of-both-worlds situation as >> far as making the _developer experience_ also pleasant. >> >> I've been pushing around ideas about how to manage possibly re-exporting >> pinned versions of particular external libraries as part of the libstd >> namespace, as a way to mediate these tensions. Doing so would have >> possibly-weird, possibly-ok effects: >> >> - We might have to teach rustpkg to handle the idea of a mod >> directive resolving against a pkgid, the same way we're going >> to be teaching it to resolve extern mod directives. That is, we >> might need to be able to write 'mod foo = "github.com/user/foo";' >> and have it imply that the package manager check out that >> library but _build it into the referencing crate_ rather than as >> an extern. But I think that's ... possibly ok, and might even be >> pleasantly uniform in practice. >> >> - The libstd major-version might advance as the _maximum_ of advances >> in included libraries. It might bump with nearly every release, >> though I have a long-standing idea in mind to mitigate this: version >> attributes on module items. This is essentially a way to turn what >> _would_ be a major-version bump (API change) into a minor-version >> bump (API addition), since the items wind up qualified by separate >> version numbers. This might wind up weird or it might wind up quite >> practical. We haven't implemented it yet. Put concretely, we might >> get away with doing this (in libstd): >> >> #[vers="1.0.0"] >> pub mod foo = "github.com/user/foo#1.0"; >> >> #[vers="1.1.0"] >> pub mod foo = "github.com/user/foo#2.0"; >> >> which would "absorb" the major-version change between two versions >> of libfoo into a minor-version change to libstd, because we're >> "keeping the old API" of foo around qualified with std vers 1.0.0. >> Anyone who bound to "pkg.rust-lang.org/std#1.0.0" would get the >> old libfoo API they are expecting, but the package manager would >> be willing to provide it by downloading 1.0.0 or 1.1.0; in semver >> logic we literally are just "adding API" so are treated as such by >> version-reasoning tools. Moreover if a user wants to use a mixture >> of old and new APIs they can: >> >> extern mod std = "pkg.rust-lang.org/std#1.0.0"; >> std::foo::bar(1); // using foo::bar 1.0 API >> >> mod futuristic { >> // This module's been upgraded. >> extern mod std = "pkg.rust-lang.org/std#1.1.0"; >> std::foo::bar(1, true); // using foo::bar 2.0 API >> } >> >> of course if we got sick of maintaining foo 1.0 in libstd, we'd >> remove it and that would cause a major-version bump to libstd. >> Presumably we'd clear out a bunch of old re-exports at once in >> such a case -- anything that we're convinced is obsolete & unused, >> or causing undue maintenance pain. >> >> I'm interested to hear thoughts from others, as usual. This is tricky to >> get just right but it's important. API compatibility is the thing >> hardest to handle over time as they'll _always_ evolve, no matter how >> stable the language; having a strategy for thinking about backward >> compatibility might help us avoid the version tarpit that has happened >> to so many languages (inability to ship new APIs due to mismatches in >> users' willingness to upgrade, essentially). How we do this will have >> pretty major implications for how we work over time. >> >> -Graydon >> >> [1] https://en.wikipedia.org/wiki/Standard_library#Philosophies >> [2] >> http://docs.factorcode.org/content/article-handbook-library-reference.html >> >> _______________________________________________ >> Rust-dev mailing list >> Rust-dev at mozilla.org >> https://mail.mozilla.org/listinfo/rust-dev >> From pwalton at mozilla.com Thu Feb 28 21:18:09 2013 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 28 Feb 2013 21:18:09 -0800 Subject: [rust-dev] RFC: Remove custom enum variant discriminants Message-ID: <51303A11.9020702@mozilla.com> Hi everyone, There is currently a feature whereby custom enum variant discriminants can be specified: pub enum Foo { Bar = 1, Baz = 2, Boo = 3, } The sole use of this is casting from the enum to an int: println(fmt!("%d", Bar as int)); // prints 1 This feature currently doesn't really meet people's needs. Chief among the issues are: 1. Only ints are supported, but many enums want to correspond to different sizes of types. 2. Only casting *from* an enum value is supported, not casting *to* an enum value. Casting to an enum value is not supported because this is a partial operation. 3. There is no way to have multiple values correspond to a single enum variant. We could extend the syntax to support these in some way, but I'm personally leaning toward just moving the machinery into a syntax extension. You could write something like: numeric_enum!(Foo : uint { Bar = 1, Baz = 2 | 3, Boo = 4 }) Then the compiler would generate functions like: Foo::from_uint(uint) -> Result Foo::to_uint(self) -> uint One could also imagine a similar syntax extension for bitfields. Besides the obvious advantage that it simplifies the language, we can make the `from_foo` type return a proper Result (or use the condition system) without building Result into the compiler. Thoughts? Patrick