These are chat archives for rust-lang/rust

9th
Dec 2016
Paul Betts
@paulcbetts
Dec 09 2016 07:08
Is there a way to add methods onto Traits?
Like, "any object who implements the Foo trait, gets these methods for free"
Jonas Platte
@jplatte
Dec 09 2016 07:09
@paulcbetts Yeah, you can do that. itertools does this for example.
Paul Betts
@paulcbetts
Dec 09 2016 07:09
In C#, you'd write an Extension Method onto an Interface
I can see Traits can bolt on things to concrete types
Aha ok, I see how you do it
You declare an inherited trait onto the trait you want to extend, with all default-impl'd methods
Jonas Platte
@jplatte
Dec 09 2016 07:14
Yeah exactly
Paul Betts
@paulcbetts
Dec 09 2016 07:15
Then you add impl<T: ?Sized> MyCoolExtensions for T where T: OriginalTrait { }
Jonas Platte
@jplatte
Dec 09 2016 07:15
And then you just need an empty impl block like this: https://github.com/bluss/rust-itertools/blob/master/src/lib.rs#L1512
Yeah
If your original trait requires Sized, you can leave out the : ?Sized part of the impl block.
Paul Betts
@paulcbetts
Dec 09 2016 07:26
So here's a dumb question, does Rust have field access modifiers like public, private, etc?
Jonas Platte
@jplatte
Dec 09 2016 07:27
Yes, it has pub. The only alternative is just leaving it out, resulting in a field being module-internal.
Paul Betts
@paulcbetts
Dec 09 2016 07:28
So the two options are public or module-internal, got it
Jonas Platte
@jplatte
Dec 09 2016 07:32
Yeah. AFAICT having pub on fields only makes sense when the overall struct is also exported (pub struct ...). And it might be worth knowing that you can directly initialize structs outside of their module if all their fields are public (so when you have a pub struct MyType(pub u32) you can create a MyType outside of its module by writing MyType(42), without a new function or similar.
Same goes for pattern matching on a value of MyType, all fields need to be visible (so either your pattern matching code is in the same module, or all the fields are public)
xialvjun
@xialvjun
Dec 09 2016 08:21

I got to know it yesterday: ownership is from varibles sharing the same object in the heap and from different thread have different lifecycle, then we do not know when to deallocate it.

But just now, I came up this idea: we can save the references count in the object in the heap, then every reference's lifecycle ends, the count minus 1. When the count is 0, deallocate the memory.

So, ownership is needless and the compiler can do the minus references count and deallocate memory job for us too.

Sergey Noskov
@Albibek
Dec 09 2016 08:23
@xialvjun in Rust the Rc<T> and Arc<T> types exist for exactly this purpose
xialvjun
@xialvjun
Dec 09 2016 08:25
Eh, I'm not asking about types. I mean: there are two way for auto deallocate memory except GC, one is ownership, one is reference count. I just want to know why Rust choose ownership?
Sergey Noskov
@Albibek
Dec 09 2016 08:27
Rust gives you both possibilities
Jonas Platte
@jplatte
Dec 09 2016 08:28
@xialvjun The default is ownership because it's much slower to reference count every single object.
xialvjun
@xialvjun
Dec 09 2016 08:30
Oh, I see. Thank you @jplatte @Albibek .
Well, I think deallocating the memory some what slower doesn't matter. Well, Rust is a System Programing Language, maybe that's important.
Sergey Noskov
@Albibek
Dec 09 2016 08:34
It's not about only freeing memory, it's also about overhead of changing something when you only need to take another reference to memory location.
With ownership you don't need to do it at all, because it's checked statically
Peter Atashian
@retep998
Dec 09 2016 08:44
Ownership let's you work with pointers with no runtime overhead at all, but comes with some restrictions such as lifetime checks and stuff
xialvjun
@xialvjun
Dec 09 2016 08:48
@Albibek what do you mean by changing something when you only need to take another reference to memory location
Sergey Noskov
@Albibek
Dec 09 2016 08:59
@xialvjun this is how RC is supposed to work - wvery time you need a reference to memory area, you have to increase some counter. This definitely lowers cache efficiency in some cases.
xialvjun
@xialvjun
Dec 09 2016 09:05
Oh, I just thought about there is a consume on deallocating memory, didn't notice there are also consumings on every time the references count change, and the consuming must be atomic. The total consuming must be huge.
Sergey Noskov
@Albibek
Dec 09 2016 09:06
the must is only need in the multithreaded environment, and this is why Rust has 2 RC types - Arc is atomic, Rc is not
xialvjun
@xialvjun
Dec 09 2016 09:10
Well, I don't know what RC is now. I'll go on reading the docs.
Zhang Cheng
@Matrix-Zhang
Dec 09 2016 09:47
Hi, I use crate syslog to redirect the logs to journal, the application is manage by Systemd, how to redirect the RUST_BACKTRACE err log to journal too?
Sergey Noskov
@Albibek
Dec 09 2016 09:50
@Matrix-Zhang afaik, systemd just catches the stderr of the process, so you should write the backtrace there
Zhang Cheng
@Matrix-Zhang
Dec 09 2016 09:58
the RUST_BACKTRACE is auto generated... how to write my self?
In Systemd Service unite file , i also write StandardError=journal
xialvjun
@xialvjun
Dec 09 2016 16:24
fn main() {
    let y: &Vec<i32>;
    {
        let x = &vec![1, 2, 3];
        y = x;
    }
    println!("{}", y[0]);
}
why it cannot compile? I have move the ownership from x to y, why the error is borrowed value does not live long enough
Aleksey Kladov
@matklad
Dec 09 2016 16:25
This is equivalent to
fn main() {
    let y: &Vec<i32>;
    {
        let tmp = vec![1, 2, 3]; 
        let x = &tmp;
        y = x;
        // tmp gets deallocated here
    }
    println!("{}", y[0]);
}
xialvjun
@xialvjun
Dec 09 2016 16:26
...... Oh, it is........ Thank you very much..
Aleksey Kladov
@matklad
Dec 09 2016 16:26
The variant with explicit tmp variant can't work because the vector is dropped at the end of the inner block.
And when you take a reference to the result of an expression, the rust compiler creates this tmp variable automatically.
xialvjun
@xialvjun
Dec 09 2016 16:46
Well, your code made me understand, but your next sentence made me confused... I don't know what are you saying..... :cry:
Aleksey Kladov
@matklad
Dec 09 2016 16:47
Usually, when you evaluate an expression, like (1 + 2) + 3 there are several intermediate results
that is, compiler has to generate code for adding 1 and 2 and than code to add 3 to the result.
Normally, such temporaries live only during the evaluation of the expression itself.
However, if you take a reference to such temporary object &(1 + 12)
xialvjun
@xialvjun
Dec 09 2016 16:49
Yeah, we didn't name it.
Aleksey Kladov
@matklad
Dec 09 2016 16:49
compiler makes sure that the object lives longer, by introducing a secret named object to hold the result.
Basically, it would be possible just to flat out forbid to take the references to temporaries, and to require programmers to introduce variables.
But this is a simple transformation, and compiler can do it on behalf of the programmer automatically.
xialvjun
@xialvjun
Dec 09 2016 16:51
Got it, that the difference between ASM and higher level programing language.
In ASM, one sentence can only do one job.
Grizmoblust
@Grizmoblust
Dec 09 2016 17:07
I been doing research on next generation browser. Would it be better to drop the whole concept of dom, and use imgui? No more css/html haggles, and annoying culprits that causes multiple issues on different browser platform. I was reading this thread, and find it interesting and figuring out where to go from here. https://www.reddit.com/r/rust/comments/57pgjz/now_that_rust_can_now_compile_to/

I want a complete web framework, frontend and backend with transparent data synchronisation between the two, with blazing fast performance, all held together by Rust's exquisite type system.

This I can support.

Maciej Hirsz
@maciejhirsz
Dec 09 2016 17:19
you can already drop DOM (kinda, you still need one element) with <canvas> and render everything pixel perfect in all browsers
the reality of the situation seems to be that HTML+CSS is the go-to tool for UI not just for the web, but often for desktop and mobile apps using webviews
WASM is a step in the right direction. I'm not sure if you can kill the current browser ecosystem, we already tried that (Microsoft dissolving IE team after IE6 took over because "web is dead"), didn't turn out so well :p.
Grizmoblust
@Grizmoblust
Dec 09 2016 17:24
It seems that a lot of people rather use react to curb the html/css issues. But taking a step further, why not drop it all together and have users control the UI. The only thing that should matter is getting static data from the network. Where it is placed should be up to the user, not server side decision. Think like emacs browser.
or like desktop window manager, more control on the layout.
Joe Grund
@jgrund
Dec 09 2016 17:32
Hi, Is there a way to produce custom output from cargo test?
Or has someone created a crate that parses the current output?
I want to integrate test results into my CI
Grizmoblust
@Grizmoblust
Dec 09 2016 17:32
clippy
maybe that?
Joe Grund
@jgrund
Dec 09 2016 17:34
I thought clippy was for linting, does it run tests as well?
Robyn Speer
@rspeer
Dec 09 2016 18:25
Is there a straightforward way to iterate through the lines of a file in Rust? The answers about this on Stack Overflow tend to be about pre-1.0 versions of Rust, I had to piece together something ugly, and usually this means that I've missed something so simple that nobody even has to ask about it.
Here's what I'm doing:
use std::io::{BufReader, BufRead};
use std::fs::File;

pub fn handle_file(filename: &str) -> Result<(), io::Error> {
    let file = BufReader::new(File::open(filename)?);
    for (i, line) in file.lines().filter_map(|result| result.ok()).enumerate() {
        // do stuff
    }
    Ok(())
}
Robyn Speer
@rspeer
Dec 09 2016 18:32
(edited to clean it up a bit and to show the imports that all seem to be necessary)
boats
@withoutboats
Dec 09 2016 18:42
@rspeer What you're doing seems fine, is there something you don't like about it?
Robyn Speer
@rspeer
Dec 09 2016 18:42
The most confusing part is having to import both BufReader and BufRead just to get a .lines() method
boats
@withoutboats
Dec 09 2016 18:43
You have to import traits in order to use their methods.
Robyn Speer
@rspeer
Dec 09 2016 18:44
Right... so my question is, is there an abstraction over this where I wouldn't have to carefully explain to Rust how to iterate lines of a file every time I want to iterate lines of a file?
Aleksey Kladov
@matklad
Dec 09 2016 18:44
You can do use std::io::prelude::* IIRC
Robyn Speer
@rspeer
Dec 09 2016 18:45
Interesting. That seems convenient. Is it recommended or is it an anti-pattern like from package import * in Python?
boats
@withoutboats
Dec 09 2016 18:46
@rspeer I don't know what you mean about carefully explaining. All you've had to do is decide how to do error handling
For example, you've chosen to ignore errors encountered while reading the file here, but someone else may make a different choice
On the other hand, the mechanics of reading, buffering, and iterating by line are all handled for you in the implementation of File, BufReader, and the Lines iterator.
Robyn Speer
@rspeer
Dec 09 2016 18:47
Well, I have to say that I want the mechanics of buffering, even though that's the only way to read lines
boats
@withoutboats
Dec 09 2016 18:49
Yea, the file needs to be buffered to iterate over it by lines, but it doesn't need to be buffered for every kind of reading from it.
Robyn Speer
@rspeer
Dec 09 2016 18:49
...also, I'm not ignoring errors, I'm propagating them
well, some of them
couldn't figure out a way to question-mark the individual lines
boats
@withoutboats
Dec 09 2016 18:50
for that, you can do this:
Robyn Speer
@rspeer
Dec 09 2016 18:50
though I don't care if the error happens when opening the file or later, it's an I/O problem I want to propagate either way
boats
@withoutboats
Dec 09 2016 18:51
for (i, line) in file.lines().enumerate() { let line = line?; // do stuff }
I believe that should work
Robyn Speer
@rspeer
Dec 09 2016 18:51
ah okay, that's a bit clearer
hey, I just found where this is all documented! https://doc.rust-lang.org/std/io/trait.BufRead.html#examples
I wish that page had more Google-juice.
std::io::prelude is a useful thing to learn about, thanks.
Ross
@breadmenace_twitter
Dec 09 2016 19:45
Yeah, I'm with you there @rspeer--I had no idea what std::io::prelude was for, though now that I look it's imported in all the examples on the docs page for std::io
Matanel Levi
@matanelevi
Dec 09 2016 20:38
Someone can please explain how the byteorder crate and io::Cursor "interact"?
I didn't get how Cursor got the read_u16 method
Aleksey Kladov
@matklad
Dec 09 2016 20:45
At the bottom of the page there's a list of implementations
with impl<R: Read + ?Sized> ReadBytesExt for R
That means that anything that is Read is also ReadBytesExt
And the cursor over bytes is Read because there is impl<T> Read for Cursor<T> where T: AsRef<[u8]> (https://doc.rust-lang.org/std/io/trait.Read.html)
Matanel Levi
@matanelevi
Dec 09 2016 21:03
@matklad thanks!
Dale Wijnand
@dwijnand
Dec 09 2016 21:46
Is there the equivalent of bash's exec in Rust? i.e. replaces the running rust program with the specified program.
Aleksey Kladov
@matklad
Dec 09 2016 21:47
There's nothing buildin, but you can call into your system libarary for similar functionality. nix crate for unices and winapi for windows.
Dale Wijnand
@dwijnand
Dec 09 2016 21:50
Thanks. How would I do it with the nix crate?
Aleksey Kladov
@matklad
Dec 09 2016 21:52
Dale Wijnand
@dwijnand
Dec 09 2016 21:52
Thanks I'll give it a shot.
Ross
@breadmenace_twitter
Dec 09 2016 21:52
Dale Wijnand
@dwijnand
Dec 09 2016 21:53
looks promising, thank you
Aleksey Kladov
@matklad
Dec 09 2016 21:53
@breadmenace_twitter wow, I didn't know about that one, thanks a bunch!
Dale Wijnand
@dwijnand
Dec 09 2016 21:54
avoids me having to have 2 crates and having to conditionally dispatch to the appropriate one

or maybe not (I should learn to read):

Unix-specific extensions to the std::process::Command builder

Pavel Meledin
@btbvoy
Dec 09 2016 22:00
trait EventValidator<EVENT, ERROR> {
    fn is_valid(&self, event: EVENT) -> Result<&self, ERROR>;
}

I want to indicate that any impl which will implement this trait could return either self or an Error but compiler says that :

  |
5 |     fn is_valid(&self, event: EVENT) -> Result<self, ERROR>;
  |                                                ^^^^ undefined or not in scope
  |
  = help: no candidates by the name of `self` found in your project; maybe you misspelled the name or forgot to import an external crate?

How I to achieve it ?

I want that instead of self there will be certain type which impl has
Matanel Levi
@matanelevi
Dec 09 2016 22:01
@btbvoy Self?
Pavel Meledin
@btbvoy
Dec 09 2016 22:01
just Self without & ?
Dale Wijnand
@dwijnand
Dec 09 2016 22:02
Worked like a charm. Thank you @matklad and @breadmenace_twitter
Matanel Levi
@matanelevi
Dec 09 2016 22:02
@btbvoy yep
Pavel Meledin
@btbvoy
Dec 09 2016 22:03
@matanelevi but what if I want to return a reference ? :-)
Alexander Irbis
@alexander-irbis
Dec 09 2016 22:04
@btbvoy what can stop you? :-)
self - is an alias for the current instance, Self - is an alias for the type of the current instance.
Pavel Meledin
@btbvoy
Dec 09 2016 22:07

@alexander-irbis

trait EventValidator<EVENT, ERROR> {
    fn is_valid(self: &Self, event: EVENT) -> Result<&Self, ERROR>;
}

so this is correct signature ? :-)

Alexander Irbis
@alexander-irbis
Dec 09 2016 22:09
@btbvoy just try to compile.
fn xxx(&self) is the same as fn xxx(self: &Self)
Peter Atashian
@retep998
Dec 09 2016 22:40
@dwijnand Windows doesn't have a way to replace the current process with a new program anyway. That CommandExt trait is unix specific.
Dale Wijnand
@dwijnand
Dec 09 2016 22:41
I see. Thanks.